Исправлены отступы в списке слов
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 56s

This commit is contained in:
poignatov
2026-01-20 21:33:23 +03:00
parent 2626722af9
commit e41f721106
12 changed files with 115 additions and 144 deletions

View File

@@ -765,7 +765,7 @@ function AppContent() {
}, [activeTab])
// Определяем, нужно ли скрывать нижнюю панель (для fullscreen экранов)
const isFullscreenTab = activeTab === 'test' || activeTab === 'add-words' || activeTab === 'task-form' || activeTab === 'wishlist-form' || activeTab === 'wishlist-detail' || activeTab === 'todoist-integration' || activeTab === 'telegram-integration' || activeTab === 'full' || activeTab === 'priorities' || activeTab === 'dictionaries'
const isFullscreenTab = activeTab === 'test' || activeTab === 'add-words' || activeTab === 'task-form' || activeTab === 'wishlist-form' || activeTab === 'wishlist-detail' || activeTab === 'todoist-integration' || activeTab === 'telegram-integration' || activeTab === 'full' || activeTab === 'priorities' || activeTab === 'dictionaries' || activeTab === 'words'
// Определяем отступы для контейнера
const getContainerPadding = () => {
@@ -788,6 +788,10 @@ function AppContent() {
if (activeTab === 'dictionaries') {
return 'px-4 md:px-8 py-0'
}
// Для экрана списка слов используем такие же отступы как для словарей
if (activeTab === 'words') {
return 'px-4 md:px-8 py-0'
}
// Для остальных fullscreen экранов без отступов
return 'p-0'
}

View File

@@ -89,42 +89,28 @@ function DictionaryList({ onNavigate, refreshTrigger = 0 }) {
setSelectedDictionary(null)
}
// Показываем загрузку только при первой инициализации и если нет данных для отображения
const shouldShowLoading = loading && !isInitializedRef.current && dictionaries.length === 0
if (shouldShowLoading) {
return (
<div className="dictionary-list">
<div className="fixed inset-0 bottom-20 flex justify-center items-center">
<div className="flex flex-col items-center">
<div className="w-12 h-12 border-4 border-indigo-200 border-t-indigo-600 rounded-full animate-spin mb-4"></div>
<div className="text-gray-600 font-medium">Загрузка...</div>
</div>
</div>
</div>
)
}
if (error) {
return (
<div className="dictionary-list">
<LoadingError onRetry={fetchDictionaries} />
</div>
)
}
return (
<div className="dictionary-list">
{/* Кнопка закрытия */}
<button
<button
className="dictionary-close-button"
onClick={() => onNavigate?.('profile')}
title="Закрыть"
>
</button>
<div className="dictionaries-grid">
{/* Показываем загрузку только при первой инициализации и если нет данных для отображения */}
{loading && !isInitializedRef.current && dictionaries.length === 0 ? (
<div className="fixed inset-0 bottom-20 flex justify-center items-center">
<div className="flex flex-col items-center">
<div className="w-12 h-12 border-4 border-indigo-200 border-t-indigo-600 rounded-full animate-spin mb-4"></div>
<div className="text-gray-600 font-medium">Загрузка...</div>
</div>
</div>
) : error ? (
<LoadingError onRetry={fetchDictionaries} />
) : (
<div className="dictionaries-grid">
{dictionaries.map((dict) => (
<div
key={dict.id}
@@ -151,7 +137,8 @@ function DictionaryList({ onNavigate, refreshTrigger = 0 }) {
<div className="add-dictionary-icon">+</div>
<div className="add-dictionary-text">Добавить</div>
</button>
</div>
</div>
)}
{selectedDictionary && (
<div className="dictionary-modal-overlay" onClick={closeDictionaryModal}>

View File

@@ -117,19 +117,7 @@ function FullStatistics({ selectedProject, onClearSelection, data, loading, erro
const chartData = processData()
// Показываем loading только если данных нет и идет загрузка
if (loading && !chartData) {
return (
<div className="fixed inset-0 flex justify-center items-center">
<div className="flex flex-col items-center">
<div className="w-12 h-12 border-4 border-indigo-200 border-t-indigo-600 rounded-full animate-spin mb-4"></div>
<div className="text-gray-600 font-medium">Загрузка...</div>
</div>
</div>
)
}
if (error && !chartData) {
if (error && !chartData && !loading) {
return <LoadingError onRetry={onRetry} />
}
@@ -194,13 +182,6 @@ function FullStatistics({ selectedProject, onClearSelection, data, loading, erro
},
}
if (!chartData) {
return (
<div className="flex justify-center items-center py-16">
<div className="text-gray-500 text-lg">Нет данных для отображения</div>
</div>
)
}
return (
<div className="max-w-2xl mx-auto">
@@ -213,10 +194,25 @@ function FullStatistics({ selectedProject, onClearSelection, data, loading, erro
</button>
)}
<div style={{ height: '550px', paddingTop: '100px' }}>
<Line data={chartData} options={chartOptions} />
</div>
<WeekProgressChart data={data} allProjectsSorted={getAllProjectsSorted(data)} currentWeekData={currentWeekData} selectedProject={selectedProject} />
{loading && !chartData ? (
<div className="fixed inset-0 flex justify-center items-center">
<div className="flex flex-col items-center">
<div className="w-12 h-12 border-4 border-indigo-200 border-t-indigo-600 rounded-full animate-spin mb-4"></div>
<div className="text-gray-600 font-medium">Загрузка...</div>
</div>
</div>
) : !chartData ? (
<div className="flex justify-center items-center py-16">
<div className="text-gray-500 text-lg">Нет данных для отображения</div>
</div>
) : (
<>
<div style={{ height: '550px', paddingTop: '100px' }}>
<Line data={chartData} options={chartOptions} />
</div>
<WeekProgressChart data={data} allProjectsSorted={getAllProjectsSorted(data)} currentWeekData={currentWeekData} selectedProject={selectedProject} />
</>
)}
</div>
)
}

View File

@@ -705,7 +705,6 @@ function TaskDetail({ taskId, onClose, onRefresh, onTaskCompleted, onNavigate })
</div>
</>
)}
</div>
</div>
{toastMessage && (
<Toast
@@ -715,7 +714,8 @@ function TaskDetail({ taskId, onClose, onRefresh, onTaskCompleted, onNavigate })
/>
)}
</div>
)
</div>
)
}
export default TaskDetail

View File

@@ -765,25 +765,21 @@ function TaskForm({ onNavigate, taskId, wishlistId, isTest: isTestFromProps = fa
}
}
if (loadingTask) {
return (
<div className="task-form">
return (
<div className="task-form">
<button className="close-x-button" onClick={handleCancel}>
</button>
{loadingTask ? (
<div className="fixed inset-0 flex justify-center items-center">
<div className="flex flex-col items-center">
<div className="w-12 h-12 border-4 border-indigo-200 border-t-indigo-600 rounded-full animate-spin mb-4"></div>
<div className="text-gray-600 font-medium">Загрузка...</div>
</div>
</div>
</div>
)
}
return (
<div className="task-form">
<button className="close-x-button" onClick={handleCancel}>
</button>
<h2>{taskId ? 'Редактировать задачу' : 'Новая задача'}</h2>
) : (
<>
<h2>{taskId ? 'Редактировать задачу' : 'Новая задача'}</h2>
<form onSubmit={handleSubmit}>
<div className="form-group">
@@ -1196,14 +1192,17 @@ function TaskForm({ onNavigate, taskId, wishlistId, isTest: isTestFromProps = fa
)}
</div>
</form>
{toastMessage && (
<Toast
message={toastMessage.text}
type={toastMessage.type}
onClose={() => setToastMessage(null)}
/>
)}
</div>
{toastMessage && (
<Toast
message={toastMessage.text}
type={toastMessage.type}
onClose={() => setToastMessage(null)}
/>
)}
</>
)}
)}
</div>
)
}

View File

@@ -595,21 +595,7 @@ function Wishlist({ onNavigate, refreshTrigger = 0, isActive = false, initialBoa
)
}
// Показываем loading только если и доски и желания грузятся
if (boardsLoading && loading) {
return (
<div className="wishlist">
<div className="fixed inset-0 bottom-20 flex justify-center items-center">
<div className="flex flex-col items-center">
<div className="w-12 h-12 border-4 border-indigo-200 border-t-indigo-600 rounded-full animate-spin mb-4"></div>
<div className="text-gray-600 font-medium">Загрузка...</div>
</div>
</div>
</div>
)
}
if (error && items.length === 0) {
if (error && items.length === 0 && !boardsLoading && !loading) {
return (
<div className="wishlist">
<BoardSelector
@@ -638,7 +624,14 @@ function Wishlist({ onNavigate, refreshTrigger = 0, isActive = false, initialBoa
/>
{/* Основной список */}
{loading ? (
{boardsLoading && loading ? (
<div className="fixed inset-0 bottom-20 flex justify-center items-center">
<div className="flex flex-col items-center">
<div className="w-12 h-12 border-4 border-indigo-200 border-t-indigo-600 rounded-full animate-spin mb-4"></div>
<div className="text-gray-600 font-medium">Загрузка...</div>
</div>
</div>
) : loading ? (
<div className="wishlist-loading">
<div className="w-8 h-8 border-4 border-indigo-200 border-t-indigo-600 rounded-full animate-spin"></div>
</div>

View File

@@ -298,24 +298,20 @@ function WishlistDetail({ wishlistId, onNavigate, onRefresh, boardId }) {
)
}
if (loadingWishlist) {
return (
<div className="wishlist-detail">
<div className="fixed inset-0 bottom-20 flex justify-center items-center">
<div className="flex flex-col items-center">
<div className="w-12 h-12 border-4 border-indigo-200 border-t-indigo-600 rounded-full animate-spin mb-4"></div>
<div className="text-gray-600 font-medium">Загрузка...</div>
</div>
</div>
</div>
)
}
return (
<div className="wishlist-detail">
<button className="close-x-button" onClick={() => onNavigate?.('wishlist')}>
</button>
{loadingWishlist && (
<div className="fixed inset-0 bottom-20 flex justify-center items-center">
<div className="flex flex-col items-center">
<div className="w-12 h-12 border-4 border-indigo-200 border-t-indigo-600 rounded-full animate-spin mb-4"></div>
<div className="text-gray-600 font-medium">Загрузка...</div>
</div>
</div>
)}
<h2>{wishlistItem ? wishlistItem.name : 'Желание'}</h2>
<div className="wishlist-detail-content">

View File

@@ -645,25 +645,21 @@ function WishlistForm({ onNavigate, wishlistId, editConditionIndex, newTaskId, b
}
}
if (loadingWishlist) {
return (
<div className="wishlist-form">
<div className="fixed inset-0 bottom-20 flex justify-center items-center">
<div className="flex flex-col items-center">
<div className="w-12 h-12 border-4 border-indigo-200 border-t-indigo-600 rounded-full animate-spin mb-4"></div>
<div className="text-gray-600 font-medium">Загрузка...</div>
</div>
</div>
</div>
)
}
return (
<div className="wishlist-form">
<button className="close-x-button" onClick={handleCancel}>
</button>
<h2>{wishlistId ? 'Редактировать желание' : 'Новое желание'}</h2>
{loadingWishlist ? (
<div className="fixed inset-0 flex justify-center items-center">
<div className="flex flex-col items-center">
<div className="w-12 h-12 border-4 border-indigo-200 border-t-indigo-600 rounded-full animate-spin mb-4"></div>
<div className="text-gray-600 font-medium">Загрузка...</div>
</div>
</div>
) : (
<>
<h2>{wishlistId ? 'Редактировать желание' : 'Новое желание'}</h2>
<form onSubmit={handleSubmit}>
<div className="form-group">
@@ -855,14 +851,17 @@ function WishlistForm({ onNavigate, wishlistId, editConditionIndex, newTaskId, b
/>
)}
{toastMessage && (
<Toast
message={toastMessage.text}
type={toastMessage.type}
onClose={() => setToastMessage(null)}
/>
)}
</div>
{toastMessage && (
<Toast
message={toastMessage.text}
type={toastMessage.type}
onClose={() => setToastMessage(null)}
/>
)}
</>
)}
)}
</div>
)
}

View File

@@ -1,5 +1,7 @@
.word-list {
position: relative;
max-width: 42rem; /* max-w-2xl = 672px */
margin: 0 auto;
}
.close-x-button {

View File

@@ -161,20 +161,7 @@ function WordList({ onNavigate, dictionaryId, isNewDictionary, refreshTrigger =
// Show save button only if name is not empty and has changed
const showSaveButton = dictionaryName.trim() !== '' && dictionaryName.trim() !== originalDictionaryName
if (loading) {
return (
<div className="word-list">
<div className="fixed inset-0 flex justify-center items-center">
<div className="flex flex-col items-center">
<div className="w-12 h-12 border-4 border-indigo-200 border-t-indigo-600 rounded-full animate-spin mb-4"></div>
<div className="text-gray-600 font-medium">Загрузка...</div>
</div>
</div>
</div>
)
}
if (error) {
if (error && !loading) {
return (
<div className="word-list">
<LoadingError onRetry={() => {
@@ -188,13 +175,21 @@ function WordList({ onNavigate, dictionaryId, isNewDictionary, refreshTrigger =
return (
<div className="word-list">
<button
onClick={() => onNavigate?.('dictionaries')}
<button
onClick={() => onNavigate?.('dictionaries')}
className="close-x-button"
title="Закрыть"
>
</button>
{loading && (
<div className="fixed inset-0 flex justify-center items-center">
<div className="flex flex-col items-center">
<div className="w-12 h-12 border-4 border-indigo-200 border-t-indigo-600 rounded-full animate-spin mb-4"></div>
<div className="text-gray-600 font-medium">Загрузка...</div>
</div>
</div>
)}
{/* Dictionary name input */}
<div className="dictionary-name-input-container">