import React, { useState, useEffect, useMemo } from 'react'; import { X, Paperclip, HelpCircle, Calendar } from 'lucide-react'; import { CreateApplicationPayload } from '../../types'; import { backendApi } from '../../services/apiClient'; import { Building, Employee } from '../../types'; type ResidentOption = { key: string; fullName: string; apartment: string; phone?: string }; function residentsFromBuilding(building: Building | null): ResidentOption[] { if (!building?.accounts?.length) return []; const list: ResidentOption[] = []; for (const acc of building.accounts) { const apt = acc.apartmentNumber || ''; (acc.owners || []).forEach((o) => { if (o?.fullName) list.push({ key: `o:${acc.id}:${o.fullName}`, fullName: o.fullName, apartment: apt, phone: o.phone }); }); (acc.registered || []).forEach((r) => { if (r?.fullName) list.push({ key: `r:${acc.id}:${r.id}`, fullName: r.fullName, apartment: apt, phone: r.phone }); }); } const seen = new Set(); return list.filter((r) => { const k = `${r.apartment}::${r.fullName}`.toLowerCase(); if (seen.has(k)) return false; seen.add(k); return true; }); } const SOURCE_CHANNELS = [ { value: '', label: 'Выбрать' }, { value: 'call', label: 'Звонок' }, { value: 'website', label: 'Заявка с сайта' }, { value: 'reception', label: 'Личный приём' }, { value: 'mobile', label: 'Мобильное приложение' }, { value: 'other', label: 'Другое' }, ]; const WORK_TYPES = [ { value: '', label: 'Выбрать' }, { value: 'plumbing', label: 'Сантехника' }, { value: 'electrical', label: 'Электрика' }, { value: 'heating', label: 'Отопление' }, { value: 'elevator', label: 'Лифт' }, { value: 'common', label: 'Общедомовое имущество' }, { value: 'other', label: 'Другое' }, ]; const PROBLEM_DETAIL_OPTIONS = [ { value: '', label: 'Выбрать' }, { value: 'leak', label: 'Протечка' }, { value: 'no_water', label: 'Нет воды' }, { value: 'no_heat', label: 'Нет отопления' }, { value: 'no_power', label: 'Нет электричества' }, { value: 'blockage', label: 'Засор' }, { value: 'other', label: 'Другое' }, ]; const MAX_DESCRIPTION_LENGTH = 700; interface Props { isOpen: boolean; onClose: () => void; onSuccess: () => void; } export const CreateApplicationCard: React.FC = ({ isOpen, onClose, onSuccess }) => { const [buildingId, setBuildingId] = useState(''); const [address, setAddress] = useState(''); const [apartment, setApartment] = useState(''); const [sourceChannel, setSourceChannel] = useState(''); const [isFromResident, setIsFromResident] = useState(true); const [contactPhone, setContactPhone] = useState(''); const [contactName, setContactName] = useState(''); const [selectedResidentKey, setSelectedResidentKey] = useState(''); const [description, setDescription] = useState(''); const [placeIncident, setPlaceIncident] = useState(''); const [workType, setWorkType] = useState(''); const [problemDetail, setProblemDetail] = useState(''); const [isEmergency, setIsEmergency] = useState(false); const [isPaid, setIsPaid] = useState(false); const [isWarranty, setIsWarranty] = useState(false); const [deadlineAt, setDeadlineAt] = useState(''); const [executorName, setExecutorName] = useState(''); const [responsibleName, setResponsibleName] = useState(''); const [observersText, setObserversText] = useState(''); const [showInApp, setShowInApp] = useState(false); const [buildings, setBuildings] = useState([]); const [selectedBuilding, setSelectedBuilding] = useState(null); const [employees, setEmployees] = useState([]); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const residents = useMemo(() => residentsFromBuilding(selectedBuilding), [selectedBuilding]); useEffect(() => { if (isOpen) { backendApi.getBuildings().then(setBuildings).catch(() => setBuildings([])); backendApi.getEmployees().then(setEmployees).catch(() => setEmployees([])); const defaultDeadline = new Date(); defaultDeadline.setDate(defaultDeadline.getDate() + 8); setDeadlineAt(defaultDeadline.toISOString().slice(0, 10)); setBuildingId(''); setSelectedBuilding(null); setAddress(''); setPlaceIncident(''); setSelectedResidentKey(''); setContactName(''); setContactPhone(''); setApartment(''); } }, [isOpen]); useEffect(() => { if (!buildingId) { setSelectedBuilding(null); setAddress(''); setPlaceIncident(''); setSelectedResidentKey(''); setContactName(''); setContactPhone(''); setApartment(''); return; } backendApi.getBuilding(buildingId).then((b) => { setSelectedBuilding(b); setAddress((b.passport as any)?.address || buildingId); setPlaceIncident(buildingId); }).catch(() => { setSelectedBuilding(null); setAddress(''); setPlaceIncident(''); }); setSelectedResidentKey(''); setContactName(''); setContactPhone(''); setApartment(''); }, [buildingId]); if (!isOpen) return null; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setError(null); if (!buildingId || !address.trim()) { setError('Выберите адрес (дом)'); return; } if (isFromResident && !selectedResidentKey) { setError('Выберите заявителя (жителя/собственника)'); return; } if (!description.trim()) { setError('Опишите проблему'); return; } if (description.length > MAX_DESCRIPTION_LENGTH) { setError(`Проблема не более ${MAX_DESCRIPTION_LENGTH} символов`); return; } setLoading(true); try { const placeBuilding = buildings.find(b => b.id === placeIncident) || selectedBuilding; const payload: CreateApplicationPayload = { address: address.trim(), description: description.trim(), apartment: apartment.trim() || undefined, sourceChannel: sourceChannel || undefined, isFromResident, contactPhone: contactPhone.trim() || undefined, contactName: contactName.trim() || undefined, placeIncident: placeBuilding?.passport?.address || placeIncident || undefined, workType: workType || undefined, problemDetail: problemDetail || undefined, isEmergency, isPaid, isWarranty, deadlineAt: deadlineAt ? new Date(deadlineAt).toISOString() : undefined, executorName: executorName.trim() || undefined, responsibleName: responsibleName.trim() || undefined, observersText: observersText.trim() || undefined, showInApp, buildingId: buildingId || undefined, }; await backendApi.createApplication(payload); window.dispatchEvent(new CustomEvent('mkd-applications-changed')); onSuccess(); onClose(); } catch (err: any) { setError(err.message || 'Ошибка при создании заявки'); } finally { setLoading(false); } }; const handleClose = () => { if (!loading) onClose(); }; return (
e.stopPropagation()}>

Новая заявка

{error && (
{error}
)} {/* Откуда поступила заявка * */}
{/* Адрес (дом) * */}
{/* Заявка от жителя / не от жителя */}
{isFromResident ? (
{selectedResidentKey && (contactPhone || contactName) && (

{contactName}{contactPhone ? ` · ${contactPhone}` : ''}{apartment ? ` · кв. ${apartment}` : ''}

)}
) : (
+7 setContactPhone(e.target.value)} placeholder="900 123-45-67" className="flex-1 px-4 py-2 border border-slate-200 rounded-r-xl text-sm outline-none focus:ring-2 focus:ring-primary-500 focus:border-primary-500" />
setContactName(e.target.value)} placeholder="Фамилия Имя Отчество" className="w-full px-4 py-2 border border-slate-200 rounded-xl text-sm outline-none focus:ring-2 focus:ring-primary-500 focus:border-primary-500" />
)}
{/* Проблема * */}