import React, { useState, useEffect, useRef } from 'react'; import { useSearchParams, Link } from 'react-router-dom'; import { getRooms } from '../../features/rooms/services/roomService'; import type { Room } from '../../features/rooms/services/roomService'; import RoomFilter from '../../features/rooms/components/RoomFilter'; import RoomCard from '../../features/rooms/components/RoomCard'; import RoomCardSkeleton from '../../features/rooms/components/RoomCardSkeleton'; import Pagination from '../../shared/components/Pagination'; import { ArrowLeft, Hotel, Filter, ChevronDown, ChevronUp, Tag, X, CheckCircle } from 'lucide-react'; import { logger } from '../../shared/utils/logger'; import { toast } from 'react-toastify'; const RoomListPage: React.FC = () => { const [searchParams] = useSearchParams(); const [rooms, setRooms] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [isFilterOpen, setIsFilterOpen] = useState(false); const filterRef = useRef(null); const [pagination, setPagination] = useState({ total: 0, page: 1, limit: 10, totalPages: 1, }); const abortControllerRef = useRef(null); const [activePromotion, setActivePromotion] = useState(null); const [showPromotionBanner, setShowPromotionBanner] = useState(false); // Check for active promotion from URL or sessionStorage useEffect(() => { const promoCode = searchParams.get('promo'); // Check sessionStorage first (from homepage promotion click) try { const storedPromotion = sessionStorage.getItem('activePromotion'); if (storedPromotion) { const promo = JSON.parse(storedPromotion); setActivePromotion(promo); setShowPromotionBanner(true); return; } } catch (error) { console.warn('Failed to read promotion from sessionStorage:', error); } // Check URL params (fallback) if (promoCode) { setActivePromotion({ code: promoCode, title: 'Special Offer', discount: searchParams.get('discount') || '', }); setShowPromotionBanner(true); } }, [searchParams]); const handleDismissPromotion = () => { setShowPromotionBanner(false); try { sessionStorage.removeItem('activePromotion'); } catch (error) { console.warn('Failed to remove promotion from sessionStorage:', error); } }; useEffect(() => { if (isFilterOpen && filterRef.current && window.innerWidth < 1280) { setTimeout(() => { filterRef.current?.scrollIntoView({ behavior: 'smooth', block: 'start' }); }, 100); } }, [isFilterOpen]); useEffect(() => { // Cancel previous request if exists if (abortControllerRef.current) { abortControllerRef.current.abort(); } // Create new abort controller abortControllerRef.current = new AbortController(); const fetchRooms = async () => { setLoading(true); setError(null); try { const params = { type: searchParams.get('type') || undefined, minPrice: searchParams.get('minPrice') ? Number(searchParams.get('minPrice')) : undefined, maxPrice: searchParams.get('maxPrice') ? Number(searchParams.get('maxPrice')) : undefined, capacity: searchParams.get('capacity') ? Number(searchParams.get('capacity')) : undefined, page: searchParams.get('page') ? Number(searchParams.get('page')) : 1, limit: 12, }; const response = await getRooms(params); if ((response.status === 'success' || response.success) && response.data) { setRooms(response.data.rooms || []); if (response.data.pagination) { setPagination(response.data.pagination); } } else { throw new Error('Failed to fetch rooms'); } } catch (err: any) { // Don't show error if request was aborted if (err.name === 'AbortError') { return; } // Clear data when API connection fails setRooms([]); setPagination({ total: 0, page: 1, limit: 12, totalPages: 0, }); logger.error('Error fetching rooms', err); setError('Unable to load room list. Please try again.'); } finally { setLoading(false); } }; fetchRooms(); // Cleanup: abort request on unmount return () => { if (abortControllerRef.current) { abortControllerRef.current.abort(); } }; }, [searchParams]); return (
{} {/* Promotion Banner */} {showPromotionBanner && activePromotion && (
Active Promotion: {activePromotion.code || activePromotion.title}
{activePromotion.discount && (

{activePromotion.discount} - {activePromotion.description || 'Valid on bookings'}

)}

The promotion code will be automatically applied when you book a room

)}
{} Back to home {}

Our Rooms & Suites

Discover our collection of luxurious accommodations, each designed to provide an exceptional stay

{}
{}
{} {}
{loading && (
{Array.from({ length: 6 }).map((_, index) => ( ))}
)} {error && !loading && (

{error}

)} {!loading && !error && rooms.length === 0 && (

No matching rooms found

Please try adjusting the filters or search differently

)} {!loading && !error && rooms.length > 0 && ( <> {}

Showing {rooms.length} of{' '} {pagination.total} rooms

{}
{rooms.map((room) => ( ))}
{pagination.totalPages > 1 && (
)} )}
); }; export default RoomListPage;