Public Access
1
0

feat: add deep research planning and postal batch runs

Add a dedicated Deep Research view with postal-area preview overlays, batch execution, and bundled map results.

Also add postal dataset import tooling and fix local API networking and research insert issues needed to support the new workflow.
This commit is contained in:
pguerrerox
2026-04-05 18:05:04 +00:00
parent a1ba5ee093
commit cc00a439bf
29 changed files with 1860 additions and 82 deletions
+26 -19
View File
@@ -1,7 +1,8 @@
import { type ReactElement, type SVGProps, useEffect, useState } from 'react';
import { APIProvider } from '@vis.gl/react-google-maps';
import { AlertCircle, Briefcase, LogIn, ShieldAlert, UserPlus } from 'lucide-react';
import { Layout } from './components/Layout';
import { DeepResearchView } from './components/DeepResearchView';
import { Layout, type AppTab } from './components/Layout';
import { SearchSetup } from './components/SearchSetup';
import { Dashboard } from './components/Dashboard';
import { MapView } from './components/MapView';
@@ -15,7 +16,7 @@ const hasValidMapsKey = Boolean(GOOGLE_MAPS_API_KEY) && GOOGLE_MAPS_API_KEY !==
export default function App() {
const [user, setUser] = useState<AppUser | null>(null);
const [loading, setLoading] = useState(true);
const [activeTab, setActiveTab] = useState<'setup' | 'dashboard' | 'map'>('setup');
const [activeTab, setActiveTab] = useState<AppTab>('setup');
const [selectedJobIds, setSelectedJobIds] = useState<string[]>([]);
const [authError, setAuthError] = useState<string | null>(null);
const [authNotice, setAuthNotice] = useState<string | null>(null);
@@ -79,6 +80,11 @@ export default function App() {
setSelectedJobIds([]);
};
const handleShowJobIdsOnMap = (jobIds: string[]) => {
setSelectedJobIds(jobIds);
setActiveTab('map');
};
const handleLogin = async () => {
setAuthError(null);
setAuthNotice(null);
@@ -146,23 +152,6 @@ export default function App() {
);
}
if (!hasValidMapsKey) {
return (
<ConfigScreen
icon={<MapIcon className="h-8 w-8" />}
title="Google Maps API Key Required"
description="Add a browser key for map rendering and a server key for the local search API."
steps={[
'Create a Google Maps Platform API key for the browser app.',
'Set VITE_GOOGLE_MAPS_PLATFORM_KEY locally for the frontend.',
'Set GOOGLE_MAPS_SERVER_KEY for the local API server.',
'Enable Geocoding API and Places API in Google Cloud.',
]}
footer="The app will start once the browser key is available."
/>
);
}
if (!user) {
return (
<div className="flex h-screen flex-col items-center justify-center bg-stone-50 p-4">
@@ -291,6 +280,23 @@ export default function App() {
);
}
if (!hasValidMapsKey) {
return (
<ConfigScreen
icon={<MapIcon className="h-8 w-8" />}
title="Google Maps API Key Required"
description="Add a browser key for map rendering and a server key for the local search API."
steps={[
'Create a Google Maps Platform API key for the browser app.',
'Set VITE_GOOGLE_MAPS_PLATFORM_KEY locally for the frontend.',
'Set GOOGLE_MAPS_SERVER_KEY for the local API server.',
'Enable Geocoding API and Places API in Google Cloud.',
]}
footer="You can create a local account without the maps key, but the workspace needs it before loading."
/>
);
}
return (
<APIProvider apiKey={GOOGLE_MAPS_API_KEY} version="weekly">
<Layout
@@ -309,6 +315,7 @@ export default function App() {
onClearSelection={handleClearSelectedJobs}
/>
)}
{activeTab === 'deepResearch' && <DeepResearchView onShowBatchOnMap={handleShowJobIdsOnMap} />}
{activeTab === 'dashboard' && <Dashboard user={user} />}
{activeTab === 'map' && <MapView user={user} jobIds={selectedJobIds} />}
</Layout>