From 5e4ed810c046555582056bc6dbab98548cdad9ee Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Wed, 5 Nov 2025 20:05:01 +0000 Subject: [PATCH] feat: Add error boundaries to submission queries --- .../error/SubmissionErrorBoundary.tsx | 43 ++++++++++++++++++ src/components/error/index.ts | 1 + .../moderation/EntityEditPreview.tsx | 18 +++++++- .../moderation/SubmissionReviewManager.tsx | 45 ++++++++++--------- src/hooks/usePhotoSubmissionItems.ts | 6 ++- 5 files changed, 90 insertions(+), 23 deletions(-) create mode 100644 src/components/error/SubmissionErrorBoundary.tsx diff --git a/src/components/error/SubmissionErrorBoundary.tsx b/src/components/error/SubmissionErrorBoundary.tsx new file mode 100644 index 00000000..a6604633 --- /dev/null +++ b/src/components/error/SubmissionErrorBoundary.tsx @@ -0,0 +1,43 @@ +import React, { ReactNode } from 'react'; +import { AlertCircle } from 'lucide-react'; +import { Alert, AlertDescription } from '@/components/ui/alert'; +import { ModerationErrorBoundary } from './ModerationErrorBoundary'; + +interface SubmissionErrorBoundaryProps { + children: ReactNode; + submissionId?: string; +} + +/** + * Lightweight Error Boundary for Submission-Related Components + * + * Wraps ModerationErrorBoundary with a submission-specific fallback UI. + * Use this for any component that displays submission data. + * + * Usage: + * ```tsx + * + * + * + * ``` + */ +export function SubmissionErrorBoundary({ + children, + submissionId +}: SubmissionErrorBoundaryProps) { + return ( + + + + Failed to load submission data. Please try refreshing the page. + + + } + > + {children} + + ); +} diff --git a/src/components/error/index.ts b/src/components/error/index.ts index 4c8aaf57..933d29ab 100644 --- a/src/components/error/index.ts +++ b/src/components/error/index.ts @@ -10,3 +10,4 @@ export { AdminErrorBoundary } from './AdminErrorBoundary'; export { EntityErrorBoundary } from './EntityErrorBoundary'; export { RouteErrorBoundary } from './RouteErrorBoundary'; export { ModerationErrorBoundary } from './ModerationErrorBoundary'; +export { SubmissionErrorBoundary } from './SubmissionErrorBoundary'; diff --git a/src/components/moderation/EntityEditPreview.tsx b/src/components/moderation/EntityEditPreview.tsx index 73c8a76b..7f7fe1d7 100644 --- a/src/components/moderation/EntityEditPreview.tsx +++ b/src/components/moderation/EntityEditPreview.tsx @@ -4,7 +4,9 @@ import { Card, CardContent } from '@/components/ui/card'; import { supabase } from '@/lib/supabaseClient'; import { Image as ImageIcon } from 'lucide-react'; import { PhotoModal } from './PhotoModal'; -import { handleError } from '@/lib/errorHandler'; +import { handleError, getErrorMessage } from '@/lib/errorHandler'; +import { Alert, AlertDescription } from '@/components/ui/alert'; +import { AlertCircle } from 'lucide-react'; interface EntityEditPreviewProps { submissionId: string; @@ -68,6 +70,7 @@ interface SubmissionItemData { export const EntityEditPreview = ({ submissionId, entityType, entityName }: EntityEditPreviewProps) => { const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); const [itemData, setItemData] = useState | null>(null); const [originalData, setOriginalData] = useState | null>(null); const [changedFields, setChangedFields] = useState([]); @@ -196,10 +199,12 @@ export const EntityEditPreview = ({ submissionId, entityType, entityName }: Enti setChangedFields(changed); } } catch (error: unknown) { + const errorMsg = getErrorMessage(error); handleError(error, { action: 'Load Submission Preview', metadata: { submissionId, entityType } }); + setError(errorMsg); } finally { setLoading(false); } @@ -213,6 +218,17 @@ export const EntityEditPreview = ({ submissionId, entityType, entityName }: Enti ); } + if (error) { + return ( + + + + {error} + + + ); + } + if (!itemData) { return (
diff --git a/src/components/moderation/SubmissionReviewManager.tsx b/src/components/moderation/SubmissionReviewManager.tsx index cf49b316..c9a2196d 100644 --- a/src/components/moderation/SubmissionReviewManager.tsx +++ b/src/components/moderation/SubmissionReviewManager.tsx @@ -40,6 +40,7 @@ import { ConflictResolutionModal } from './ConflictResolutionModal'; import { EditHistoryAccordion } from './EditHistoryAccordion'; import { validateMultipleItems, ValidationResult } from '@/lib/entityValidationSchemas'; import { logger } from '@/lib/logger'; +import { ModerationErrorBoundary } from '@/components/error'; interface SubmissionReviewManagerProps { submissionId: string; @@ -588,27 +589,29 @@ export function SubmissionReviewManager({ return ( <> - {isMobile ? ( - - - Review Submission - - {pendingCount} pending item(s) • {selectedCount} selected - - - - - ) : ( - - - Review Submission - - {pendingCount} pending item(s) • {selectedCount} selected - - - - - )} + + {isMobile ? ( + + + Review Submission + + {pendingCount} pending item(s) • {selectedCount} selected + + + + + ) : ( + + + Review Submission + + {pendingCount} pending item(s) • {selectedCount} selected + + + + + )} +