From 93c03dea3c243906a7330b64287ccdb2fae9238d Mon Sep 17 00:00:00 2001 From: Amr Gaber Date: Fri, 6 Feb 2026 18:24:45 -0600 Subject: [PATCH] Extract shared ItemCard component with value and date Move ItemCard into its own component at src/components/item-card.tsx and use it in both the All Items page and collection detail page. Cards now consistently show estimated value, date added, collection name badge, tag badges, and condition badge everywhere. --- src/components/item-card.tsx | 73 +++++++++++++++++++ .../collections/collection-detail-page.tsx | 49 +------------ src/pages/items/all-items-page.tsx | 71 +----------------- 3 files changed, 75 insertions(+), 118 deletions(-) create mode 100644 src/components/item-card.tsx diff --git a/src/components/item-card.tsx b/src/components/item-card.tsx new file mode 100644 index 0000000..5072ed9 --- /dev/null +++ b/src/components/item-card.tsx @@ -0,0 +1,73 @@ +import { Link } from "@tanstack/react-router" +import { Package } from "lucide-react" +import type { ItemRead } from "@/api/generated/types" +import { ImageCarousel } from "@/components/image-carousel" +import { Badge } from "@/components/ui/badge" +import { Card, CardContent } from "@/components/ui/card" + +export function ItemCard({ item }: { item: ItemRead }) { + const images = item.images ?? [] + return ( + + + {images.length > 0 ? ( + + ) : ( +
+ +
+ )} + +

{item.name}

+ {item.description && ( +

+ {item.description} +

+ )} +
+ {item.estimated_value && ( + + $ + {parseFloat(item.estimated_value).toLocaleString(undefined, { + minimumFractionDigits: 2, + maximumFractionDigits: 2, + })} + + )} + {item.estimated_value && item.created_at && ·} + + {new Date(item.created_at).toLocaleDateString(undefined, { + month: "short", + day: "numeric", + year: "numeric", + })} + +
+
+ {item.collection_name && ( + + {item.collection_name} + + )} + {item.tags?.map((t) => ( + + {t.name} + + ))} + {item.condition && item.condition !== "unknown" && ( + + {item.condition} + + )} +
+
+
+ + ) +} diff --git a/src/pages/collections/collection-detail-page.tsx b/src/pages/collections/collection-detail-page.tsx index f642960..d449b6b 100644 --- a/src/pages/collections/collection-detail-page.tsx +++ b/src/pages/collections/collection-detail-page.tsx @@ -30,9 +30,8 @@ import { useCreateItemNoteItemsItemIdNotesPost } from "@/api/generated/hooks/not import type { ItemRead } from "@/api/generated/types" import { getErrorMessage } from "@/lib/api-errors" import { AppLayout } from "@/components/app-layout" -import { ImageCarousel } from "@/components/image-carousel" +import { ItemCard } from "@/components/item-card" import { Button } from "@/components/ui/button" -import { Badge } from "@/components/ui/badge" import { Card, CardContent } from "@/components/ui/card" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" @@ -259,52 +258,6 @@ export function CollectionDetailPage() { ) } -function ItemCard({ item }: { item: ItemRead }) { - const images = item.images ?? [] - return ( - - - {images.length > 0 ? ( - - ) : ( -
- -
- )} - -

{item.name}

- {item.description && ( -

- {item.description} -

- )} - {((item.tags && item.tags.length > 0) || - (item.condition && item.condition !== "unknown")) && ( -
- {item.tags?.map((t) => ( - - {t.name} - - ))} - {item.condition && item.condition !== "unknown" && ( - - {item.condition} - - )} -
- )} -
-
- - ) -} - function CollectionHeaderSkeleton() { return (
diff --git a/src/pages/items/all-items-page.tsx b/src/pages/items/all-items-page.tsx index 927b766..ce4e13d 100644 --- a/src/pages/items/all-items-page.tsx +++ b/src/pages/items/all-items-page.tsx @@ -4,11 +4,9 @@ import { ArrowLeft, Package, Search, ChevronsUpDown } from "lucide-react" import { useListItemsItemsGet } from "@/api/generated/hooks/items/items" import { useListCollectionsCollectionsGet } from "@/api/generated/hooks/collections/collections" import { useListTagsTagsGet } from "@/api/generated/hooks/tags/tags" -import type { ItemRead } from "@/api/generated/types" import { AppLayout } from "@/components/app-layout" -import { ImageCarousel } from "@/components/image-carousel" +import { ItemCard } from "@/components/item-card" import { Button } from "@/components/ui/button" -import { Badge } from "@/components/ui/badge" import { Card, CardContent } from "@/components/ui/card" import { Input } from "@/components/ui/input" import { Skeleton } from "@/components/ui/skeleton" @@ -229,73 +227,6 @@ export function AllItemsPage() { ) } -function ItemCard({ item }: { item: ItemRead }) { - const images = item.images ?? [] - return ( - - - {images.length > 0 ? ( - - ) : ( -
- -
- )} - -

{item.name}

- {item.description && ( -

- {item.description} -

- )} -
- {item.estimated_value && ( - - $ - {parseFloat(item.estimated_value).toLocaleString(undefined, { - minimumFractionDigits: 2, - maximumFractionDigits: 2, - })} - - )} - {item.estimated_value && item.created_at && ·} - - {new Date(item.created_at).toLocaleDateString(undefined, { - month: "short", - day: "numeric", - year: "numeric", - })} - -
-
- {item.collection_name && ( - - {item.collection_name} - - )} - {item.tags?.map((t) => ( - - {t.name} - - ))} - {item.condition && item.condition !== "unknown" && ( - - {item.condition} - - )} -
-
-
- - ) -} - function ItemsSkeleton() { return (