From 3b180728e1a5c7e7d84f7d7b5295afa9a2a2fd6e Mon Sep 17 00:00:00 2001 From: Greg Date: Sun, 18 May 2025 16:03:53 +0200 Subject: [PATCH] feat: implement initial app layout and Supabase integration with item grid display --- myfavstuff/app/layout.js | 36 +++++- myfavstuff/app/page.js | 191 ++++++++++++++++--------------- myfavstuff/lib/supabaseClient.js | 23 ++++ 3 files changed, 152 insertions(+), 98 deletions(-) create mode 100644 myfavstuff/lib/supabaseClient.js diff --git a/myfavstuff/app/layout.js b/myfavstuff/app/layout.js index 7bf337d..4a923b4 100644 --- a/myfavstuff/app/layout.js +++ b/myfavstuff/app/layout.js @@ -12,17 +12,45 @@ const geistMono = Geist_Mono({ }); export const metadata = { - title: "Create Next App", - description: "Generated by create next app", + title: "MyFavStuff", + description: "A curated collection of favorite things.", }; +// Basic Navbar component (can be moved to its own file later) +function Navbar() { + return ( + + ); +} + export default function RootLayout({ children }) { return ( - {children} + +
+ {children} +
+
+ © {new Date().getFullYear()} MyFavStuff. All rights reserved. +
); diff --git a/myfavstuff/app/page.js b/myfavstuff/app/page.js index 560d8bf..e8c3c70 100644 --- a/myfavstuff/app/page.js +++ b/myfavstuff/app/page.js @@ -1,103 +1,106 @@ -import Image from "next/image"; +import { supabase } from '../lib/supabaseClient'; + +// Function to generate star ratings +const StarRating = ({ rating }) => { + const totalStars = 5; + let stars = []; + for (let i = 1; i <= totalStars; i++) { + stars.push( + + ★ + + ); + } + return
{stars}
; +}; + +export default async function Home() { + let items = []; + let fetchError = null; + + if (supabase) { + try { + const { data, error } = await supabase + .from('items') + .select('*') + .order('created_at', { ascending: false }); // Assuming you have a created_at timestamp + + if (error) { + throw error; + } + items = data || []; + } catch (error) { + console.error('Error fetching items:', error.message); + fetchError = 'Could not fetch items. Please check the connection and try again.'; + // If Supabase client isn't initialized (e.g. missing .env.local), items will remain [] + // and this error message will be displayed if supabase itself was the issue. + } + } else { + fetchError = 'Supabase client is not initialized. Please check your .env.local file and ensure it has the correct Supabase URL and Anon key.'; + } + -export default function Home() { return ( -
-
- Next.js logo -
    -
  1. - Get started by editing{" "} - - app/page.js - - . -
  2. -
  3. - Save and see your changes instantly. -
  4. -
+
+
+

My Favorite Stuff

+

+ A curated list of things I've enjoyed, in reverse chronological order. +

+
- + )} + + {!fetchError && items.length === 0 && ( + -
- + )} + + {items.length > 0 && ( +
+ {items.map((item) => ( +
+ {item.image_url ? ( +
+ {item.title +
+ ) : ( +
+ No Image +
+ )} +

{item.title || 'Untitled'}

+

{item.type || 'N/A'}

+ {typeof item.rating === 'number' && } + {item.notes && ( +

+ {item.notes} +

+ )} + {/* Placeholder for a details link/modal trigger */} + {/* + View Details + */} +
+ ))} +
+ )}
); } diff --git a/myfavstuff/lib/supabaseClient.js b/myfavstuff/lib/supabaseClient.js new file mode 100644 index 0000000..acec01e --- /dev/null +++ b/myfavstuff/lib/supabaseClient.js @@ -0,0 +1,23 @@ +import { createClient } from '@supabase/supabase-js'; + +const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL; +const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY; + +if (!supabaseUrl) { + console.error('Error: Missing Supabase URL. Please set NEXT_PUBLIC_SUPABASE_URL in .env.local'); +} + +if (!supabaseAnonKey) { + console.error('Error: Missing Supabase Anon Key. Please set NEXT_PUBLIC_SUPABASE_ANON_KEY in .env.local'); +} + +// Ensure client is only created if keys are present, to avoid errors during build or in environments where keys might not be set. +// The actual fetch operations in components should handle cases where supabase might not be initialized. +let supabaseInstance = null; +if (supabaseUrl && supabaseAnonKey) { + supabaseInstance = createClient(supabaseUrl, supabaseAnonKey); +} else { + console.warn('Supabase client not initialized due to missing URL or Anon Key. App will run without Supabase functionality.'); +} + +export const supabase = supabaseInstance;