import { useEffect, useState } from 'react' import { useNavigate } from 'react-router-dom' import { Panel } from '../ui/Panel' import { useMapLibreMap } from '../maplibre/maplibreContext' import { useChallengeStore } from '../store/challengeStore' import { fetchChallengeDetail, participateInChallenge } from '../api/challenges' import type { ChallengeDetail } from '../types/api' import styles from './ChallengePanel.module.css' export function ChallengePanel() { const map = useMapLibreMap() const navigate = useNavigate() const { selectedChallengeId, setSelectedChallengeId } = useChallengeStore() const [detail, setDetail] = useState(null) const [participating, setParticipating] = useState(false) useEffect(() => { if (!selectedChallengeId) { setDetail(null) return } fetchChallengeDetail(selectedChallengeId) .then((d) => { setDetail(d) setParticipating(d.is_participating) }) .catch(console.error) }, [selectedChallengeId]) function handleCenterMap() { if (!detail?.region_centroid) return const [lon, lat] = detail.region_centroid.coordinates map.flyTo({ center: [lon, lat], zoom: 14, pitch: 50, duration: 1500 }) } async function handleParticipate() { if (!selectedChallengeId) return await participateInChallenge(selectedChallengeId) setParticipating(true) } return ( setSelectedChallengeId(null)} title={detail?.title ?? 'Challenge'} > {!detail ? (

Loading…

) : (
{detail.description && (

{detail.description}

)}
Created by
{detail.creator_username}
Submissions
{detail.submission_count} {detail.max_submissions ? ` / ${detail.max_submissions}` : ''}
{detail.expires_at && ( <>
Expires
{new Date(detail.expires_at).toLocaleDateString()}
)}
{detail.status === 'active' && !participating && ( )} {participating && (

You've accepted this challenge

)} {detail.preview_splats.length > 0 && (

Submissions

{detail.preview_splats.map((s) => (
{s.preview_url ? ( Splat preview ) : (
3D
)}
))}
)}
)}
) }