/** * Map Actions Context * Coordinates actions across all map contexts * Provides a unified interface for map operations * Separated from MapContexts.tsx for better SRP */ import { createContext, ReactNode, useCallback, useContext } from 'react'; import { useNavigate } from 'react-router-dom'; import { useGetWebIntelligence } from '@/hooks/useGemini.ts'; import { useTranslation } from '@/hooks/useI18n.tsx'; import type { HistoricalLandmark } from '@/schemas/historical.ts'; import { analyzeSymbiosis } from '@/services/aiService.ts'; import type { Organization } from '@/types.ts'; import { useMapFilter } from '@/contexts/MapFilterContext.tsx'; import { useMapInteraction } from '@/contexts/MapInteractionContext.tsx'; import { useMapUI } from '@/contexts/MapUIContext.tsx'; import { useMapViewport } from '@/contexts/MapViewportContext.tsx'; interface MapActionsContextType { // Organization actions handleAddOrganization: () => void; handleViewOrganization: (org: Organization) => void; handleSelectOrg: (org: Organization | null) => void; handleSelectLandmark: (landmark: HistoricalLandmark | null) => void; // Navigation actions handleMapNavigation: () => void; // AI actions handleAnalyzeSymbiosis: () => void; handleFetchWebIntelligence: () => void; // Composite actions resetMapState: () => void; } const MapActionsContext = createContext(undefined); export const useMapActions = () => { const context = useContext(MapActionsContext); if (context === undefined) { throw new Error('useMapActions must be used within a MapActionsProvider'); } return context; }; interface MapActionsProviderProps { children: ReactNode; } export const MapActionsProvider = ({ children }: MapActionsProviderProps) => { const navigate = useNavigate(); const { t } = useTranslation(); // Use all the focused contexts const viewport = useMapViewport(); const interaction = useMapInteraction(); const filter = useMapFilter(); const ui = useMapUI(); // Web intelligence hook const { refetch: fetchWebIntelligence } = useGetWebIntelligence( interaction.selectedOrg?.Name, t ); const handleAddOrganization = useCallback(() => { // Could navigate to add organization page or open modal navigate('/add-organization'); }, [navigate]); const handleViewOrganization = useCallback( (org: Organization) => { navigate(`/organization/${org.ID}`); }, [navigate] ); const handleSelectOrg = useCallback( (org: Organization | null) => { interaction.handleSelectOrg(org); // Open sidebar to show organization details when an org is selected if (org) { ui.setIsSidebarOpen(true); } }, [interaction, ui] ); const handleSelectLandmark = useCallback( (landmark: HistoricalLandmark | null) => { interaction.handleSelectLandmark(landmark); // Open sidebar to show landmark details when a landmark is selected if (landmark) { ui.setIsSidebarOpen(true); } }, [interaction, ui] ); const handleMapNavigation = useCallback(() => { navigate('/map'); }, [navigate]); const handleAnalyzeSymbiosis = useCallback(async () => { if (!interaction.selectedOrg) return; try { interaction.setIsAnalyzing(true); interaction.setAnalysisError(null); const result = await analyzeSymbiosis(interaction.selectedOrg, []); interaction.setSymbiosisResult(result); } catch (error) { interaction.setAnalysisError(error instanceof Error ? error.message : 'Analysis failed'); } finally { interaction.setIsAnalyzing(false); } }, [interaction, analyzeSymbiosis]); const handleFetchWebIntelligence = useCallback(async () => { if (!interaction.selectedOrg?.Name) return; try { interaction.setIsFetchingWebIntel(true); interaction.setWebIntelError(null); const result = await fetchWebIntelligence(); if (result.data) { interaction.setWebIntelResult(result.data); } } catch (error) { interaction.setWebIntelError( error instanceof Error ? error.message : 'Web intelligence failed' ); } finally { interaction.setIsFetchingWebIntel(false); } }, [interaction, fetchWebIntelligence]); const resetMapState = useCallback(() => { // Reset viewport viewport.resetView(); // Clear interactions interaction.handleSelectOrg(null); interaction.handleSelectLandmark(null); interaction.clearAnalysisResults(); // Clear filters filter.clearFilters(); // Close sidebar ui.closeSidebar(); }, [viewport, interaction, filter, ui]); const value: MapActionsContextType = { handleAddOrganization, handleViewOrganization, handleSelectOrg, handleSelectLandmark, handleMapNavigation, handleAnalyzeSymbiosis, handleFetchWebIntelligence, resetMapState, }; return {children}; };