Refactor user lists

This commit is contained in:
gpt-engineer-app[bot]
2025-10-02 03:38:55 +00:00
parent 7df81a6ba0
commit 8ec0d59e75
7 changed files with 1041 additions and 0 deletions

View File

@@ -0,0 +1,154 @@
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>
);
}