mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 10:31:13 -05:00
155 lines
4.6 KiB
TypeScript
155 lines
4.6 KiB
TypeScript
import { useState, useEffect } from "react";
|
|
import { UserTopList, UserTopListItem, Park, Ride, Company } from "@/types/database";
|
|
import { supabase } from "@/integrations/supabase/client";
|
|
import { Link } from "react-router-dom";
|
|
import { Badge } from "@/components/ui/badge";
|
|
|
|
interface ListDisplayProps {
|
|
list: UserTopList;
|
|
}
|
|
|
|
interface EnrichedListItem extends UserTopListItem {
|
|
entity?: Park | Ride | Company;
|
|
}
|
|
|
|
export function ListDisplay({ list }: ListDisplayProps) {
|
|
const [items, setItems] = useState<EnrichedListItem[]>([]);
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
useEffect(() => {
|
|
fetchItemsWithEntities();
|
|
}, [list.id]);
|
|
|
|
const fetchItemsWithEntities = async () => {
|
|
setLoading(true);
|
|
|
|
// First, get the list items
|
|
const { data: itemsData, error: itemsError } = await supabase
|
|
.from("user_top_list_items")
|
|
.select("*")
|
|
.eq("list_id", list.id)
|
|
.order("position", { ascending: true });
|
|
|
|
if (itemsError) {
|
|
console.error("Error fetching items:", itemsError);
|
|
setLoading(false);
|
|
return;
|
|
}
|
|
|
|
// Then, fetch the entities for each item
|
|
const enrichedItems = await Promise.all(
|
|
(itemsData as UserTopListItem[]).map(async (item) => {
|
|
let entity = null;
|
|
|
|
if (item.entity_type === "park") {
|
|
const { data } = await supabase
|
|
.from("parks")
|
|
.select("id, name, slug, park_type, location_id")
|
|
.eq("id", item.entity_id)
|
|
.single();
|
|
entity = data;
|
|
} else if (item.entity_type === "ride") {
|
|
const { data } = await supabase
|
|
.from("rides")
|
|
.select("id, name, slug, category, park_id")
|
|
.eq("id", item.entity_id)
|
|
.single();
|
|
entity = data;
|
|
} else if (item.entity_type === "company") {
|
|
const { data } = await supabase
|
|
.from("companies")
|
|
.select("id, name, slug, company_type")
|
|
.eq("id", item.entity_id)
|
|
.single();
|
|
entity = data;
|
|
}
|
|
|
|
return { ...item, entity };
|
|
})
|
|
);
|
|
|
|
setItems(enrichedItems);
|
|
setLoading(false);
|
|
};
|
|
|
|
const getEntityUrl = (item: EnrichedListItem) => {
|
|
if (!item.entity) return "#";
|
|
|
|
const entity = item.entity as any;
|
|
|
|
if (item.entity_type === "park") {
|
|
return `/parks/${entity.slug}`;
|
|
} else if (item.entity_type === "ride") {
|
|
// We need park slug for rides
|
|
return `/rides/${entity.slug}`;
|
|
} else if (item.entity_type === "company") {
|
|
return `/companies/${entity.slug}`;
|
|
}
|
|
|
|
return "#";
|
|
};
|
|
|
|
if (loading) {
|
|
return <div className="text-center py-4 text-muted-foreground">Loading...</div>;
|
|
}
|
|
|
|
if (items.length === 0) {
|
|
return (
|
|
<div className="text-center py-8 text-muted-foreground">
|
|
This list is empty. Click "Edit" to add items.
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<ol className="space-y-2">
|
|
{items.map((item, index) => (
|
|
<li key={item.id} className="flex items-start gap-3 p-3 rounded-lg hover:bg-muted/50 transition-colors">
|
|
<span className="font-bold text-lg text-muted-foreground min-w-[2rem]">
|
|
{index + 1}.
|
|
</span>
|
|
<div className="flex-1">
|
|
{item.entity ? (
|
|
<Link
|
|
to={getEntityUrl(item)}
|
|
className="font-medium hover:underline"
|
|
>
|
|
{(item.entity as any).name}
|
|
</Link>
|
|
) : (
|
|
<span className="font-medium text-muted-foreground">
|
|
[Deleted or unavailable]
|
|
</span>
|
|
)}
|
|
<div className="flex gap-2 mt-1">
|
|
<Badge variant="secondary" className="text-xs">
|
|
{item.entity_type}
|
|
</Badge>
|
|
{item.entity && item.entity_type === "park" && (
|
|
<Badge variant="outline" className="text-xs">
|
|
{(item.entity as Park).park_type}
|
|
</Badge>
|
|
)}
|
|
{item.entity && item.entity_type === "ride" && (
|
|
<Badge variant="outline" className="text-xs">
|
|
{(item.entity as Ride).category}
|
|
</Badge>
|
|
)}
|
|
{item.entity && item.entity_type === "company" && (
|
|
<Badge variant="outline" className="text-xs">
|
|
{(item.entity as Company).company_type}
|
|
</Badge>
|
|
)}
|
|
</div>
|
|
{item.notes && (
|
|
<p className="text-sm text-muted-foreground mt-2 italic">
|
|
"{item.notes}"
|
|
</p>
|
|
)}
|
|
</div>
|
|
</li>
|
|
))}
|
|
</ol>
|
|
);
|
|
}
|