mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-21 02:11:13 -05:00
198 lines
7.5 KiB
TypeScript
198 lines
7.5 KiB
TypeScript
import { Plus, Trash2, Calendar } from "lucide-react";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Input } from "@/components/ui/input";
|
|
import { Label } from "@/components/ui/label";
|
|
import { Textarea } from "@/components/ui/textarea";
|
|
import { Card } from "@/components/ui/card";
|
|
import { DatePicker } from "@/components/ui/date-picker";
|
|
|
|
interface FormerName {
|
|
former_name: string;
|
|
date_changed?: Date | null;
|
|
reason?: string;
|
|
from_year?: number;
|
|
to_year?: number;
|
|
order_index: number;
|
|
}
|
|
|
|
interface FormerNamesEditorProps {
|
|
names: FormerName[];
|
|
onChange: (names: FormerName[]) => void;
|
|
currentName: string;
|
|
}
|
|
|
|
export function FormerNamesEditor({ names, onChange, currentName }: FormerNamesEditorProps) {
|
|
|
|
const addName = () => {
|
|
onChange([
|
|
...names,
|
|
{
|
|
former_name: '',
|
|
date_changed: null,
|
|
reason: '',
|
|
order_index: names.length
|
|
}
|
|
]);
|
|
};
|
|
|
|
const removeName = (index: number) => {
|
|
const newNames = names.filter((_, i) => i !== index);
|
|
onChange(newNames.map((name, i) => ({ ...name, order_index: i })));
|
|
};
|
|
|
|
const updateName = (index: number, field: keyof FormerName, value: string | number | Date | null | undefined) => {
|
|
const newNames = [...names];
|
|
newNames[index] = { ...newNames[index], [field]: value };
|
|
onChange(newNames);
|
|
};
|
|
|
|
// Sort names by date_changed (most recent first) for display
|
|
const sortedNames = [...names].sort((a, b) => {
|
|
if (!a.date_changed && !b.date_changed) return 0;
|
|
if (!a.date_changed) return 1;
|
|
if (!b.date_changed) return -1;
|
|
return new Date(b.date_changed).getTime() - new Date(a.date_changed).getTime();
|
|
});
|
|
|
|
return (
|
|
<div className="space-y-4">
|
|
<div className="flex items-center justify-between">
|
|
<div>
|
|
<Label>Former Names</Label>
|
|
<p className="text-xs text-muted-foreground mt-1">
|
|
Current name: <span className="font-medium">{currentName}</span>
|
|
</p>
|
|
</div>
|
|
<Button type="button" variant="outline" size="sm" onClick={addName}>
|
|
<Plus className="h-4 w-4 mr-2" />
|
|
Add Former Name
|
|
</Button>
|
|
</div>
|
|
|
|
{names.length === 0 ? (
|
|
<Card className="p-6 text-center text-muted-foreground">
|
|
No former names recorded. This entity has kept its original name.
|
|
</Card>
|
|
) : (
|
|
<div className="space-y-3">
|
|
{sortedNames.map((name, displayIndex) => {
|
|
const actualIndex = names.findIndex(n => n === name);
|
|
return (
|
|
<Card key={actualIndex} className="p-4">
|
|
<div className="space-y-4">
|
|
<div className="flex items-start gap-4">
|
|
<div className="flex-1 space-y-4">
|
|
<div>
|
|
<Label className="text-xs">Former Name</Label>
|
|
<Input
|
|
value={name.former_name}
|
|
onChange={(e) => updateName(actualIndex, 'former_name', e.target.value)}
|
|
placeholder="Enter former name..."
|
|
/>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-3">
|
|
<div>
|
|
<Label className="text-xs">Date Changed</Label>
|
|
<DatePicker
|
|
date={name.date_changed ? new Date(name.date_changed) : undefined}
|
|
onSelect={(date) => updateName(actualIndex, 'date_changed', date || undefined)}
|
|
placeholder="When was the name changed?"
|
|
fromYear={1800}
|
|
toYear={new Date().getFullYear()}
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<Label className="text-xs">From Year (optional)</Label>
|
|
<Input
|
|
type="number"
|
|
value={name.from_year || ''}
|
|
onChange={(e) => updateName(actualIndex, 'from_year', e.target.value ? parseInt(e.target.value) : undefined)}
|
|
placeholder="Year"
|
|
min="1800"
|
|
max={new Date().getFullYear()}
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<Label className="text-xs">To Year (optional)</Label>
|
|
<Input
|
|
type="number"
|
|
value={name.to_year || ''}
|
|
onChange={(e) => updateName(actualIndex, 'to_year', e.target.value ? parseInt(e.target.value) : undefined)}
|
|
placeholder="Year"
|
|
min="1800"
|
|
max={new Date().getFullYear()}
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<Label className="text-xs">Reason for Change (optional)</Label>
|
|
<Textarea
|
|
value={name.reason || ''}
|
|
onChange={(e) => updateName(actualIndex, 'reason', e.target.value)}
|
|
placeholder="Why was the name changed?"
|
|
rows={2}
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<Button
|
|
type="button"
|
|
variant="ghost"
|
|
size="sm"
|
|
onClick={() => removeName(actualIndex)}
|
|
>
|
|
<Trash2 className="h-4 w-4 text-destructive" />
|
|
</Button>
|
|
</div>
|
|
|
|
{name.date_changed && (
|
|
<div className="flex items-center gap-2 text-xs text-muted-foreground border-t pt-2">
|
|
<Calendar className="h-3 w-3" />
|
|
<span>
|
|
Changed on {new Date(name.date_changed).toLocaleDateString()}
|
|
{name.from_year && name.to_year && ` (used from ${name.from_year} to ${name.to_year})`}
|
|
</span>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</Card>
|
|
);
|
|
})}
|
|
</div>
|
|
)}
|
|
|
|
{names.length > 0 && (
|
|
<Card className="p-4 bg-muted/50">
|
|
<div className="text-sm">
|
|
<strong>Name Timeline:</strong>
|
|
<div className="mt-2 space-y-1">
|
|
{sortedNames
|
|
.filter(n => n.former_name)
|
|
.map((name, idx) => (
|
|
<div key={idx} className="flex items-center gap-2">
|
|
<div className="h-2 w-2 rounded-full bg-primary" />
|
|
<span className="font-medium">{name.former_name}</span>
|
|
{name.from_year && name.to_year && (
|
|
<span className="text-muted-foreground">
|
|
({name.from_year} - {name.to_year})
|
|
</span>
|
|
)}
|
|
</div>
|
|
))}
|
|
<div className="flex items-center gap-2">
|
|
<div className="h-2 w-2 rounded-full bg-green-500" />
|
|
<span className="font-medium">{currentName}</span>
|
|
<span className="text-muted-foreground">(Current)</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</Card>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|