import { useState, useMemo } from 'react' import { Modal } from '../ui/Modal' import { cn } from '../../lib/utils' import type { BedType, RoomStatus } from '../../types' import { useAmenities } from '../../contexts/AmenitiesContext' const BED_TYPES: { value: BedType; label: string }[] = [ { value: 'single', label: 'Одна кровать' }, { value: 'double', label: 'Двуспальная' }, { value: 'queen', label: 'Queen' }, { value: 'king', label: 'King' }, { value: 'twin', label: 'Две кровати' }, ] export interface BulkRoomData { number: string floor: number type: string categoryId?: string bedType: BedType maxGuests: number baseRate: number status: RoomStatus amenities: string[] housekeepingStatus: 'clean' sortOrder: number allowHourly: false } interface BulkRoomModalProps { open: boolean existingNumbers: string[] categories: { id: string; name: string }[] onClose: () => void onSave: (rooms: BulkRoomData[]) => Promise } function deriveFloor(num: number): number { if (num < 10) return 1 if (num < 100) return Math.floor(num / 10) return Math.floor(num / 100) } export function BulkRoomModal({ open, existingNumbers, categories, onClose, onSave }: BulkRoomModalProps) { const { amenities: allAmenities } = useAmenities() const [from, setFrom] = useState(101) const [to, setTo] = useState(110) const [autoFloor, setAutoFloor] = useState(true) const [floor, setFloor] = useState(1) const [categoryId, setCategoryId] = useState(categories[0]?.id ?? '') const [bedType, setBedType] = useState('double') const [maxGuests, setMaxGuests] = useState(2) const [baseRate, setBaseRate] = useState(5000) const [amenities, setAmenities] = useState(['Wi-Fi', 'TV', 'AC']) const [saving, setSaving] = useState(false) const [error, setError] = useState(null) const toggleAmenity = (a: string) => setAmenities(prev => prev.includes(a) ? prev.filter(x => x !== a) : [...prev, a]) const taken = useMemo(() => new Set(existingNumbers), [existingNumbers]) const preview = useMemo(() => { if (from > to || to - from > 499) return [] const rows: { number: string; floor: number; skip: boolean }[] = [] for (let n = from; n <= to; n++) { const numStr = String(n) rows.push({ number: numStr, floor: autoFloor ? deriveFloor(n) : floor, skip: taken.has(numStr), }) } return rows }, [from, to, autoFloor, floor, taken]) const newCount = preview.filter(r => !r.skip).length const skipCount = preview.filter(r => r.skip).length const catName = categories.find(c => c.id === categoryId)?.name ?? '' const handleSave = async () => { if (newCount === 0) return setSaving(true) setError(null) try { const rooms: BulkRoomData[] = preview .filter(r => !r.skip) .map((r, i) => ({ number: r.number, floor: r.floor, type: catName || 'Стандарт', categoryId: categoryId || undefined, bedType, maxGuests, baseRate, status: 'available' as RoomStatus, housekeepingStatus: 'clean' as const, amenities, sortOrder: i + 1, allowHourly: false as const, })) await onSave(rooms) } catch (err) { setError(err instanceof Error ? err.message : 'Ошибка сохранения') setSaving(false) } } const rangeValid = from > 0 && to >= from && (to - from) <= 499 return ( {error &&

{error}

} } >
{/* Range */}
setFrom(parseInt(e.target.value) || 1)} />
setTo(parseInt(e.target.value) || 1)} />
{!rangeValid && (

{to < from ? 'Конец диапазона меньше начала' : 'Максимум 500 номеров за раз'}

)}
{/* Floor */}
{!autoFloor && ( setFloor(parseInt(e.target.value) || 1)} /> )} {autoFloor && (

101–199 → этаж 1, 201–299 → этаж 2, и т.д.

)}
{/* Category + Bed type */}
{categories.length > 0 ? ( ) : (
Нет категорий
)}
{/* Guests + Rate */}
setMaxGuests(parseInt(e.target.value) || 1)} />
setBaseRate(parseInt(e.target.value) || 0)} />
{/* Amenities */}
{allAmenities.map(a => { const selected = amenities.includes(a) return ( ) })}
{/* Preview */} {rangeValid && preview.length > 0 && (
{newCount > 0 && ( {newCount} будет создано )} {skipCount > 0 && ( ещё {skipCount} уже существуют — пропущены )}
{preview.map(r => ( {r.number} ))}
)}
) }