From 5867fb82ffe00b2179b8f0f6bc5a1618a36a796e Mon Sep 17 00:00:00 2001 From: phillip-tech Date: Mon, 21 Oct 2024 15:19:06 +0200 Subject: [PATCH 01/62] nav bar setup --- app/components/Navbar.jsx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/components/Navbar.jsx b/app/components/Navbar.jsx index e69de29..c9f7dd2 100644 --- a/app/components/Navbar.jsx +++ b/app/components/Navbar.jsx @@ -0,0 +1,9 @@ +import React from 'react' + +export default function NavBar() { + return ( +
+ +
+ ) +} From d26196a8ed3aab629b6951c5199a5e59cbd1dbde Mon Sep 17 00:00:00 2001 From: kutlwano10 Date: Mon, 21 Oct 2024 15:42:37 +0200 Subject: [PATCH 02/62] Created an Api endpoint to fetch Data --- app/api/recipe/[id]/route.js | 14 ++++++++++++++ app/api/recipe/route.js | 14 ++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 app/api/recipe/[id]/route.js create mode 100644 app/api/recipe/route.js diff --git a/app/api/recipe/[id]/route.js b/app/api/recipe/[id]/route.js new file mode 100644 index 0000000..894fae3 --- /dev/null +++ b/app/api/recipe/[id]/route.js @@ -0,0 +1,14 @@ +const fetchSingleRecipe = async (id) => { + try { + const res = await fetch(`https://dummyjson.com/recipes/${id}`, {cache : 'force-cache'}); + if (!res.ok) { + throw new Error("Fetch Product Failed"); + } + const data = await res.json(); + return data; + } catch (error) { + console.error("Failed to Fetch Data:", error) + } + }; + + export default fetchSingleRecipe; \ No newline at end of file diff --git a/app/api/recipe/route.js b/app/api/recipe/route.js new file mode 100644 index 0000000..5bed881 --- /dev/null +++ b/app/api/recipe/route.js @@ -0,0 +1,14 @@ +const fetchRecipes = async () => { + try { + const res = await fetch("https://dummyjson.com/recipes", {cache : 'force-cache'}); + if (!res.ok) { + throw new Error("Fetch Products Failed"); + } + const data = await res.json(); + return data; + } catch (error) { + console.error("Failed to Fetch Data:", error) + } +}; + +export default fetchRecipes; From eaf326b2a4af3016148059f65918bc7b1a3a7dae Mon Sep 17 00:00:00 2001 From: Koketso Moilwe Date: Mon, 21 Oct 2024 16:13:11 +0200 Subject: [PATCH 03/62] use client-side rendering for RecipeGrid component - Added 'use client' directive to enable client-side rendering - Imported React, useState, and useEffect hooks - Integrated RecipeCards component for displaying recipe data --- app/components/RecipeGrid.jsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/components/RecipeGrid.jsx b/app/components/RecipeGrid.jsx index e69de29..d27c5fb 100644 --- a/app/components/RecipeGrid.jsx +++ b/app/components/RecipeGrid.jsx @@ -0,0 +1,4 @@ +"use client" + +import React, { useEffect, useState } from 'react'; +import RecipeCards from './RecipeCards'; From 32d01552868709b5dadf49aebc63cd9b9c09272c Mon Sep 17 00:00:00 2001 From: Koketso Moilwe Date: Mon, 21 Oct 2024 16:14:34 +0200 Subject: [PATCH 04/62] implement useState for managing recipe data in RecipeGrid - Added useState to store and manage fetched recipes - Set up initial state for recipes as an empty array - Prepared RecipeGrid for client-side data fetching --- app/components/RecipeGrid.jsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/components/RecipeGrid.jsx b/app/components/RecipeGrid.jsx index d27c5fb..f64963b 100644 --- a/app/components/RecipeGrid.jsx +++ b/app/components/RecipeGrid.jsx @@ -2,3 +2,7 @@ import React, { useEffect, useState } from 'react'; import RecipeCards from './RecipeCards'; + +const RecipeGrid = () => { + const [recipes, setRecipes] = useState([]); + From 21eac7449eed9abb990061bfa86a8dab87b81d84 Mon Sep 17 00:00:00 2001 From: Koketso Moilwe Date: Mon, 21 Oct 2024 16:17:14 +0200 Subject: [PATCH 05/62] add useEffect hook for fetching recipe data - Implemented useEffect to fetch recipes from the API - Fetched recipe data from 'https://dummyjson.com/recipes' - Updated state with fetched recipes and handled potential errors --- app/components/RecipeGrid.jsx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/app/components/RecipeGrid.jsx b/app/components/RecipeGrid.jsx index f64963b..627bf72 100644 --- a/app/components/RecipeGrid.jsx +++ b/app/components/RecipeGrid.jsx @@ -6,3 +6,16 @@ import RecipeCards from './RecipeCards'; const RecipeGrid = () => { const [recipes, setRecipes] = useState([]); + useEffect(() => { + const fetchRecipes = async () => { + try { + const response = await fetch('https://dummyjson.com/recipes'); + const data = await response.json(); + setRecipes(data.recipes); + } catch (error) { + console.error('Error fetching recipes:', error); + } + }; + + fetchRecipes(); + }, []); From cf9ecb711413cdd2f310a58f15f31009fb41db39 Mon Sep 17 00:00:00 2001 From: Koketso Moilwe Date: Mon, 21 Oct 2024 16:18:32 +0200 Subject: [PATCH 06/62] render RecipeCards in a responsive grid layout - Display RecipeCards using a responsive grid with Tailwind CSS - Passed recipe data to RecipeCards component - Utilized grid layout for different screen sizes with padding and spacing --- app/components/RecipeGrid.jsx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/components/RecipeGrid.jsx b/app/components/RecipeGrid.jsx index 627bf72..5cddc37 100644 --- a/app/components/RecipeGrid.jsx +++ b/app/components/RecipeGrid.jsx @@ -19,3 +19,14 @@ const RecipeGrid = () => { fetchRecipes(); }, []); + + return ( +
+ {recipes.map(recipe => ( + + ))} +
+ ); +}; + +export default RecipeGrid; From 60ea6b8c029e5d57f05844773c6c6e3e96ae5e48 Mon Sep 17 00:00:00 2001 From: Koketso Moilwe Date: Mon, 21 Oct 2024 16:19:44 +0200 Subject: [PATCH 07/62] create RecipeCard component for displaying recipe details - Rendered recipe image, title, prep time, cook time, and rating - Styled the card with Tailwind CSS using shadow, rounded corners, and padding - Displayed rating with a star icon and appropriate formatting --- app/components/RecipeCards.jsx | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/app/components/RecipeCards.jsx b/app/components/RecipeCards.jsx index e69de29..ef1f236 100644 --- a/app/components/RecipeCards.jsx +++ b/app/components/RecipeCards.jsx @@ -0,0 +1,20 @@ +import React from 'react'; + +const RecipeCard = ({ recipe }) => { + return ( +
+ {recipe.title} +
+

{recipe.title}

+

Prep time: {recipe.prepTimeMinutes} mins

+

Cook time: {recipe.cookTimeMinutes} mins

+
+ + {recipe.rating} +
+
+
+ ); +}; + +export default RecipeCard; From 6d750a64c2a8c25c8f791bacb995b13a09c02ca2 Mon Sep 17 00:00:00 2001 From: Koketso Moilwe Date: Mon, 21 Oct 2024 16:20:12 +0200 Subject: [PATCH 08/62] Render RecipeGrid component --- app/page.js | 97 ++++------------------------------------------------- 1 file changed, 6 insertions(+), 91 deletions(-) diff --git a/app/page.js b/app/page.js index 7f0afc2..c086860 100644 --- a/app/page.js +++ b/app/page.js @@ -1,101 +1,16 @@ -import Image from "next/image"; +import RecipeGrid from "./components/RecipeGrid"; // Make sure the path is correct 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. -
- + {/* RecipeGrid component added here */} +
+ +
- +
); } From aa77c910611cfabd82e16f4339043d7f5f18e2bb Mon Sep 17 00:00:00 2001 From: Kitso Mogale Date: Mon, 21 Oct 2024 16:41:15 +0200 Subject: [PATCH 09/62] loading state with skeletonMain component --- app/components/SkeletonMain.jsx | 23 +++++++++++++++++++++++ app/loading.jsx | 8 ++++++++ 2 files changed, 31 insertions(+) create mode 100644 app/components/SkeletonMain.jsx create mode 100644 app/loading.jsx diff --git a/app/components/SkeletonMain.jsx b/app/components/SkeletonMain.jsx new file mode 100644 index 0000000..73b4fec --- /dev/null +++ b/app/components/SkeletonMain.jsx @@ -0,0 +1,23 @@ +const SkeletonGrid = () => { + return ( +
+ {/* Creating 8 skeletons to mimic the recipe cards */} + {Array(8).fill("").map((_, index) => ( +
+ {/* Image Skeleton */} +
+ {/* Text Skeleton */} +
+
+
+
+
+ ))} +
+ ); + }; + + export default SkeletonGrid; \ No newline at end of file diff --git a/app/loading.jsx b/app/loading.jsx new file mode 100644 index 0000000..7f50bed --- /dev/null +++ b/app/loading.jsx @@ -0,0 +1,8 @@ +import React from 'react' +import SkeletonGrid from './components/SkeletonMain' + +export default function loading() { + return ( + + ) +} From 1c0799a335f2b1b495a631e4248e5896187f2056 Mon Sep 17 00:00:00 2001 From: Koketso Moilwe Date: Mon, 21 Oct 2024 16:45:02 +0200 Subject: [PATCH 10/62] change title to name for recipe name display --- app/components/RecipeCards.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/components/RecipeCards.jsx b/app/components/RecipeCards.jsx index ef1f236..d4a6f41 100644 --- a/app/components/RecipeCards.jsx +++ b/app/components/RecipeCards.jsx @@ -5,7 +5,7 @@ const RecipeCard = ({ recipe }) => {
{recipe.title}
-

{recipe.title}

+

{recipe.name}

Prep time: {recipe.prepTimeMinutes} mins

Cook time: {recipe.cookTimeMinutes} mins

From a6684e35ad3657ecaaddb0e24748bad0b207d0a9 Mon Sep 17 00:00:00 2001 From: SABELOMAWELA Date: Mon, 21 Oct 2024 19:03:52 +0200 Subject: [PATCH 11/62] Testing --- app/components/Productdetail.jsx | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 app/components/Productdetail.jsx diff --git a/app/components/Productdetail.jsx b/app/components/Productdetail.jsx new file mode 100644 index 0000000..e69de29 From 4740d09cf5c5bfadf08e077d527780a199363d22 Mon Sep 17 00:00:00 2001 From: SABELOMAWELA Date: Mon, 21 Oct 2024 21:51:43 +0200 Subject: [PATCH 12/62] "Wrapped RecipeCard component with Next.js Link component, adding navigation to recipe details page." --- app/components/Productdetail.jsx | 0 app/components/RecipeCards.jsx | 27 ++++++++++++++++----------- 2 files changed, 16 insertions(+), 11 deletions(-) delete mode 100644 app/components/Productdetail.jsx diff --git a/app/components/Productdetail.jsx b/app/components/Productdetail.jsx deleted file mode 100644 index e69de29..0000000 diff --git a/app/components/RecipeCards.jsx b/app/components/RecipeCards.jsx index d4a6f41..5788019 100644 --- a/app/components/RecipeCards.jsx +++ b/app/components/RecipeCards.jsx @@ -1,19 +1,24 @@ import React from 'react'; +import Link from 'next/link'; const RecipeCard = ({ recipe }) => { return ( -
- {recipe.title} -
-

{recipe.name}

-

Prep time: {recipe.prepTimeMinutes} mins

-

Cook time: {recipe.cookTimeMinutes} mins

-
- - {recipe.rating} + + +
+ {recipe.title} +
+

{recipe.name}

+

Prep time: {recipe.prepTimeMinutes} mins

+

Cook time: {recipe.cookTimeMinutes} mins

+
+ + {recipe.rating} +
+
-
-
+ + ); }; From c69e292ce6ad27176b958db9f215c13496fcd57d Mon Sep 17 00:00:00 2001 From: SABELOMAWELA Date: Mon, 21 Oct 2024 22:33:15 +0200 Subject: [PATCH 13/62] "Display recipe title and description on the recipe detail page" --- app/recipes/[id]/page.jsx | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 app/recipes/[id]/page.jsx diff --git a/app/recipes/[id]/page.jsx b/app/recipes/[id]/page.jsx new file mode 100644 index 0000000..1d4b769 --- /dev/null +++ b/app/recipes/[id]/page.jsx @@ -0,0 +1,28 @@ + +"use client" +import { useEffect, useState } from 'react'; +import fetchSingleRecipe from '../../api/recipe/[id]/route'; + +const RecipeDetail = ({ params }) => { + const { id } = params; + const [recipe, setRecipe] = useState(null); + + useEffect(() => { + const getRecipe = async () => { + const data = await fetchSingleRecipe(id); + if (data) { + setRecipe(data); + } + }; + getRecipe(); + }, [id]); + + return ( +
+

{recipe?.name}

+

{recipe?.instructions?.join(", ")}

+
+ ); +}; + +export default RecipeDetail; \ No newline at end of file From 83213f4d797b564757fc9510ac26c625cdbf7f30 Mon Sep 17 00:00:00 2001 From: SABELOMAWELA Date: Mon, 21 Oct 2024 23:22:18 +0200 Subject: [PATCH 14/62] "Added servings information to RecipeCard component and reformatted layout" --- app/components/RecipeCards.jsx | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/app/components/RecipeCards.jsx b/app/components/RecipeCards.jsx index 5788019..f0ab765 100644 --- a/app/components/RecipeCards.jsx +++ b/app/components/RecipeCards.jsx @@ -4,20 +4,25 @@ import Link from 'next/link'; const RecipeCard = ({ recipe }) => { return ( - -
- {recipe.title} -
-

{recipe.name}

-

Prep time: {recipe.prepTimeMinutes} mins

-

Cook time: {recipe.cookTimeMinutes} mins

-
+
+ {recipe.title} +
+

{recipe.name}

+

Prep time: {recipe.prepTimeMinutes} mins

+

Cook time: {recipe.cookTimeMinutes} mins

+ + +
+
{recipe.rating}
+
+ Servings: {recipe.servings} +
- +
); }; From d554da4267702f2aac62c11c740562de2716e882 Mon Sep 17 00:00:00 2001 From: SABELOMAWELA Date: Tue, 22 Oct 2024 07:04:26 +0200 Subject: [PATCH 15/62] "Added formatTime function, updated RecipeDetail component to display additional recipe details, and reformatted JSX code" --- app/recipes/[id]/page.jsx | 54 ++++++++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/app/recipes/[id]/page.jsx b/app/recipes/[id]/page.jsx index 1d4b769..e37c44e 100644 --- a/app/recipes/[id]/page.jsx +++ b/app/recipes/[id]/page.jsx @@ -1,10 +1,16 @@ - "use client" import { useEffect, useState } from 'react'; -import fetchSingleRecipe from '../../api/recipe/[id]/route'; +import fetchSingleRecipe from '../../api/recipe/[id]/route'; + + +const formatTime = (minutes) => { + const hours = Math.floor(minutes / 60); + const mins = minutes % 60; + return hours > 0 ? `${hours}h ${mins}m` : `${mins}m`; +}; const RecipeDetail = ({ params }) => { - const { id } = params; + const { id } = params; const [recipe, setRecipe] = useState(null); useEffect(() => { @@ -17,12 +23,48 @@ const RecipeDetail = ({ params }) => { getRecipe(); }, [id]); + + if (!recipe) { + return null; + } + + + const totalTime = recipe.prepTimeMinutes + recipe.cookTimeMinutes; + return (
-

{recipe?.name}

-

{recipe?.instructions?.join(", ")}

+

{recipe.name}

+ + {recipe.name} + +
+

Prep Time: {formatTime(recipe.prepTimeMinutes)}

+

Cook Time: {formatTime(recipe.cookTimeMinutes)}

+

Total Time: {formatTime(totalTime)}

+

Servings: {recipe.servings} servings

+
+ + +
+

Ingredients:

+
    + {recipe.ingredients.map((ingredient, index) => ( +
  • {ingredient}
  • + ))} +
+
+ + +
+

Instructions:

+
    + {recipe.instructions.map((instruction, index) => ( +
  • {instruction}
  • + ))} +
+
); }; -export default RecipeDetail; \ No newline at end of file +export default RecipeDetail; From d54d53bd91ded20c6e10f6b962a941b7ca784df6 Mon Sep 17 00:00:00 2001 From: SABELOMAWELA Date: Tue, 22 Oct 2024 09:30:26 +0200 Subject: [PATCH 16/62] "Refactored RecipeDetail component to include router, added active tab state, and rearranged layout with new CSS classes" --- app/recipes/[id]/page.jsx | 125 ++++++++++++++++++++++++++++---------- 1 file changed, 92 insertions(+), 33 deletions(-) diff --git a/app/recipes/[id]/page.jsx b/app/recipes/[id]/page.jsx index e37c44e..5cd175a 100644 --- a/app/recipes/[id]/page.jsx +++ b/app/recipes/[id]/page.jsx @@ -1,6 +1,7 @@ -"use client" -import { useEffect, useState } from 'react'; -import fetchSingleRecipe from '../../api/recipe/[id]/route'; +"use client"; +import { useEffect, useState } from "react"; +import { useRouter } from "next/navigation"; +import fetchSingleRecipe from "../../api/recipe/[id]/route"; const formatTime = (minutes) => { @@ -12,6 +13,8 @@ const formatTime = (minutes) => { const RecipeDetail = ({ params }) => { const { id } = params; const [recipe, setRecipe] = useState(null); + const [activeTab, setActiveTab] = useState("ingredients"); + const router = useRouter(); useEffect(() => { const getRecipe = async () => { @@ -23,45 +26,101 @@ const RecipeDetail = ({ params }) => { getRecipe(); }, [id]); - if (!recipe) { - return null; + return null; } - const totalTime = recipe.prepTimeMinutes + recipe.cookTimeMinutes; return ( -
-

{recipe.name}

- - {recipe.name} - -
-

Prep Time: {formatTime(recipe.prepTimeMinutes)}

-

Cook Time: {formatTime(recipe.cookTimeMinutes)}

-

Total Time: {formatTime(totalTime)}

-

Servings: {recipe.servings} servings

-
- +
-
-

Ingredients:

-
    - {recipe.ingredients.map((ingredient, index) => ( -
  • {ingredient}
  • - ))} -
-
+ + + +
+
+ {recipe.name} +
+ +
+ +

+ {recipe.name} +

+ + +

+ Discover how to make this delicious {recipe.name}. Perfect for {recipe.mealType || "any occasion"}. +

+ +
+

+ Prep Time: {formatTime(recipe.prepTimeMinutes)} +

+

+ Cook Time: {formatTime(recipe.cookTimeMinutes)} +

+

+ Total Time: {formatTime(totalTime)} +

+

+ Servings: {recipe.servings} servings +

+
+ +
    +
  • setActiveTab("ingredients")} + > + Ingredients +
  • +
  • setActiveTab("instructions")} + > + Instructions +
  • +
-
-

Instructions:

-
    - {recipe.instructions.map((instruction, index) => ( -
  • {instruction}
  • - ))} -
+ +
+ {activeTab === "ingredients" ? ( +
+

Ingredients

+
    + {recipe.ingredients.map((ingredient, index) => ( +
  • {ingredient}
  • + ))} +
+
+ ) : ( +
+

Instructions

+
    + {recipe.instructions.map((instruction, index) => ( +
  • {instruction}
  • + ))} +
+
+ )} +
+
); From a611b3ec160e31a8181452d9c48c2f7cc7915465 Mon Sep 17 00:00:00 2001 From: phillip-tech Date: Tue, 22 Oct 2024 10:26:52 +0200 Subject: [PATCH 17/62] "Updated Navbar component, removed RecipeCards component, refactored RecipeGrid component, and updated dependencies in package.json" --- app/components/Footer.jsx | 141 ++++++++++++++++++ app/components/Navbar.jsx | 122 ++++++++++++++- .../{RecipeCards.jsx => RecipeCard.jsx} | 3 +- app/components/RecipeGrid.jsx | 9 +- app/layout.js | 49 +++--- app/page.js | 12 +- package-lock.json | 62 +++++++- package.json | 11 +- 8 files changed, 359 insertions(+), 50 deletions(-) create mode 100644 app/components/Footer.jsx rename app/components/{RecipeCards.jsx => RecipeCard.jsx} (89%) diff --git a/app/components/Footer.jsx b/app/components/Footer.jsx new file mode 100644 index 0000000..237906e --- /dev/null +++ b/app/components/Footer.jsx @@ -0,0 +1,141 @@ +import { AiOutlineArrowRight } from 'react-icons/ai'; // Correct icon import for ArrowRight +import { FaUtensils, FaEnvelope, FaPhone, FaMapPin, FaTwitter, FaYoutube, FaFacebook, FaInstagram } from 'react-icons/fa'; // Correct icon imports +import Link from 'next/link'; // Corrected import for Link + +const Footer = () => { + const socialLinks = [ + { + icon: FaTwitter, + href: 'https://twitter.com', + color: 'hover:text-[#1DA1F2] transition-colors duration-300', + label: 'Twitter' + }, + { + icon: FaYoutube, + href: 'https://youtube.com', + color: 'hover:text-[#FF0000] transition-colors duration-300', + label: 'YouTube' + }, + { + icon: FaFacebook, + href: 'https://facebook.com', + color: 'hover:text-[#4267B2] transition-colors duration-300', + label: 'Facebook' + }, + { + icon: FaInstagram, + href: 'https://instagram.com', + color: 'hover:text-[#E1306C] transition-colors duration-300', + label: 'Instagram' + }, + ]; + + const quickLinks = [ + { name: 'About Us', href: '/about' }, + { name: 'Contact', href: '/contact' }, + { name: 'Recipe Index', href: '/recipes' }, + { name: 'Privacy Policy', href: '/privacy' }, + { name: 'Terms of Service', href: '/terms' }, + ]; + + return ( +
+
+ {/* Main Footer Content */} +
+ {/* About Section */} +
+

+ + RecipeApp +

+

+ Discover and share delicious recipes from around the world. +

+
+ + {/* Quick Links */} +
+

Quick Links

+
    + {quickLinks.map((link) => ( +
  • + + + {link.name} + +
  • + ))} +
+
+ + {/* Contact Info */} +
+

Contact Us

+
    +
  • + + contact@recipeapp.com +
  • +
  • + + +1 (555) 123-4567 +
  • +
  • + + 123 Recipe Street, Foodville +
  • +
+
+ + {/* Newsletter */} +
+

Newsletter

+

+ Subscribe for new recipes and cooking tips. +

+
+ + +
+
+
+ + {/* Social Links */} +
+
+
+ {socialLinks.map((social) => ( + + + + ))} +
+

+ © {new Date().getFullYear()} RecipeApp. All rights reserved. +

+
+
+
+
+ ); +}; + +export default Footer; + diff --git a/app/components/Navbar.jsx b/app/components/Navbar.jsx index c9f7dd2..036dff6 100644 --- a/app/components/Navbar.jsx +++ b/app/components/Navbar.jsx @@ -1,9 +1,117 @@ -import React from 'react' +'use client'; + +import React, { useState, useEffect } from 'react'; +import Link from 'next/link'; + +const Navbar = ({ position }) => { + const [isSearchOpen, setIsSearchOpen] = useState(false); + const [isSubNavVisible, setIsSubNavVisible] = useState(false); + + useEffect(() => { + let timeoutId; + const handleMouseMove = (e) => { + if (e.clientY <= 100) { + setIsSubNavVisible(true); + clearTimeout(timeoutId); + } else { + timeoutId = setTimeout(() => setIsSubNavVisible(false), 1000); + } + }; + + window.addEventListener('mousemove', handleMouseMove); + return () => { + window.removeEventListener('mousemove', handleMouseMove); + clearTimeout(timeoutId); + }; + }, []); + + const navLinks = [ + { name: 'Home', href: '/' }, + { + name: 'Recipes', + href: '/recipes', + sublinks: [ + { name: 'Breakfast', href: '/recipes/breakfast' }, + { name: 'Lunch', href: '/recipes/lunch' }, + { name: 'Dinner', href: '/recipes/dinner' }, + ] + }, + { name: 'Favorites', href: '/favorites' }, + { name: 'About', href: '/about' }, + { name: 'Contact', href: '/contact' }, + { + name: 'Account', + href: '/account', + sublinks: [ + { name: 'Sign Up', href: '/account/signup' }, + { name: 'Sign In', href: '/account/signin' }, + ] + }, + ]; -export default function NavBar() { return ( -
- -
- ) -} + <> + +
+
+ +
+
+ + ); +}; + +export default Navbar; \ No newline at end of file diff --git a/app/components/RecipeCards.jsx b/app/components/RecipeCard.jsx similarity index 89% rename from app/components/RecipeCards.jsx rename to app/components/RecipeCard.jsx index ef1f236..7acef64 100644 --- a/app/components/RecipeCards.jsx +++ b/app/components/RecipeCard.jsx @@ -1,3 +1,4 @@ +// app/components/RecipeCard.jsx (rename from RecipeCards.jsx) import React from 'react'; const RecipeCard = ({ recipe }) => { @@ -17,4 +18,4 @@ const RecipeCard = ({ recipe }) => { ); }; -export default RecipeCard; +export default RecipeCard; \ No newline at end of file diff --git a/app/components/RecipeGrid.jsx b/app/components/RecipeGrid.jsx index 5cddc37..bbda000 100644 --- a/app/components/RecipeGrid.jsx +++ b/app/components/RecipeGrid.jsx @@ -1,7 +1,7 @@ +// app/components/RecipeGrid.jsx "use client" - import React, { useEffect, useState } from 'react'; -import RecipeCards from './RecipeCards'; +import RecipeCard from './RecipeCard'; // Update this import const RecipeGrid = () => { const [recipes, setRecipes] = useState([]); @@ -16,17 +16,16 @@ const RecipeGrid = () => { console.error('Error fetching recipes:', error); } }; - fetchRecipes(); }, []); return (
{recipes.map(recipe => ( - + ))}
); }; -export default RecipeGrid; +export default RecipeGrid; \ No newline at end of file diff --git a/app/layout.js b/app/layout.js index 9800bf8..5162eec 100644 --- a/app/layout.js +++ b/app/layout.js @@ -1,30 +1,35 @@ -import localFont from "next/font/local"; -import "./globals.css"; -const geistSans = localFont({ - src: "./fonts/GeistVF.woff", - variable: "--font-geist-sans", - weight: "100 900", -}); -const geistMono = localFont({ - src: "./fonts/GeistMonoVF.woff", - variable: "--font-geist-mono", - weight: "100 900", -}); - -export const metadata = { - title: "Create Next App", - description: "Generated by create next app", -}; +'use client'; +import { useState, useEffect } from 'react'; +import Navbar from './components/Navbar'; +import Footer from './components/Footer'; +import './globals.css'; export default function RootLayout({ children }) { + const [navbarPosition, setNavbarPosition] = useState(0); + + useEffect(() => { + const handleKeyDown = (e) => { + if (e.key === 'ArrowLeft') { + setNavbarPosition((prev) => Math.max(prev - 10, -100)); + } else if (e.key === 'ArrowRight') { + setNavbarPosition((prev) => Math.min(prev + 10, 100)); + } + }; + + window.addEventListener('keydown', handleKeyDown); + return () => window.removeEventListener('keydown', handleKeyDown); + }, []); + return ( - - {children} + + +
{/* Add padding-top to account for fixed navbar */} + {children} +
+