import { useEffect, useState } from 'react'; import { useSearchParams } from 'react-router-dom'; import { Helmet } from 'react-helmet-async'; import Box from '@mui/material/Box'; import Grid from '@mui/material/Grid'; import Typography from '@mui/material/Typography'; import TextField from '@mui/material/TextField'; import MenuItem from '@mui/material/MenuItem'; import Chip from '@mui/material/Chip'; import Drawer from '@mui/material/Drawer'; import IconButton from '@mui/material/IconButton'; import FilterListIcon from '@mui/icons-material/FilterList'; import CloseIcon from '@mui/icons-material/Close'; import SearchIcon from '@mui/icons-material/Search'; import InputAdornment from '@mui/material/InputAdornment'; import CircularProgress from '@mui/material/CircularProgress'; import { PageContainer, SectionWrapper, ProfileCard, SectionHeader, LuxeButton } from '@/components/ui'; import { SearchFilterPanel } from '@/components/search/SearchFilterPanel'; import { useSearchStore } from '@/store'; import { useMediaQuery } from '@/hooks'; import { profileApi } from '@/api/profile'; import type { Profile } from '@/types'; export function SearchPage() { const [searchParams, setSearchParams] = useSearchParams(); const { filters, setFilters, resetFilters } = useSearchStore(); const [mobileOpen, setMobileOpen] = useState(false); const isMdUp = useMediaQuery('(min-width:900px)'); // Sync URL query param to search store on load const queryParam = searchParams.get('q') ?? ''; const cityParam = searchParams.get('city') ?? ''; const categoryParam = searchParams.get('category') ?? ''; useEffect(() => { const initialFilters: any = {}; if (queryParam) initialFilters.query = queryParam; if (cityParam) initialFilters.city = cityParam; if (categoryParam) initialFilters.categories = [categoryParam]; if (Object.keys(initialFilters).length > 0) { setFilters(initialFilters); } }, [queryParam, cityParam, categoryParam, setFilters]); const [profiles, setProfiles] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { const fetchProfiles = async () => { try { setLoading(true); const params: any = {}; if (filters.query) params.query = filters.query; if (filters.city) params.city = filters.city; if (filters.categories && filters.categories.length > 0) { params.category = filters.categories[0]; } if (filters.ageMin !== undefined) params.ageMin = filters.ageMin; if (filters.ageMax !== undefined) params.ageMax = filters.ageMax; if (filters.priceMin !== undefined) params.priceMin = filters.priceMin; if (filters.priceMax !== undefined) params.priceMax = filters.priceMax; if (filters.verified) params.verified = 'true'; if (filters.premium) params.featured = 'true'; if (filters.sortBy) params.sortBy = filters.sortBy; const res = await profileApi.searchProfiles(params); if (res.success && res.data) { const mapped = res.data.map((listing: any) => { const primaryImg = listing.gallery?.find((g: any) => g.isPrimary)?.url || listing.gallery?.[0]?.url || 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=600&h=800&fit=crop'; return { id: listing.id, slug: listing.slug, name: listing.title, age: listing.age || 21, city: listing.city?.name || 'New York', area: listing.area?.name || '', avatar: primaryImg, coverImage: primaryImg, rating: listing.advertiser?.rating || 5.0, reviewCount: listing.advertiser?.reviewCount || 0, isVerified: listing.isVerified || false, isPremium: listing.isPremium || false, isOnline: listing.isOnline || true, priceFrom: listing.price || 200, currency: listing.currency || 'USD', categories: listing.category ? [listing.category.name] : ['VIP Escorts'], languages: listing.languages || ['English'], height: listing.height || '170 cm', tagline: listing.tagline || '', }; }); setProfiles(mapped); } } catch (err) { console.error('Failed to load profiles:', err); } finally { setLoading(false); } }; fetchProfiles(); }, [filters]); const sortedResults = profiles; const handleSearchInputChange = (e: React.ChangeEvent) => { const val = e.target.value; setFilters({ query: val || undefined }); // Update URL params const nextParams = new URLSearchParams(searchParams); if (val) { nextParams.set('q', val); } else { nextParams.delete('q'); } setSearchParams(nextParams); }; const handleSortChange = (e: React.ChangeEvent) => { setFilters({ sortBy: e.target.value as any }); }; const handleRemoveFilter = (key: keyof typeof filters, value?: any) => { if (key === 'categories' && value) { setFilters({ categories: filters.categories?.filter((c) => c !== value) }); } else if (key === 'languages' && value) { setFilters({ languages: filters.languages?.filter((l) => l !== value) }); } else { setFilters({ [key]: undefined }); } }; const activeFilterChips = []; if (filters.city) activeFilterChips.push({ label: `City: ${filters.city}`, onClick: () => handleRemoveFilter('city') }); if (filters.verified) activeFilterChips.push({ label: 'Verified', onClick: () => handleRemoveFilter('verified') }); if (filters.online) activeFilterChips.push({ label: 'Online Now', onClick: () => handleRemoveFilter('online') }); if (filters.premium) activeFilterChips.push({ label: 'Premium Showcase', onClick: () => handleRemoveFilter('premium') }); if (filters.ageMin || filters.ageMax) { activeFilterChips.push({ label: `Age: ${filters.ageMin ?? 18}-${filters.ageMax ?? 50}`, onClick: () => { setFilters({ ageMin: undefined, ageMax: undefined }); } }); } if (filters.priceMin || filters.priceMax) { activeFilterChips.push({ label: `Price: $${filters.priceMin ?? 100}-$${filters.priceMax ?? 2000}`, onClick: () => { setFilters({ priceMin: undefined, priceMax: undefined }); } }); } filters.categories?.forEach((cat) => { activeFilterChips.push({ label: `Category: ${cat}`, onClick: () => handleRemoveFilter('categories', cat) }); }); filters.languages?.forEach((lang) => { activeFilterChips.push({ label: `Lang: ${lang}`, onClick: () => handleRemoveFilter('languages', lang) }); }); return ( <> {filters.query ? `Search: ${filters.query}` : 'Premium Companions Directory'} — Luxe {/* Header */} {/* Controls Bar */} ), } }} /> Premium First Highest Rated Price: Low to High Price: High to Low New Listings {!isMdUp && ( } onClick={() => setMobileOpen(true)} sx={{ py: 1 }} > Filters )} {/* Active Filters Display */} {activeFilterChips.length > 0 && ( Active Filters: {activeFilterChips.map((chip, idx) => ( ))} Reset Filters )} {/* Directory Listings and Filter Sidebar Grid */} {/* Desktop Filters Panel */} {isMdUp && ( )} {/* Profiles Directory */} Showing {sortedResults.length} premium profile{sortedResults.length !== 1 && 's'} {loading ? ( ) : sortedResults.length > 0 ? ( {sortedResults.map((profile, i) => ( ))} ) : ( No Companions Found We couldn't find any profiles matching your filters. Try clearing some options or changing your search terms. Clear All Filters )} {/* Mobile Drawer Filter Panel */} setMobileOpen(false)} slotProps={{ backdrop: { sx: { backdropFilter: 'blur(4px)' } } }} PaperProps={{ sx: { width: '100%', maxWidth: 360, bgcolor: 'background.default', p: 0 } }} > Filter Options setMobileOpen(false)} size="small" aria-label="Close filters"> ); } export default SearchPage;