import { useEffect, useRef, useState } from 'react' import { createPortal } from 'react-dom' import { Wrench, Ban, CheckCircle, Sparkles, ClipboardList, Pencil, ChevronRight, X as XIcon, CalendarDays, AlertTriangle, Zap, Camera, Loader2 } from 'lucide-react' import { format } from 'date-fns' import type { Room, RoomStatus, HousekeepingStatus } from '../../types' import { cn } from '../../lib/utils' import { api } from '../../lib/api' const today = () => format(new Date(), 'yyyy-MM-dd') export type HkPriority = 'urgent' | 'medium' | 'low' interface RoomContextMenuProps { room: Room x: number y: number onClose: () => void onStatusChange: (roomId: string, status: RoomStatus, maintenanceFrom?: string | null, maintenanceTo?: string | null) => void onHkStatusChange: (roomId: string, status: HousekeepingStatus, priority?: HkPriority) => void onMaintenanceTask?: (roomId: string, description: string, priority: HkPriority, photos: string[]) => void onEdit?: (room: Room) => void } const HK_ITEMS: { status: HousekeepingStatus; label: string; icon: React.ReactNode; color: string }[] = [ { status: 'clean', label: 'Чисто', icon: , color: 'text-emerald-600 dark:text-emerald-400' }, { status: 'inspect', label: 'Проверить', icon: , color: 'text-amber-600 dark:text-amber-400' }, { status: 'dirty', label: 'Убрать', icon: , color: 'text-red-500 dark:text-red-400' }, ] const PRIORITY_ITEMS: { value: HkPriority; label: string; color: string }[] = [ { value: 'urgent', label: 'Срочно', color: 'text-red-600 dark:text-red-400' }, { value: 'medium', label: 'Средний', color: 'text-yellow-600 dark:text-yellow-400' }, { value: 'low', label: 'Низкий', color: 'text-slate-500 dark:text-slate-400' }, ] type SubForm = 'maintenance' | 'blocked' | 'hk_priority' | 'tech_task' | null export function RoomContextMenu({ room, x, y, onClose, onStatusChange, onHkStatusChange, onMaintenanceTask, onEdit }: RoomContextMenuProps) { const ref = useRef(null) const [subForm, setSubForm] = useState(null) const [dateFrom, setDateFrom] = useState(room.maintenanceFrom ? room.maintenanceFrom.slice(0, 10) : today()) const [dateTo, setDateTo] = useState(room.maintenanceTo ? room.maintenanceTo.slice(0, 10) : '') const [indefinite, setIndefinite] = useState(false) const [pendingHkStatus, setPendingHkStatus] = useState(null) const [techDesc, setTechDesc] = useState('') const [techPriority, setTechPriority] = useState('medium') const [techPhotos, setTechPhotos] = useState([]) const [photoUploading, setPhotoUploading] = useState(false) const photoInputRef = useRef(null) useEffect(() => { const handler = (e: MouseEvent) => { if (ref.current && !ref.current.contains(e.target as Node)) onClose() } const keyHandler = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose() } document.addEventListener('mousedown', handler) document.addEventListener('keydown', keyHandler) if (ref.current) { const rect = ref.current.getBoundingClientRect() const overflowX = rect.right - window.innerWidth + 8 const overflowY = rect.bottom - window.innerHeight + 8 if (overflowX > 0) ref.current.style.left = `${rect.left - overflowX}px` if (overflowY > 0) ref.current.style.top = `${rect.top - overflowY}px` } return () => { document.removeEventListener('mousedown', handler) document.removeEventListener('keydown', keyHandler) } }, [onClose, subForm]) const handleApplyStatus = (status: RoomStatus) => { if (status === 'maintenance' || status === 'blocked') { if (subForm === status) { onStatusChange(room.id, status, dateFrom || null, indefinite ? null : (dateTo || null)) onClose() } else { setSubForm(status) } } else { onStatusChange(room.id, status, null, null) onClose() } } const handleHkClick = (status: HousekeepingStatus) => { if (status === 'dirty') { // Show priority sub-form setPendingHkStatus(status) setSubForm('hk_priority') } else { onHkStatusChange(room.id, status) onClose() } } const handleHkWithPriority = (priority: HkPriority) => { if (pendingHkStatus) { onHkStatusChange(room.id, pendingHkStatus, priority) } onClose() } const handleTechPhotoUpload = async (file: File) => { setPhotoUploading(true) try { const url = await api.upload.photo(file, 'tasks') setTechPhotos(prev => [...prev, url]) } catch { /* ignore */ } finally { setPhotoUploading(false) } } const handleTechSubmit = () => { if (onMaintenanceTask && techDesc.trim()) { onMaintenanceTask(room.id, techDesc.trim(), techPriority, techPhotos) } onClose() } const menuX = Math.min(x, window.innerWidth - 260) const menuY = y return createPortal(
e.preventDefault()} > {/* Header */}

Номер {room.number}

{/* Room status */}

Статус номера

{subForm === 'maintenance' && ( { onStatusChange(room.id, 'maintenance', dateFrom || null, indefinite ? null : (dateTo || null)) onClose() }} onCancel={() => setSubForm(null)} /> )} {subForm === 'blocked' && ( { onStatusChange(room.id, 'blocked', dateFrom || null, indefinite ? null : (dateTo || null)) onClose() }} onCancel={() => setSubForm(null)} /> )}
{/* Housekeeping */}

Уборка

{subForm === 'hk_priority' ? (

Срочность

{PRIORITY_ITEMS.map(p => ( ))}
) : ( HK_ITEMS.map(item => ( )) )}
{onMaintenanceTask && ( <>

Тех. задача

{subForm === 'tech_task' ? (

Описание проблемы