Версия 3.25.0: исправлено добавление слов в словарь
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 52s

This commit is contained in:
poignatov
2026-01-20 22:16:08 +03:00
parent e41f721106
commit 24be9fad27
8 changed files with 203 additions and 82 deletions

View File

@@ -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 (
<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 (
<div className="add-words">
<button className="close-x-button" onClick={handleClose}>

View File

@@ -50,7 +50,7 @@ function DictionaryList({ onNavigate, refreshTrigger = 0 }) {
}
const handleDictionarySelect = (dict) => {
onNavigate?.('words', { dictionaryId: dict.id })
onNavigate?.('words', { dictionaryId: dict.id, dictionaryName: dict.name })
}
const handleDictionaryMenuClick = (dict, e) => {
@@ -130,13 +130,6 @@ function DictionaryList({ onNavigate, refreshTrigger = 0 }) {
<div className="dictionary-name">{dict.name}</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>
)}

View File

@@ -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)}
/>
)}
<button onClick={handleAddClick} className="add-task-button">
Добавить
</button>
{projectNames.length === 0 && !loading && tasks.length === 0 && (
<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 && (() => {

View File

@@ -639,12 +639,6 @@ function Wishlist({ onNavigate, refreshTrigger = 0, isActive = false, initialBoa
<>
<div className="wishlist-grid">
{items.map(renderItem)}
<button
onClick={handleAddClick}
className="add-wishlist-button"
>
<div className="add-wishlist-icon">+</div>
</button>
</div>
{/* Завершённые */}

View File

@@ -217,18 +217,12 @@ function WordList({ onNavigate, dictionaryId, isNewDictionary, refreshTrigger =
<>
{(!words || words.length === 0) ? (
<>
<button onClick={() => onNavigate?.('add-words', { dictionaryId: currentDictionaryId, dictionaryName })} className="add-button">
Добавить
</button>
<div className="empty-state">
<p>Слов пока нет. Добавьте слова через экран "Добавить слова".</p>
</div>
</>
) : (
<>
<button onClick={() => onNavigate?.('add-words', { dictionaryId: currentDictionaryId, dictionaryName })} className="add-button">
Добавить
</button>
<div className="words-grid">
{words.map((word) => (
<div key={word.id} className="word-card">