import { useState } from 'react' import { Search, Star, Phone, Mail, User, TrendingUp, Award, Users, Calendar, CreditCard, X, ChevronRight, MessageSquare, Tag, Repeat2, ShieldCheck, Plus, } from 'lucide-react' import { cn } from '../lib/utils' // ─── Types ─────────────────────────────────────────────────────────────────── type GuestTag = 'VIP' | 'Постоянный' | 'Корпоративный' | 'Медовый месяц' | 'Проблемный' interface StayRecord { id: string checkIn: string checkOut: string roomNumber: string roomType: string amount: number paid: number status: 'completed' | 'cancelled' | 'no_show' } interface Guest { id: string name: string email: string phone: string rating: number // 1–5 tags: GuestTag[] totalStays: number totalSpent: number lastVisit: string notes: string history: StayRecord[] } // ─── Mock Data ──────────────────────────────────────────────────────────────── const MOCK_GUESTS: Guest[] = [ { id: 'g-1', name: 'Александр Петров', email: 'a.petrov@gmail.com', phone: '+7 916 123-45-67', rating: 5, tags: ['VIP', 'Постоянный'], totalStays: 14, totalSpent: 287400, lastVisit: '2026-03-01', notes: 'Предпочитает номера с видом на море. Всегда заказывает завтрак. Любит тихие номера подальше от лифта.', history: [ { id: 'b-101', checkIn: '2026-03-01', checkOut: '2026-03-05', roomNumber: '205', roomType: 'Делюкс', amount: 24000, paid: 24000, status: 'completed' }, { id: 'b-102', checkIn: '2025-12-20', checkOut: '2025-12-26', roomNumber: '205', roomType: 'Делюкс', amount: 36000, paid: 36000, status: 'completed' }, { id: 'b-103', checkIn: '2025-09-10', checkOut: '2025-09-14', roomNumber: '301', roomType: 'Сьют', amount: 48000, paid: 48000, status: 'completed' }, { id: 'b-104', checkIn: '2025-06-01', checkOut: '2025-06-07', roomNumber: '205', roomType: 'Делюкс', amount: 42000, paid: 42000, status: 'completed' }, ], }, { id: 'g-2', name: 'Мария Сидорова', email: 'm.sidorova@mail.ru', phone: '+7 903 456-78-90', rating: 4, tags: ['Корпоративный'], totalStays: 6, totalSpent: 98200, lastVisit: '2026-02-15', notes: 'Корпоративный гость компании ООО "ТехСтрой". Нужен ранний заезд.', history: [ { id: 'b-201', checkIn: '2026-02-13', checkOut: '2026-02-15', roomNumber: '102', roomType: 'Стандарт', amount: 11200, paid: 11200, status: 'completed' }, { id: 'b-202', checkIn: '2025-11-20', checkOut: '2025-11-23', roomNumber: '102', roomType: 'Стандарт', amount: 16800, paid: 16800, status: 'completed' }, ], }, { id: 'g-3', name: 'Дмитрий Козлов', email: 'dkozlov@yandex.ru', phone: '+7 926 789-01-23', rating: 3, tags: [], totalStays: 2, totalSpent: 18600, lastVisit: '2026-01-20', notes: '', history: [ { id: 'b-301', checkIn: '2026-01-18', checkOut: '2026-01-20', roomNumber: '110', roomType: 'Стандарт', amount: 9300, paid: 9300, status: 'completed' }, { id: 'b-302', checkIn: '2025-08-05', checkOut: '2025-08-07', roomNumber: '108', roomType: 'Стандарт', amount: 9300, paid: 0, status: 'no_show' }, ], }, { id: 'g-4', name: 'Елена Новикова', email: 'e.novikova@gmail.com', phone: '+7 985 234-56-78', rating: 5, tags: ['VIP', 'Медовый месяц'], totalStays: 3, totalSpent: 76500, lastVisit: '2026-02-28', notes: 'Отмечала медовый месяц. Очень довольна обслуживанием, оставила 5* отзыв на Booking.', history: [ { id: 'b-401', checkIn: '2026-02-14', checkOut: '2026-02-21', roomNumber: '401', roomType: 'Люкс', amount: 63000, paid: 63000, status: 'completed' }, { id: 'b-402', checkIn: '2024-12-30', checkOut: '2025-01-03', roomNumber: '301', roomType: 'Сьют', amount: 13500, paid: 13500, status: 'completed' }, ], }, { id: 'g-5', name: 'Игорь Волков', email: 'i.volkov@corp.ru', phone: '+7 909 345-67-89', rating: 2, tags: ['Проблемный'], totalStays: 4, totalSpent: 44000, lastVisit: '2025-11-10', notes: 'Были жалобы от соседних номеров на шум. Конфликт с персоналом 11.11.2025. Требует внимания при заселении.', history: [ { id: 'b-501', checkIn: '2025-11-08', checkOut: '2025-11-10', roomNumber: '215', roomType: 'Делюкс', amount: 14000, paid: 14000, status: 'completed' }, { id: 'b-502', checkIn: '2025-07-14', checkOut: '2025-07-17', roomNumber: '108', roomType: 'Стандарт', amount: 13500, paid: 13500, status: 'completed' }, ], }, { id: 'g-6', name: 'Анна Лебедева', email: 'anna.l@mail.ru', phone: '+7 965 567-89-01', rating: 4, tags: ['Постоянный'], totalStays: 8, totalSpent: 132000, lastVisit: '2026-03-10', notes: 'Регулярно приезжает в командировку. Всегда берёт одноместный стандарт.', history: [ { id: 'b-601', checkIn: '2026-03-08', checkOut: '2026-03-10', roomNumber: '104', roomType: 'Стандарт', amount: 11200, paid: 11200, status: 'completed' }, { id: 'b-602', checkIn: '2026-02-01', checkOut: '2026-02-04', roomNumber: '104', roomType: 'Стандарт', amount: 16800, paid: 16800, status: 'completed' }, ], }, { id: 'g-7', name: 'Сергей Морозов', email: '', phone: '+7 977 678-90-12', rating: 4, tags: [], totalStays: 1, totalSpent: 8400, lastVisit: '2026-03-12', notes: '', history: [ { id: 'b-701', checkIn: '2026-03-11', checkOut: '2026-03-12', roomNumber: '109', roomType: 'Стандарт', amount: 8400, paid: 8400, status: 'completed' }, ], }, ] // ─── Helpers ────────────────────────────────────────────────────────────────── const STAY_STATUS: Record = { completed: { label: 'Выполнено', cls: 'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400' }, cancelled: { label: 'Отменено', cls: 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400' }, no_show: { label: 'Неявка', cls: 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400' }, } const TAG_META: Record = { VIP: { cls: 'bg-amber-100 text-amber-700 border-amber-200 dark:bg-amber-900/30 dark:text-amber-400' }, Постоянный: { cls: 'bg-brand-100 text-brand-700 border-brand-200 dark:bg-brand-900/30 dark:text-brand-400' }, Корпоративный: { cls: 'bg-blue-100 text-blue-700 border-blue-200 dark:bg-blue-900/30 dark:text-blue-400' }, 'Медовый месяц':{ cls: 'bg-pink-100 text-pink-700 border-pink-200 dark:bg-pink-900/30 dark:text-pink-400' }, Проблемный: { cls: 'bg-red-100 text-red-700 border-red-200 dark:bg-red-900/30 dark:text-red-400' }, } function StarRating({ value, onChange }: { value: number; onChange?: (v: number) => void }) { return (
{[1, 2, 3, 4, 5].map(i => ( onChange?.(i)} /> ))}
) } function formatDate(iso: string) { if (!iso) return '—' const d = new Date(iso) return d.toLocaleDateString('ru-RU', { day: '2-digit', month: '2-digit', year: 'numeric' }) } function nights(checkIn: string, checkOut: string) { const n = Math.round((new Date(checkOut).getTime() - new Date(checkIn).getTime()) / 86400000) return `${n} ${n === 1 ? 'ночь' : n < 5 ? 'ночи' : 'ночей'}` } // ─── Guest Detail Modal ─────────────────────────────────────────────────────── function GuestModal({ guest, onClose }: { guest: Guest; onClose: () => void }) { const [tab, setTab] = useState<'overview' | 'history' | 'payments'>('overview') const [editNotes, setEditNotes] = useState(guest.notes) const [rating, setRating] = useState(guest.rating) const completedStays = guest.history.filter(s => s.status === 'completed') const totalPaid = guest.history.reduce((s, h) => s + h.paid, 0) const avgBill = completedStays.length ? Math.round(totalPaid / completedStays.length) : 0 return (
{/* Header */}
{guest.name.split(' ').map(p => p[0]).join('').slice(0, 2)}

{guest.name}

{guest.tags.includes('VIP') && ( VIP )}
{guest.phone && ( {guest.phone} )} {guest.email && ( {guest.email} )}
{/* Stats strip */}
{[ { label: 'Визитов', value: guest.totalStays }, { label: 'Потрачено', value: `${guest.totalSpent.toLocaleString('ru-RU')} ₽` }, { label: 'Средний чек', value: `${avgBill.toLocaleString('ru-RU')} ₽` }, { label: 'Последний визит', value: formatDate(guest.lastVisit) }, ].map(s => (

{s.label}

{s.value}

))}
{/* Tabs */}
{([ { id: 'overview' as const, label: 'Обзор' }, { id: 'history' as const, label: 'История проживания' }, { id: 'payments' as const, label: 'Платежи' }, ]).map(t => ( ))}
{/* Body */}
{tab === 'overview' && (
{/* Tags */}

Метки

{guest.tags.length > 0 ? guest.tags.map(tag => ( {tag} )) : ( Метки не назначены )}
{/* Notes */}

Заметки о госте