feat: configurable bed types via BedTypesContext

- Add BedTypesContext with default types + add/remove/update operations
- Replace hardcoded BED_ITEM_TYPES array in RoomModal with useBedTypes()
- Add "Справочник спальных мест" section to RoomCategoriesPage
  (expandable, same UX as amenities: add icon+label, rename, delete)
- BedItem.type changed from union to string for dynamic support

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-23 14:20:09 +03:00
parent 6bf1391890
commit 8c6cdfb1c7
5 changed files with 206 additions and 15 deletions

View File

@@ -1,9 +1,10 @@
import { useState, useRef } from 'react'
import { Modal } from '../ui/Modal'
import { cn } from '../../lib/utils'
import type { Room, RoomStatus, HousekeepingStatus, BedType, BedItem, BedItemType, ExtraPlace, ChildPolicy } from '../../types'
import type { Room, RoomStatus, HousekeepingStatus, BedType, BedItem, ExtraPlace, ChildPolicy } from '../../types'
import { ImagePlus, X as XIcon, ChevronLeft, ChevronRight, Plus, Minus, Baby, Trash2 } from 'lucide-react'
import { useAmenities } from '../../contexts/AmenitiesContext'
import { useBedTypes } from '../../contexts/BedTypesContext'
const ROOM_TYPES = ['Стандарт', 'Делюкс', 'Полулюкс', 'Люкс', 'Пентхаус', 'Апартаменты', 'Другой']
@@ -29,16 +30,6 @@ const HK_STATUSES: { value: HousekeepingStatus; label: string }[] = [
{ value: 'inspect', label: 'Проверка' },
]
const BED_ITEM_TYPES: { value: BedItemType; label: string; icon: string }[] = [
{ value: 'single', label: 'Кровать 1-сп.', icon: '🛏' },
{ value: 'double', label: 'Кровать 2-сп.', icon: '🛏' },
{ value: 'queen', label: 'Queen-кровать', icon: '🛏' },
{ value: 'king', label: 'King-кровать', icon: '🛏' },
{ value: 'twin', label: 'Две кровати', icon: '🛏' },
{ value: 'sofa', label: 'Диван', icon: '🛋' },
{ value: 'bunk', label: 'Двухъярусная', icon: '🛏' },
{ value: 'cot', label: 'Раскладушка', icon: '🪑' },
]
// ── Tab type ───────────────────────────────────────────────────────────────────
type ModalTab = 'main' | 'places' | 'description' | 'photos'
@@ -78,6 +69,7 @@ export function RoomModal({ open, room, existingNumbers = [], categories = [], o
})
const { amenities: allAmenities } = useAmenities()
const { bedTypes } = useBedTypes()
const [amenities, setAmenities] = useState<string[]>(room?.amenities ?? ['Wi-Fi', 'TV', 'AC'])
const [photos, setPhotos] = useState<string[]>(room?.photos ?? [])
const [photoIdx, setPhotoIdx] = useState(0)
@@ -423,14 +415,14 @@ export function RoomModal({ open, room, existingNumbers = [], categories = [], o
{beds.map((bed, i) => (
<div key={i} className="flex items-center gap-2">
<span className="text-lg w-7 text-center shrink-0">
{BED_ITEM_TYPES.find(b => b.value === bed.type)?.icon ?? '🛏'}
{bedTypes.find(b => b.value === bed.type)?.icon ?? '🛏'}
</span>
<select
className="input flex-1"
value={bed.type}
onChange={e => updateBed(i, { type: e.target.value as BedItemType })}
onChange={e => updateBed(i, { type: e.target.value })}
>
{BED_ITEM_TYPES.map(b => (
{bedTypes.map(b => (
<option key={b.value} value={b.value}>{b.label}</option>
))}
</select>