diff --git a/Inputs/Tech stack for MyFavStuff.md b/Inputs/Tech stack for MyFavStuff.md index 4ae1dec..0de0f52 100644 --- a/Inputs/Tech stack for MyFavStuff.md +++ b/Inputs/Tech stack for MyFavStuff.md @@ -7,4 +7,15 @@ The tech stack for MyFavStuff should be based on: - Authentication: basic_auth with Caddy (reverse proxy) to get started with (You shouldn't do anything about this yet) - +# Coding pattern preferences +- Always prefer simple solutions +- Avoid duplication of code whenever possible, which means checking for other areas of the codebase that might already have similar code and functionality +- Write code that takes into account the different environments: dev, test and prod +- You are careful to only make changes that are requested or you are confident that all changes are well understood and related to the change being requested +- When fixing an issue or bug, do not introduce a new pattern or technology without first exhausting all options for the existing implementation. And if you finally do this, make sure to remove the old implementation afterwards so we don't have duplicate logic. +- Keep the codebase very clean and organized +- Avoid writing scripts in files if possible, especially if the script is likely only to be run once +- Avoid having files over 200-300 lines of code. Refactor at that point +- Mocking data is only needed for test, never mock data for dev or prod +- Never add stubbing or fake data patterns to code that affects the dev or prod environments +- Never overwrite my .env file without first asking and confirming diff --git a/myfavstuff/app/add-item/actions.js b/myfavstuff/app/add-item/actions.js new file mode 100644 index 0000000..b582e7c --- /dev/null +++ b/myfavstuff/app/add-item/actions.js @@ -0,0 +1,50 @@ +// app/add-item/actions.js +'use server'; + +import { supabase } from '@/lib/supabaseClient'; // Assuming alias @ is configured for root +import { revalidatePath } from 'next/cache'; +import { redirect } from 'next/navigation'; + +export async function createItem(formData) { + if (!supabase) { + return { error: 'Supabase client is not initialized. Cannot create item.' }; + } + + const newItem = { + title: formData.get('title'), + type: formData.get('type'), + rating: formData.get('rating') ? parseInt(formData.get('rating'), 10) : null, + notes: formData.get('notes'), + image_url: formData.get('image_url'), + // created_at will be set by default in Supabase or can be added here if needed + }; + + // Basic validation + if (!newItem.title || !newItem.type) { + return { error: 'Title and Type are required.' }; + } + if (newItem.rating !== null && (newItem.rating < 1 || newItem.rating > 5)) { + return { error: 'Rating must be between 1 and 5.' }; + } + + try { + const { data, error } = await supabase + .from('items') + .insert([newItem]) + .select(); // .select() to get the inserted data back + + if (error) { + console.error('Supabase insert error:', error); + return { error: `Failed to create item: ${error.message}` }; + } + + console.log('Item created successfully:', data); + revalidatePath('/'); // Revalidate the homepage to show the new item + // No explicit redirect here, form can handle success message + return { success: true, message: 'Item added successfully!', createdItem: data ? data[0] : null }; + + } catch (e) { + console.error('Error in createItem action:', e); + return { error: 'An unexpected error occurred.' }; + } +} diff --git a/myfavstuff/app/add-item/page.js b/myfavstuff/app/add-item/page.js index 26f5237..fd388f9 100644 --- a/myfavstuff/app/add-item/page.js +++ b/myfavstuff/app/add-item/page.js @@ -1,11 +1,134 @@ // app/add-item/page.js +'use client'; + +import { useState, useTransition } from 'react'; +import { createItem } from './actions'; // Server Action +import { useRouter } from 'next/navigation'; export default function AddItemPage() { + const router = useRouter(); + const [isPending, startTransition] = useTransition(); + const [error, setError] = useState(null); + const [successMessage, setSuccessMessage] = useState(''); + + const handleSubmit = async (event) => { + event.preventDefault(); + setError(null); + setSuccessMessage(''); + const formData = new FormData(event.currentTarget); + + startTransition(async () => { + const result = await createItem(formData); + if (result.error) { + setError(result.error); + } else if (result.success) { + setSuccessMessage(result.message); + // Optionally clear the form or redirect + event.target.reset(); // Clear form fields + // router.push('/'); // Or redirect to homepage after a delay + setTimeout(() => router.push('/'), 1500); // Redirect after 1.5s + } + }); + }; + return ( -
-

Add New Item

-

This is where the form to add a new item will go.

- {/* You can add your form component or elements here */} +
+
+

Add New Favorite Item

+

+ Fill in the details below to add a new item to your collection. +

+
+ + {error && ( +
+

Error:

+

{error}

+
+ )} + {successMessage && ( +
+

Success:

+

{successMessage}

+
+ )} + +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+
); }