import React, { useState, useEffect } from 'react'; import { BuildingTask, User, Employee, Building, TaskComment } from '../types'; import { X, User as UserIcon, Calendar, Flag, MessageSquare } from 'lucide-react'; import { backendApi } from '../services/apiClient'; import { storageService } from '../services/storageService'; import { MOCK_EMPLOYEES } from '../constants'; interface DashboardTaskModalProps { isOpen: boolean; onClose: () => void; onSave: (task: BuildingTask) => void; currentUser: User; task?: BuildingTask | null; } /** Модалка задачи на сводке — без фото отчёта, ответственные из списка сотрудников */ export const DashboardTaskModal: React.FC = ({ isOpen, onClose, onSave, currentUser, task, }) => { const [title, setTitle] = useState(''); const [description, setDescription] = useState(''); const [deadline, setDeadline] = useState(''); const [priority, setPriority] = useState('medium'); const [status, setStatus] = useState('new'); const [assignedTo, setAssignedTo] = useState(''); const [createdBy, setCreatedBy] = useState(''); const [buildingId, setBuildingId] = useState(''); const [employees, setEmployees] = useState([]); const [employeesLoading, setEmployeesLoading] = useState(false); const [buildings, setBuildings] = useState([]); const [comments, setComments] = useState([]); const [commentText, setCommentText] = useState(''); const [draftTaskId, setDraftTaskId] = useState(null); useEffect(() => { if (!isOpen) return; const load = async () => { setEmployeesLoading(true); try { const [empList, bldList] = await Promise.all([ backendApi.getEmployees().then((l) => (Array.isArray(l) ? l : [])).catch(() => MOCK_EMPLOYEES), backendApi.getBuildings().catch(() => storageService.getAllBuildings()), ]); setEmployees(empList); setBuildings(Array.isArray(bldList) ? bldList : storageService.getAllBuildings()); } catch { setEmployees(MOCK_EMPLOYEES); setBuildings(storageService.getAllBuildings()); } finally { setEmployeesLoading(false); } }; load(); }, [isOpen]); useEffect(() => { if (!isOpen) return; if (task) { setTitle(task.title || ''); setDescription(task.description || ''); setDeadline(task.deadline ? new Date(task.deadline).toISOString().slice(0, 10) : ''); setPriority(task.priority || 'medium'); setStatus(task.status || 'new'); setAssignedTo(task.assignedTo || ''); setCreatedBy(task.createdBy ?? currentUser.id); setBuildingId(task.buildingId || ''); setComments(task.comments ?? []); setDraftTaskId(null); } else { setTitle(''); setDescription(''); const d = new Date(); d.setDate(d.getDate() + 7); setDeadline(d.toISOString().slice(0, 10)); setPriority('medium'); setStatus('new'); setAssignedTo(''); setCreatedBy(currentUser.id); setBuildingId(''); setComments([]); setDraftTaskId(`dt-${Date.now()}`); } setCommentText(''); }, [isOpen, task, currentUser.id]); const assigneeList: { id: string; name: string; position: string }[] = [ { id: currentUser.id, name: currentUser.name, position: '' }, ...employees.filter((e) => e.id !== currentUser.id).map((e) => ({ id: e.id, name: e.name, position: e.position })), ]; if (task?.createdBy && !assigneeList.some((p) => p.id === task.createdBy)) { assigneeList.push({ id: task.createdBy, name: task.createdByName ?? task.createdBy, position: '' }); } const executorList = employees.filter((e) => e.status === 'active'); if (task?.assignedTo && !executorList.some((e) => e.id === task.assignedTo)) { executorList.push({ id: task.assignedTo, name: task.assignedToName ?? task.assignedTo, position: '' } as Employee); } const selectedBuilding = buildings.find((b) => b.id === buildingId); const buildingAddress = selectedBuilding?.passport?.address ?? ''; const buildTaskData = (commentsOverride?: TaskComment[]) => { const now = new Date().toISOString(); const exec = executorList.find((e) => e.id === assignedTo); const author = assigneeList.find((p) => p.id === createdBy); const taskId = task?.id ?? draftTaskId ?? `dt-${Date.now()}`; return { id: taskId, title: title.trim() || 'Задача', description: description.trim() || undefined, deadline: deadline ? new Date(deadline).toISOString() : now, status, priority, assignedTo: assignedTo || undefined, assignedToName: exec?.name ?? (assignedTo && task?.assignedTo === assignedTo ? task?.assignedToName : undefined), createdBy: createdBy || undefined, createdByName: author?.name ?? (createdBy && task?.createdBy === createdBy ? task?.createdByName : undefined), createdAt: task?.createdAt || now, updatedAt: now, buildingId: buildingId || '', buildingAddress: buildingId ? buildingAddress : undefined, requirePhotoReport: false, coAssignees: [], coAssigneesNames: [], observers: [], observersNames: [], comments: commentsOverride ?? comments, } as BuildingTask; }; const handleAddComment = () => { if (!commentText.trim()) return; const author = assigneeList.find((p) => p.id === createdBy)?.name ?? currentUser.name; const newComment: TaskComment = { id: `comment-${Date.now()}`, authorId: createdBy || undefined, authorName: author, text: commentText.trim(), createdAt: new Date().toISOString(), }; const nextComments = [...comments, newComment]; setComments(nextComments); setCommentText(''); onSave(buildTaskData(nextComments)); }; const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); if (!title.trim()) return; onSave(buildTaskData()); onClose(); }; if (!isOpen) return null; return (
e.stopPropagation()}>

{task ? 'Редактировать задачу' : 'Новая задача'}

setTitle(e.target.value)} className="w-full border border-slate-200 rounded-xl px-4 py-2 focus:ring-2 focus:ring-primary-500 outline-none" required />