From 24be9fad27d02d381914f8d24679709ac3a5adf6 Mon Sep 17 00:00:00 2001 From: poignatov Date: Tue, 20 Jan 2026 22:16:08 +0300 Subject: [PATCH] =?UTF-8?q?=D0=92=D0=B5=D1=80=D1=81=D0=B8=D1=8F=203.25.0:?= =?UTF-8?q?=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=BE?= =?UTF-8?q?=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5?= =?UTF-8?q?=20=D1=81=D0=BB=D0=BE=D0=B2=20=D0=B2=20=D1=81=D0=BB=D0=BE=D0=B2?= =?UTF-8?q?=D0=B0=D1=80=D1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- VERSION | 2 +- play-life-web/package.json | 2 +- play-life-web/src/App.jsx | 157 +++++++++++++++++- play-life-web/src/components/AddWords.jsx | 52 +++++- .../src/components/DictionaryList.jsx | 9 +- play-life-web/src/components/TaskList.jsx | 51 ------ play-life-web/src/components/Wishlist.jsx | 6 - play-life-web/src/components/WordList.jsx | 6 - 8 files changed, 203 insertions(+), 82 deletions(-) diff --git a/VERSION b/VERSION index 5edc0a6..0914443 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.24.2 +3.25.0 diff --git a/play-life-web/package.json b/play-life-web/package.json index 54c5685..8a78f38 100644 --- a/play-life-web/package.json +++ b/play-life-web/package.json @@ -1,6 +1,6 @@ { "name": "play-life-web", - "version": "3.24.2", + "version": "3.25.0", "type": "module", "scripts": { "dev": "vite", diff --git a/play-life-web/src/App.jsx b/play-life-web/src/App.jsx index 14fc242..3b1f3f9 100644 --- a/play-life-web/src/App.jsx +++ b/play-life-web/src/App.jsx @@ -89,7 +89,10 @@ function AppContent() { // Параметры для навигации между вкладками const [tabParams, setTabParams] = useState({}) - + + // Модальное окно выбора типа задачи + const [showAddModal, setShowAddModal] = useState(false) + // Кеширование данных const [currentWeekData, setCurrentWeekData] = useState(null) const [fullStatisticsData, setFullStatisticsData] = useState(null) @@ -701,6 +704,21 @@ function AppContent() { } } + // Обработчики для кнопки добавления задачи + const handleAddClick = () => { + setShowAddModal(true) + } + + const handleAddTask = () => { + setShowAddModal(false) + handleNavigate('task-form', { taskId: undefined, isTest: false }) + } + + const handleAddTest = () => { + setShowAddModal(false) + handleNavigate('task-form', { taskId: undefined, isTest: true }) + } + // Обработчик навигации для компонентов const handleNavigate = (tab, params = {}) => { handleTabChange(tab, params) @@ -765,13 +783,13 @@ 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' || activeTab === 'words' + 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 === 'words' || activeTab === 'dictionaries' // Определяем отступы для контейнера const getContainerPadding = () => { if (!isFullscreenTab) { - // Для tasks и profile на широких экранах увеличиваем отступ - if (activeTab === 'tasks' || activeTab === 'profile') { + // Для tasks, wishlist и profile на широких экранах увеличиваем отступ + if (activeTab === 'tasks' || activeTab === 'wishlist' || activeTab === 'profile') { return 'p-4 md:p-8' } return 'p-4 md:p-6' @@ -792,13 +810,17 @@ function AppContent() { if (activeTab === 'words') { return 'px-4 md:px-8 py-0' } + // Для экрана желаний используем такие же отступы как для словарей + if (activeTab === 'wishlist') { + return 'px-4 md:px-8 py-0' + } // Для остальных fullscreen экранов без отступов return 'p-0' } return (
-
+
{loadedTabs.current && (
@@ -993,7 +1015,95 @@ function AppContent() { )}
- + + {/* Кнопка добавления задачи (только для таба задач) */} + {!isFullscreenTab && activeTab === 'tasks' && ( + + )} + + {/* Кнопка добавления желания (только для таба wishlist) */} + {!isFullscreenTab && activeTab === 'wishlist' && ( + + )} + + {/* Кнопка добавления словаря (только для таба dictionaries) */} + {activeTab === 'dictionaries' && ( + + )} + + {/* Кнопка добавления слов (только для таба words) */} + {activeTab === 'words' && ( + + )} + {!isFullscreenTab && (
@@ -1081,6 +1191,41 @@ function AppContent() {
)} + + {/* Модальное окно выбора типа задачи */} + {showAddModal && ( +
setShowAddModal(false)}> +
e.stopPropagation()}> +
+

Что добавить?

+
+
+ + +
+
+
+ )}
) } diff --git a/play-life-web/src/components/AddWords.jsx b/play-life-web/src/components/AddWords.jsx index c717e5e..19b9288 100644 --- a/play-life-web/src/components/AddWords.jsx +++ b/play-life-web/src/components/AddWords.jsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react' +import React, { useState, useEffect } from 'react' import { useAuth } from './auth/AuthContext' import './AddWords.css' @@ -9,9 +9,41 @@ function AddWords({ onNavigate, dictionaryId, dictionaryName }) { const [markdownText, setMarkdownText] = useState('') const [message, setMessage] = useState('') const [loading, setLoading] = useState(false) - + const [currentDictionaryName, setCurrentDictionaryName] = useState(dictionaryName || '') + const [dictionaryLoading, setDictionaryLoading] = useState(false) + + // Fetch dictionary name if not provided and dictionaryId exists + useEffect(() => { + if (dictionaryName) { + setCurrentDictionaryName(dictionaryName) + } else if (dictionaryId) { + fetchDictionaryName(dictionaryId) + } + }, [dictionaryId, dictionaryName]) + + const fetchDictionaryName = async (dictId) => { + if (!dictId) return + + setDictionaryLoading(true) + try { + const response = await authFetch(`${API_URL}/dictionaries`) + if (!response.ok) { + throw new Error('Ошибка при загрузке словарей') + } + const dictionaries = await response.json() + const dict = dictionaries.find(d => d.id === dictId) + if (dict) { + setCurrentDictionaryName(dict.name) + } + } catch (err) { + console.error('Error fetching dictionary name:', err) + } finally { + setDictionaryLoading(false) + } + } + // Hide add button if dictionary name is not set - const canAddWords = dictionaryName && dictionaryName.trim() !== '' + const canAddWords = currentDictionaryName && currentDictionaryName.trim() !== '' const parseMarkdownTable = (text) => { const lines = text.split('\n') @@ -110,6 +142,20 @@ function AddWords({ onNavigate, dictionaryId, dictionaryName }) { onNavigate?.('words', dictionaryId !== undefined && dictionaryId !== null ? { dictionaryId } : {}) } + // Show loading state while fetching dictionary name + if (dictionaryLoading) { + return ( +
+
+
+
+
Загрузка...
+
+
+
+ ) + } + return (
))} -
)} diff --git a/play-life-web/src/components/TaskList.jsx b/play-life-web/src/components/TaskList.jsx index af82f58..6bc3159 100644 --- a/play-life-web/src/components/TaskList.jsx +++ b/play-life-web/src/components/TaskList.jsx @@ -18,7 +18,6 @@ function TaskList({ onNavigate, data, loading, backgroundLoading, error, onRetry const [postponeDate, setPostponeDate] = useState('') const [isPostponing, setIsPostponing] = useState(false) const [toast, setToast] = useState(null) - const [showAddModal, setShowAddModal] = useState(false) const dateInputRef = useRef(null) useEffect(() => { @@ -72,19 +71,6 @@ function TaskList({ onNavigate, data, loading, backgroundLoading, error, onRetry setSelectedTaskForDetail(null) } - const handleAddClick = () => { - setShowAddModal(true) - } - - const handleAddTask = () => { - setShowAddModal(false) - onNavigate?.('task-form', { taskId: undefined, isTest: false }) - } - - const handleAddTest = () => { - setShowAddModal(false) - onNavigate?.('task-form', { taskId: undefined, isTest: true }) - } // Функция для вычисления следующей даты по repetition_date @@ -749,9 +735,6 @@ function TaskList({ onNavigate, data, loading, backgroundLoading, error, onRetry onClose={() => setToast(null)} /> )} - {projectNames.length === 0 && !loading && tasks.length === 0 && (
@@ -816,40 +799,6 @@ function TaskList({ onNavigate, data, loading, backgroundLoading, error, onRetry /> )} - {/* Модальное окно выбора типа задачи */} - {showAddModal && ( -
setShowAddModal(false)}> -
e.stopPropagation()}> -
-

Что добавить?

-
-
- - -
-
-
- )} {/* Модальное окно для переноса задачи */} {selectedTaskForPostpone && (() => { diff --git a/play-life-web/src/components/Wishlist.jsx b/play-life-web/src/components/Wishlist.jsx index 913257a..af316fc 100644 --- a/play-life-web/src/components/Wishlist.jsx +++ b/play-life-web/src/components/Wishlist.jsx @@ -639,12 +639,6 @@ function Wishlist({ onNavigate, refreshTrigger = 0, isActive = false, initialBoa <>
{items.map(renderItem)} -
{/* Завершённые */} diff --git a/play-life-web/src/components/WordList.jsx b/play-life-web/src/components/WordList.jsx index d71a242..2436f41 100644 --- a/play-life-web/src/components/WordList.jsx +++ b/play-life-web/src/components/WordList.jsx @@ -217,18 +217,12 @@ function WordList({ onNavigate, dictionaryId, isNewDictionary, refreshTrigger = <> {(!words || words.length === 0) ? ( <> -

Слов пока нет. Добавьте слова через экран "Добавить слова".

) : ( <> -
{words.map((word) => (