Версия 3.25.0: исправлено добавление слов в словарь
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 52s
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 52s
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "play-life-web",
|
"name": "play-life-web",
|
||||||
"version": "3.24.2",
|
"version": "3.25.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
@@ -90,6 +90,9 @@ function AppContent() {
|
|||||||
// Параметры для навигации между вкладками
|
// Параметры для навигации между вкладками
|
||||||
const [tabParams, setTabParams] = useState({})
|
const [tabParams, setTabParams] = useState({})
|
||||||
|
|
||||||
|
// Модальное окно выбора типа задачи
|
||||||
|
const [showAddModal, setShowAddModal] = useState(false)
|
||||||
|
|
||||||
// Кеширование данных
|
// Кеширование данных
|
||||||
const [currentWeekData, setCurrentWeekData] = useState(null)
|
const [currentWeekData, setCurrentWeekData] = useState(null)
|
||||||
const [fullStatisticsData, setFullStatisticsData] = 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 = {}) => {
|
const handleNavigate = (tab, params = {}) => {
|
||||||
handleTabChange(tab, params)
|
handleTabChange(tab, params)
|
||||||
@@ -765,13 +783,13 @@ function AppContent() {
|
|||||||
}, [activeTab])
|
}, [activeTab])
|
||||||
|
|
||||||
// Определяем, нужно ли скрывать нижнюю панель (для fullscreen экранов)
|
// Определяем, нужно ли скрывать нижнюю панель (для 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 = () => {
|
const getContainerPadding = () => {
|
||||||
if (!isFullscreenTab) {
|
if (!isFullscreenTab) {
|
||||||
// Для tasks и profile на широких экранах увеличиваем отступ
|
// Для tasks, wishlist и profile на широких экранах увеличиваем отступ
|
||||||
if (activeTab === 'tasks' || activeTab === 'profile') {
|
if (activeTab === 'tasks' || activeTab === 'wishlist' || activeTab === 'profile') {
|
||||||
return 'p-4 md:p-8'
|
return 'p-4 md:p-8'
|
||||||
}
|
}
|
||||||
return 'p-4 md:p-6'
|
return 'p-4 md:p-6'
|
||||||
@@ -792,13 +810,17 @@ function AppContent() {
|
|||||||
if (activeTab === 'words') {
|
if (activeTab === 'words') {
|
||||||
return 'px-4 md:px-8 py-0'
|
return 'px-4 md:px-8 py-0'
|
||||||
}
|
}
|
||||||
|
// Для экрана желаний используем такие же отступы как для словарей
|
||||||
|
if (activeTab === 'wishlist') {
|
||||||
|
return 'px-4 md:px-8 py-0'
|
||||||
|
}
|
||||||
// Для остальных fullscreen экранов без отступов
|
// Для остальных fullscreen экранов без отступов
|
||||||
return 'p-0'
|
return 'p-0'
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col h-screen h-dvh overflow-hidden">
|
<div className="flex flex-col h-screen h-dvh overflow-hidden">
|
||||||
<div className={`flex-1 overflow-y-auto ${isFullscreenTab ? 'pb-0' : 'pb-20'}`}>
|
<div className={`flex-1 overflow-y-auto ${isFullscreenTab ? (activeTab === 'words' || activeTab === 'dictionaries' ? 'pb-16' : 'pb-0') : activeTab === 'tasks' || activeTab === 'wishlist' ? 'pb-20' : 'pb-20'}`}>
|
||||||
<div className={`max-w-7xl mx-auto ${getContainerPadding()}`}>
|
<div className={`max-w-7xl mx-auto ${getContainerPadding()}`}>
|
||||||
{loadedTabs.current && (
|
{loadedTabs.current && (
|
||||||
<div className={activeTab === 'current' ? 'block' : 'hidden'}>
|
<div className={activeTab === 'current' ? 'block' : 'hidden'}>
|
||||||
@@ -994,6 +1016,94 @@ function AppContent() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Кнопка добавления задачи (только для таба задач) */}
|
||||||
|
{!isFullscreenTab && activeTab === 'tasks' && (
|
||||||
|
<button
|
||||||
|
onClick={handleAddClick}
|
||||||
|
className="fixed bottom-16 right-4 z-20 bg-gradient-to-r from-indigo-600 to-purple-600 hover:from-indigo-700 hover:to-purple-700 text-white w-[61px] h-[61px] rounded-2xl shadow-lg transition-all duration-200 hover:scale-105 flex items-center justify-center"
|
||||||
|
title="Добавить задачу"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="2"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M12 5v14M5 12h14" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Кнопка добавления желания (только для таба wishlist) */}
|
||||||
|
{!isFullscreenTab && activeTab === 'wishlist' && (
|
||||||
|
<button
|
||||||
|
onClick={() => handleNavigate('wishlist-form', { wishlistId: undefined })}
|
||||||
|
className="fixed bottom-16 right-4 z-20 bg-gradient-to-r from-indigo-600 to-purple-600 hover:from-indigo-700 hover:to-purple-700 text-white w-[61px] h-[61px] rounded-2xl shadow-lg transition-all duration-200 hover:scale-105 flex items-center justify-center"
|
||||||
|
title="Добавить желание"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="2"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M12 5v14M5 12h14" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Кнопка добавления словаря (только для таба dictionaries) */}
|
||||||
|
{activeTab === 'dictionaries' && (
|
||||||
|
<button
|
||||||
|
onClick={() => handleNavigate('words', { dictionaryId: null, isNewDictionary: true })}
|
||||||
|
className="fixed bottom-4 right-4 z-20 bg-gradient-to-r from-indigo-600 to-purple-600 hover:from-indigo-700 hover:to-purple-700 text-white w-[61px] h-[61px] rounded-2xl shadow-lg transition-all duration-200 hover:scale-105 flex items-center justify-center"
|
||||||
|
title="Добавить словарь"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="2"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M12 5v14M5 12h14" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Кнопка добавления слов (только для таба words) */}
|
||||||
|
{activeTab === 'words' && (
|
||||||
|
<button
|
||||||
|
onClick={() => handleNavigate('add-words', { dictionaryId: tabParams.dictionaryId })}
|
||||||
|
className="fixed bottom-4 right-4 z-20 bg-gradient-to-r from-indigo-600 to-purple-600 hover:from-indigo-700 hover:to-purple-700 text-white w-[61px] h-[61px] rounded-2xl shadow-lg transition-all duration-200 hover:scale-105 flex items-center justify-center"
|
||||||
|
title="Добавить слова"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="2"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M12 5v14M5 12h14" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
|
||||||
{!isFullscreenTab && (
|
{!isFullscreenTab && (
|
||||||
<div className="fixed bottom-0 left-0 right-0 flex bg-white/90 backdrop-blur-md border-t border-white/20 flex-shrink-0 overflow-x-auto shadow-lg z-10 justify-center items-center w-full" style={{ paddingBottom: 'env(safe-area-inset-bottom)' }}>
|
<div className="fixed bottom-0 left-0 right-0 flex bg-white/90 backdrop-blur-md border-t border-white/20 flex-shrink-0 overflow-x-auto shadow-lg z-10 justify-center items-center w-full" style={{ paddingBottom: 'env(safe-area-inset-bottom)' }}>
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
@@ -1081,6 +1191,41 @@ function AppContent() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Модальное окно выбора типа задачи */}
|
||||||
|
{showAddModal && (
|
||||||
|
<div className="task-add-modal-overlay" onClick={() => setShowAddModal(false)}>
|
||||||
|
<div className="task-add-modal" onClick={(e) => e.stopPropagation()}>
|
||||||
|
<div className="task-add-modal-header">
|
||||||
|
<h3>Что добавить?</h3>
|
||||||
|
</div>
|
||||||
|
<div className="task-add-modal-buttons">
|
||||||
|
<button
|
||||||
|
className="task-add-modal-button task-add-modal-button-task"
|
||||||
|
onClick={handleAddTask}
|
||||||
|
>
|
||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||||
|
<path d="M9 11l3 3L22 4"></path>
|
||||||
|
<path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"></path>
|
||||||
|
</svg>
|
||||||
|
Задача
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="task-add-modal-button task-add-modal-button-test"
|
||||||
|
onClick={handleAddTest}
|
||||||
|
>
|
||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||||
|
<path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"></path>
|
||||||
|
<path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"></path>
|
||||||
|
<path d="M8 7h6"></path>
|
||||||
|
<path d="M8 11h4"></path>
|
||||||
|
</svg>
|
||||||
|
Тест
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useState } from 'react'
|
import React, { useState, useEffect } from 'react'
|
||||||
import { useAuth } from './auth/AuthContext'
|
import { useAuth } from './auth/AuthContext'
|
||||||
import './AddWords.css'
|
import './AddWords.css'
|
||||||
|
|
||||||
@@ -9,9 +9,41 @@ function AddWords({ onNavigate, dictionaryId, dictionaryName }) {
|
|||||||
const [markdownText, setMarkdownText] = useState('')
|
const [markdownText, setMarkdownText] = useState('')
|
||||||
const [message, setMessage] = useState('')
|
const [message, setMessage] = useState('')
|
||||||
const [loading, setLoading] = useState(false)
|
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
|
// Hide add button if dictionary name is not set
|
||||||
const canAddWords = dictionaryName && dictionaryName.trim() !== ''
|
const canAddWords = currentDictionaryName && currentDictionaryName.trim() !== ''
|
||||||
|
|
||||||
const parseMarkdownTable = (text) => {
|
const parseMarkdownTable = (text) => {
|
||||||
const lines = text.split('\n')
|
const lines = text.split('\n')
|
||||||
@@ -110,6 +142,20 @@ function AddWords({ onNavigate, dictionaryId, dictionaryName }) {
|
|||||||
onNavigate?.('words', dictionaryId !== undefined && dictionaryId !== null ? { dictionaryId } : {})
|
onNavigate?.('words', dictionaryId !== undefined && dictionaryId !== null ? { dictionaryId } : {})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show loading state while fetching dictionary name
|
||||||
|
if (dictionaryLoading) {
|
||||||
|
return (
|
||||||
|
<div className="add-words">
|
||||||
|
<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 (
|
return (
|
||||||
<div className="add-words">
|
<div className="add-words">
|
||||||
<button className="close-x-button" onClick={handleClose}>
|
<button className="close-x-button" onClick={handleClose}>
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ function DictionaryList({ onNavigate, refreshTrigger = 0 }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleDictionarySelect = (dict) => {
|
const handleDictionarySelect = (dict) => {
|
||||||
onNavigate?.('words', { dictionaryId: dict.id })
|
onNavigate?.('words', { dictionaryId: dict.id, dictionaryName: dict.name })
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleDictionaryMenuClick = (dict, e) => {
|
const handleDictionaryMenuClick = (dict, e) => {
|
||||||
@@ -130,13 +130,6 @@ function DictionaryList({ onNavigate, refreshTrigger = 0 }) {
|
|||||||
<div className="dictionary-name">{dict.name}</div>
|
<div className="dictionary-name">{dict.name}</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
<button
|
|
||||||
onClick={() => onNavigate?.('words', { dictionaryId: null, isNewDictionary: true })}
|
|
||||||
className="add-dictionary-button"
|
|
||||||
>
|
|
||||||
<div className="add-dictionary-icon">+</div>
|
|
||||||
<div className="add-dictionary-text">Добавить</div>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ function TaskList({ onNavigate, data, loading, backgroundLoading, error, onRetry
|
|||||||
const [postponeDate, setPostponeDate] = useState('')
|
const [postponeDate, setPostponeDate] = useState('')
|
||||||
const [isPostponing, setIsPostponing] = useState(false)
|
const [isPostponing, setIsPostponing] = useState(false)
|
||||||
const [toast, setToast] = useState(null)
|
const [toast, setToast] = useState(null)
|
||||||
const [showAddModal, setShowAddModal] = useState(false)
|
|
||||||
const dateInputRef = useRef(null)
|
const dateInputRef = useRef(null)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -72,19 +71,6 @@ function TaskList({ onNavigate, data, loading, backgroundLoading, error, onRetry
|
|||||||
setSelectedTaskForDetail(null)
|
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
|
// Функция для вычисления следующей даты по repetition_date
|
||||||
@@ -749,9 +735,6 @@ function TaskList({ onNavigate, data, loading, backgroundLoading, error, onRetry
|
|||||||
onClose={() => setToast(null)}
|
onClose={() => setToast(null)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<button onClick={handleAddClick} className="add-task-button">
|
|
||||||
Добавить
|
|
||||||
</button>
|
|
||||||
|
|
||||||
{projectNames.length === 0 && !loading && tasks.length === 0 && (
|
{projectNames.length === 0 && !loading && tasks.length === 0 && (
|
||||||
<div className="empty-state">
|
<div className="empty-state">
|
||||||
@@ -816,40 +799,6 @@ function TaskList({ onNavigate, data, loading, backgroundLoading, error, onRetry
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Модальное окно выбора типа задачи */}
|
|
||||||
{showAddModal && (
|
|
||||||
<div className="task-add-modal-overlay" onClick={() => setShowAddModal(false)}>
|
|
||||||
<div className="task-add-modal" onClick={(e) => e.stopPropagation()}>
|
|
||||||
<div className="task-add-modal-header">
|
|
||||||
<h3>Что добавить?</h3>
|
|
||||||
</div>
|
|
||||||
<div className="task-add-modal-buttons">
|
|
||||||
<button
|
|
||||||
className="task-add-modal-button task-add-modal-button-task"
|
|
||||||
onClick={handleAddTask}
|
|
||||||
>
|
|
||||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
||||||
<path d="M9 11l3 3L22 4"></path>
|
|
||||||
<path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"></path>
|
|
||||||
</svg>
|
|
||||||
Задача
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
className="task-add-modal-button task-add-modal-button-test"
|
|
||||||
onClick={handleAddTest}
|
|
||||||
>
|
|
||||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
||||||
<path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"></path>
|
|
||||||
<path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"></path>
|
|
||||||
<path d="M8 7h6"></path>
|
|
||||||
<path d="M8 11h4"></path>
|
|
||||||
</svg>
|
|
||||||
Тест
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Модальное окно для переноса задачи */}
|
{/* Модальное окно для переноса задачи */}
|
||||||
{selectedTaskForPostpone && (() => {
|
{selectedTaskForPostpone && (() => {
|
||||||
|
|||||||
@@ -639,12 +639,6 @@ function Wishlist({ onNavigate, refreshTrigger = 0, isActive = false, initialBoa
|
|||||||
<>
|
<>
|
||||||
<div className="wishlist-grid">
|
<div className="wishlist-grid">
|
||||||
{items.map(renderItem)}
|
{items.map(renderItem)}
|
||||||
<button
|
|
||||||
onClick={handleAddClick}
|
|
||||||
className="add-wishlist-button"
|
|
||||||
>
|
|
||||||
<div className="add-wishlist-icon">+</div>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Завершённые */}
|
{/* Завершённые */}
|
||||||
|
|||||||
@@ -217,18 +217,12 @@ function WordList({ onNavigate, dictionaryId, isNewDictionary, refreshTrigger =
|
|||||||
<>
|
<>
|
||||||
{(!words || words.length === 0) ? (
|
{(!words || words.length === 0) ? (
|
||||||
<>
|
<>
|
||||||
<button onClick={() => onNavigate?.('add-words', { dictionaryId: currentDictionaryId, dictionaryName })} className="add-button">
|
|
||||||
Добавить
|
|
||||||
</button>
|
|
||||||
<div className="empty-state">
|
<div className="empty-state">
|
||||||
<p>Слов пока нет. Добавьте слова через экран "Добавить слова".</p>
|
<p>Слов пока нет. Добавьте слова через экран "Добавить слова".</p>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<button onClick={() => onNavigate?.('add-words', { dictionaryId: currentDictionaryId, dictionaryName })} className="add-button">
|
|
||||||
Добавить
|
|
||||||
</button>
|
|
||||||
<div className="words-grid">
|
<div className="words-grid">
|
||||||
{words.map((word) => (
|
{words.map((word) => (
|
||||||
<div key={word.id} className="word-card">
|
<div key={word.id} className="word-card">
|
||||||
|
|||||||
Reference in New Issue
Block a user