import { useEffect, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { MapContainer, TileLayer, Marker } from 'react-leaflet'
import 'leaflet/dist/leaflet.css'
import '../utils/leafletIcons'
import Icon from '../components/Icon'
import HomeBanner from '../components/HomeBanner'
import { Cafe, City, fetchCafes, fetchCities, MatchEvent } from '../services/campaignApi'
import { useMatchEvents } from '../hooks/useMatchEvents'
import { formatMatchLabel } from '../utils/matchCountdown'
import { formatPersianNumber } from '../utils/formatNumber'
function findTehran(cities: City[]): City | undefined {
return cities.find((c) => c.city_name === 'تهران' || c.city_name.toLowerCase() === 'tehran')
}
function MapIcon() {
return (
)
}
function ListIcon() {
return (
)
}
function CafesMapPreview({ cafes }: { cafes: Cafe[] }) {
const navigate = useNavigate()
const center: [number, number] =
cafes.length > 0
? [cafes[0].location.coordinates[1], cafes[0].location.coordinates[0]]
: [35.6892, 51.389]
return (
{cafes.map((cafe) => (
))}
{/* transparent overlay — captures all clicks and opens the full-page map */}
navigate('/map', { state: { cafes } })}
/>
)
}
function CitySelectorRow({
label,
value,
options,
onChange,
}: {
label: string
value: string
options: City[]
onChange: (uuid: string) => void
}) {
const [open, setOpen] = useState(false)
const selectedCity = options.find((city) => city.uuid === value)
return (
{label}
{open && (
<>
setOpen(false)} />
{options.map((city) => (
))}
>
)}
)
}
function MatchSelectorRow({
label,
value,
options,
now,
onChange,
}: {
label: string
value: string
options: MatchEvent[]
now: Date
onChange: (uuid: string) => void
}) {
const [open, setOpen] = useState(false)
const selectedMatch = options.find((match) => match.uuid === value)
const hasMatches = options.length > 0
return (
{label}
{open && hasMatches && (
<>
setOpen(false)} />
{options.map((match) => (
))}
>
)}
)
}
function MyReservationsRow() {
const navigate = useNavigate()
return (
)
}
function CafeCard({ cafe }: { cafe: Cafe }) {
const navigate = useNavigate()
const remainingTickets = cafe.schedules?.[0]?.remaining_tickets
return (
)
}
export default function Home() {
const [view, setView] = useState<'list' | 'map'>('list')
const [cities, setCities] = useState
([])
const [selectedCityUuid, setSelectedCityUuid] = useState('')
const [selectedMatchUuid, setSelectedMatchUuid] = useState('')
const { matches, now } = useMatchEvents()
const [cafes, setCafes] = useState([])
const nearestMatch = [...matches].sort(
(a, b) => new Date(a.match_datetime).getTime() - new Date(b.match_datetime).getTime(),
)[0]
// defaults to Tehran + the nearest upcoming match, but the user can override either
const effectiveCityUuid = selectedCityUuid || findTehran(cities)?.uuid || ''
const effectiveMatchUuid = selectedMatchUuid || nearestMatch?.uuid || ''
useEffect(() => {
fetchCities()
.then(setCities)
.catch(() => {})
}, [])
useEffect(() => {
// wait until both real defaults are known — city_uuid/event_id must always be sent together
if (!effectiveCityUuid || !effectiveMatchUuid) return
fetchCafes({ city_uuid: effectiveCityUuid, event_id: effectiveMatchUuid })
.then(setCafes)
.catch(() => {})
}, [effectiveCityUuid, effectiveMatchUuid])
return (
کافهها
{view === 'map' ? (
) : (
{cafes.map((cafe) => (
))}
)}
)
}