import React, { useState, useEffect } from 'react'; import { X, Calendar, HelpCircle, Sparkles } from 'lucide-react'; import { CreateOutagePayload, OutageWorkType } from '../../types'; import { backendApi } from '../../services/apiClient'; import { Building } from '../../types'; const CATEGORIES = [ { value: '', label: 'Выбрать' }, { value: 'water', label: 'Вода' }, { value: 'electric', label: 'Электрика' }, { value: 'heating', label: 'Отопление' }, { value: 'elevator', label: 'Лифт' }, { value: 'common', label: 'Общедомовое' }, { value: 'other', label: 'Другое' }, ]; const PROBLEMS_BY_CATEGORY: Record = { water: [ { value: 'leak', label: 'Течь сантехнических приборов' }, { value: 'no_water', label: 'Нет воды' }, { value: 'blockage', label: 'Засор' }, { value: 'other', label: 'Другое' }, ], electric: [ { value: 'no_power', label: 'Нет электричества' }, { value: 'repair', label: 'Ремонт сети' }, { value: 'other', label: 'Другое' }, ], heating: [ { value: 'no_heat', label: 'Нет отопления' }, { value: 'repair', label: 'Ремонт системы' }, { value: 'other', label: 'Другое' }, ], elevator: [ { value: 'repair', label: 'Ремонт лифта' }, { value: 'inspection', label: 'Техобслуживание' }, { value: 'other', label: 'Другое' }, ], common: [ { value: 'repair', label: 'Ремонт' }, { value: 'other', label: 'Другое' }, ], other: [{ value: 'other', label: 'Другое' }], }; const WORK_TYPES: { value: OutageWorkType; label: string }[] = [ { value: 'absent', label: 'Отсутствует' }, { value: 'planned', label: 'Плановый' }, { value: 'emergency', label: 'Аварийный' }, ]; const MAX_WHAT_HAPPENED = 1500; const MAX_RESIDENT_MESSAGE = 1000; interface Props { isOpen: boolean; onClose: () => void; onSuccess: () => void; /** Если передан — форма «из дома», дом уже выбран; иначе — диспетчерская, выбор адресов */ buildingId?: string; } export const CreateOutageCard: React.FC = ({ isOpen, onClose, onSuccess, buildingId }) => { const [buildingIds, setBuildingIds] = useState([]); const [selectAll, setSelectAll] = useState(false); const [startAt, setStartAt] = useState(''); const [endAt, setEndAt] = useState(''); const [category, setCategory] = useState(''); const [problemDetail, setProblemDetail] = useState(''); const [workType, setWorkType] = useState('absent'); const [whatHappened, setWhatHappened] = useState(''); const [residentMessage, setResidentMessage] = useState(''); const [generateNews, setGenerateNews] = useState(false); const [buildings, setBuildings] = useState([]); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const fromHouse = !!buildingId; useEffect(() => { if (isOpen) { backendApi.getBuildings().then(setBuildings).catch(() => setBuildings([])); const now = new Date(); setStartAt(now.toISOString().slice(0, 16)); setEndAt(''); if (fromHouse) { setBuildingIds(buildingId ? [buildingId] : []); } else { setBuildingIds([]); setSelectAll(false); } setCategory(''); setProblemDetail(''); setWorkType('absent'); setWhatHappened(''); setResidentMessage(''); setGenerateNews(false); setError(null); } }, [isOpen, buildingId, fromHouse]); useEffect(() => { if (selectAll && !fromHouse) { setBuildingIds(buildings.map(b => b.id)); } else if (!selectAll && !fromHouse) { setBuildingIds([]); } }, [selectAll, fromHouse, buildings]); if (!isOpen) return null; const problemOptions = category ? (PROBLEMS_BY_CATEGORY[category] || [{ value: 'other', label: 'Другое' }]) : []; const selectedBuildingAddresses = fromHouse ? buildings.filter(b => b.id === buildingId).map(b => (b.passport as any)?.address || b.id) : buildings.filter(b => buildingIds.includes(b.id)).map(b => (b.passport as any)?.address || b.id); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setError(null); const ids = fromHouse ? (buildingId ? [buildingId] : []) : buildingIds; if (ids.length === 0) { setError('Выберите хотя бы один адрес'); return; } if (!startAt.trim()) { setError('Укажите начало работ'); return; } if (!category) { setError('Выберите категорию'); return; } if (!whatHappened.trim()) { setError('Заполните поле «Что случилось»'); return; } if (whatHappened.length > MAX_WHAT_HAPPENED) { setError(`«Что случилось» — не более ${MAX_WHAT_HAPPENED} символов`); return; } setLoading(true); try { const categoryLabel = CATEGORIES.find(c => c.value === category)?.label || category; const payload: CreateOutagePayload = { buildingId: ids.length === 1 ? ids[0] : undefined, buildingIds: ids.length > 1 ? ids : undefined, startAt: new Date(startAt).toISOString(), endAt: endAt ? new Date(endAt).toISOString() : undefined, type: categoryLabel, description: whatHappened.trim(), authorName: 'Администратор', category: categoryLabel, problemDetail: problemOptions.find(p => p.value === problemDetail)?.label || problemDetail || undefined, workType, residentMessage: residentMessage.trim() || undefined, generateNews, }; await backendApi.createOutage(payload); onSuccess(); onClose(); } catch (err: any) { setError(err.message || 'Ошибка при создании записи'); } finally { setLoading(false); } }; const handleClose = () => { if (!loading) onClose(); }; return (
e.stopPropagation()}>

Новая запись

{error && (
{error}
)} {/* Адреса */}
{fromHouse ? (
{selectedBuildingAddresses[0] || buildingId || '—'}
) : ( <> )}
{/* Начало работ */}
setStartAt(e.target.value)} className="flex-1 px-4 py-3 border border-slate-200 rounded-xl text-sm outline-none focus:ring-2 focus:ring-primary-500 focus:border-primary-500" />
{/* Завершение работ */}
setEndAt(e.target.value)} min={startAt || undefined} className="flex-1 px-4 py-3 border border-slate-200 rounded-xl text-sm outline-none focus:ring-2 focus:ring-primary-500 focus:border-primary-500" />
{/* Категория */}
{/* Проблема (подкатегория) */}
{/* Тип работ */}
{WORK_TYPES.map(opt => ( ))}
{/* Что случилось */}