"use client"; /** * TEE OFF SYSTEM INSTRUCTIONS - FACILITY CARDS v3.6 (STABLE) * --------------------------------------------------------------------------- * REGEL 1: Status-badge SKAL vises øverst til venstre FOR ALLE BANER. * Bruk STATUS_MAP for tekst. * REGEL 2: DATA-PARSING: Bruk parseJson() for 'course_statuses', 'amenities' og 'nsg_data' * fordi API-et ofte returnerer disse som strenger. * REGEL 3: Avstand-pillen skal ha fargen #2d3319 (Mørk oliven) med hvit tekst. * REGEL 4: NSG (Blå 'N') og Golfamore (Oransje 'G') sirkler skal ha hvit kant (border-2). * REGEL 5: Bunnen: Antall Hull (grønn pill), Banetype (grå pill), og Ikon-sirkler. * REGEL 6: Viser dato (f.eks "05. mars 2026") rett til høyre for øverste status-pille. * Datoen har en svak bakgrunnsfarge for å sikre lesbarhet på lys bakgrunn. * --------------------------------------------------------------------------- */ import { STATUS_MAP } from "@/config/constants"; import { useState, useEffect, useMemo } from 'react'; import Link from 'next/link'; function getDistance(lat1: number, lon1: number, lat2: number, lon2: number) { try { const R = 6371; const dLat = (lat2 - lat1) * Math.PI / 180; const dLon = (lon2 - lon1) * Math.PI / 180; const a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) * Math.sin(dLon/2) * Math.sin(dLon/2); return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); } catch (e) { return Infinity; } } export default function FacilitySearch({ initialFacilities }: { initialFacilities: any[] }) { const [searchQuery, setSearchQuery] = useState(""); const [userLocation, setUserLocation] = useState<{ lat: number, lng: number } | null>(null); const [sortMethod, setSortMethod] = useState<'dist' | 'alpha'>('alpha'); useEffect(() => { if ("geolocation" in navigator) { navigator.geolocation.getCurrentPosition(p => { setUserLocation({ lat: p.coords.latitude, lng: p.coords.longitude }); setSortMethod('dist'); }); } }, []); const processed = useMemo(() => { if (!Array.isArray(initialFacilities)) return []; return initialFacilities.map(f => { // --- ROBUST DATA-PARSING (Håndterer tekst vs objekt fra API) --- const parseJson = (val: any, fallback: any) => { if (!val) return fallback; if (typeof val === 'object') return val; try { return JSON.parse(val); } catch (e) { return fallback; } }; const statuses = parseJson(f.course_statuses, []); const amenities = parseJson(f.amenities, {}); const nsgData = parseJson(f.nsg_data, {}); const dist = userLocation && f.lat && f.lng ? getDistance(userLocation.lat, userLocation.lng, f.lat, f.lng) : Infinity; const hasNSG = nsgData && Object.keys(nsgData).length > 0; const hasGolfamore = f.golfamore === true; const words = searchQuery.toLowerCase().trim().split(/\s+/).filter(w => w.length > 0); const blob = `${f.name} ${f.city} ${f.county}`.toLowerCase(); const matches = words.every(w => blob.includes(w)); return { ...f, statuses, amenities, dist, hasNSG, hasGolfamore, matches }; }) .filter(f => f.matches) .sort((a, b) => { if (sortMethod === 'dist' && a.dist !== b.dist) return a.dist - b.dist; return a.name.localeCompare(b.name, 'nb'); }); }, [searchQuery, initialFacilities, userLocation, sortMethod]); return (
{f.city} • {f.county}