import React, { useState } from 'react'; import { Search, User, Hotel, CheckCircle, AlertCircle } from 'lucide-react'; import { bookingService, Booking } from '../../services/api'; import { toast } from 'react-toastify'; import Loading from '../../components/common/Loading'; interface GuestInfo { name: string; id_number: string; phone: string; } const CheckInPage: React.FC = () => { const [bookingNumber, setBookingNumber] = useState(''); const [booking, setBooking] = useState(null); const [loading, setLoading] = useState(false); const [searching, setSearching] = useState(false); const [actualRoomNumber, setActualRoomNumber] = useState(''); const [guests, setGuests] = useState([{ name: '', id_number: '', phone: '' }]); const [extraPersons, setExtraPersons] = useState(0); const [children, setChildren] = useState(0); const [additionalFee, setAdditionalFee] = useState(0); const handleSearch = async () => { if (!bookingNumber.trim()) { toast.error('Please enter booking number'); return; } try { setSearching(true); const response = await bookingService.checkBookingByNumber(bookingNumber); setBooking(response.data.booking); setActualRoomNumber(response.data.booking.room?.room_number || ''); toast.success('Booking found'); } catch (error: any) { toast.error(error.response?.data?.message || 'Booking not found'); setBooking(null); } finally { setSearching(false); } }; const handleAddGuest = () => { setGuests([...guests, { name: '', id_number: '', phone: '' }]); }; const handleRemoveGuest = (index: number) => { if (guests.length > 1) { setGuests(guests.filter((_, i) => i !== index)); } }; const handleGuestChange = (index: number, field: keyof GuestInfo, value: string) => { const newGuests = [...guests]; newGuests[index][field] = value; setGuests(newGuests); }; const calculateAdditionalFee = () => { // Logic to calculate additional fees: children and extra person const extraPersonFee = extraPersons * 200000; // 200k/person const childrenFee = children * 100000; // 100k/child const total = extraPersonFee + childrenFee; setAdditionalFee(total); return total; }; const handleCheckIn = async () => { if (!booking) return; // Validate if (!actualRoomNumber.trim()) { toast.error('Please enter actual room number'); return; } const mainGuest = guests[0]; if (!mainGuest.name || !mainGuest.id_number || !mainGuest.phone) { toast.error('Please fill in all main guest information'); return; } try { setLoading(true); // Calculate additional fee calculateAdditionalFee(); await bookingService.updateBooking(booking.id, { status: 'checked_in', // Can send additional data about guests, room_number, additional_fee } as any); toast.success('Check-in successful'); // Reset form setBooking(null); setBookingNumber(''); setActualRoomNumber(''); setGuests([{ name: '', id_number: '', phone: '' }]); setExtraPersons(0); setChildren(0); setAdditionalFee(0); } catch (error: any) { toast.error(error.response?.data?.message || 'An error occurred during check-in'); } finally { setLoading(false); } }; const formatCurrency = (amount: number) => { return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(amount); }; if (loading) { return ; } return (

Check-in

Customer check-in process

{/* Search Booking */}

1. Search booking

setBookingNumber(e.target.value)} onKeyPress={(e) => e.key === 'Enter' && handleSearch()} placeholder="Enter booking number" className="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500" />
{/* Booking Info */} {booking && ( <>

2. Booking Information

Booking Number: {booking.booking_number}
Customer: {booking.user?.full_name}
Email: {booking.user?.email}
Phone: {booking.user?.phone_number || 'N/A'}
Room Type: {booking.room?.room_type?.name || 'N/A'}
Check-in: {booking.check_in_date ? new Date(booking.check_in_date).toLocaleDateString('en-US') : 'N/A'}
Check-out: {booking.check_out_date ? new Date(booking.check_out_date).toLocaleDateString('en-US') : 'N/A'}
Number of Guests: {booking.guest_count} guest(s)
{booking.status !== 'confirmed' && (

Warning

Booking status: {booking.status}. Only check-in confirmed bookings.

)}
{/* Assign Room */}

3. Assign Actual Room Number

setActualRoomNumber(e.target.value)} placeholder="VD: 101, 202, 305" className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500" />

Enter the actual room number to assign to the guest

{/* Guest Information */}

4. Guest Information

{guests.map((guest, index) => (

{index === 0 ? 'Main Guest' : `Guest ${index + 1}`} {index === 0 && *}

{index > 0 && ( )}
handleGuestChange(index, 'name', e.target.value)} className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500" placeholder="Nguyễn Văn A" />
handleGuestChange(index, 'id_number', e.target.value)} className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500" placeholder="001234567890" />
handleGuestChange(index, 'phone', e.target.value)} className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500" placeholder="0912345678" />
))}
{/* Additional Charges */}

5. Additional Fees (if any)

{ setExtraPersons(parseInt(e.target.value) || 0); calculateAdditionalFee(); }} className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500" />

200,000 VND/person

{ setChildren(parseInt(e.target.value) || 0); calculateAdditionalFee(); }} className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500" />

100,000 VND/child

{formatCurrency(calculateAdditionalFee())}
{/* Summary & Action */}

Confirm Check-in

Guest: {booking.user?.full_name} | Room: {actualRoomNumber || 'Not assigned'} {additionalFee > 0 && ( <> | Additional Fee: {formatCurrency(additionalFee)} )}

)} {/* Empty State */} {!booking && !searching && (

No booking selected

Please enter booking number above to start check-in process

)}
); }; export default CheckInPage;