import { useState } from 'react' import { Plus, Edit2, Trash2, Wrench, AlertTriangle, CheckCircle2, Clock, BedDouble, Dumbbell, Waves, UtensilsCrossed, Wifi, Car, Sparkles, Package, X, CalendarClock, } from 'lucide-react' import { Modal } from '../components/ui/Modal' import { cn } from '../lib/utils' import { format } from 'date-fns' import { ru } from 'date-fns/locale' import { RENTAL_OBJECTS } from '../data/rentalData' // ─── Types ──────────────────────────────────────────────────────────────────── type MaintenanceTarget = 'room' | 'service' | 'rental' type MaintenanceStatus = 'scheduled' | 'in_progress' | 'done' | 'cancelled' interface MaintenanceRecord { id: string type: MaintenanceTarget targetId: string // roomId or serviceId targetLabel: string // "Номер 205" or "Бассейн" startDate: string endDate: string startTime?: string // HH:MM endTime?: string reason: string notes: string status: MaintenanceStatus assignedTo?: string } interface ServiceDef { id: string label: string icon: React.ElementType } // ─── Mock Data ──────────────────────────────────────────────────────────────── const MOCK_ROOMS = [ { id: 'r101', label: 'Номер 101 — Стандарт' }, { id: 'r102', label: 'Номер 102 — Стандарт' }, { id: 'r205', label: 'Номер 205 — Делюкс' }, { id: 'r301', label: 'Номер 301 — Сьют' }, { id: 'r401', label: 'Номер 401 — Люкс' }, ] const SERVICES: ServiceDef[] = [ { id: 'pool', label: 'Бассейн', icon: Waves }, { id: 'gym', label: 'Тренажёрный зал', icon: Dumbbell }, { id: 'restaurant', label: 'Ресторан', icon: UtensilsCrossed }, { id: 'spa', label: 'СПА', icon: Sparkles }, { id: 'wifi', label: 'Wi-Fi', icon: Wifi }, { id: 'parking', label: 'Парковка', icon: Car }, { id: 'laundry', label: 'Прачечная', icon: Package }, ] const MOCK_RECORDS: MaintenanceRecord[] = [ { id: 'm-1', type: 'room', targetId: 'r205', targetLabel: 'Номер 205 — Делюкс', startDate: '2026-03-16', endDate: '2026-03-18', reason: 'Замена сантехники', notes: 'Полная замена смесителей, ремонт душевой кабины. Подрядчик: ООО ТехСервис', status: 'scheduled', assignedTo: 'Иванов А.А.', }, { id: 'm-2', type: 'service', targetId: 'pool', targetLabel: 'Бассейн', startDate: '2026-03-20', endDate: '2026-03-22', startTime: '08:00', endTime: '20:00', reason: 'Плановая чистка и обработка воды', notes: 'Проводится раз в квартал. Замена фильтров.', status: 'scheduled', assignedTo: 'Технический отдел', }, { id: 'm-3', type: 'room', targetId: 'r101', targetLabel: 'Номер 101 — Стандарт', startDate: '2026-03-10', endDate: '2026-03-14', reason: 'Косметический ремонт: покраска стен', notes: 'Перекраска стен, замена штор', status: 'done', assignedTo: 'Строительная бригада', }, { id: 'm-4', type: 'service', targetId: 'restaurant', targetLabel: 'Ресторан', startDate: '2026-03-15', endDate: '2026-03-15', startTime: '14:00', endTime: '18:00', reason: 'Санитарная обработка', notes: 'Плановая дезинфекция кухни', status: 'in_progress', }, { id: 'm-5', type: 'room', targetId: 'r401', targetLabel: 'Номер 401 — Люкс', startDate: '2026-03-25', endDate: '2026-04-05', reason: 'Капитальный ремонт', notes: 'Полный ремонт: полы, потолки, мебель', status: 'scheduled', }, { id: 'm-6', type: 'rental', targetId: 'sauna', targetLabel: '🛁 Баня', startDate: '2026-03-16', endDate: '2026-03-16', startTime: '14:00', endTime: '16:00', reason: 'Подготовка между гостями — проветривание и уборка', notes: 'Плановый тех. перерыв 2 часа после каждого заезда. Температурное охлаждение + мытьё полков.', status: 'scheduled', assignedTo: 'Горничная', }, { id: 'm-7', type: 'rental', targetId: 'court', targetLabel: '🎾 Теннисный корт', startDate: '2026-03-18', endDate: '2026-03-19', reason: 'Замена покрытия', notes: 'Полная замена резинового покрытия. Корт закрыт на 2 дня.', status: 'scheduled', assignedTo: 'Хозяйственная служба', }, ] // ─── Status helpers ─────────────────────────────────────────────────────────── const STATUS_META: Record = { scheduled: { label: 'Запланировано', cls: 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400', icon: Clock }, in_progress: { label: 'Выполняется', cls: 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400', icon: Wrench }, done: { label: 'Завершено', cls: 'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400', icon: CheckCircle2 }, cancelled: { label: 'Отменено', cls: 'bg-slate-100 text-slate-500 dark:bg-slate-700 dark:text-slate-400', icon: X }, } function formatDateRange(from: string, to: string, startTime?: string, endTime?: string) { const f = new Date(from), t = new Date(to) const sameDay = from === to const fmt = (d: Date) => format(d, 'd MMM', { locale: ru }) if (sameDay) { return `${fmt(f)}${startTime ? ` ${startTime}–${endTime ?? '...'}` : ''}` } return `${fmt(f)} — ${fmt(t)}` } function daysCount(from: string, to: string) { const n = Math.round((new Date(to).getTime() - new Date(from).getTime()) / 86400000) + 1 return `${n} ${n === 1 ? 'день' : n < 5 ? 'дня' : 'дней'}` } // ─── Modal ──────────────────────────────────────────────────────────────────── const EMPTY: Omit = { type: 'room', targetId: MOCK_ROOMS[0].id, targetLabel: MOCK_ROOMS[0].label, startDate: format(new Date(), 'yyyy-MM-dd'), endDate: format(new Date(), 'yyyy-MM-dd'), reason: '', notes: '', status: 'scheduled', } function MaintenanceModal({ record, onSave, onClose, }: { record?: MaintenanceRecord onSave: (r: Omit) => void onClose: () => void }) { const [form, setForm] = useState>( record ? { ...record } : { ...EMPTY } ) const set = (k: K, v: typeof form[K]) => setForm(prev => ({ ...prev, [k]: v })) const targets = form.type === 'room' ? MOCK_ROOMS : form.type === 'rental' ? RENTAL_OBJECTS.map(o => ({ id: o.id, label: `${o.icon} ${o.name}` })) : SERVICES.map(s => ({ id: s.id, label: s.label })) const handleTargetChange = (id: string) => { const t = targets.find(t => t.id === id) if (t) { set('targetId', id); set('targetLabel', t.label) } } return ( } >
{/* Type selector */}
{([ { id: 'room' as const, label: 'Номер', icon: BedDouble }, { id: 'service' as const, label: 'Услуга', icon: Wrench }, { id: 'rental' as const, label: 'Аренда', icon: CalendarClock }, ]).map(t => ( ))}
{/* Target */}
{/* Dates */}
set('startDate', e.target.value)} />
set('endDate', e.target.value)} />
{/* Time (for services and rental) */} {(form.type === 'service' || form.type === 'rental') && (
set('startTime', e.target.value)} />
set('endTime', e.target.value)} />
)} {/* Reason */}
set('reason', e.target.value)} />
{/* Notes */}