From 2fc78cbde584d6578917a3f1626a2f1a0419e8fb Mon Sep 17 00:00:00 2001 From: pac7 <47831526-pac7@users.noreply.replit.com> Date: Wed, 8 Oct 2025 12:23:22 +0000 Subject: [PATCH] Improve error handling and dependency checks for data processing Address issues in FieldHistoryDialog by clearing changes on error, enhance useEntityVersions to provide default profiles for missing users, add localStorage availability check in useLocationAutoDetect, and improve dependency resolution logic in supabase/functions/process-selective-approval. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 334e80ad-8f74-4e3a-acec-6dd811858e98 Replit-Commit-Checkpoint-Type: intermediate_checkpoint --- .../versioning/FieldHistoryDialog.tsx | 1 + src/hooks/useEntityVersions.ts | 14 +++++++--- src/hooks/useLocationAutoDetect.ts | 28 +++++++++++++++++-- .../process-selective-approval/index.ts | 5 ++-- 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/components/versioning/FieldHistoryDialog.tsx b/src/components/versioning/FieldHistoryDialog.tsx index 5fc21ae1..f0161118 100644 --- a/src/components/versioning/FieldHistoryDialog.tsx +++ b/src/components/versioning/FieldHistoryDialog.tsx @@ -88,6 +88,7 @@ export function FieldHistoryDialog({ setChanges(mergedData as FieldChange[]); } catch (error) { console.error('Error fetching field history:', error); + setChanges([]); } finally { setLoading(false); } diff --git a/src/hooks/useEntityVersions.ts b/src/hooks/useEntityVersions.ts index e94727e7..17c8a4c1 100644 --- a/src/hooks/useEntityVersions.ts +++ b/src/hooks/useEntityVersions.ts @@ -65,10 +65,16 @@ export function useEntityVersions(entityType: string, entityId: string) { .select('user_id, username, avatar_url') .in('user_id', userIds); - const versionsWithProfiles = data?.map(v => ({ - ...v, - changer_profile: profiles?.find(p => p.user_id === v.changed_by) - })) as EntityVersion[]; + const versionsWithProfiles = data?.map(v => { + const profile = profiles?.find(p => p.user_id === v.changed_by); + return { + ...v, + changer_profile: profile || { + username: 'Unknown', + avatar_url: null + } + }; + }) as EntityVersion[]; // Only update state if component is still mounted if (isMountedRef.current) { diff --git a/src/hooks/useLocationAutoDetect.ts b/src/hooks/useLocationAutoDetect.ts index 6da98f56..0e3f5d65 100644 --- a/src/hooks/useLocationAutoDetect.ts +++ b/src/hooks/useLocationAutoDetect.ts @@ -2,6 +2,20 @@ import { useEffect } from 'react'; import { useAuth } from '@/hooks/useAuth'; import { useUnitPreferences } from '@/hooks/useUnitPreferences'; +function isLocalStorageAvailable(): boolean { + try { + if (typeof window === 'undefined' || typeof localStorage === 'undefined') { + return false; + } + const testKey = '__localStorage_test__'; + localStorage.setItem(testKey, 'test'); + localStorage.removeItem(testKey); + return true; + } catch { + return false; + } +} + export function useLocationAutoDetect() { const { user } = useAuth(); const { preferences, autoDetectPreferences, loading } = useUnitPreferences(); @@ -10,16 +24,26 @@ export function useLocationAutoDetect() { // Only run auto-detection after preferences have loaded if (loading) return; + // Check if localStorage is available + if (!isLocalStorageAvailable()) { + console.warn('localStorage is not available, skipping location auto-detection'); + return; + } + // Check if we've already attempted detection const hasAttemptedDetection = localStorage.getItem('location_detection_attempted'); // Auto-detect if we haven't attempted it yet and auto_detect is enabled if (preferences.auto_detect && !hasAttemptedDetection) { autoDetectPreferences().then(() => { - localStorage.setItem('location_detection_attempted', 'true'); + if (isLocalStorageAvailable()) { + localStorage.setItem('location_detection_attempted', 'true'); + } }).catch((error) => { console.error('❌ Failed to auto-detect location:', error); - localStorage.setItem('location_detection_attempted', 'true'); + if (isLocalStorageAvailable()) { + localStorage.setItem('location_detection_attempted', 'true'); + } }); } }, [user, loading, preferences.auto_detect]); diff --git a/supabase/functions/process-selective-approval/index.ts b/supabase/functions/process-selective-approval/index.ts index 90bcc120..ca97e9fb 100644 --- a/supabase/functions/process-selective-approval/index.ts +++ b/supabase/functions/process-selective-approval/index.ts @@ -318,9 +318,10 @@ function topologicalSort(items: any[]): any[] { if (item.depends_on) { const parent = items.find(i => i.id === item.depends_on); - if (parent) { - visit(parent); + if (!parent) { + throw new Error(`Missing dependency: item ${item.id} depends on ${item.depends_on} which is not in the submission`); } + visit(parent); } visiting.delete(item.id);