mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-28 15:06:58 -05:00
feat: Implement rich timeline event display
Implement the plan to enhance the display of timeline event submissions in the moderation queue. This includes fixing the database function to fetch timeline event data, creating a new `RichTimelineEventDisplay` component, and updating the `SubmissionItemsList` and `TimelineEventPreview` components to leverage this new display. The goal is to provide moderators with complete and contextually rich information for timeline events.
This commit is contained in:
@@ -1,38 +1,93 @@
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { Calendar, Tag } from 'lucide-react';
|
||||
import { Calendar, Tag, Building2, MapPin } from 'lucide-react';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { FlexibleDateDisplay } from '@/components/ui/flexible-date-display';
|
||||
import type { TimelineSubmissionData } from '@/types/timeline';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { supabase } from '@/lib/supabaseClient';
|
||||
|
||||
interface TimelineEventPreviewProps {
|
||||
data: TimelineSubmissionData;
|
||||
}
|
||||
|
||||
export function TimelineEventPreview({ data }: TimelineEventPreviewProps) {
|
||||
const [entityName, setEntityName] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!data?.entity_id || !data?.entity_type) return;
|
||||
|
||||
const fetchEntityName = async () => {
|
||||
const table = data.entity_type === 'park' ? 'parks' : 'rides';
|
||||
const { data: entity } = await supabase
|
||||
.from(table)
|
||||
.select('name')
|
||||
.eq('id', data.entity_id)
|
||||
.single();
|
||||
setEntityName(entity?.name || null);
|
||||
};
|
||||
|
||||
fetchEntityName();
|
||||
}, [data?.entity_id, data?.entity_type]);
|
||||
|
||||
const formatEventType = (type: string) => {
|
||||
return type.replace(/_/g, ' ').replace(/\b\w/g, (l) => l.toUpperCase());
|
||||
};
|
||||
|
||||
const getEventTypeColor = (type: string) => {
|
||||
const colors: Record<string, string> = {
|
||||
opening: 'bg-green-600',
|
||||
closure: 'bg-red-600',
|
||||
reopening: 'bg-blue-600',
|
||||
renovation: 'bg-purple-600',
|
||||
expansion: 'bg-indigo-600',
|
||||
acquisition: 'bg-amber-600',
|
||||
name_change: 'bg-cyan-600',
|
||||
operator_change: 'bg-orange-600',
|
||||
owner_change: 'bg-orange-600',
|
||||
location_change: 'bg-pink-600',
|
||||
status_change: 'bg-yellow-600',
|
||||
milestone: 'bg-emerald-600',
|
||||
};
|
||||
return colors[type] || 'bg-gray-600';
|
||||
};
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Tag className="h-4 w-4" />
|
||||
Timeline Event: {data.title}
|
||||
<Calendar className="h-4 w-4" />
|
||||
{data.title}
|
||||
</CardTitle>
|
||||
<div className="flex items-center gap-2 mt-2 flex-wrap">
|
||||
<Badge className={`${getEventTypeColor(data.event_type)} text-white text-xs`}>
|
||||
{formatEventType(data.event_type)}
|
||||
</Badge>
|
||||
<Badge variant="outline" className="text-xs">
|
||||
{data.entity_type}
|
||||
</Badge>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
{entityName && (
|
||||
<div className="flex items-center gap-2 text-sm">
|
||||
<Building2 className="h-4 w-4 text-muted-foreground" />
|
||||
<span className="font-medium">Entity:</span>
|
||||
<span className="text-foreground">{entityName}</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="grid grid-cols-2 gap-4 text-sm">
|
||||
<div>
|
||||
<span className="font-medium">Event Type:</span>
|
||||
<p className="text-muted-foreground">
|
||||
{formatEventType(data.event_type)}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<span className="font-medium">Date:</span>
|
||||
<p className="text-muted-foreground flex items-center gap-1">
|
||||
<span className="font-medium">Event Date:</span>
|
||||
<p className="text-muted-foreground flex items-center gap-1 mt-1">
|
||||
<Calendar className="h-3 w-3" />
|
||||
{new Date(data.event_date).toLocaleDateString()}
|
||||
({data.event_date_precision})
|
||||
<FlexibleDateDisplay
|
||||
date={data.event_date}
|
||||
precision={data.event_date_precision}
|
||||
/>
|
||||
</p>
|
||||
<p className="text-xs text-muted-foreground mt-0.5">
|
||||
Precision: {data.event_date_precision}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -45,6 +100,20 @@ export function TimelineEventPreview({ data }: TimelineEventPreviewProps) {
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{(data.from_entity_id || data.to_entity_id) && (
|
||||
<div className="text-xs text-muted-foreground">
|
||||
<Tag className="h-3 w-3 inline mr-1" />
|
||||
Related entities: {data.from_entity_id ? 'From entity' : ''} {data.to_entity_id ? 'To entity' : ''}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{(data.from_location_id || data.to_location_id) && (
|
||||
<div className="text-xs text-muted-foreground">
|
||||
<MapPin className="h-3 w-3 inline mr-1" />
|
||||
Location change involved
|
||||
</div>
|
||||
)}
|
||||
|
||||
{data.description && (
|
||||
<div>
|
||||
|
||||
Reference in New Issue
Block a user