Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Productdetail #66

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 26 additions & 14 deletions app/api/recipe/[id]/route.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,26 @@
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;
import connectToDatabase from "../../../../lib/connectMongoose";
import Recipe from "../../../../models/Recipe";
import { NextResponse } from "next/server";
import mongoose from "mongoose";

/**
*
* @param {*} req
* @param {id} param1 - This Will get the exact recipe id from database
* @returns - The recipe object by its Id
*/

export async function GET(req, { params }) {
try {
let { id } = params;
console.log(id)
// id = new mongoose.Types.ObjectId();
console.log(id)
await connectToDatabase();
const recipe = await Recipe.findOne({_id: id}).lean();
console.log(recipe,'123456789df')
return NextResponse.json({ recipe }, { status: 200 });
} catch (error) {
console.error(error);
}
}
24 changes: 13 additions & 11 deletions app/api/recipe/route.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
const fetchRecipes = async () => {
import connectToDatabase from "../../../lib/connectMongoose";
import Recipe from "../../../models/Recipe";
import { NextResponse } from "next/server";

export async function GET(req) {
console.log('cjsd csdcdsc')
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;
let db = await connectToDatabase();
console.log('mdcakmdcma')
const recipes = await Recipe.find({}, { _id: 1, title: 1, description: 1, prep: 1, cook: 1, images: 1, ingredients: 1, instructions: 1, nutrition: 1, servings: 1 }).limit(50).lean();
//console.log(recipes[0])
return NextResponse.json({ recipes });
} catch (error) {
console.error("Failed to Fetch Data:", error)
console.error(error);
}
};

export default fetchRecipes;
}
82 changes: 79 additions & 3 deletions app/components/Navbar.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
'use client';

import React, { useState, useEffect } from 'react';
import React, { useState, useEffect, useRef } from 'react';
import Link from 'next/link';

const Navbar = ({ position }) => {
const [isSearchOpen, setIsSearchOpen] = useState(false);
const [isSubNavVisible, setIsSubNavVisible] = useState(false);
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
const [dragPosition, setDragPosition] = useState(0);
const [isDragging, setIsDragging] = useState(false);
const dragRef = useRef(null);
const startXRef = useRef(0);

useEffect(() => {
let timeoutId;
Expand All @@ -25,6 +30,26 @@ const Navbar = ({ position }) => {
};
}, []);

const handleDragStart = (e) => {
setIsDragging(true);
startXRef.current = e.touches ? e.touches[0].clientX - dragPosition : e.clientX - dragPosition;
};

const handleDragMove = (e) => {
if (!isDragging) return;

const currentX = e.touches ? e.touches[0].clientX : e.clientX;
const newPosition = currentX - startXRef.current;

// Limit the drag range
const limitedPosition = Math.min(Math.max(newPosition, -100), 100);
setDragPosition(limitedPosition);
};

const handleDragEnd = () => {
setIsDragging(false);
};

const navLinks = [
{ name: 'Home', href: '/' },
{
Expand Down Expand Up @@ -53,7 +78,15 @@ const Navbar = ({ position }) => {
<>
<nav
className="fixed top-0 left-0 right-0 z-50 backdrop-blur-md bg-white/30 shadow-lg transition-all duration-300 ease-in-out"
style={{ transform: `translateX(${position}px)` }}
style={{ transform: `translateX(${position + dragPosition}px)` }}
ref={dragRef}
onTouchStart={handleDragStart}
onTouchMove={handleDragMove}
onTouchEnd={handleDragEnd}
onMouseDown={handleDragStart}
onMouseMove={handleDragMove}
onMouseUp={handleDragEnd}
onMouseLeave={handleDragEnd}
>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex items-center justify-between h-16">
Expand All @@ -62,6 +95,8 @@ const Navbar = ({ position }) => {
RecipeApp
</Link>
</div>

{/* Desktop Navigation */}
<div className="hidden md:block">
<div className="ml-10 flex items-baseline space-x-4">
{navLinks.map((link) => (
Expand All @@ -84,7 +119,24 @@ const Navbar = ({ position }) => {
))}
</div>
</div>
<div className="flex items-center">

{/* Mobile Navigation Button */}
<div className="md:hidden flex items-center">
<button
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
className="p-2 rounded-md text-gray-800 hover:text-gray-600 focus:outline-none"
aria-label="Toggle menu"
>
<div className="w-6 h-6 flex flex-col justify-between">
<span className={`block w-full h-0.5 bg-current transform transition duration-300 ease-in-out ${isMobileMenuOpen ? 'rotate-45 translate-y-2.5' : ''}`} />
<span className={`block w-full h-0.5 bg-current transition duration-300 ease-in-out ${isMobileMenuOpen ? 'opacity-0' : ''}`} />
<span className={`block w-full h-0.5 bg-current transform transition duration-300 ease-in-out ${isMobileMenuOpen ? '-rotate-45 -translate-y-2.5' : ''}`} />
</div>
</button>
</div>

{/* Search Button */}
<div className="flex items-center ml-4">
<button
onClick={() => setIsSearchOpen(!isSearchOpen)}
className="p-2 rounded-md text-gray-800 hover:text-gray-600 focus:outline-none"
Expand All @@ -96,7 +148,31 @@ const Navbar = ({ position }) => {
</div>
</div>
</div>

{/* Mobile Menu */}
<div className={`md:hidden transition-all duration-300 ease-in-out ${isMobileMenuOpen ? 'max-h-screen' : 'max-h-0'} overflow-hidden`}>
<div className="px-2 pt-2 pb-3 space-y-1">
{navLinks.map((link) => (
<div key={link.name}>
<Link href={link.href} className="block px-3 py-2 rounded-md text-base font-medium text-gray-800 hover:text-gray-600 hover:bg-gray-50">
{link.name}
</Link>
{link.sublinks && (
<div className="pl-4 space-y-1">
{link.sublinks.map((sublink) => (
<Link key={sublink.name} href={sublink.href} className="block px-3 py-2 rounded-md text-sm font-medium text-gray-600 hover:text-gray-800 hover:bg-gray-50">
{sublink.name}
</Link>
))}
</div>
)}
</div>
))}
</div>
</div>
</nav>

{/* Search Overlay */}
<div
className={`fixed top-16 left-0 right-0 z-40 backdrop-blur-md bg-white/30 shadow-lg transition-all duration-300 ease-in-out ${
isSubNavVisible ? 'opacity-100 translate-y-0' : 'opacity-0 -translate-y-full'
Expand Down
15 changes: 7 additions & 8 deletions app/components/RecipeCard.jsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
// app/components/RecipeCard.jsx (rename from RecipeCards.jsx)
import React from 'react';
import Link from 'next/link';

const RecipeCard = ({ recipe }) => {
console.log(recipe)
return (
<Link href={`/recipes/${recipe.id}`}>
<Link href={`/recipes/${recipe._id}`}>
<div className="bg-white shadow-md rounded-lg overflow-hidden">
<img src={recipe.image} alt={recipe.title} className="w-full h-48 object-cover" />
<img src={recipe.images[0]} alt={recipe.title} className="w-full h-48 object-cover" />
<div className="p-4">
<h2 className="text-xl font-bold text-gray-800">{recipe.name}</h2>
<p className="text-gray-600 mt-2">Prep time: {recipe.prepTimeMinutes} mins</p>
<p className="text-gray-600">Cook time: {recipe.cookTimeMinutes} mins</p>
<h2 className="text-xl font-bold text-gray-800">{recipe.title}</h2>
<p className="text-gray-600 mt-2">Prep time: {recipe.prep} mins</p>
<p className="text-gray-600">Cook time: {recipe.cook} mins</p>


<div className="flex items-center justify-between mt-2">
<div className="flex items-center">
<span className="text-yellow-500">★</span>
Expand All @@ -28,4 +27,4 @@ const RecipeCard = ({ recipe }) => {
);
};

export default RecipeCard;
export default RecipeCard;
11 changes: 8 additions & 3 deletions app/components/RecipeGrid.jsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// app/components/RecipeGrid.jsx
"use client"
import React, { useEffect, useState } from 'react';
import RecipeCard from './RecipeCard'; // Update this import
Expand All @@ -8,9 +9,13 @@ const RecipeGrid = () => {

useEffect(() => {
const fetchRecipes = async () => {
console.log('hdbachbdashcb')
try {
const response = await fetch('https://dummyjson.com/recipes');
console
const response = await fetch('http://localhost:3000/api/recipe',{cache:"no-store"});
console.log(response)
const data = await response.json();
console.log(data)
setRecipes(data.recipes);
} catch (error) {
console.error('Error fetching recipes:', error);
Expand All @@ -26,10 +31,10 @@ const RecipeGrid = () => {
return (
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6 p-6">
{recipes.map(recipe => (
<RecipeCard key={recipe._id} recipe={recipe} /> // Use _id if recipes are fetched from MongoDB
<RecipeCard key={recipe.title} recipe={recipe} />
))}
</div>
);
};

export default RecipeGrid;
export default RecipeGrid;
59 changes: 31 additions & 28 deletions app/recipes/[id]/page.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
"use client";
import { useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import fetchSingleRecipe from "../../api/recipe/[id]/route";
import { useRouter } from "next/navigation";
import RecipeSkeleton from "../../components/RecipeDetailSkeleton";


const formatTime = (minutes) => {
const hours = Math.floor(minutes / 60);
const mins = minutes % 60;
Expand All @@ -13,59 +11,66 @@ const formatTime = (minutes) => {

const RecipeDetail = ({ params }) => {
const { id } = params;
const router = useRouter();

const [recipe, setRecipe] = useState(null);
const [activeTab, setActiveTab] = useState("ingredients");
const router = useRouter();

// Log the ID to make sure it's correctly passed
console.log("Recipe ID from params:", id); // Log ID to verify it's correct

useEffect(() => {
const getRecipe = async () => {
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

// Delay for 2 seconds
await delay(4000);
const data = await fetchSingleRecipe(id);
if (data) {
setRecipe(data);
try {
if (!id) {
console.error("No ID found in params");
return;
}
const response = await fetch(`/api/recipe/${id}`);
if (!response.ok) {
throw new Error("Failed to fetch recipe");
}
const data = await response.json();
console.log(data.recipe,'data')
setRecipe(data.recipe);
} catch (error) {
console.error("Error fetching recipe:", error);
}
};

getRecipe();
}, [id]);

if (!recipe) {
return <RecipeSkeleton/>
return <RecipeSkeleton />;
}

const totalTime = recipe.prepTimeMinutes + recipe.cookTimeMinutes;

return (
<div className="p-6 max-w-6xl mx-auto font-sans">

<button
onClick={() => router.back()}
onClick={() => router.back()}
className="text-gray-600 hover:text-gray-900 mb-4 flex items-center"
>
← Back
</button>


<div className="grid items-start grid-cols-1 md:grid-cols-2 gap-6">
<div className="w-full lg:sticky top-0 flex gap-3">
<img
src={recipe.image}
alt={recipe.name}
src={recipe.images[0]}
alt={recipe.title}
className="w-3/4 rounded-lg object-cover"
/>
</div>

<div>

<h1 className="text-3xl font-bold mb-2 text-gray-800">
{recipe.name}
</h1>
<h1 className="text-3xl font-bold mb-2 text-gray-800">{recipe.title}</h1>


<p className="text-lg italic text-gray-600 mb-6">
Discover how to make this delicious {recipe.name}. Perfect for {recipe.mealType || "any occasion"}.
Discover how to make this delicious {recipe.title}. Perfect for{" "}
{recipe.mealType || "any occasion"}.
</p>

<div className="text-lg text-gray-800 space-y-2">
Expand All @@ -83,7 +88,6 @@ const RecipeDetail = ({ params }) => {
</p>
</div>


<ul className="grid grid-cols-2 mt-10 border-b-2">
<li
className={`text-gray-800 font-semibold text-base text-center py-3 cursor-pointer ${
Expand All @@ -103,15 +107,14 @@ const RecipeDetail = ({ params }) => {
</li>
</ul>


<div className="mt-6">
{activeTab === "ingredients" ? (
<div>
<h2 className="text-2xl font-semibold mb-4">Ingredients</h2>
<ul className="list-disc pl-6 mt-2 text-gray-700">
{recipe.ingredients.map((ingredient, index) => (
{/* {recipe.ingredients.map((ingredient, index) => (
<li key={index}>{ingredient}</li>
))}
))} */}
</ul>
</div>
) : (
Expand All @@ -131,4 +134,4 @@ const RecipeDetail = ({ params }) => {
);
};

export default RecipeDetail;
export default RecipeDetail;
Loading