mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-22 19:31:12 -05:00
Refactor: Add History Tab
This commit is contained in:
120
src/components/history/EntityHistoryTimeline.tsx
Normal file
120
src/components/history/EntityHistoryTimeline.tsx
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
|
import { Calendar, MapPin, Building2, Tag, Milestone, ArrowRight } from "lucide-react";
|
||||||
|
import { format } from "date-fns";
|
||||||
|
|
||||||
|
export type HistoryEventType = 'name_change' | 'status_change' | 'ownership_change' | 'relocation' | 'milestone';
|
||||||
|
|
||||||
|
export interface HistoryEvent {
|
||||||
|
date: string;
|
||||||
|
title: string;
|
||||||
|
description?: string;
|
||||||
|
type: HistoryEventType;
|
||||||
|
from?: string;
|
||||||
|
to?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface EntityHistoryTimelineProps {
|
||||||
|
events: HistoryEvent[];
|
||||||
|
entityName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const eventTypeConfig: Record<HistoryEventType, { icon: typeof Tag; color: string; label: string }> = {
|
||||||
|
name_change: { icon: Tag, color: 'text-blue-500', label: 'Name Change' },
|
||||||
|
status_change: { icon: Calendar, color: 'text-amber-500', label: 'Status Change' },
|
||||||
|
ownership_change: { icon: Building2, color: 'text-purple-500', label: 'Ownership Change' },
|
||||||
|
relocation: { icon: MapPin, color: 'text-green-500', label: 'Relocation' },
|
||||||
|
milestone: { icon: Milestone, color: 'text-pink-500', label: 'Milestone' },
|
||||||
|
};
|
||||||
|
|
||||||
|
export function EntityHistoryTimeline({ events, entityName }: EntityHistoryTimelineProps) {
|
||||||
|
if (events.length === 0) {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>No Historical Events</CardTitle>
|
||||||
|
<CardDescription>
|
||||||
|
No historical events recorded for {entityName}
|
||||||
|
</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort events by date (most recent first)
|
||||||
|
const sortedEvents = [...events].sort((a, b) => {
|
||||||
|
const dateA = new Date(a.date);
|
||||||
|
const dateB = new Date(b.date);
|
||||||
|
return dateB.getTime() - dateA.getTime();
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="relative space-y-4">
|
||||||
|
{/* Timeline line */}
|
||||||
|
<div className="absolute left-6 top-0 bottom-0 w-0.5 bg-border" />
|
||||||
|
|
||||||
|
{sortedEvents.map((event, index) => {
|
||||||
|
const config = eventTypeConfig[event.type];
|
||||||
|
const Icon = config.icon;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div key={index} className="relative flex gap-4">
|
||||||
|
{/* Timeline dot */}
|
||||||
|
<div className="relative flex-shrink-0">
|
||||||
|
<div className={`flex h-12 w-12 items-center justify-center rounded-full border-2 border-background bg-card ${config.color}`}>
|
||||||
|
<Icon className="h-5 w-5" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Event content */}
|
||||||
|
<Card className="flex-1">
|
||||||
|
<CardHeader className="pb-3">
|
||||||
|
<div className="flex items-start justify-between gap-4">
|
||||||
|
<div className="space-y-1">
|
||||||
|
<CardTitle className="text-lg">{event.title}</CardTitle>
|
||||||
|
<CardDescription className="flex items-center gap-2">
|
||||||
|
<Calendar className="h-3 w-3" />
|
||||||
|
{formatEventDate(event.date)}
|
||||||
|
<span className="text-xs">•</span>
|
||||||
|
<span className={config.color}>{config.label}</span>
|
||||||
|
</CardDescription>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardHeader>
|
||||||
|
{(event.description || (event.from && event.to)) && (
|
||||||
|
<CardContent className="pt-0">
|
||||||
|
{event.from && event.to && (
|
||||||
|
<div className="flex items-center gap-2 text-sm text-muted-foreground mb-2">
|
||||||
|
<span className="font-medium">{event.from}</span>
|
||||||
|
<ArrowRight className="h-4 w-4" />
|
||||||
|
<span className="font-medium">{event.to}</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{event.description && (
|
||||||
|
<p className="text-sm text-muted-foreground">{event.description}</p>
|
||||||
|
)}
|
||||||
|
</CardContent>
|
||||||
|
)}
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatEventDate(dateString: string): string {
|
||||||
|
try {
|
||||||
|
// Handle year-only dates
|
||||||
|
if (/^\d{4}$/.test(dateString)) {
|
||||||
|
return dateString;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle full dates
|
||||||
|
const date = new Date(dateString);
|
||||||
|
return format(date, 'MMMM d, yyyy');
|
||||||
|
} catch {
|
||||||
|
return dateString;
|
||||||
|
}
|
||||||
|
}
|
||||||
100
src/components/history/FormerNamesSection.tsx
Normal file
100
src/components/history/FormerNamesSection.tsx
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
|
import { Tag, Calendar } from "lucide-react";
|
||||||
|
|
||||||
|
interface FormerName {
|
||||||
|
former_name?: string;
|
||||||
|
name?: string;
|
||||||
|
from_year?: number;
|
||||||
|
to_year?: number;
|
||||||
|
reason?: string;
|
||||||
|
date_changed?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FormerNamesSectionProps {
|
||||||
|
currentName: string;
|
||||||
|
formerNames: FormerName[];
|
||||||
|
entityType: 'ride' | 'park' | 'company';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function FormerNamesSection({ currentName, formerNames, entityType }: FormerNamesSectionProps) {
|
||||||
|
if (!formerNames || formerNames.length === 0) {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle className="flex items-center gap-2">
|
||||||
|
<Tag className="h-5 w-5" />
|
||||||
|
Former Names
|
||||||
|
</CardTitle>
|
||||||
|
<CardDescription>
|
||||||
|
This {entityType} has not had any previous names
|
||||||
|
</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort by date (most recent first)
|
||||||
|
const sortedNames = [...formerNames].sort((a, b) => {
|
||||||
|
const yearA = a.to_year || (a.date_changed ? new Date(a.date_changed).getFullYear() : 0);
|
||||||
|
const yearB = b.to_year || (b.date_changed ? new Date(b.date_changed).getFullYear() : 0);
|
||||||
|
return yearB - yearA;
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle className="flex items-center gap-2">
|
||||||
|
<Tag className="h-5 w-5" />
|
||||||
|
Former Names
|
||||||
|
</CardTitle>
|
||||||
|
<CardDescription>
|
||||||
|
Historical names for this {entityType}
|
||||||
|
</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<div className="space-y-4">
|
||||||
|
{/* Current name */}
|
||||||
|
<div className="flex items-start gap-3 p-3 rounded-lg bg-primary/5 border border-primary/20">
|
||||||
|
<div className="flex-shrink-0 mt-1">
|
||||||
|
<div className="h-3 w-3 rounded-full bg-primary" />
|
||||||
|
</div>
|
||||||
|
<div className="flex-1">
|
||||||
|
<h4 className="font-semibold text-foreground">{currentName}</h4>
|
||||||
|
<p className="text-sm text-muted-foreground">Current Name</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Former names */}
|
||||||
|
{sortedNames.map((name, index) => {
|
||||||
|
const displayName = name.former_name || name.name;
|
||||||
|
const yearRange = name.from_year && name.to_year
|
||||||
|
? `${name.from_year} - ${name.to_year}`
|
||||||
|
: name.date_changed
|
||||||
|
? `Until ${new Date(name.date_changed).getFullYear()}`
|
||||||
|
: null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div key={index} className="flex items-start gap-3 p-3 rounded-lg border">
|
||||||
|
<div className="flex-shrink-0 mt-1">
|
||||||
|
<div className="h-3 w-3 rounded-full bg-muted-foreground/30" />
|
||||||
|
</div>
|
||||||
|
<div className="flex-1 space-y-1">
|
||||||
|
<h4 className="font-medium text-foreground">{displayName}</h4>
|
||||||
|
{yearRange && (
|
||||||
|
<p className="text-sm text-muted-foreground flex items-center gap-1">
|
||||||
|
<Calendar className="h-3 w-3" />
|
||||||
|
{yearRange}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
{name.reason && (
|
||||||
|
<p className="text-sm text-muted-foreground italic">{name.reason}</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -16,6 +16,9 @@ import { useUserRole } from '@/hooks/useUserRole';
|
|||||||
import { toast } from '@/hooks/use-toast';
|
import { toast } from '@/hooks/use-toast';
|
||||||
import { submitCompanyUpdate } from '@/lib/companyHelpers';
|
import { submitCompanyUpdate } from '@/lib/companyHelpers';
|
||||||
import { VersionIndicator } from '@/components/versioning/VersionIndicator';
|
import { VersionIndicator } from '@/components/versioning/VersionIndicator';
|
||||||
|
import { EntityVersionHistory } from '@/components/versioning/EntityVersionHistory';
|
||||||
|
import { EntityHistoryTimeline, HistoryEvent } from '@/components/history/EntityHistoryTimeline';
|
||||||
|
import { FormerNamesSection } from '@/components/history/FormerNamesSection';
|
||||||
|
|
||||||
export default function DesignerDetail() {
|
export default function DesignerDetail() {
|
||||||
const { slug } = useParams<{ slug: string }>();
|
const { slug } = useParams<{ slug: string }>();
|
||||||
@@ -226,10 +229,11 @@ export default function DesignerDetail() {
|
|||||||
|
|
||||||
{/* Tabs */}
|
{/* Tabs */}
|
||||||
<Tabs defaultValue="overview" className="w-full">
|
<Tabs defaultValue="overview" className="w-full">
|
||||||
<TabsList className="grid w-full grid-cols-2 md:grid-cols-3">
|
<TabsList className="grid w-full grid-cols-2 md:grid-cols-4">
|
||||||
<TabsTrigger value="overview">Overview</TabsTrigger>
|
<TabsTrigger value="overview">Overview</TabsTrigger>
|
||||||
<TabsTrigger value="rides">Rides</TabsTrigger>
|
<TabsTrigger value="rides">Rides</TabsTrigger>
|
||||||
<TabsTrigger value="photos">Photos</TabsTrigger>
|
<TabsTrigger value="photos">Photos</TabsTrigger>
|
||||||
|
<TabsTrigger value="history">History</TabsTrigger>
|
||||||
</TabsList>
|
</TabsList>
|
||||||
|
|
||||||
<TabsContent value="overview" className="space-y-6">
|
<TabsContent value="overview" className="space-y-6">
|
||||||
@@ -270,6 +274,37 @@ export default function DesignerDetail() {
|
|||||||
designerName={designer.name}
|
designerName={designer.name}
|
||||||
/>
|
/>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
|
|
||||||
|
<TabsContent value="history" className="mt-6">
|
||||||
|
<Tabs defaultValue="company-history" className="w-full">
|
||||||
|
<TabsList className="w-full max-w-md">
|
||||||
|
<TabsTrigger value="company-history">Company History</TabsTrigger>
|
||||||
|
<TabsTrigger value="version-history">Version History</TabsTrigger>
|
||||||
|
</TabsList>
|
||||||
|
|
||||||
|
<TabsContent value="company-history" className="mt-6 space-y-6">
|
||||||
|
<EntityHistoryTimeline
|
||||||
|
events={[
|
||||||
|
...(designer.founded_year ? [{
|
||||||
|
date: `${designer.founded_year}`,
|
||||||
|
title: `${designer.name} Founded`,
|
||||||
|
description: `${designer.name} was established`,
|
||||||
|
type: 'milestone' as const
|
||||||
|
}] : []),
|
||||||
|
]}
|
||||||
|
entityName={designer.name}
|
||||||
|
/>
|
||||||
|
</TabsContent>
|
||||||
|
|
||||||
|
<TabsContent value="version-history" className="mt-6">
|
||||||
|
<EntityVersionHistory
|
||||||
|
entityType="company"
|
||||||
|
entityId={designer.id}
|
||||||
|
entityName={designer.name}
|
||||||
|
/>
|
||||||
|
</TabsContent>
|
||||||
|
</Tabs>
|
||||||
|
</TabsContent>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ import { useUserRole } from '@/hooks/useUserRole';
|
|||||||
import { toast } from '@/hooks/use-toast';
|
import { toast } from '@/hooks/use-toast';
|
||||||
import { submitCompanyUpdate } from '@/lib/companyHelpers';
|
import { submitCompanyUpdate } from '@/lib/companyHelpers';
|
||||||
import { VersionIndicator } from '@/components/versioning/VersionIndicator';
|
import { VersionIndicator } from '@/components/versioning/VersionIndicator';
|
||||||
|
import { EntityVersionHistory } from '@/components/versioning/EntityVersionHistory';
|
||||||
|
import { EntityHistoryTimeline, HistoryEvent } from '@/components/history/EntityHistoryTimeline';
|
||||||
|
import { FormerNamesSection } from '@/components/history/FormerNamesSection';
|
||||||
|
|
||||||
export default function ManufacturerDetail() {
|
export default function ManufacturerDetail() {
|
||||||
const { slug } = useParams<{ slug: string }>();
|
const { slug } = useParams<{ slug: string }>();
|
||||||
@@ -228,11 +231,12 @@ export default function ManufacturerDetail() {
|
|||||||
|
|
||||||
{/* Tabs */}
|
{/* Tabs */}
|
||||||
<Tabs defaultValue="overview" className="w-full">
|
<Tabs defaultValue="overview" className="w-full">
|
||||||
<TabsList className="grid w-full grid-cols-2 md:grid-cols-4">
|
<TabsList className="grid w-full grid-cols-2 md:grid-cols-5">
|
||||||
<TabsTrigger value="overview">Overview</TabsTrigger>
|
<TabsTrigger value="overview">Overview</TabsTrigger>
|
||||||
<TabsTrigger value="rides">Rides</TabsTrigger>
|
<TabsTrigger value="rides">Rides</TabsTrigger>
|
||||||
<TabsTrigger value="models">Models</TabsTrigger>
|
<TabsTrigger value="models">Models</TabsTrigger>
|
||||||
<TabsTrigger value="photos">Photos</TabsTrigger>
|
<TabsTrigger value="photos">Photos</TabsTrigger>
|
||||||
|
<TabsTrigger value="history">History</TabsTrigger>
|
||||||
</TabsList>
|
</TabsList>
|
||||||
|
|
||||||
<TabsContent value="overview" className="space-y-6">
|
<TabsContent value="overview" className="space-y-6">
|
||||||
@@ -292,6 +296,37 @@ export default function ManufacturerDetail() {
|
|||||||
manufacturerName={manufacturer.name}
|
manufacturerName={manufacturer.name}
|
||||||
/>
|
/>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
|
|
||||||
|
<TabsContent value="history" className="mt-6">
|
||||||
|
<Tabs defaultValue="company-history" className="w-full">
|
||||||
|
<TabsList className="w-full max-w-md">
|
||||||
|
<TabsTrigger value="company-history">Company History</TabsTrigger>
|
||||||
|
<TabsTrigger value="version-history">Version History</TabsTrigger>
|
||||||
|
</TabsList>
|
||||||
|
|
||||||
|
<TabsContent value="company-history" className="mt-6 space-y-6">
|
||||||
|
<EntityHistoryTimeline
|
||||||
|
events={[
|
||||||
|
...(manufacturer.founded_year ? [{
|
||||||
|
date: `${manufacturer.founded_year}`,
|
||||||
|
title: `${manufacturer.name} Founded`,
|
||||||
|
description: `${manufacturer.name} was established`,
|
||||||
|
type: 'milestone' as const
|
||||||
|
}] : []),
|
||||||
|
]}
|
||||||
|
entityName={manufacturer.name}
|
||||||
|
/>
|
||||||
|
</TabsContent>
|
||||||
|
|
||||||
|
<TabsContent value="version-history" className="mt-6">
|
||||||
|
<EntityVersionHistory
|
||||||
|
entityType="company"
|
||||||
|
entityId={manufacturer.id}
|
||||||
|
entityName={manufacturer.name}
|
||||||
|
/>
|
||||||
|
</TabsContent>
|
||||||
|
</Tabs>
|
||||||
|
</TabsContent>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ import { useUserRole } from '@/hooks/useUserRole';
|
|||||||
import { toast } from '@/hooks/use-toast';
|
import { toast } from '@/hooks/use-toast';
|
||||||
import { submitCompanyUpdate } from '@/lib/companyHelpers';
|
import { submitCompanyUpdate } from '@/lib/companyHelpers';
|
||||||
import { VersionIndicator } from '@/components/versioning/VersionIndicator';
|
import { VersionIndicator } from '@/components/versioning/VersionIndicator';
|
||||||
|
import { EntityVersionHistory } from '@/components/versioning/EntityVersionHistory';
|
||||||
|
import { EntityHistoryTimeline, HistoryEvent } from '@/components/history/EntityHistoryTimeline';
|
||||||
|
import { FormerNamesSection } from '@/components/history/FormerNamesSection';
|
||||||
|
|
||||||
export default function OperatorDetail() {
|
export default function OperatorDetail() {
|
||||||
const { slug } = useParams<{ slug: string }>();
|
const { slug } = useParams<{ slug: string }>();
|
||||||
@@ -255,10 +258,11 @@ export default function OperatorDetail() {
|
|||||||
|
|
||||||
{/* Tabs */}
|
{/* Tabs */}
|
||||||
<Tabs defaultValue="overview" className="w-full">
|
<Tabs defaultValue="overview" className="w-full">
|
||||||
<TabsList className="grid w-full grid-cols-2 md:grid-cols-3">
|
<TabsList className="grid w-full grid-cols-2 md:grid-cols-4">
|
||||||
<TabsTrigger value="overview">Overview</TabsTrigger>
|
<TabsTrigger value="overview">Overview</TabsTrigger>
|
||||||
<TabsTrigger value="parks">Parks</TabsTrigger>
|
<TabsTrigger value="parks">Parks</TabsTrigger>
|
||||||
<TabsTrigger value="photos">Photos</TabsTrigger>
|
<TabsTrigger value="photos">Photos</TabsTrigger>
|
||||||
|
<TabsTrigger value="history">History</TabsTrigger>
|
||||||
</TabsList>
|
</TabsList>
|
||||||
|
|
||||||
<TabsContent value="overview" className="space-y-6">
|
<TabsContent value="overview" className="space-y-6">
|
||||||
@@ -315,6 +319,37 @@ export default function OperatorDetail() {
|
|||||||
operatorName={operator.name}
|
operatorName={operator.name}
|
||||||
/>
|
/>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
|
|
||||||
|
<TabsContent value="history" className="mt-6">
|
||||||
|
<Tabs defaultValue="company-history" className="w-full">
|
||||||
|
<TabsList className="w-full max-w-md">
|
||||||
|
<TabsTrigger value="company-history">Company History</TabsTrigger>
|
||||||
|
<TabsTrigger value="version-history">Version History</TabsTrigger>
|
||||||
|
</TabsList>
|
||||||
|
|
||||||
|
<TabsContent value="company-history" className="mt-6 space-y-6">
|
||||||
|
<EntityHistoryTimeline
|
||||||
|
events={[
|
||||||
|
...(operator.founded_year ? [{
|
||||||
|
date: `${operator.founded_year}`,
|
||||||
|
title: `${operator.name} Founded`,
|
||||||
|
description: `${operator.name} was established`,
|
||||||
|
type: 'milestone' as const
|
||||||
|
}] : []),
|
||||||
|
]}
|
||||||
|
entityName={operator.name}
|
||||||
|
/>
|
||||||
|
</TabsContent>
|
||||||
|
|
||||||
|
<TabsContent value="version-history" className="mt-6">
|
||||||
|
<EntityVersionHistory
|
||||||
|
entityType="company"
|
||||||
|
entityId={operator.id}
|
||||||
|
entityName={operator.name}
|
||||||
|
/>
|
||||||
|
</TabsContent>
|
||||||
|
</Tabs>
|
||||||
|
</TabsContent>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,9 @@ import { toast } from '@/hooks/use-toast';
|
|||||||
import { useUserRole } from '@/hooks/useUserRole';
|
import { useUserRole } from '@/hooks/useUserRole';
|
||||||
import { Edit } from 'lucide-react';
|
import { Edit } from 'lucide-react';
|
||||||
import { VersionIndicator } from '@/components/versioning/VersionIndicator';
|
import { VersionIndicator } from '@/components/versioning/VersionIndicator';
|
||||||
|
import { EntityVersionHistory } from '@/components/versioning/EntityVersionHistory';
|
||||||
|
import { EntityHistoryTimeline, HistoryEvent } from '@/components/history/EntityHistoryTimeline';
|
||||||
|
import { FormerNamesSection } from '@/components/history/FormerNamesSection';
|
||||||
|
|
||||||
export default function ParkDetail() {
|
export default function ParkDetail() {
|
||||||
const {
|
const {
|
||||||
@@ -356,11 +359,12 @@ export default function ParkDetail() {
|
|||||||
|
|
||||||
{/* Main Content */}
|
{/* Main Content */}
|
||||||
<Tabs defaultValue="overview" className="w-full">
|
<Tabs defaultValue="overview" className="w-full">
|
||||||
<TabsList className="grid w-full grid-cols-2 md:grid-cols-4">
|
<TabsList className="grid w-full grid-cols-2 md:grid-cols-5">
|
||||||
<TabsTrigger value="overview">Overview</TabsTrigger>
|
<TabsTrigger value="overview">Overview</TabsTrigger>
|
||||||
<TabsTrigger value="rides">Rides ({rides.length})</TabsTrigger>
|
<TabsTrigger value="rides">Rides ({rides.length})</TabsTrigger>
|
||||||
<TabsTrigger value="reviews">Reviews</TabsTrigger>
|
<TabsTrigger value="reviews">Reviews</TabsTrigger>
|
||||||
<TabsTrigger value="photos">Photos</TabsTrigger>
|
<TabsTrigger value="photos">Photos</TabsTrigger>
|
||||||
|
<TabsTrigger value="history">History</TabsTrigger>
|
||||||
</TabsList>
|
</TabsList>
|
||||||
|
|
||||||
<TabsContent value="overview" className="mt-6">
|
<TabsContent value="overview" className="mt-6">
|
||||||
@@ -587,6 +591,43 @@ export default function ParkDetail() {
|
|||||||
entityName={park.name}
|
entityName={park.name}
|
||||||
/>
|
/>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
|
|
||||||
|
<TabsContent value="history" className="mt-6">
|
||||||
|
<Tabs defaultValue="park-history" className="w-full">
|
||||||
|
<TabsList className="w-full max-w-md">
|
||||||
|
<TabsTrigger value="park-history">Park History</TabsTrigger>
|
||||||
|
<TabsTrigger value="version-history">Version History</TabsTrigger>
|
||||||
|
</TabsList>
|
||||||
|
|
||||||
|
<TabsContent value="park-history" className="mt-6 space-y-6">
|
||||||
|
<EntityHistoryTimeline
|
||||||
|
events={[
|
||||||
|
...(park.opening_date ? [{
|
||||||
|
date: park.opening_date,
|
||||||
|
title: `${park.name} Opened`,
|
||||||
|
description: `${park.name} opened to the public`,
|
||||||
|
type: 'milestone' as const
|
||||||
|
}] : []),
|
||||||
|
...(park.closing_date ? [{
|
||||||
|
date: park.closing_date,
|
||||||
|
title: `${park.name} Closed`,
|
||||||
|
description: `${park.name} ceased operation`,
|
||||||
|
type: 'status_change' as const
|
||||||
|
}] : []),
|
||||||
|
]}
|
||||||
|
entityName={park.name}
|
||||||
|
/>
|
||||||
|
</TabsContent>
|
||||||
|
|
||||||
|
<TabsContent value="version-history" className="mt-6">
|
||||||
|
<EntityVersionHistory
|
||||||
|
entityType="park"
|
||||||
|
entityId={park.id}
|
||||||
|
entityName={park.name}
|
||||||
|
/>
|
||||||
|
</TabsContent>
|
||||||
|
</Tabs>
|
||||||
|
</TabsContent>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
{/* Add Ride Modal */}
|
{/* Add Ride Modal */}
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ import { useUserRole } from '@/hooks/useUserRole';
|
|||||||
import { toast } from '@/hooks/use-toast';
|
import { toast } from '@/hooks/use-toast';
|
||||||
import { submitCompanyUpdate } from '@/lib/companyHelpers';
|
import { submitCompanyUpdate } from '@/lib/companyHelpers';
|
||||||
import { VersionIndicator } from '@/components/versioning/VersionIndicator';
|
import { VersionIndicator } from '@/components/versioning/VersionIndicator';
|
||||||
|
import { EntityVersionHistory } from '@/components/versioning/EntityVersionHistory';
|
||||||
|
import { EntityHistoryTimeline, HistoryEvent } from '@/components/history/EntityHistoryTimeline';
|
||||||
|
import { FormerNamesSection } from '@/components/history/FormerNamesSection';
|
||||||
|
|
||||||
export default function PropertyOwnerDetail() {
|
export default function PropertyOwnerDetail() {
|
||||||
const { slug } = useParams<{ slug: string }>();
|
const { slug } = useParams<{ slug: string }>();
|
||||||
@@ -255,10 +258,11 @@ export default function PropertyOwnerDetail() {
|
|||||||
|
|
||||||
{/* Tabs */}
|
{/* Tabs */}
|
||||||
<Tabs defaultValue="overview" className="w-full">
|
<Tabs defaultValue="overview" className="w-full">
|
||||||
<TabsList className="grid w-full grid-cols-2 md:grid-cols-3">
|
<TabsList className="grid w-full grid-cols-2 md:grid-cols-4">
|
||||||
<TabsTrigger value="overview">Overview</TabsTrigger>
|
<TabsTrigger value="overview">Overview</TabsTrigger>
|
||||||
<TabsTrigger value="parks">Parks</TabsTrigger>
|
<TabsTrigger value="parks">Parks</TabsTrigger>
|
||||||
<TabsTrigger value="photos">Photos</TabsTrigger>
|
<TabsTrigger value="photos">Photos</TabsTrigger>
|
||||||
|
<TabsTrigger value="history">History</TabsTrigger>
|
||||||
</TabsList>
|
</TabsList>
|
||||||
|
|
||||||
<TabsContent value="overview" className="space-y-6">
|
<TabsContent value="overview" className="space-y-6">
|
||||||
@@ -315,6 +319,37 @@ export default function PropertyOwnerDetail() {
|
|||||||
propertyOwnerName={owner.name}
|
propertyOwnerName={owner.name}
|
||||||
/>
|
/>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
|
|
||||||
|
<TabsContent value="history" className="mt-6">
|
||||||
|
<Tabs defaultValue="company-history" className="w-full">
|
||||||
|
<TabsList className="w-full max-w-md">
|
||||||
|
<TabsTrigger value="company-history">Company History</TabsTrigger>
|
||||||
|
<TabsTrigger value="version-history">Version History</TabsTrigger>
|
||||||
|
</TabsList>
|
||||||
|
|
||||||
|
<TabsContent value="company-history" className="mt-6 space-y-6">
|
||||||
|
<EntityHistoryTimeline
|
||||||
|
events={[
|
||||||
|
...(owner.founded_year ? [{
|
||||||
|
date: `${owner.founded_year}`,
|
||||||
|
title: `${owner.name} Founded`,
|
||||||
|
description: `${owner.name} was established`,
|
||||||
|
type: 'milestone' as const
|
||||||
|
}] : []),
|
||||||
|
]}
|
||||||
|
entityName={owner.name}
|
||||||
|
/>
|
||||||
|
</TabsContent>
|
||||||
|
|
||||||
|
<TabsContent value="version-history" className="mt-6">
|
||||||
|
<EntityVersionHistory
|
||||||
|
entityType="company"
|
||||||
|
entityId={owner.id}
|
||||||
|
entityName={owner.name}
|
||||||
|
/>
|
||||||
|
</TabsContent>
|
||||||
|
</Tabs>
|
||||||
|
</TabsContent>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,9 @@ import { useAuth } from '@/hooks/useAuth';
|
|||||||
import { useUserRole } from '@/hooks/useUserRole';
|
import { useUserRole } from '@/hooks/useUserRole';
|
||||||
import { toast } from '@/hooks/use-toast';
|
import { toast } from '@/hooks/use-toast';
|
||||||
import { VersionIndicator } from '@/components/versioning/VersionIndicator';
|
import { VersionIndicator } from '@/components/versioning/VersionIndicator';
|
||||||
|
import { EntityVersionHistory } from '@/components/versioning/EntityVersionHistory';
|
||||||
|
import { EntityHistoryTimeline, HistoryEvent } from '@/components/history/EntityHistoryTimeline';
|
||||||
|
import { FormerNamesSection } from '@/components/history/FormerNamesSection';
|
||||||
|
|
||||||
export default function RideDetail() {
|
export default function RideDetail() {
|
||||||
const { parkSlug, rideSlug } = useParams<{ parkSlug: string; rideSlug: string }>();
|
const { parkSlug, rideSlug } = useParams<{ parkSlug: string; rideSlug: string }>();
|
||||||
@@ -379,11 +382,12 @@ export default function RideDetail() {
|
|||||||
|
|
||||||
{/* Main Content */}
|
{/* Main Content */}
|
||||||
<Tabs value={activeTab} onValueChange={setActiveTab} className="w-full">
|
<Tabs value={activeTab} onValueChange={setActiveTab} className="w-full">
|
||||||
<TabsList className="grid w-full grid-cols-2 md:grid-cols-4">
|
<TabsList className="grid w-full grid-cols-2 md:grid-cols-5">
|
||||||
<TabsTrigger value="overview">Overview</TabsTrigger>
|
<TabsTrigger value="overview">Overview</TabsTrigger>
|
||||||
<TabsTrigger value="specs">Specifications</TabsTrigger>
|
<TabsTrigger value="specs">Specifications</TabsTrigger>
|
||||||
<TabsTrigger value="reviews">Reviews</TabsTrigger>
|
<TabsTrigger value="reviews">Reviews</TabsTrigger>
|
||||||
<TabsTrigger value="photos">Photos</TabsTrigger>
|
<TabsTrigger value="photos">Photos</TabsTrigger>
|
||||||
|
<TabsTrigger value="history">History</TabsTrigger>
|
||||||
</TabsList>
|
</TabsList>
|
||||||
|
|
||||||
<TabsContent value="overview" className="mt-6">
|
<TabsContent value="overview" className="mt-6">
|
||||||
@@ -653,6 +657,51 @@ export default function RideDetail() {
|
|||||||
parentId={(ride as any).currentParkId}
|
parentId={(ride as any).currentParkId}
|
||||||
/>
|
/>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
|
|
||||||
|
<TabsContent value="history" className="mt-6">
|
||||||
|
<Tabs defaultValue="ride-history" className="w-full">
|
||||||
|
<TabsList className="w-full max-w-md">
|
||||||
|
<TabsTrigger value="ride-history">Ride History</TabsTrigger>
|
||||||
|
<TabsTrigger value="version-history">Version History</TabsTrigger>
|
||||||
|
</TabsList>
|
||||||
|
|
||||||
|
<TabsContent value="ride-history" className="mt-6 space-y-6">
|
||||||
|
{ride.name_history && ride.name_history.length > 0 && (
|
||||||
|
<FormerNamesSection
|
||||||
|
currentName={ride.name}
|
||||||
|
formerNames={ride.name_history}
|
||||||
|
entityType="ride"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<EntityHistoryTimeline
|
||||||
|
events={[
|
||||||
|
...(ride.opening_date ? [{
|
||||||
|
date: ride.opening_date,
|
||||||
|
title: `${ride.name} Opened`,
|
||||||
|
description: `${ride.name} opened to the public at ${ride.park.name}`,
|
||||||
|
type: 'milestone' as const
|
||||||
|
}] : []),
|
||||||
|
...(ride.closing_date ? [{
|
||||||
|
date: ride.closing_date,
|
||||||
|
title: `${ride.name} Closed`,
|
||||||
|
description: `${ride.name} ceased operation`,
|
||||||
|
type: 'status_change' as const
|
||||||
|
}] : []),
|
||||||
|
]}
|
||||||
|
entityName={ride.name}
|
||||||
|
/>
|
||||||
|
</TabsContent>
|
||||||
|
|
||||||
|
<TabsContent value="version-history" className="mt-6">
|
||||||
|
<EntityVersionHistory
|
||||||
|
entityType="ride"
|
||||||
|
entityId={ride.id}
|
||||||
|
entityName={ride.name}
|
||||||
|
/>
|
||||||
|
</TabsContent>
|
||||||
|
</Tabs>
|
||||||
|
</TabsContent>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
{/* Edit Ride Modal */}
|
{/* Edit Ride Modal */}
|
||||||
|
|||||||
Reference in New Issue
Block a user