import React, { useState } from 'react'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Plus, Search, Map } from 'lucide-react'; import { toast } from 'sonner'; import GeoStats from './GeoStats'; import ClusterCard from './ClusterCard'; import GeoMap from './GeoMap'; // Client-side API fetcher (no Directus client needed) async function fetchGeoData(collection: string) { const res = await fetch(`/api/directus/${collection}`); if (!res.ok) throw new Error('Failed to fetch'); return res.json(); } export default function GeoIntelligenceManager() { const queryClient = useQueryClient(); const [search, setSearch] = useState(''); const [showMap, setShowMap] = useState(true); // 1. Fetch Data via API (not Directus client) const { data: clusters = [], isLoading: isLoadingClusters } = useQuery({ queryKey: ['geo_clusters'], queryFn: () => fetchGeoData('geo_clusters') }); const { data: locations = [], isLoading: isLoadingLocations } = useQuery({ queryKey: ['geo_locations'], queryFn: () => fetchGeoData('geo_locations') }); // 2. Mutations const deleteMutation = useMutation({ mutationFn: async (id: string) => { const res = await fetch(`/api/directus/geo_clusters/${id}`, { method: 'DELETE' }); if (!res.ok) throw new Error('Delete failed'); }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['geo_clusters'] }); toast.success('Cluster deleted'); }, onError: (err: any) => toast.error(err.message) }); const handleDelete = (id: string) => { if (confirm('Delete this cluster and all its locations?')) { deleteMutation.mutate(id); } }; // 3. Filter const filteredClusters = clusters.filter((c: any) => c.name.toLowerCase().includes(search.toLowerCase()) || c.state?.toLowerCase().includes(search.toLowerCase()) ); const filteredLocations = locations.filter((l: any) => l.city?.toLowerCase().includes(search.toLowerCase()) || l.zip?.includes(search) ); // Combine locations for map (either all if no search, or filtered) const mapLocations = search ? filteredLocations : locations; if (isLoadingClusters || isLoadingLocations) { return
Loading Geospatial Data...
; } return (
{/* Left Column: List */}
setSearch(e.target.value)} className="pl-9 bg-zinc-950 border-zinc-800" />
{filteredClusters.map((cluster: any) => ( console.log('Edit', id)} onDelete={handleDelete} onTarget={(id) => toast.info(`Targeting ${cluster.name} for content`)} /> ))}
{/* Right Column: Map */}
{showMap && (
{/* Client-side only rendering for map is handled inside GeoMap/Astro usually, but since this is React component loaded via client:load, it mounts in browser. */}
)} {!showMap && (
Map view hidden
)}
); }