From 3e62bbdbd470a8fd6688e4f25a933604261a8998 Mon Sep 17 00:00:00 2001 From: Tara Kaviani Date: Tue, 20 Jan 2026 22:14:18 -0800 Subject: [PATCH 1/2] Request Store Page --- .../request/[storeId]/[storeItemId]/page.tsx | 88 +++++++++++++++++++ app/(main)/request/[storeId]/page.tsx | 80 +++++++++++++++++ .../components/RequestStoreItemCard.tsx | 25 ++++++ 3 files changed, 193 insertions(+) create mode 100644 app/(main)/request/[storeId]/[storeItemId]/page.tsx create mode 100644 app/(main)/request/[storeId]/page.tsx create mode 100644 app/(main)/request/components/RequestStoreItemCard.tsx diff --git a/app/(main)/request/[storeId]/[storeItemId]/page.tsx b/app/(main)/request/[storeId]/[storeItemId]/page.tsx new file mode 100644 index 0000000..8360aec --- /dev/null +++ b/app/(main)/request/[storeId]/[storeItemId]/page.tsx @@ -0,0 +1,88 @@ +import { createClient } from '@/app/lib/supabase/server-client'; + +export default async function RequestStoreItemPage({ + params, +}: { + params: Promise<{ storeId: string; storeItemId: string }>; +}) { + const { storeId, storeItemId } = await params; + + const supabase = await createClient(); + + const { data: storeItem, error: itemError } = await supabase + .from('store_items') + .select( + ` + store_item_id, + quantity_available, + inventory_items ( + name, + description, + photo_url, + subcategories ( + name, + categories ( + name + ) + ) + ) + ` + ) + .eq('store_item_id', storeItemId) + .single(); + + if (itemError) { + console.error('Error fetching store item:', itemError); + return
Failed to load data.
; + } + + const inv = storeItem.inventory_items?.[0]; + const subcat = inv?.subcategories?.[0]; + const category = subcat?.categories?.[0]; + + return ( +
+

Request Item Details

+ +

{inv?.name}

+ + {inv?.photo_url && ( + {inv?.name} + )} + +

+ Description:{' '} + {inv?.description ?? 'No description available'} +

+ +

+ Category: {category?.name ?? 'None'} +

+ +

+ Subcategory: {subcat?.name ?? 'None'} +

+ +

+ Quantity Available:{' '} + {storeItem.quantity_available ?? 'Unknown'} +

+ + + + +
+ ); +} diff --git a/app/(main)/request/[storeId]/page.tsx b/app/(main)/request/[storeId]/page.tsx new file mode 100644 index 0000000..b8b80d4 --- /dev/null +++ b/app/(main)/request/[storeId]/page.tsx @@ -0,0 +1,80 @@ +import { createClient } from '@/app/lib/supabase/server-client'; +import RequestStoreItemCard from '@/app/(main)/request/components/RequestStoreItemCard'; + +export default async function RequestStorePage({ + params, +}: { + params: Promise<{ storeId: string }>; +}) { + const { storeId } = await params; + + const supabase = await createClient(); + const { + data: { user }, + } = await supabase.auth.getUser(); + + const { data: store } = await supabase + .from('stores') + .select('*') + .eq('store_id', storeId) + .single(); + + const { data: storeItems } = await supabase + .from('store_items') + .select( + ` + store_item_id, + inventory_items ( + name, + photo_url, + subcategories ( + name, + categories ( + name + ) + ) + ) + ` + ) + .eq('store_id', storeId) + .eq('hidden', false); + + return ( +
+

Store – {store.name}

+

Street Address: {store.street_address}

+ +

Available Items

+ + {storeItems && storeItems.length > 0 ? ( +
+ {storeItems.map((item) => { + const inv = item.inventory_items?.[0]; + const subcat = inv?.subcategories?.[0]; + const category = subcat?.categories?.[0]; + + return ( + + + + ); + })} +
+ ) : ( +

No items available.

+ )} + + + + +
+ ); +} diff --git a/app/(main)/request/components/RequestStoreItemCard.tsx b/app/(main)/request/components/RequestStoreItemCard.tsx new file mode 100644 index 0000000..bc29dcc --- /dev/null +++ b/app/(main)/request/components/RequestStoreItemCard.tsx @@ -0,0 +1,25 @@ +export default function RequestStoreItemCard({ + name, + subcategoryName, + categoryName, +}: { + name: string | undefined; + subcategoryName: string | undefined; + categoryName: string | undefined; +}) { + return ( +
+

{name}

+

Category: {categoryName}

+

Subcategory: {subcategoryName}

+
+ ); +} \ No newline at end of file From 859ff56d249398ca3b288704b533a065f5413a40 Mon Sep 17 00:00:00 2001 From: Tara Kaviani Date: Tue, 20 Jan 2026 22:58:53 -0800 Subject: [PATCH 2/2] comments --- .../request/[storeId]/[storeItemId]/page.tsx | 18 +++++++++++++----- app/(main)/request/[storeId]/page.tsx | 14 +++++++++++--- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/app/(main)/request/[storeId]/[storeItemId]/page.tsx b/app/(main)/request/[storeId]/[storeItemId]/page.tsx index 8360aec..1185112 100644 --- a/app/(main)/request/[storeId]/[storeItemId]/page.tsx +++ b/app/(main)/request/[storeId]/[storeItemId]/page.tsx @@ -1,14 +1,17 @@ import { createClient } from '@/app/lib/supabase/server-client'; - +// exports server component RequestStoreItemPage export default async function RequestStoreItemPage({ params, }: { params: Promise<{ storeId: string; storeItemId: string }>; }) { - const { storeId, storeItemId } = await params; + const { storeId, storeItemId } = await params; // page takes storeId and storeItemId as props const supabase = await createClient(); + // select store_item_id and quantity_available from store_items + // select name, description, and photo_url from inventory_items + // select subcategories.name and categories.name const { data: storeItem, error: itemError } = await supabase .from('store_items') .select( @@ -28,6 +31,7 @@ export default async function RequestStoreItemPage({ ) ` ) + // match storeItemId .eq('store_item_id', storeItemId) .single(); @@ -35,7 +39,7 @@ export default async function RequestStoreItemPage({ console.error('Error fetching store item:', itemError); return
Failed to load data.
; } - +// extract nested values: name description, category, subcategory const inv = storeItem.inventory_items?.[0]; const subcat = inv?.subcategories?.[0]; const category = subcat?.categories?.[0]; @@ -50,8 +54,8 @@ export default async function RequestStoreItemPage({ }} >

Request Item Details

- -

{inv?.name}

+ {/* display inventory item name */} +

{inv?.name}

{inv?.photo_url && ( )} +{/* Display inventory item description */}

Description:{' '} {inv?.description ?? 'No description available'}

+{/* display category name */}

Category: {category?.name ?? 'None'}

+{/* display subcategory name */}

Subcategory: {subcat?.name ?? 'None'}

+{/* display quantity available */}

Quantity Available:{' '} {storeItem.quantity_available ?? 'Unknown'} diff --git a/app/(main)/request/[storeId]/page.tsx b/app/(main)/request/[storeId]/page.tsx index b8b80d4..068bcb6 100644 --- a/app/(main)/request/[storeId]/page.tsx +++ b/app/(main)/request/[storeId]/page.tsx @@ -1,9 +1,11 @@ import { createClient } from '@/app/lib/supabase/server-client'; import RequestStoreItemCard from '@/app/(main)/request/components/RequestStoreItemCard'; +// server component exported export default async function RequestStorePage({ params, }: { + // takes in storeId as prop params: Promise<{ storeId: string }>; }) { const { storeId } = await params; @@ -13,12 +15,15 @@ export default async function RequestStorePage({ data: { user }, } = await supabase.auth.getUser(); + //fetch store's entry in stores table (filters on store_id) const { data: store } = await supabase .from('stores') .select('*') .eq('store_id', storeId) .single(); +// get all non-hidden store items for store +// fetch nested inventory + category data const { data: storeItems } = await supabase .from('store_items') .select( @@ -40,12 +45,13 @@ export default async function RequestStorePage({ .eq('hidden', false); return ( + // display store's name and street address

Store – {store.name}

Street Address: {store.street_address}

Available Items

- + {/* iterates through store items */} {storeItems && storeItems.length > 0 ? (
{storeItems.map((item) => { @@ -56,20 +62,22 @@ export default async function RequestStorePage({ return ( + {/* pass each store item to a RequestItemCard component */} + /> ); })}
) : ( -

No items available.

+

N/A. No items to display.

)}