import React, { useState, useEffect, useCallback } from 'react' import { useAuth } from './auth/AuthContext' import './TaskDetail.css' const API_URL = '/api/tasks' function TaskDetail({ taskId, onClose, onRefresh, onTaskCompleted }) { const { authFetch } = useAuth() const [taskDetail, setTaskDetail] = useState(null) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) const [selectedSubtasks, setSelectedSubtasks] = useState(new Set()) const [progressionValue, setProgressionValue] = useState('') const [isCompleting, setIsCompleting] = useState(false) const fetchTaskDetail = useCallback(async () => { try { setLoading(true) setError(null) const response = await authFetch(`${API_URL}/${taskId}`) if (!response.ok) { throw new Error('Ошибка загрузки задачи') } const data = await response.json() setTaskDetail(data) } catch (err) { setError(err.message) console.error('Error fetching task detail:', err) } finally { setLoading(false) } }, [taskId, authFetch]) useEffect(() => { if (taskId) { fetchTaskDetail() } else { // Сбрасываем состояние при закрытии модального окна setTaskDetail(null) setLoading(true) setError(null) setSelectedSubtasks(new Set()) setProgressionValue('') } }, [taskId, fetchTaskDetail]) const handleSubtaskToggle = (subtaskId) => { setSelectedSubtasks(prev => { const newSet = new Set(prev) if (newSet.has(subtaskId)) { newSet.delete(subtaskId) } else { newSet.add(subtaskId) } return newSet }) } const handleComplete = async () => { if (!taskDetail) return // Валидация: если progression_base != null, то value обязателен if (taskDetail.task.progression_base != null && !progressionValue.trim()) { alert('Поле "Значение" обязательно для задач с прогрессией') return } setIsCompleting(true) try { const payload = { children_task_ids: Array.from(selectedSubtasks) } if (taskDetail.task.progression_base != null && progressionValue.trim()) { payload.value = parseFloat(progressionValue) if (isNaN(payload.value)) { throw new Error('Неверное значение') } } const response = await authFetch(`${API_URL}/${taskId}/complete`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(payload), }) if (!response.ok) { const errorData = await response.json().catch(() => ({})) throw new Error(errorData.message || 'Ошибка при выполнении задачи') } // Показываем уведомление о выполнении if (onTaskCompleted) { onTaskCompleted() } // Обновляем список и закрываем модальное окно if (onRefresh) { onRefresh() } if (onClose) { onClose() } } catch (err) { console.error('Error completing task:', err) alert(err.message || 'Ошибка при выполнении задачи') } finally { setIsCompleting(false) } } if (!taskId) return null const { task, rewards, subtasks } = taskDetail || {} const hasProgression = task?.progression_base != null const canComplete = !hasProgression || (hasProgression && progressionValue.trim()) return (
e.stopPropagation()}>

{loading ? 'Загрузка...' : error ? 'Ошибка' : taskDetail ? task.name : 'Задача'}

{loading && (
Загрузка...
)} {error && (
{error}
)} {!loading && !error && taskDetail && ( <> {subtasks && subtasks.length > 0 && (
{subtasks.map((subtask) => { const subtaskName = subtask.task.name || 'Подзадача' return (
) })}
)}
{hasProgression ? (
setProgressionValue(e.target.value)} placeholder={`Значение (~${task.progression_base})`} className="progression-input" /> {progressionValue.trim() && ( )}
) : ( )}
)}
) } export default TaskDetail