import { useState } from 'react' import { Plus, Edit2, Trash2, ToggleLeft, ToggleRight, Coffee, Utensils, Wifi, Car, Waves, Sparkles, Plane, Package, Check, X, Info, Tag, } from 'lucide-react' import { Modal } from '../components/ui/Modal' import { cn } from '../lib/utils' // ─── Types ──────────────────────────────────────────────────────────────────── type MealPlan = 'no_meals' | 'breakfast' | 'hb' | 'fb' | 'ai' interface TariffInclusion { id: string label: string icon: React.ElementType } const ALL_INCLUSIONS: TariffInclusion[] = [ { id: 'breakfast', label: 'Завтрак', icon: Coffee }, { id: 'dinner', label: 'Ужин', icon: Utensils }, { id: 'wifi', label: 'Wi-Fi', icon: Wifi }, { id: 'parking', label: 'Парковка', icon: Car }, { id: 'pool', label: 'Бассейн', icon: Waves }, { id: 'spa', label: 'СПА-доступ', icon: Sparkles }, { id: 'transfer', label: 'Трансфер', icon: Plane }, { id: 'minibar', label: 'Мини-бар', icon: Package }, ] const MEAL_PLANS: { id: MealPlan; label: string; description: string; inclusions: string[] }[] = [ { id: 'no_meals', label: 'Без питания', description: 'BB — Bed only', inclusions: [] }, { id: 'breakfast', label: 'Завтрак', description: 'BB — Bed & Breakfast', inclusions: ['breakfast'] }, { id: 'hb', label: 'Полупансион', description: 'HB — Half Board (завтрак + ужин)', inclusions: ['breakfast', 'dinner'] }, { id: 'fb', label: 'Полный пансион', description: 'FB — Full Board (3 разовое питание)', inclusions: ['breakfast', 'dinner'] }, { id: 'ai', label: 'Всё включено', description: 'AI — All Inclusive', inclusions: ['breakfast', 'dinner', 'pool', 'wifi', 'minibar'] }, ] interface Tariff { id: string name: string code: string mealPlan: MealPlan inclusions: string[] modifierType: 'percent' | 'fixed' modifierValue: number // + means surcharge, - means discount minNights: number cancellationPolicy: 'flexible' | 'moderate' | 'strict' | 'nonrefundable' description: string isActive: boolean } // ─── Mock ───────────────────────────────────────────────────────────────────── const MOCK_TARIFFS: Tariff[] = [ { id: 't-1', name: 'Стандарт без питания', code: 'STD-RO', mealPlan: 'no_meals', inclusions: ['wifi'], modifierType: 'percent', modifierValue: 0, minNights: 1, cancellationPolicy: 'moderate', description: 'Базовый тариф. Только проживание, Wi-Fi включён.', isActive: true, }, { id: 't-2', name: 'С завтраком', code: 'STD-BB', mealPlan: 'breakfast', inclusions: ['wifi', 'breakfast'], modifierType: 'fixed', modifierValue: 800, minNights: 1, cancellationPolicy: 'flexible', description: 'Проживание + шведский стол с 7:00 до 10:30. Отмена без штрафа за 24 ч.', isActive: true, }, { id: 't-3', name: 'Полупансион', code: 'STD-HB', mealPlan: 'hb', inclusions: ['wifi', 'breakfast', 'dinner'], modifierType: 'fixed', modifierValue: 2200, minNights: 2, cancellationPolicy: 'moderate', description: 'Завтрак + ужин по меню. Минимальный срок — 2 ночи.', isActive: true, }, { id: 't-4', name: 'Всё включено', code: 'AI', mealPlan: 'ai', inclusions: ['wifi', 'breakfast', 'dinner', 'pool', 'minibar', 'spa'], modifierType: 'percent', modifierValue: 35, minNights: 3, cancellationPolicy: 'strict', description: 'Питание, напитки, бассейн, СПА. Отмена — не позднее 5 дней до заезда.', isActive: true, }, { id: 't-5', name: 'Невозвратный', code: 'NR', mealPlan: 'breakfast', inclusions: ['wifi', 'breakfast'], modifierType: 'percent', modifierValue: -15, minNights: 1, cancellationPolicy: 'nonrefundable', description: 'Скидка 15% за невозвратное бронирование. Без изменений и отмены.', isActive: false, }, ] const CANCEL_POLICY: Record = { flexible: { label: 'Гибкая', cls: 'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400' }, moderate: { label: 'Умеренная', cls: 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400' }, strict: { label: 'Строгая', cls: 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400' }, nonrefundable: { label: 'Невозвратный', cls: 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400' }, } // ─── Tariff Modal ───────────────────────────────────────────────────────────── const EMPTY_TARIFF: Omit = { name: '', code: '', mealPlan: 'no_meals', inclusions: ['wifi'], modifierType: 'fixed', modifierValue: 0, minNights: 1, cancellationPolicy: 'flexible', description: '', isActive: true, } function TariffModal({ tariff, onSave, onClose, }: { tariff?: Tariff onSave: (t: Omit) => void onClose: () => void }) { const [form, setForm] = useState>( tariff ? { ...tariff } : { ...EMPTY_TARIFF } ) const set = (k: K, v: typeof form[K]) => setForm(prev => ({ ...prev, [k]: v })) const toggleInclusion = (id: string) => setForm(prev => ({ ...prev, inclusions: prev.inclusions.includes(id) ? prev.inclusions.filter(i => i !== id) : [...prev.inclusions, id], })) const applyMealPlan = (plan: MealPlan) => { const mp = MEAL_PLANS.find(m => m.id === plan)! setForm(prev => ({ ...prev, mealPlan: plan, inclusions: [ ...new Set([ ...prev.inclusions.filter(i => !['breakfast', 'dinner'].includes(i)), ...mp.inclusions, ]), ], })) } const sampleBase = 5600 const modifier = form.modifierType === 'percent' ? Math.round(sampleBase * form.modifierValue / 100) : form.modifierValue const effectivePrice = sampleBase + modifier return ( } >
{/* Name + Code */}
set('name', e.target.value)} />
set('code', e.target.value.toUpperCase())} />
{/* Meal Plan */}
{MEAL_PLANS.map(mp => ( ))}
{/* Inclusions */}
{ALL_INCLUSIONS.map(inc => { const active = form.inclusions.includes(inc.id) return ( ) })}
{/* Price modifier + min nights + cancellation */}
set('modifierValue', parseInt(e.target.value) || 0)} />
{form.modifierValue !== 0 && (

Пример: {sampleBase.toLocaleString('ru-RU')} + {modifier > 0 ? '+' : ''}{modifier.toLocaleString('ru-RU')} = {effectivePrice.toLocaleString('ru-RU')} ₽/ночь

)}
set('minNights', Math.max(1, parseInt(e.target.value) || 1))} />
{/* Description */}