Исправлены отступы в списке слов
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

@@ -1 +1 @@
3.24.1
3.24.2

View File

@@ -1,6 +1,6 @@
{
"name": "play-life-web",
"version": "3.24.1",
"version": "3.24.2",
"type": "module",
"scripts": {
"dev": "vite",

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,30 +89,6 @@ 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">
{/* Кнопка закрытия */}
@@ -123,7 +99,17 @@ function DictionaryList({ onNavigate, refreshTrigger = 0 }) {
>
</button>
{/* Показываем загрузку только при первой инициализации и если нет данных для отображения */}
{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
@@ -152,6 +138,7 @@ function DictionaryList({ onNavigate, refreshTrigger = 0 }) {
<div className="add-dictionary-text">Добавить</div>
</button>
</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>
)}
{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

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

View File

@@ -765,24 +765,20 @@ function TaskForm({ onNavigate, taskId, wishlistId, isTest: isTestFromProps = fa
}
}
if (loadingTask) {
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>
<form onSubmit={handleSubmit}>
@@ -1203,6 +1199,9 @@ function TaskForm({ onNavigate, taskId, wishlistId, isTest: isTestFromProps = fa
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,24 +645,20 @@ 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>
{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}>
@@ -862,6 +858,9 @@ function WishlistForm({ onNavigate, wishlistId, editConditionIndex, newTaskId, b
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={() => {
@@ -195,6 +182,14 @@ function WordList({ onNavigate, dictionaryId, isNewDictionary, refreshTrigger =
>
</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">