import { useState } from 'react'; import { Plus, Clock, CheckCircle } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Separator } from '@/components/ui/separator'; import { TimelineEventEditorDialog } from './TimelineEventEditorDialog'; import { TimelineEventCard } from './TimelineEventCard'; import { EntityHistoryTimeline } from '@/components/history/EntityHistoryTimeline'; import { useQuery } from '@tanstack/react-query'; import { supabase } from '@/lib/supabaseClient'; import { useAuth } from '@/hooks/useAuth'; import { toast } from 'sonner'; import { getErrorMessage, handleError } from '@/lib/errorHandler'; import { logger } from '@/lib/logger'; import { deleteTimelineEvent } from '@/lib/entitySubmissionHelpers'; import type { EntityType, TimelineEvent } from '@/types/timeline'; interface EntityTimelineManagerProps { entityType: EntityType; entityId: string; entityName: string; } export function EntityTimelineManager({ entityType, entityId, entityName, }: EntityTimelineManagerProps) { const [isDialogOpen, setIsDialogOpen] = useState(false); const [editingEvent, setEditingEvent] = useState(null); const [showPending, setShowPending] = useState(true); const { user } = useAuth(); // Fetch approved timeline events const { data: approvedEvents, refetch: refetchApproved } = useQuery({ queryKey: ['timeline-events', 'approved', entityType, entityId], queryFn: async () => { const { data, error } = await supabase .from('entity_timeline_events') .select('*') .eq('entity_type', entityType) .eq('entity_id', entityId) .eq('is_public', true) .not('approved_by', 'is', null) .order('event_date', { ascending: false }); if (error) throw error; return data as TimelineEvent[]; }, }); // Fetch user's pending timeline events const { data: pendingEvents, refetch: refetchPending } = useQuery({ queryKey: ['timeline-events', 'pending', entityType, entityId, user?.id], queryFn: async () => { if (!user) return []; const { data, error } = await supabase .from('entity_timeline_events') .select('*') .eq('entity_type', entityType) .eq('entity_id', entityId) .eq('created_by', user.id) .is('approved_by', null) .order('created_at', { ascending: false }); if (error) throw error; return data as TimelineEvent[]; }, enabled: !!user, }); // Refetch both queries const refetchAll = () => { refetchApproved(); refetchPending(); }; // Convert approved events to HistoryEvent format for EntityHistoryTimeline const historyEvents = approvedEvents?.map((event) => { let mappedType: 'name_change' | 'status_change' | 'ownership_change' | 'relocation' | 'milestone' = 'milestone'; if (event.event_type === 'name_change') mappedType = 'name_change'; else if (event.event_type === 'status_change') mappedType = 'status_change'; else if (event.event_type === 'operator_change' || event.event_type === 'owner_change') mappedType = 'ownership_change'; else if (event.event_type === 'location_change') mappedType = 'relocation'; return { date: event.event_date, title: event.title, description: event.description, type: mappedType, from: event.from_value, to: event.to_value, }; }) || []; // Handle edit const handleEdit = (event: TimelineEvent) => { setEditingEvent(event); setIsDialogOpen(true); }; // Convert TimelineEvent to the format expected by the dialog const editingEventForDialog = editingEvent ? { ...editingEvent, event_date: new Date(editingEvent.event_date), id: editingEvent.id, approved_by: editingEvent.approved_by || null, } : undefined; // Handle delete const handleDelete = async (eventId: string) => { if (!user) { toast.error('Authentication required', { description: 'Please sign in to delete timeline events.' }); return; } try { await deleteTimelineEvent(eventId, user.id); refetchAll(); toast.success('Event deleted', { description: 'Your timeline event has been deleted successfully.' }); } catch (error: unknown) { handleError(error, { action: 'Delete Timeline Event', userId: user?.id, metadata: { eventId } }); } }; // Handle dialog close const handleDialogChange = (open: boolean) => { setIsDialogOpen(open); if (!open) { setEditingEvent(null); } }; // Handle success const handleSuccess = () => { refetchAll(); setEditingEvent(null); setIsDialogOpen(false); }; const hasPendingEvents = pendingEvents && pendingEvents.length > 0; return (
{/* Header with Add Event button */}
{user && hasPendingEvents && ( )}
{user && ( )}
{/* Pending Events Section */} {user && hasPendingEvents && showPending && (

Pending Submissions

{pendingEvents.map((event) => ( ))}
)} {/* Approved Timeline Events */}

Timeline History

{historyEvents.length > 0 ? ( ) : (

No timeline events yet. Be the first to add one!

)}
{/* Editor Dialog */}
); }