From 4fc41f2eebbe4057158b6467da54511c651ba90e Mon Sep 17 00:00:00 2001 From: Babayaga Date: Thu, 26 Mar 2026 00:44:56 +0100 Subject: [PATCH] Maintenance Love :) --- .../src/modules/places/client-gridsearch.ts | 57 +++++++++++++++++++ .../gridsearch/CompetitorsReportView.tsx | 4 +- .../places/gridsearch/GridSearchWizard.tsx | 4 +- .../modules/places/gridsearch/JobViewer.tsx | 10 +++- .../places/gridsearch/OngoingSearches.tsx | 8 +-- .../gridsearch/RestoredSearchContext.tsx | 4 +- 6 files changed, 75 insertions(+), 12 deletions(-) diff --git a/packages/ui/src/modules/places/client-gridsearch.ts b/packages/ui/src/modules/places/client-gridsearch.ts index ce869fe6..aed410d9 100644 --- a/packages/ui/src/modules/places/client-gridsearch.ts +++ b/packages/ui/src/modules/places/client-gridsearch.ts @@ -198,3 +198,60 @@ export const fetchGridSearchExport = async (jobId: string, format: 'md' | 'json' if (!res.ok) throw new Error(`Failed to load report: ${res.statusText}`); return await res.text(); }; + +// --- Places GridSearch API Methods (New C++ backend) --- + +export const fetchPlacesGridSearches = async (): Promise => { + const headers = await getAuthHeaders(); + const res = await fetch(`${serverUrl}/api/places/gridsearch`, { headers }); + if (!res.ok) throw new Error(`Failed to fetch places grid searches: ${res.statusText}`); + const json = await res.json(); + return json.data || []; +}; + +export const fetchPlacesGridSearchById = async (id: string): Promise => { + const cacheKey = `places-gridsearch-id-${id}`; + return fetchWithDeduplication(cacheKey, async () => { + const headers = await getAuthHeaders(); + const res = await fetch(`${serverUrl}/api/places/gridsearch/${id}`, { headers }); + if (!res.ok) throw new Error(`Failed to fetch places grid search result: ${res.statusText}`); + const json = await res.json(); + return json.data; + }, 60000 * 5); +}; + +export const fetchPlacesGridSearchRunState = async (id: string): Promise => { + const headers = await getAuthHeaders(); + const res = await fetch(`${serverUrl}/api/places/gridsearch/${id}/state`, { headers }); + if (!res.ok) throw new Error(`Failed to fetch run state: ${res.statusText}`); + const json = await res.json(); + return json.data; +}; + +export const submitPlacesGridSearchJob = async (payload: GridSearchJobPayload): Promise<{ message: string; jobId: string }> => { + const headers = await getAuthHeaders(); + const res = await fetch(`${serverUrl}/api/places/gridsearch`, { + method: 'POST', + headers, + body: JSON.stringify(payload) + }); + if (!res.ok) throw new Error(`Failed to submit places grid search job: ${res.statusText}`); + return await res.json(); +}; + +export const deletePlacesGridSearch = async (id: string): Promise => { + // We will just call the old locations route for deletion to keep it simple, + // since both manipulate the exact same Postgres table (grid_search_runs). + return deleteGridSearch(id); +}; + +export const getPlacesGridSearchStreamUrl = (jobId: string, token?: string): string => { + // If not implemented in places, fallback to locations or just use the same URL format + const url = `${serverUrl}/api/places/gridsearch/${jobId}/stream`; + return token ? `${url}?token=${token}` : url; +}; + +export const fetchPlacesGridSearchExport = async (jobId: string, format: 'md' | 'json' = 'md'): Promise => { + // If not implemented in places, fallback to locations export since they share the database + return fetchGridSearchExport(jobId, format); +}; diff --git a/packages/ui/src/modules/places/gridsearch/CompetitorsReportView.tsx b/packages/ui/src/modules/places/gridsearch/CompetitorsReportView.tsx index c9b1c652..3b414ca9 100644 --- a/packages/ui/src/modules/places/gridsearch/CompetitorsReportView.tsx +++ b/packages/ui/src/modules/places/gridsearch/CompetitorsReportView.tsx @@ -1,7 +1,7 @@ import React, { useState, useEffect } from 'react'; import { Loader2, AlertCircle, Download } from 'lucide-react'; import MarkdownRenderer from '@/components/MarkdownRenderer'; -import { fetchGridSearchExport } from '../client-gridsearch'; +import { fetchPlacesGridSearchExport } from '../client-gridsearch'; export function CompetitorsReportView({ jobId }: { jobId: string }) { const [markdown, setMarkdown] = useState(null); @@ -17,7 +17,7 @@ export function CompetitorsReportView({ jobId }: { jobId: string }) { setLoading(true); setError(null); - const text = await fetchGridSearchExport(jobId, 'md'); + const text = await fetchPlacesGridSearchExport(jobId, 'md'); if (active) { setMarkdown(text); diff --git a/packages/ui/src/modules/places/gridsearch/GridSearchWizard.tsx b/packages/ui/src/modules/places/gridsearch/GridSearchWizard.tsx index 065edaee..8b08a9cf 100644 --- a/packages/ui/src/modules/places/gridsearch/GridSearchWizard.tsx +++ b/packages/ui/src/modules/places/gridsearch/GridSearchWizard.tsx @@ -1,6 +1,6 @@ import React, { useState, useEffect, useRef } from 'react'; import { Loader2, Search, MapPin, CheckCircle, ChevronRight, ChevronLeft } from 'lucide-react'; -import { previewGridSearch, submitGridSearchJob, addActiveGridSearchJob } from '../client-gridsearch'; +import { previewGridSearch, submitPlacesGridSearchJob, addActiveGridSearchJob } from '../client-gridsearch'; import { searchGadmRegions } from '../client-searches'; import { CompetitorsGridView } from '../CompetitorsGridView'; @@ -96,7 +96,7 @@ export function GridSearchWizard({ onJobSubmitted }: { onJobSubmitted: (jobId: s setSubmitting(true); setError(''); try { - const res = await submitGridSearchJob({ + const res = await submitPlacesGridSearchJob({ region: selectedRegionName, types: [searchQuery], level, diff --git a/packages/ui/src/modules/places/gridsearch/JobViewer.tsx b/packages/ui/src/modules/places/gridsearch/JobViewer.tsx index ef58f5ce..557c4ec6 100644 --- a/packages/ui/src/modules/places/gridsearch/JobViewer.tsx +++ b/packages/ui/src/modules/places/gridsearch/JobViewer.tsx @@ -1,6 +1,6 @@ import React, { useState, useEffect } from 'react'; import { Loader2, AlertCircle, Plus, Lock, MapPin } from 'lucide-react'; -import { fetchGridSearchById } from '../client-gridsearch'; +import { fetchPlacesGridSearchById } from '../client-gridsearch'; import { GridSearchResults } from './GridSearchResults'; import { useSearchParams, useNavigate } from 'react-router-dom'; import { useRestoredSearch } from './RestoredSearchContext'; @@ -28,7 +28,7 @@ export function JobViewer({ jobId }: { jobId: string }) { try { setLoading(true); setError(null); - const data = await fetchGridSearchById(jobId); + const data = await fetchPlacesGridSearchById(jobId); console.log(`job results`, data); if (!active) return; @@ -92,6 +92,12 @@ export function JobViewer({ jobId }: { jobId: string }) { const allResults = jobData?.result?.searchResult?.results || competitors; const foundTypes = Array.from(new Set(allResults.flatMap((r: any) => r.types || []).filter(Boolean))).sort() as string[]; + console.log(`foundTypes`, foundTypes); + console.log(`allResults`, allResults); + console.log(`jobData`, jobData); + console.log('guidedAreas', guidedAreas); + console.log('searchSettings', searchSettings); + console.log('searchQuery', searchQuery); return (
diff --git a/packages/ui/src/modules/places/gridsearch/OngoingSearches.tsx b/packages/ui/src/modules/places/gridsearch/OngoingSearches.tsx index bd49c4f2..dfebe9b4 100644 --- a/packages/ui/src/modules/places/gridsearch/OngoingSearches.tsx +++ b/packages/ui/src/modules/places/gridsearch/OngoingSearches.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useState } from 'react'; -import { getActiveGridSearchJobs, removeActiveGridSearchJob, getGridSearchStreamUrl, fetchGridSearches, deleteGridSearch, GridSearchSummary } from '../client-gridsearch'; +import { getActiveGridSearchJobs, removeActiveGridSearchJob, getPlacesGridSearchStreamUrl, fetchPlacesGridSearches, deletePlacesGridSearch, GridSearchSummary } from '../client-gridsearch'; import { supabase } from '@/integrations/supabase/client'; import { Loader2, XCircle, CheckCircle, Search, ChevronRight, Trash2 } from 'lucide-react'; @@ -19,7 +19,7 @@ const ActiveJobItem = ({ jobId, onSelectJob }: { jobId: string, onSelectJob?: (j if (!isSubscribed) return; - const url = getGridSearchStreamUrl(jobId, token); + const url = getPlacesGridSearchStreamUrl(jobId, token); es = new EventSource(url); es.addEventListener('progress', (e) => { @@ -117,7 +117,7 @@ export const OngoingSearches = ({ onSelectJob, selectedJobId, onSearchDeleted }: const loadPast = async () => { try { - const history = await fetchGridSearches(); + const history = await fetchPlacesGridSearches(); setPastSearches(history); } catch (err) { console.error('Failed to load past searches', err); @@ -190,7 +190,7 @@ export const OngoingSearches = ({ onSelectJob, selectedJobId, onSearchDeleted }: e.stopPropagation(); if (confirm('Are you sure you want to delete this search?')) { try { - await deleteGridSearch(search.id); + await deletePlacesGridSearch(search.id); setPastSearches(prev => prev.filter(s => s.id !== search.id)); if (onSearchDeleted) onSearchDeleted(search.id); } catch (err) { diff --git a/packages/ui/src/modules/places/gridsearch/RestoredSearchContext.tsx b/packages/ui/src/modules/places/gridsearch/RestoredSearchContext.tsx index bdc55172..10ac43bc 100644 --- a/packages/ui/src/modules/places/gridsearch/RestoredSearchContext.tsx +++ b/packages/ui/src/modules/places/gridsearch/RestoredSearchContext.tsx @@ -1,5 +1,5 @@ import React, { createContext, useContext, useState, useEffect, useCallback } from 'react'; -import { fetchGridSearchRunState, RestoredRunState } from '../client-gridsearch'; +import { fetchPlacesGridSearchRunState, RestoredRunState } from '../client-gridsearch'; interface RestoredSearchContextValue { /** The loaded run state, null until fetched */ @@ -42,7 +42,7 @@ export function RestoredSearchProvider({ setLoading(true); setError(null); try { - const data = await fetchGridSearchRunState(id); + const data = await fetchPlacesGridSearchRunState(id); setState(data); } catch (err: any) { setError(err.message || 'Failed to load run state');