"use client"; import React, { useState, useEffect, useCallback } from "react"; import { GoogleMap, useLoadScript, Marker, InfoWindow } from "@react-google-maps/api"; import Link from "next/link"; import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/Card"; import { Button } from "@/components/ui/Button"; interface Activity { id: string; title: string; description: string | null; sportType: string; date: string; duration: number; maxParticipants: number; currentParticipants: number; location: string; locationName: string | null; latitude: number; longitude: number; price: number; organizer: { id: string; name: string; image: string | null; }; } const sportTypeLabels: Record = { FOOTBALL: "⚽ Futbal", BASKETBALL: "🏀 Basketbal", TENNIS: "🎾 Tenis", VOLLEYBALL: "🏐 Volejbal", BADMINTON: "🏸 Bedminton", TABLE_TENNIS: "🏓 Stolný tenis", RUNNING: "🏃 Beh", CYCLING: "🚴 Cyklistika", SWIMMING: "🏊 Plávanie", GYM: "💪 Posilňovňa", OTHER: "🎯 Iné", }; const mapContainerStyle = { width: "100%", height: "calc(100vh - 120px)", }; const defaultCenter = { lat: 48.1486, // Bratislava lng: 17.1077, }; export default function VenuesPage() { const { isLoaded, loadError } = useLoadScript({ googleMapsApiKey: process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY || "", }); const [activities, setActivities] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(""); const [selectedActivity, setSelectedActivity] = useState(null); const [userLocation, setUserLocation] = useState<{ lat: number; lng: number } | null>(null); const [mapCenter, setMapCenter] = useState(defaultCenter); useEffect(() => { fetchActivities(); getUserLocation(); }, []); const getUserLocation = () => { if (navigator.geolocation) { navigator.geolocation.getCurrentPosition( (position) => { const location = { lat: position.coords.latitude, lng: position.coords.longitude, }; setUserLocation(location); setMapCenter(location); }, (error) => { console.error("Error getting location:", error); } ); } }; const fetchActivities = async () => { try { const response = await fetch( `${process.env.NEXT_PUBLIC_API_URL}/api/activities?status=OPEN` ); if (!response.ok) { throw new Error("Chyba pri načítaní aktivít"); } const data = await response.json(); // Filter activities that have coordinates const activitiesWithCoords = data.filter( (a: Activity) => a.latitude != null && a.longitude != null ); setActivities(activitiesWithCoords); } catch (err: any) { setError(err.message); } finally { setLoading(false); } }; const onMarkerClick = useCallback((activity: Activity) => { setSelectedActivity(activity); }, []); const onInfoWindowClose = useCallback(() => { setSelectedActivity(null); }, []); if (loading) { return (

Načítavam...

); } if (loadError) { return (

Chyba pri načítaní mapy

); } if (!isLoaded) { return (

Načítavam mapu...

); } if (error) { return (

{error}

); } return (
{/* Header */}

Mapa aktivít

{activities.length} aktivít v tvojom okolí

{/* Map */} {/* User location marker */} {userLocation && ( )} {/* Activity markers */} {activities.map((activity) => ( onMarkerClick(activity)} icon={{ url: getMarkerIcon(activity.sportType), scaledSize: { width: 40, height: 40 } as google.maps.Size, }} title={activity.title} /> ))} {/* Info Window */} {selectedActivity && (

{selectedActivity.title}

{sportTypeLabels[selectedActivity.sportType] || selectedActivity.sportType}

{new Date(selectedActivity.date).toLocaleDateString("sk-SK", { day: "numeric", month: "short", year: "numeric", })}{" "} o{" "} {new Date(selectedActivity.date).toLocaleTimeString("sk-SK", { hour: "2-digit", minute: "2-digit", })}

{selectedActivity.currentParticipants}/{selectedActivity.maxParticipants} účastníkov

📍 {selectedActivity.locationName || selectedActivity.location}

{selectedActivity.price > 0 && (

{selectedActivity.price} €

)}
)}
{/* Legend */} Legenda
Tvoja poloha
{Object.entries(sportTypeLabels).map(([key, label]) => (
{label.split(" ")[0]} {label.split(" ").slice(1).join(" ")}
))}
); } // Helper function to get marker icon based on sport type function getMarkerIcon(sportType: string): string { // Using emoji as markers - you can replace with custom icons const icons: Record = { FOOTBALL: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40'%3E%3Ctext x='50%25' y='50%25' font-size='30' text-anchor='middle' dominant-baseline='central'%3E⚽%3C/text%3E%3C/svg%3E", BASKETBALL: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40'%3E%3Ctext x='50%25' y='50%25' font-size='30' text-anchor='middle' dominant-baseline='central'%3E🏀%3C/text%3E%3C/svg%3E", TENNIS: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40'%3E%3Ctext x='50%25' y='50%25' font-size='30' text-anchor='middle' dominant-baseline='central'%3E🎾%3C/text%3E%3C/svg%3E", VOLLEYBALL: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40'%3E%3Ctext x='50%25' y='50%25' font-size='30' text-anchor='middle' dominant-baseline='central'%3E🏐%3C/text%3E%3C/svg%3E", BADMINTON: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40'%3E%3Ctext x='50%25' y='50%25' font-size='30' text-anchor='middle' dominant-baseline='central'%3E🏸%3C/text%3E%3C/svg%3E", TABLE_TENNIS: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40'%3E%3Ctext x='50%25' y='50%25' font-size='30' text-anchor='middle' dominant-baseline='central'%3E🏓%3C/text%3E%3C/svg%3E", RUNNING: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40'%3E%3Ctext x='50%25' y='50%25' font-size='30' text-anchor='middle' dominant-baseline='central'%3E🏃%3C/text%3E%3C/svg%3E", CYCLING: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40'%3E%3Ctext x='50%25' y='50%25' font-size='30' text-anchor='middle' dominant-baseline='central'%3E🚴%3C/text%3E%3C/svg%3E", SWIMMING: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40'%3E%3Ctext x='50%25' y='50%25' font-size='30' text-anchor='middle' dominant-baseline='central'%3E🏊%3C/text%3E%3C/svg%3E", GYM: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40'%3E%3Ctext x='50%25' y='50%25' font-size='30' text-anchor='middle' dominant-baseline='central'%3E💪%3C/text%3E%3C/svg%3E", OTHER: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40'%3E%3Ctext x='50%25' y='50%25' font-size='30' text-anchor='middle' dominant-baseline='central'%3E🎯%3C/text%3E%3C/svg%3E", }; return icons[sportType] || icons.OTHER; }