From aaaa5a901cea10cb9c7f761245164b5db7b0db81 Mon Sep 17 00:00:00 2001 From: kutlwano10 Date: Tue, 22 Oct 2024 13:20:27 +0200 Subject: [PATCH 1/9] Created Get request to get the database recipe --- app/api/recipe/route.js | 27 +- lib/connectMongoose.js | 34 ++ lib/sampleData.js | 1107 +++++++++++++++++++++++++++++++++++++++ models/Recipe.js | 34 ++ package-lock.json | 242 ++++++++- package.json | 3 + 6 files changed, 1432 insertions(+), 15 deletions(-) create mode 100644 lib/connectMongoose.js create mode 100644 lib/sampleData.js create mode 100644 models/Recipe.js diff --git a/app/api/recipe/route.js b/app/api/recipe/route.js index 5bed881..5097003 100644 --- a/app/api/recipe/route.js +++ b/app/api/recipe/route.js @@ -1,14 +1,17 @@ -const fetchRecipes = async () => { - try { - const res = await fetch("https://dummyjson.com/recipes", {cache : 'force-cache'}); - if (!res.ok) { - throw new Error("Fetch Products Failed"); +import { connectMongoose } from "@/lib/connectMongoose"; +import Recipe from "@/models/Recipe"; +import { NextResponse } from "next/server"; + +export async function GET(req) { + + try { + await connectMongoose() + const recipe = await Recipe.find({}) + console.log(recipe) + return NextResponse.json({recipe}) + } catch (error) { + } - const data = await res.json(); - return data; - } catch (error) { - console.error("Failed to Fetch Data:", error) - } -}; + +} -export default fetchRecipes; diff --git a/lib/connectMongoose.js b/lib/connectMongoose.js new file mode 100644 index 0000000..46828ad --- /dev/null +++ b/lib/connectMongoose.js @@ -0,0 +1,34 @@ + +import mongoose from 'mongoose'; + +const MONGODB_URI = process.env.MONGODB_URI; // Get MongoDB URI from environment variables + +if (!MONGODB_URI) { + throw new Error('Please add your MongoDB URI to .env.local'); +} + +/** + * Connects to MongoDB using Mongoose. + */ +let isConnected = false; // Track connection status + +export const connectMongoose = async () => { + if (isConnected) { + console.log('MongoDB is already connected.'); + return; + } + + try { + await mongoose.connect(MONGODB_URI, { + useNewUrlParser: true, + useUnifiedTopology: true, + }); + + isConnected = true; + console.log('Connected to MongoDB via Mongoose'); + } catch (error) { + console.error('Error connecting to MongoDB:', error); + throw new Error('Failed to connect to MongoDB'); + } +}; + diff --git a/lib/sampleData.js b/lib/sampleData.js new file mode 100644 index 0000000..936feee --- /dev/null +++ b/lib/sampleData.js @@ -0,0 +1,1107 @@ + const recipes = [{ + "_id": "774b0956-1286-48bf-85a2-7f5530d66deb", + "title": "Low-Fat Berry Blue Frozen Dessert", + "description": "Make and share this Low-Fat Berry Blue Frozen Dessert recipe from Food.com.", + "prep": 45, + "cook": 240, + "category": "Frozen Desserts", + "servings": "4", + "published": "1999-08-09T00:00:00.000Z", + "tags": [ + "Dessert", + "Low Protein", + "Low Cholesterol", + "Healthy", + "Free Of...", + "Summer", + "Weeknight", + "Freezer", + "Easy" + ], + "ingredients": { + "blueberries": "4", + "granulated sugar": "1/4", + "vanilla yogurt": "1", + "lemon juice": "1" + }, + "images": [ + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/38/YUeirxMLQaeE1h3v3qnM_229%20berry%20blue%20frzn%20dess.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/38/AFPDDHATWzQ0b1CDpDAT_255%20berry%20blue%20frzn%20dess.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/38/UYgf9nwMT2SGGJCuzILO_228%20berry%20blue%20frzn%20dess.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/38/PeBMJN2TGSaYks2759BA_20140722_202142.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/38/picuaETeN.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/38/pictzvxW5.jpg" + ], + "instructions": [ + "Toss 2 cups berries with sugar.", + "Let stand for 45 minutes, stirring occasionally.", + "Transfer berry-sugar mixture to food processor.", + "Add yogurt and process until smooth.", + "Strain through fine sieve. Pour into baking pan (or transfer to ice cream maker and process according to manufacturers' directions). Freeze uncovered until edges are solid but centre is soft. Transfer to processor and blend until smooth again.", + "Return to pan and freeze until edges are solid.", + "Transfer to processor and blend until smooth again.", + "Fold in remaining 2 cups of blueberries.", + "Pour into plastic mold and freeze overnight. Let soften slightly to serve." + ], + "nutrition": { + "calories": "170.9", + "fat": "2.5", + "saturated": "1.3", + "sodium": "29.8", + "carbohydrates": "37.1", + "fiber": "3.6", + "sugar": "30.2", + "protein": "3.2" + } + }, + { + "_id": "798ea2e7-0393-4aed-a274-32af496e2569", + "title": "Biryani", + "description": "Make and share this Biryani recipe from Food.com.", + "prep": 240, + "cook": 25, + "category": "Chicken Breast", + "servings": "6", + "published": "1999-08-29T00:00:00.000Z", + "tags": [ + "Chicken Thigh & Leg", + "Chicken", + "Poultry", + "Meat", + "Asian", + "Indian", + "Weeknight", + "Stove Top" + ], + "ingredients": { + "saffron": "1", + "milk": "4", + "hot green chili peppers": "2", + "onions": "2", + "garlic": "8", + "clove": "1/4", + "peppercorns": "8", + "cardamom seed": "1/2", + "cumin seed": "1", + "poppy seed": "1", + "mace": "1/4", + "cilantro": "1/4", + "mint leaf": "1/2", + "fresh lemon juice": "1/4", + "plain yogurt": "2", + "boneless chicken": "3", + "salt": "", + "ghee": "2", + "onion": "1", + "tomatoes": "1", + "basmati rice": "8", + "long-grain rice": "2", + "raisins": "1/3", + "cashews": "1/3", + "eggs": "1/3" + }, + "images": [ + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/39/picM9Mhnw.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/39/picHv4Ocr.jpg" + ], + "instructions": [ + "Soak saffron in warm milk for 5 minutes and puree in blender.", + "Add chiles, onions, ginger, garlic, cloves, peppercorns, cardamom seeds, cinnamon, coriander and cumin seeds, poppy seeds, nutmeg, mace, cilantro or mint leaves and lemon juice. Blend into smooth paste. Put paste into large bowl, add yogurt and mix well.", + "Marinate chicken in yogurt mixture with salt, covered for at least 2 - 6 hours in refrigerator.", + "In skillet. heat oil over medium heat for 1 minute. Add ghee and 15 seconds later add onion and fry for about8 minutes.", + "Reserve for garnish.", + "In same skillet, cook chicken with its marinade with tomatoes for about 10 minutes over medium heat, uncovered.", + "Remove chicken pieces from the sauce and set aside. Add rice to sauce, bring to boil, and cook, covered over low heat for 15 minutes.", + "Return chicken and add raisins, cashews and almonds; mix well.", + "Simmer, covered for 5 minutes.", + "Place chicken, eggs and rice in large serving dish in such a way that yellow of the eggs, the saffron-colored rice, the nuts and the chicken make a colorful display.", + "Add reserved onion as garnish." + ], + "nutrition": { + "calories": "1110.7", + "fat": "58.8", + "saturated": "16.6", + "sodium": "368.4", + "carbohydrates": "84.4", + "fiber": "9", + "sugar": "20.4", + "protein": "63.4" + } + }, + { + "_id": "7d3a6526-c15a-4b41-bcd7-5e326634c632", + "title": "Best Lemonade", + "description": "This is from one of my first Good House Keeping cookbooks. You must use a *zester* in order to avoid getting any of that bitter rind, and when you zest the lemons, zest them onto some sugar from the recipe (the sugar will 'catch' all of the oils). I also advise you from personal experience to use only the best skinned lemons for the best flavor.", + "prep": 30, + "cook": 5, + "category": "Beverages", + "servings": "4", + "published": "1999-09-05T00:00:00.000Z", + "tags": [ + "Low Protein", + "Low Cholesterol", + "Healthy", + "Summer", + "< 60 Mins" + ], + "ingredients": { + "sugar": "1 1/2", + "lemons, rind of": "1", + "lemon, zest of": "", + "fresh water": "1 1/2", + "fresh lemon juice": "" + }, + "images": [ + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/40/picJ4Sz3N.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/40/pic23FWio.jpg" + ], + "instructions": [ + "Into a 1 quart Jar with tight fitting lid, put sugar and lemon peel, or zest; add 1 1/2 cups very hot water (not from tap!). With lid fitted firmly, shake jar until sugar is dissolved.", + "Add lemon juice. Refrigerate until chilled.", + "To Serve: Into each 12-ounce glass, over ice cubes, pour 1/4 cup of the lemon syrup.", + "Then add chilled club soda or, if you prefer, water.", + "Stir to mix well." + ], + "nutrition": { + "calories": "311.1", + "fat": "0.2", + "saturated": "0", + "sodium": "1.8", + "carbohydrates": "81.5", + "fiber": "0.4", + "sugar": "77.2", + "protein": "0.3" + } + }, + { + "_id": "d0f05364-42d4-4b1c-92ce-41954efdde40", + "title": "Carina's Tofu-Vegetable Kebabs", + "description": "This dish is best prepared a day in advance to allow the ingredients to soak in the marinade overnight.", + "prep": 240, + "cook": 20, + "category": "Soy/Tofu", + "servings": "2", + "published": "1999-09-03T00:00:00.000Z", + "tags": [ + "Beans", + "Vegetable", + "Low Cholesterol", + "Weeknight", + "Broil/Grill", + "Oven" + ], + "ingredients": { + "extra firm tofu": "12", + "eggplant": "1", + "zucchini": "2", + "mushrooms": "1", + "soy sauce": "10", + "low sodium soy sauce": "1", + "olive oil": "3", + "maple syrup": "2", + "honey": "2", + "red wine vinegar": "2", + "lemon juice": "1", + "garlic cloves": "2", + "mustard powder": "1/2", + "black pepper": "1/4" + }, + "images": [ + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/41/picmbLig8.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/41/picL02w0s.jpg" + ], + "instructions": [ + "Drain the tofu, carefully squeezing out excess water, and pat dry with paper towels.", + "Cut tofu into one-inch squares.", + "Set aside. Cut eggplant lengthwise in half, then cut each half into approximately three strips.", + "Cut strips crosswise into one-inch cubes.", + "Slice zucchini into half-inch thick slices.", + "Cut red pepper in half, removing stem and seeds, and cut each half into one-inch squares.", + "Wipe mushrooms clean with a moist paper towel and remove stems.", + "Thread tofu and vegetables on to barbecue skewers in alternating color combinations: For example, first a piece of eggplant, then a slice of tofu, then zucchini, then red pepper, baby corn and mushrooms.", + "Continue in this way until all skewers are full.", + "Make the marinade by putting all ingredients in a blender, and blend on high speed for about one minute until mixed.", + "Alternatively, put all ingredients in a glass jar, cover tightly with the lid and shake well until mixed.", + "Lay the kebabs in a long, shallow baking pan or on a non-metal tray, making sure they lie flat. Evenly pour the marinade over the kebabs, turning them once so that the tofu and vegetables are coated.", + "Refrigerate the kebabs for three to eight hours, occasionally spooning the marinade over them.", + "Broil or grill the kebabs at 450 F for 15-20 minutes, or on the grill, until the vegetables are browned.", + "Suggestions This meal can be served over cooked, brown rice. Amounts can easily be doubled to make four servings." + ], + "nutrition": { + "calories": "536.1", + "fat": "24", + "saturated": "3.8", + "sodium": "1558.6", + "carbohydrates": "64.2", + "fiber": "17.3", + "sugar": "32.1", + "protein": "29.3" + } + }, + { + "_id": "a71f9756-fd61-4514-977d-261e38345d55", + "title": "Cabbage Soup", + "description": "Make and share this Cabbage Soup recipe from Food.com.", + "prep": 20, + "cook": 30, + "category": "Vegetable", + "servings": "4", + "published": "1999-09-19T00:00:00.000Z", + "tags": [ + "Low Protein", + "Vegan", + "Low Cholesterol", + "Healthy", + "Winter", + "< 60 Mins", + "Easy" + ], + "ingredients": { + "plain tomato juice": "46", + "cabbage": "4", + "onion": "1", + "carrots": "2", + "celery": "1" + }, + "images": [ + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/42/picVEMxk8.jpg" + ], + "instructions": [ + "Mix everything together and bring to a boil.", + "Reduce heat and simmer for 30 minutes (longer if you prefer your veggies to be soft).", + "Refrigerate until cool.", + "Serve chilled with sour cream." + ], + "nutrition": { + "calories": "103.6", + "fat": "0.4", + "saturated": "0.1", + "sodium": "959.3", + "carbohydrates": "25.1", + "fiber": "4.8", + "sugar": "17.7", + "protein": "4.3" + } + }, + { + "_id": "9749017f-1875-4f4b-8088-d225362cb122", + "title": "Warm Chicken A La King", + "description": "I copied this one out of a friend's book so many moons ago that I can't remember where it's from, but it's so decadently fattening that I can't resist pigging out now and then. I usually serve with rice, but I suppose it would go with noodles or new potatoes just as well.", + "prep": 35, + "cook": 3, + "category": "Chicken", + "servings": "2", + "published": "1999-09-17T00:00:00.000Z", + "tags": [ + "Poultry", + "Meat", + "< 60 Mins" + ], + "ingredients": { + "chicken": "12", + "butter": "2", + "flour": "3", + "milk": "450", + "celery": "1", + "button mushrooms": "2", + "green pepper": "1/4", + "canned pimiento": "1", + "salt": "", + "black pepper": "", + "Worcestershire sauce": "2", + "parsley": "2" + }, + "images": [ + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/44/picsSKvFd.jpg" + ], + "instructions": [ + "Melt 1 1/2 ozs butter, add the flour and cook for 2 to 3 minutes, stirring.", + "Gradually add milk and cook, stirring, until thick and smooth.", + "Melt the remaining butter and saute sliced celery, button mushrooms and chopped pepper until soft but not coloured.", + "Add celery, mushrooms, pepper, chicken and pimiento to the sauce and heat through.", + "Season to taste. Combine the egg yolks, double cream and Worcestershire sauce. Add to the chicken mixture and heat through.", + "Transfer to a serving dish and sprinkle with chopped parsley." + ], + "nutrition": { + "calories": "895.5", + "fat": "66.8", + "saturated": "31.9", + "sodium": "557.2", + "carbohydrates": "29.1", + "fiber": "3.1", + "sugar": "5", + "protein": "45.3" + } + }, + { + "_id": "c1bfe127-d4bc-406d-8d45-4f1d2a872a8e", + "title": "Buttermilk Pie With Gingersnap Crumb Crust", + "description": "Make and share this Buttermilk Pie With Gingersnap Crumb Crust recipe from Food.com.", + "prep": 30, + "cook": 50, + "category": "Pie", + "servings": "8", + "published": "1999-08-06T00:00:00.000Z", + "tags": [ + "Dessert", + "Healthy", + "Weeknight", + "Oven", + "< 4 Hours" + ], + "ingredients": { + "sugar": "3/4", + "margarine": "1/2", + "egg": "1", + "flour": "2", + "salt": "3", + "buttermilk": "1/4", + "graham cracker crumbs": "1" + }, + "images": [ + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/45/pic79tPh5.jpg" + ], + "instructions": [ + "Preheat oven to 350°F.", + "Make pie crust, using 8 inch pie pan, do not bake.", + "Mix sugar and margarine in medium bowl until blended; beat in egg whites and egg.", + "Stir in flour, salt, and buttermilk until well blended.", + "Pour filling into prepared crust, bake 40 minutes or until sharp knife inserted near center comes out clean.", + "Sprinkle with nutmeg and serve warm or chilled.", + "Combine graham crumbs, gingersnap crumbs, and margarine in 8 or 9 inch pie pan, pat mixture evenly on bottom and side of pan.", + "Bake 8 to 10 minutes or until edge of crust is lightly browned.", + "Cool on wire rack." + ], + "nutrition": { + "calories": "228", + "fat": "7.1", + "saturated": "1.7", + "sodium": "281.8", + "carbohydrates": "37.5", + "fiber": "0.5", + "sugar": "24.7", + "protein": "4.2" + } + }, + { + "_id": "6b432ef8-a563-4eef-9f31-827987a3e0c9", + "title": "Butter Pecan Cookies", + "description": "Make and share this Butter Pecan Cookies recipe from Food.com.", + "prep": 55, + "cook": 9, + "category": "Dessert", + "servings": "", + "published": "1999-09-07T00:00:00.000Z", + "tags": [ + "Cookie & Brownie", + "Fruit", + "Nuts", + "Weeknight", + "Oven", + "< 4 Hours" + ], + "ingredients": { + "butter": "3/4", + "brown sugar": "1/2", + "granulated sugar": "1", + "vanilla extract": "1", + "flour": "1", + "pecan halves": "2" + }, + "images": [ + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/47/picfnmxck.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/47/picCPvxZU.jpg" + ], + "instructions": [ + "Preheat oven to 350 degrees.", + "Cream butter in large mixing bowl.", + "Gradually add brown sugar and granulated sugar.", + "Cream well.", + "Add unbeaten egg yolk and vanilla and beat well.", + "Blend in sifted flour to form a stiff dough.", + "Shape dough into small balls.", + "Place on greased cookie sheet. Flatten cookies with bottom of glass dipped in sugar.", + "Bake at 350 degrees for 7-9 minutes, till golden brown (do not overbrown.) Cool before frosting.", + "Garnish with pecan halves." + ], + "nutrition": { + "calories": "69", + "fat": "5.6", + "saturated": "1.4", + "sodium": "15", + "carbohydrates": "4.5", + "fiber": "0.6", + "sugar": "1.6", + "protein": "0.8" + } + }, + { + "_id": "1a2a1e8b-a56c-4c38-ba94-89ab19e21fe6", + "title": "Chicken Breasts Lombardi", + "description": "Make and share this Chicken Breasts Lombardi recipe from Food.com.", + "prep": 45, + "cook": 30, + "category": "Chicken Breast", + "servings": "6", + "published": "1999-08-14T00:00:00.000Z", + "tags": [ + "Chicken", + "Poultry", + "Meat", + "European", + "Very Low Carbs", + "Weeknight", + "Oven", + "< 4 Hours" + ], + "ingredients": { + "fresh mushrooms": "2", + "butter": "1/3", + "boneless skinless chicken breast halves": "12", + "flour": "1/2", + "marsala": "3/4", + "chicken broth": "1/2", + "salt": "1/2", + "mozzarella cheese": "1/2", + "parmesan cheese": "1/2", + "green onion": "1/4" + }, + "images": [ + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/49/m1z1F8S5mAZgyImm5zYw_Lombardi%20Chicken%203.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/49/01481162521.jpeg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/49/Sa0Yu0UyRoyh1B03oLnD_20161102_174049.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/49/01477708512.jpeg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/49/tHou0UsyTiAsfQo29Fpi_Lombardi%20Chicken%202.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/49/X2b0bl8aTGivq4ErsD3g_Lombardi%20chicken%201.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/49/picvZU6rd.jpg" + ], + "instructions": [ + "Cook mushrooms in 2 tbsp butter in a large skillet, stirring constantly, just until tender.", + "Remove from heat; set aside. Cut each chicken breast half in half lengthwise. Place each piece of chicken between two sheets of wax paper; flatten to 1/8\" thickness, using a meat mallet or rolling pin.", + "Dredge chicken pieces in flour.", + "Place 5 or 6 pieces of chicken in 1 to 2 tbsp butter in a large skillet; cook over medium heat 3 to 4 minutes on each side or until golden.", + "Place chicken in a lightly greased 13x9\" baking dish, overlapping edges.", + "Repeat procedure with remaining chicken and butter.", + "Reserve pan drippings in skillet. Sprinkle reserved mushrooms over chicken.", + "Add wine and broth to skillet. Bring to a boil; reduce heat, and simmer, uncovered, 10 minutes, stirring occasionally.", + "Stir in salt and pepper.", + "Pour sauce over chicken.", + "Combine cheeses and green onions; sprinkle over chicken.", + "Bake uncovered at 450 for 12 to 14 minutes.", + "Broil 5 1/2\" away from heat 1 to 2 minutes or until browned." + ], + "nutrition": { + "calories": "627.7", + "fat": "24.9", + "saturated": "13", + "sodium": "848.9", + "carbohydrates": "13.7", + "fiber": "0.6", + "sugar": "2", + "protein": "57.9" + } + }, + { + "_id": "77e86402-0cfa-4d24-95cf-be3e8657dc1a", + "title": "Biscotti Di Prato", + "description": "Make and share this Biscotti Di Prato recipe from Food.com.", + "prep": 20, + "cook": 50, + "category": "Dessert", + "servings": "", + "published": "1999-08-31T00:00:00.000Z", + "tags": [ + "Cookie & Brownie", + "European", + "Weeknight", + "Oven", + "< 4 Hours" + ], + "ingredients": { + "flour": "3 3/4", + "sugar": "2", + "baking powder": "1", + "salt": "1/4", + "eggs": "4", + "vanilla": "1", + "egg": "1/2", + "water": "1 2/3" + }, + "images": [ + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/50/picyuYoeC.jpg" + ], + "instructions": [ + "EGG WASH 1 Egg, large 1 tsp Water In the bowl of an electric mixer fitted with the paddle attachment blend the flour, the sugar, the baking powder, and the salt until the mixture is combined well.", + "In a small bowl, whisk together the whole eggs, the yolks, the vanilla and the almond extract, add the mixture to the flour mixture, beating until a dough is formed, and stir in the almonds.", + "Turn the dough out onto a lightly floured surface, knead it several times, and divide it into fourths.", + "Working on 2 large buttered and floured baking sheets, with floured hands form each piece of dough into a flattish log 11 inches long and 2 inches wide, arrange the logs at least 3 inches apart on the sheets, and brush them with the egg wash.", + "Bake the logs in a preheated 350F oven for 35 minutes and let them cool on the baking sheets on racks for 10 minutes.", + "On a cutting board, cut the logs crosswise on the diagonal into 3/4\" inch slices, arrange them the biscotti, cut sides down, on the baking sheets, and bake them in the 350F oven for 5 to 7 minutes on each side, or until they are pale golden.", + "Transfer the biscotti to racks to cool and store them in airtight containers." + ], + "nutrition": { + "calories": "89.4", + "fat": "2.6", + "saturated": "0.3", + "sodium": "23.5", + "carbohydrates": "14.5", + "fiber": "0.8", + "sugar": "7.3", + "protein": "2.3" + } + }, + { + "_id": "add46690-b9dc-4c12-ad09-d19df129658e", + "title": "Cafe Cappuccino", + "description": "Make and share this Cafe Cappuccino recipe from Food.com.", + "prep": 5, + "cook": 0, + "category": "Beverages", + "servings": "18", + "published": "1999-08-31T00:00:00.000Z", + "tags": [ + "Low Cholesterol", + "High Protein", + "Healthy", + "High In...", + "< 15 Mins", + "For Large Groups", + "No Cook", + "Easy" + ], + "ingredients": { + "instant coffee": "1/2", + "sugar": "3/4", + "nonfat dry milk solid": "1" + }, + "images": [ + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/52/picAkC0UW.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/52/piccYWEE1.jpg" + ], + "instructions": [ + "Stir ingredients together.", + "Process in a blender until powdered.", + "Use 2 Tbsp. of mixture for each cup of hot water." + ], + "nutrition": { + "calories": "62.2", + "fat": "0.1", + "saturated": "0", + "sodium": "36.6", + "carbohydrates": "12.8", + "fiber": "0", + "sugar": "11.8", + "protein": "2.7" + } + }, + { + "_id": "f8ee2ec2-9a32-4a79-9be9-22877e72bef1", + "title": "Carrot Cake", + "description": "This is one of the few recipes my husband every requested from a coworker and brought home for me to make.", + "prep": 45, + "cook": 50, + "category": "Dessert", + "servings": "12", + "published": "1999-09-13T00:00:00.000Z", + "tags": [ + "Vegetable", + "Weeknight", + "Oven", + "< 4 Hours" + ], + "ingredients": { + "carrots": "3", + "eggs": "4", + "white sugar": "1 1/4", + "all-purpose flour": "2", + "baking powder": "2", + "baking soda": "2", + "cinnamon": "2", + "salt": "1", + "nutmeg": "1", + "golden raisin": "1/2", + "confectioners' sugar": "1", + "cream cheese": "1 1/4", + "light corn syrup": "1", + "vanilla extract": "1" + }, + "images": [ + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/54/picQ2X4D8.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/54/pic3oloIV.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/54/picf0dw0o.jpg" + ], + "instructions": [ + "Beat together the eggs, oil, and white sugar. Blend mixture for thirty seconds.", + "Sift together flour, baking powder, baking soda, salt and spices. Add the carrots and raisins.", + "Pour egg mixture into dry ingredients, and mix well. Pour batter into well greased 10 inch tube or Bundt pan.", + "Bake at 350 degrees F (175 degrees C) oven for 45 to 50 minutes. Cool cake on wire rack, and then refrigerate until completely cooled.", + "To make Cream Cheese Glaze: Blend together confectioners' sugar, cream cheese, corn syrup, and vanilla. Spread over cooled cake." + ], + "nutrition": { + "calories": "522.6", + "fat": "27.1", + "saturated": "4.9", + "sodium": "534.8", + "carbohydrates": "67", + "fiber": "1.6", + "sugar": "47.9", + "protein": "5" + } + }, + { + "_id": "6dd0e02d-7828-48be-8f08-58d67276283d", + "title": "Betty Crocker's Southwestern Guacamole Dip", + "description": "Make and share this Betty Crocker's Southwestern Guacamole Dip recipe from Food.com.", + "prep": 5, + "cook": 120, + "category": "Southwestern U.S.", + "servings": "4", + "published": "1999-09-15T00:00:00.000Z", + "tags": [ + "Mexican", + "Low Protein", + "Low Cholesterol", + "Healthy", + "Weeknight", + "No Cook", + "< 4 Hours", + "Easy" + ], + "ingredients": { + "avocados": "5", + "tomatoes": "1", + "salt": "1/2", + "garlic": "4", + "lime juice": "1/4" + }, + "images": [ + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/55/piclZzIyA.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/55/picMUqRBi.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/55/picmeltus.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/55/picO6xTtc.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/55/pic1hlVfW.jpg" + ], + "instructions": [ + "Peel and mash avocados until lumpy.", + "Add remaining ingredients and chill for 1 - 2 hours." + ], + "nutrition": { + "calories": "415.9", + "fat": "36.9", + "saturated": "5.4", + "sodium": "310.6", + "carbohydrates": "24.9", + "fiber": "17.3", + "sugar": "2.8", + "protein": "5.5" + } + }, + { + "_id": "23e12a93-9773-42d7-a1a8-4861cb70893a", + "title": "Buttermilk Pie", + "description": "This recipe was originally noted by my wife on a cooking show on TV. It was touted as an Amish recipe. All we had for a long time was the list of ingredients on the back of an old envelope. We lost it for a good while and after I found it, I originally posted it so I would never lose it again. Thank you all for all your interest ... this is my absolute favorite pie. During the "lost" phase I must have gained 20 pounds trying numerous different buttermilk pie recipes ... I was so glad when I found it again as only a few even came close in taste and texture. I've noted a lot of people mentioning reducing the sugar, which is fine, but bear in mind that the sugar quantity was a major difference between this and other recipes I tested when it was lost. Hey, it is a PIE, it is SUPPOSED to be sweet. Enjoy", + "prep": 20, + "cook": 60, + "category": "Pie", + "servings": "8", + "published": "1999-08-30T00:00:00.000Z", + "tags": [ + "Dessert", + "Oven", + "< 4 Hours", + "Easy" + ], + "ingredients": { + "butter": "1/2", + "margarine": "1 1/2", + "sugar": "3", + "flour": "3", + "eggs": "1", + "salt": "1", + "vanilla": "1", + "buttermilk": "1" + }, + "images": [ + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/56/nTwHmSmmRqGCr5HAUapC_pie-1194.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/56/KVgOoNMtRF6wvr5F2LN8_IMG_20180506_232451.jpg", + "https://img.sndimg.com/food/image/upload/v1/img/feed/56/FNPRvh8RVDt87oJMvdaQ_166757453857297.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/a_270/v1/img/recipes/56/YrLhorGAT1ifQL8kR6Wi_image.jpg?rotate=270", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/56/picJXAlyG.jpg", + "https://img.sndimg.com/food/image/upload/v1/img/feed/56/JOBnvLyxTLOaUX9iAHwY_10158835129563134.jpg", + "https://img.sndimg.com/food/image/upload/v1/img/feed/56/ZdWr5wSqTXxLp9gQKZva_6177182B-027F-47EE-9C80-39990213CCFC.jpeg", + "https://img.sndimg.com/food/image/upload/v1/img/feed/56/VZPyxCFZRGDdqWjVI3Ig_0553DC1D-4ACE-4409-9EDD-5E05816DABF8.jpeg", + "https://img.sndimg.com/food/image/upload/v1/img/feed/56/PqvYaX51TkK0ftMAzQpW_SPhotoEditor-20180123_200317.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/56/J2tzJWCfRymRlQleEd6y_pie-1181.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/56/LOQPyV1SkSvINuu2lHnQ_pie-1178.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/56/FKfvNy09TZOJZXhks55M_image.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/56/WcvltJdQpaBj0VuIwkRM_20150221_185141.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/56/pfKfVg22RWae0KXp4Zxx_IMG_20150221_124006.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/56/picJEONrC.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/56/picrMc1hm.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/56/picI0FnqN.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/56/picm865Ry.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/56/picpY7xxC.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/56/picG0knyL.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/56/picMujOhS.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/56/6mu4U7FdQvSbUJcZsfnb_2285843731647190.jpg", + "https://img.sndimg.com/food/image/upload/v1/img/feed/56/irAZOAxdSjOqcEnJuVTG_2285843731647190.jpg", + "https://img.sndimg.com/food/image/upload/v1/img/feed/56/pzhS4q7QKSMqZASDBtNB_IMG_20180506_232451.jpg", + "https://img.sndimg.com/food/image/upload/v1/img/feed/56/Vg7ihmiYSTeiZMT2CpTQ_Buttermilk%20pie.JPG", + "https://img.sndimg.com/food/image/upload/v1/img/feed/56/M3067khQQjC4cYTLtBSM_20170312_211847.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/56/NNse5q3TRZum6MXQVNya_IMG_6814.JPG", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/56/pick370mI.jpg" + ], + "instructions": [ + "Preheat oven to 400°F.", + "Beat the butter and sugar together until light.", + "Add the eggs and beat; then beat in vanilla.", + "Sift the dry ingredients together and add to the batter alternatively with the buttermilk; beat until smooth.", + "Pour into a deep dish pie shell and bake at 400F for 10 minutes, reduce heat to 350F and bake for 50-60 additional minutes.", + "Pie should turn a nice golden brown and a knife inserted should come out clean.", + "I think it is absolutely best when it is just still warm. (Not too hot, or it will be like napalm.)." + ], + "nutrition": { + "calories": "395.9", + "fat": "19.1", + "saturated": "9.8", + "sodium": "269.8", + "carbohydrates": "52.2", + "fiber": "0.7", + "sugar": "39.9", + "protein": "5" + } + }, + { + "_id": "aaa6b01c-3f44-458b-a6be-dd8b529b8ded", + "title": "Low-Fat Burgundy Beef & Vegetable Stew", + "description": "Make and share this Low-Fat Burgundy Beef & Vegetable Stew recipe from Food.com.", + "prep": 30, + "cook": 134, + "category": "Stew", + "servings": "6", + "published": "1999-08-14T00:00:00.000Z", + "tags": [ + "Vegetable", + "Meat", + "Low Cholesterol", + "Healthy", + "Free Of...", + "Weeknight", + "< 4 Hours" + ], + "ingredients": { + "beef eye round": "1 1/2", + "dried thyme leaves": "1", + "salt": "1", + "pepper": "1/2", + "ready-to-serve beef broth": "1/2", + "Burgundy wine": "1", + "garlic": "1/2", + "cornstarch": "3", + "frozen sugar snap peas": "5 1/2" + }, + "images": [ + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/58/picnE8qoe.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/58/picwiayaY.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/58/picAaGXgc.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/58/picD2ey4Z.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/58/picKtSTwb.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/58/picY2Aqui.jpg" + ], + "instructions": [ + "Trim fat from beef, cut into 1-inch pieces.", + "In Dutch oven, heat oil over medium high hunt until hot. Add beef (half at a time) and brown evenly, stirring occasionally.", + "Pour off drippings.", + "Season with thyme, salt and pepper.", + "Stir in broth, wine and garlic. Bring to boil; reduce heat to low.", + "Cover tightly and simmer 1 1/2 hours.", + "Add carrots and onions.", + "Cover and continue cooking 35 to 40 minutes or until beef and vegetables are tender.", + "Bring beef stew to a boil over medium-high heat. Add cornstarch mixture; cook and stir 1 minute. Stir in sugar snap peas.", + "Reduce heat to medium and cook 3 to 4 minutes or until peas are heated through." + ], + "nutrition": { + "calories": "280.1", + "fat": "6", + "saturated": "1.5", + "sodium": "591.5", + "carbohydrates": "22.4", + "fiber": "6.1", + "sugar": "9.2", + "protein": "29.8" + } + }, + { + "_id": "a2b47185-b098-4855-b99c-ebf2521bec3f", + "title": "Lou's Fabulous Bruschetta", + "description": "Make and share this Lou's Fabulous Bruschetta recipe from Food.com.", + "prep": 30, + "cook": 10, + "category": "Vegetable", + "servings": "8", + "published": "1999-09-13T00:00:00.000Z", + "tags": [ + "European", + "Low Cholesterol", + "Healthy", + "Spring", + "Summer", + "< 60 Mins", + "Oven" + ], + "ingredients": { + "French baguette": "1", + "butter": "", + "garlic powder": "", + "ricotta cheese": "3/4", + "parmesan cheese": "", + "salt": "", + "tomatoes": "4 -5", + "olive oil": "1 -2", + "fresh basil leaves": "4 -5" + }, + "images": [ + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/59/pickKDLXe.jpg" + ], + "instructions": [ + "Cut baguette into slices.", + "Butter and then sprinkle garlic powder each piece, and bake till lightly golden brown.", + "Mix garlic powder, Parmesan cheese, and salt in the ricotta cheese, till a lovely blended taste.", + "Dice tomatoes in small cubes, add Olive Oil, and small strips of fresh basil leaves, cut into thin strips.", + "Spread the ricotta mixture, generously on the cooled garlic bread slices.", + "Top with tomato mixture and bake at 350F for 10 minutes.", + "Enjoy!" + ], + "nutrition": { + "calories": "221.5", + "fat": "6.5", + "saturated": "2.5", + "sodium": "367.8", + "carbohydrates": "32.5", + "fiber": "2.5", + "sugar": "1.8", + "protein": "8.1" + } + }, + { + "_id": "e435d459-225a-4170-8aa4-f0a0ee57ff7a", + "title": "Black Coffee Barbecue Sauce", + "description": "It's great to know folks like this sauce so much! I wish I could take credit for it but it was adopted after the original member left. Thank you, all, just the same.\r\nI have made the recipe with regular brewed coffee but highly recommend the espresso. In a pinch use strong instant if you have nothing else. The acid of the coffee balances the sweetness of the other ingredients.", + "prep": 10, + "cook": 20, + "category": "Lactose Free", + "servings": "", + "published": "1999-09-10T00:00:00.000Z", + "tags": [ + "Low Protein", + "Low Cholesterol", + "Healthy", + "Free Of...", + "< 30 Mins", + "Easy" + ], + "ingredients": { + "brewed coffee": "1/2", + "ketchup": "1", + "red wine vinegar": "1/4", + "dark brown sugar": "3/4", + "onion": "1", + "garlic cloves": "2", + "dark molasses": "2", + "hot dry mustard": "2", + "Worcestershire sauce": "2", + "cumin": "2", + "chili powder": "2" + }, + "images": [ + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/66/pic6Ysx4x.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/66/picknLY3c.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/66/piclB5wbq.jpg" + ], + "instructions": [ + "Combine all ingredients in a saucepan and simmer over low heat for 20 minutes.", + "Cool, then puree in a blender or food processor until smooth.", + "This can be stored in the refrigerator for up to 2 weeks in a covered container." + ], + "nutrition": { + "calories": "772", + "fat": "3.9", + "saturated": "0.5", + "sodium": "2241.9", + "carbohydrates": "189.6", + "fiber": "6.4", + "sugar": "164.3", + "protein": "7" + } + }, + { + "_id": "2bd11e40-6814-498f-a039-294a2d177092", + "title": "Brownie Cheesecake Torte", + "description": "Make and share this Brownie Cheesecake Torte recipe from Food.com.", + "prep": 35, + "cook": 55, + "category": "Cheesecake", + "servings": "12", + "published": "1999-08-22T00:00:00.000Z", + "tags": [ + "Dessert", + "Weeknight", + "Oven", + "< 4 Hours" + ], + "ingredients": { + "instant coffee granules": "15 1/4", + "cinnamon": "2", + "sugar": "4", + "all-purpose flour": "", + "vanilla extract": "1/2", + "fat free cream cheese": "2", + "skim milk": "4", + "fresh raspberry": "1" + }, + "images": [ + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/74/kZ2yXx22RimC8sHBAlFa_image.jpg" + ], + "instructions": [ + "Preheat oven to 425 degrees F.", + "Combine first 4 ingredients in a bowl.", + "Firmly press mixture into bottom and 1 inch up sides of a 9-inch springform pan coated with cooking spray.", + "Set aside. Combine 1/2 cup sugar, flour, vanilla, and cheeses; beat at medium speed of a mixer until well-blended.", + "Add egg whites and 2 tablespoons milk; beat well.", + "Combine 1/2 cup batter, 1 tablespoon milk, 2 tablespoons sugar, and cocoa in a small bowl; stir well.", + "Spoon remaining batter alternately with cocoa mixture into prepared crust. Swirl together using the tip of a knife. Bake at 425 degrees for 10 minutes.", + "Reduce oven temperature to 250 degrees; bake 45 minutes or until almost set. Cool completely on a wire rack.", + "Garnish with chocolate syrup and fresh raspberries, if desired." + ], + "nutrition": { + "calories": "122.1", + "fat": "4.9", + "saturated": "3", + "sodium": "194.7", + "carbohydrates": "14.4", + "fiber": "0.5", + "sugar": "10.9", + "protein": "5.7" + } + }, + { + "_id": "30f7f65c-6dc5-4c19-a556-f57ed60dd7a7", + "title": "Alfredo Sauce", + "description": "This is my son's favorite meal. I make it with shrimp for him for his birthday every year. GREAT for company because it is so easy and yet taste wonderful! I cook this in the microwave, but I'm sure you could do it on the stove too. Times are what work in my microwave. Please use your own good judgment on times to use in your microwave. (In my quest to eat healthier, I now make it with light butter, light cream and reduced fat Parmesan cheese. It still tastes wonderful, but there isn't any guilt!)\r\nPLEASE NOTE! This is an "authentic" Alfredo sauce recipe! Real Alfredo sauce *only* contains butter, cream, Parmesan cheese and pepper. It will be thin and there is no garlic in it! If you want a thicker sauce or one with garlic like modern restaurants serve, please look elsewhere! Recipe #52892 and Recipe #8596 are two good places to start.", + "prep": 5, + "cook": 10, + "category": "Sauces", + "servings": "4", + "published": "1999-09-15T00:00:00.000Z", + "tags": [ + "European", + "Very Low Carbs", + "High In...", + "< 15 Mins", + "Easy" + ], + "ingredients": { + "sweet butter": "1/4", + "heavy cream": "1", + "parmesan cheese": "3/4", + "salt": "", + "pepper": "1/4" + }, + "images": [ + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/76/lfS6kBlpRJMGzvXr3Gkz_AS%204%20-%20final_2.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/76/RU5fnqOQ6kQhNPHuyepw_AS%204%20-%20final_4.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/76/7Zay46y4T5iIMpwytGAh_9A7A15FF-075C-4696-911B-80C05EC777C8.jpeg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/76/rD6D3t6SrmNouznAOrTT_IMG_1241.JPG", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/76/pic9nC3rH.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/76/picOZfuNC.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/76/picvhwJQj.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/76/piczatR8o.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/76/picCBDhXY.jpg", + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/76/pict87aHR.jpg" + ], + "instructions": [ + "Place butter in microwave safe pot and heat on high for 30 seconds or until melted.", + "Add cream and warm on high for approximately 1 minute.", + "Add Parmesan cheese and warm until cheese melts.", + "Add salt and pepper to taste. (If serving with shrimp, you might not need much salt.).", + "Pour over 4 servings of warm noodles (I use angel hair) and toss to coat. Serve immediately.", + "Notes: I serve it with cubed, grilled or broiled chicken breast mixed in with the noodles or shrimp. Add a green salad and you have a complete meal. I have used margarine and canned Parmesan cheese and it worked fine." + ], + "nutrition": { + "calories": "489.9", + "fat": "50.4", + "saturated": "31.5", + "sodium": "312.4", + "carbohydrates": "2.5", + "fiber": "0", + "sugar": "0.2", + "protein": "8.7" + } + }, + { + "_id": "67bd289e-84c9-4706-b5e9-fc32a6b5edab", + "title": "Brazilian Empadinhas", + "description": "The empanadas in Brazil are different from those in other Latin american countries and are called empadas or empadinhas. They look more like mini pies", + "prep": 60, + "cook": 157, + "category": "Brazilian", + "servings": "8", + "published": "1999-08-24T00:00:00.000Z", + "tags": [ + "South American", + "Weeknight", + "Oven", + "< 4 Hours" + ], + "ingredients": { + "butter": "", + "flour": "2 1/2", + "salt": "1", + "margarine": "1/4", + "milk": "1", + "water": "1", + "shrimp": "3", + "onion": "1", + "tomatoes": "1/2", + "parsley": "1/2", + "lemon": "3", + "pepper": "1", + "Tabasco sauce": "", + "garlic": "", + "cornstarch": "", + "olive oil": "1/2", + "cumin": "2", + "bell peppers": "2" + }, + "images": [ + "https://img.sndimg.com/food/image/upload/w_555,h_416,c_fit,fl_progressive,q_95/v1/img/recipes/82/82.jpg" + ], + "instructions": [ + "DOUGH Cut butter into salt and flour.", + "Stir in rest of the ingredients and knead to combine or just process everything until it forms a ball.", + "Let rest covered 1 hour Make balls the size of a walnut, from 2/3 of the dough and line small muffin tins with the dough.", + "Place 2 tsp. of the cold filling into the lined tins.", + "Make small balls with the rest of the dough.", + "Flatten them to make lids for the mini pies.", + "Brush tops with egg yolk Bake in preheated 350 F oven for 30 to 35 minutes or until golden brown.", + "SHRIMP FILLING Clean and devein shrimp, saving heads and shells.", + "Make a broth with the shells and heads and 2 cups water.", + "Cook 1 hour, uncovered over low heat. Strain broth and cook it down to 1/2 cup.", + "Cook onions and garlic in olive oil until they start changing color.", + "Add bell pepper and cook 2 minutes, Add tomatoes, broth and seasonings and simmer almost to a paste. Add shrimp and cook just until they become opaque. Stir in cornstarch diluted in 2 Tbsp water.", + "Stir until thick.", + "Add parsley.", + "Let cool before using", + "NOTES : May use other fillings such as chicken, hearts of palms, cheese Miriam Podcameni Posvolsky Rio de Janeiro" + ], + "nutrition": { + "calories": "329.7", + "fat": "16.7", + "saturated": "3.4", + "sodium": "446.8", + "carbohydrates": "35.6", + "fiber": "2", + "sugar": "1.9", + "protein": "9.3" + } + }] \ No newline at end of file diff --git a/models/Recipe.js b/models/Recipe.js new file mode 100644 index 0000000..0e4c2fc --- /dev/null +++ b/models/Recipe.js @@ -0,0 +1,34 @@ + +import mongoose from 'mongoose'; + +const RecipeSchema = new mongoose.Schema({ + title: { + type: String, + required: true, + }, + description: String, + prep: Number, + cook: Number, + category: String, + servings: String, + published: Date, + tags: [String], + ingredients: { + type: Map, + of: String, + }, + images: [String], + instructions: [String], + nutrition: { + calories: String, + fat: String, + saturated: String, + sodium: String, + carbohydrates: String, + fiber: String, + sugar: String, + protein: String, + }, +}); + +export default mongoose.models.Recipe || mongoose.model('recipe', RecipeSchema); diff --git a/package-lock.json b/package-lock.json index 4f36145..97c7bb3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,10 @@ "version": "0.1.0", "dependencies": { "@fortawesome/react-fontawesome": "^0.2.2", + "dotenv": "^16.4.5", "lucide-react": "^0.453.0", + "mongodb": "^6.10.0", + "mongoose": "^8.7.2", "next": "14.2.15", "react": "^18", "react-dom": "^18", @@ -269,6 +272,14 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.9.tgz", + "integrity": "sha512-tVkljjeEaAhCqTzajSdgbQ6gE6f3oneVwa3iXR6csiEwXXOFsiC6Uh9iAjAhXPtqa/XMDHWjjeNH/77m/Yq2dw==", + "dependencies": { + "sparse-bitfield": "^3.0.3" + } + }, "node_modules/@next/env": { "version": "14.2.15", "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.15.tgz", @@ -525,6 +536,19 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==" + }, + "node_modules/@types/whatwg-url": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz", + "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==", + "dependencies": { + "@types/webidl-conversions": "*" + } + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.10.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.10.0.tgz", @@ -1104,6 +1128,14 @@ "node": ">=8" } }, + "node_modules/bson": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.9.0.tgz", + "integrity": "sha512-X9hJeyeM0//Fus+0pc5dSUMhhrrmWwQUtdavaQeF3Ta6m69matZkGWV/MrBcnwUeLC8W9kwwc2hfkZgUuCX3Ig==", + "engines": { + "node": ">=16.20.1" + } + }, "node_modules/busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -1366,7 +1398,6 @@ "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -1450,6 +1481,17 @@ "node": ">=6.0.0" } }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -3189,6 +3231,14 @@ "node": ">=4.0" } }, + "node_modules/kareem": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", + "integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -3301,6 +3351,11 @@ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc" } }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==" + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -3358,11 +3413,149 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/mongodb": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.10.0.tgz", + "integrity": "sha512-gP9vduuYWb9ZkDM546M+MP2qKVk5ZG2wPF63OvSRuUbqCR+11ZCAE1mOfllhlAG0wcoJY5yDL/rV3OmYEwXIzg==", + "dependencies": { + "@mongodb-js/saslprep": "^1.1.5", + "bson": "^6.7.0", + "mongodb-connection-string-url": "^3.0.0" + }, + "engines": { + "node": ">=16.20.1" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.1.0", + "gcp-metadata": "^5.2.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=6.0.0 <7", + "snappy": "^7.2.2", + "socks": "^2.7.1" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "gcp-metadata": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + }, + "socks": { + "optional": true + } + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.1.tgz", + "integrity": "sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg==", + "dependencies": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^13.0.0" + } + }, + "node_modules/mongoose": { + "version": "8.7.2", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.7.2.tgz", + "integrity": "sha512-Ok4VzMds9p5G3ZSUhmvBm1GdxanbzhS29jpSn02SPj+IXEVFnIdfwAlHHXWkyNscZKlcn8GuMi68FH++jo0flg==", + "dependencies": { + "bson": "^6.7.0", + "kareem": "2.6.3", + "mongodb": "6.9.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "17.1.3" + }, + "engines": { + "node": ">=16.20.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mongoose" + } + }, + "node_modules/mongoose/node_modules/mongodb": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.9.0.tgz", + "integrity": "sha512-UMopBVx1LmEUbW/QE0Hw18u583PEDVQmUmVzzBRH0o/xtE9DBRA5ZYLOjpLIa03i8FXjzvQECJcqoMvCXftTUA==", + "dependencies": { + "@mongodb-js/saslprep": "^1.1.5", + "bson": "^6.7.0", + "mongodb-connection-string-url": "^3.0.0" + }, + "engines": { + "node": ">=16.20.1" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.1.0", + "gcp-metadata": "^5.2.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=6.0.0 <7", + "snappy": "^7.2.2", + "socks": "^2.7.1" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "gcp-metadata": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + }, + "socks": { + "optional": true + } + } + }, + "node_modules/mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "dependencies": { + "debug": "4.x" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, "license": "MIT" }, "node_modules/mz": { @@ -3982,7 +4175,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -4360,6 +4552,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/sift": { + "version": "17.1.3", + "resolved": "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz", + "integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==" + }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -4382,6 +4579,14 @@ "node": ">=0.10.0" } }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "dependencies": { + "memory-pager": "^1.0.2" + } + }, "node_modules/streamsearch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", @@ -4778,6 +4983,17 @@ "node": ">=8.0" } }, + "node_modules/tr46": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", + "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "dependencies": { + "punycode": "^2.3.0" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/ts-api-utils": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", @@ -4968,6 +5184,26 @@ "dev": true, "license": "MIT" }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==", + "dependencies": { + "tr46": "^4.1.1", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index ddb8064..56d9d55 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,10 @@ }, "dependencies": { "@fortawesome/react-fontawesome": "^0.2.2", + "dotenv": "^16.4.5", "lucide-react": "^0.453.0", + "mongodb": "^6.10.0", + "mongoose": "^8.7.2", "next": "14.2.15", "react": "^18", "react-dom": "^18", From e5c2cf00f7da4144fa9dd161a161c18e802044dd Mon Sep 17 00:00:00 2001 From: kutlwano10 Date: Tue, 22 Oct 2024 13:44:29 +0200 Subject: [PATCH 2/9] changed MONGODB_URI --- app/api/recipe/route.js | 2 +- lib/connectMongoose.js | 12 +----------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/app/api/recipe/route.js b/app/api/recipe/route.js index 5097003..7e2b493 100644 --- a/app/api/recipe/route.js +++ b/app/api/recipe/route.js @@ -2,7 +2,7 @@ import { connectMongoose } from "@/lib/connectMongoose"; import Recipe from "@/models/Recipe"; import { NextResponse } from "next/server"; -export async function GET(req) { +export async function GET(req) { try { await connectMongoose() diff --git a/lib/connectMongoose.js b/lib/connectMongoose.js index 46828ad..51722ca 100644 --- a/lib/connectMongoose.js +++ b/lib/connectMongoose.js @@ -1,12 +1,5 @@ - import mongoose from 'mongoose'; -const MONGODB_URI = process.env.MONGODB_URI; // Get MongoDB URI from environment variables - -if (!MONGODB_URI) { - throw new Error('Please add your MongoDB URI to .env.local'); -} - /** * Connects to MongoDB using Mongoose. */ @@ -19,10 +12,7 @@ export const connectMongoose = async () => { } try { - await mongoose.connect(MONGODB_URI, { - useNewUrlParser: true, - useUnifiedTopology: true, - }); + await mongoose.connect(process.envMONGODB_URI) isConnected = true; console.log('Connected to MongoDB via Mongoose'); From c35bb84b9dcb3c9dc9315e6f0412b8dd70c6f18e Mon Sep 17 00:00:00 2001 From: kutlwano10 Date: Wed, 23 Oct 2024 10:03:30 +0200 Subject: [PATCH 3/9] Made Api endpoints for recipe & for recipe ID using mongoDB URI --- app/api/recipe/[id]/route.js | 36 +++++++++++++++---------- app/api/recipe/route.js | 23 +++++++--------- app/components/RecipeCard.jsx | 4 +-- lib/connectMongoose.js | 51 ++++++++++++++++++++++------------- models/Recipe.js | 10 ++++--- 5 files changed, 74 insertions(+), 50 deletions(-) diff --git a/app/api/recipe/[id]/route.js b/app/api/recipe/[id]/route.js index 894fae3..402d31b 100644 --- a/app/api/recipe/[id]/route.js +++ b/app/api/recipe/[id]/route.js @@ -1,14 +1,22 @@ -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 +import connectToDatabase from "../../../lib/connectMongoose"; +import Recipe from "../../../models/Recipe"; +import { NextResponse } from "next/server"; + +/** + * + * @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; + await connectToDatabase(); + const recipe = await Recipe.findOne({ _id: id }); + + return NextResponse.json({ recipe }, { status: 200 }); + } catch (error) { + console.error(error); + } +} diff --git a/app/api/recipe/route.js b/app/api/recipe/route.js index 7e2b493..f18e626 100644 --- a/app/api/recipe/route.js +++ b/app/api/recipe/route.js @@ -1,17 +1,14 @@ -import { connectMongoose } from "@/lib/connectMongoose"; -import Recipe from "@/models/Recipe"; +import connectToDatabase from "../../../lib/connectMongoose"; +import Recipe from "../../../models/Recipe"; import { NextResponse } from "next/server"; export async function GET(req) { - - try { - await connectMongoose() - const recipe = await Recipe.find({}) - console.log(recipe) - return NextResponse.json({recipe}) - } catch (error) { - - } - + try { + await connectToDatabase(); + const recipes = await Recipe.find({}).limit(50); + console.log(recipes) + return NextResponse.json({ recipes }); + } catch (error) { + console.error(error); + } } - diff --git a/app/components/RecipeCard.jsx b/app/components/RecipeCard.jsx index d893f1c..bd4ff34 100644 --- a/app/components/RecipeCard.jsx +++ b/app/components/RecipeCard.jsx @@ -4,9 +4,9 @@ import Link from 'next/link'; const RecipeCard = ({ recipe }) => { return ( - +
- {recipe.title} + {recipe.title}

{recipe.name}

Prep time: {recipe.prepTimeMinutes} mins

diff --git a/lib/connectMongoose.js b/lib/connectMongoose.js index 51722ca..b4ef9f3 100644 --- a/lib/connectMongoose.js +++ b/lib/connectMongoose.js @@ -1,24 +1,39 @@ import mongoose from 'mongoose'; -/** - * Connects to MongoDB using Mongoose. - */ -let isConnected = false; // Track connection status - -export const connectMongoose = async () => { - if (isConnected) { - console.log('MongoDB is already connected.'); - return; - } +const MONGODB_URI = process.env.MONGODB_URI; +console.log(process.env.MONGODB_URI) +if (!MONGODB_URI) { + throw new Error('Please define the MONGODB_URI environment variable inside .env.local'); +} + +let cached = global.mongoose; + +if (!cached) { + cached = global.mongoose = { conn: null, promise: null }; +} + +async function connectToDatabase() { + if (cached.conn) { + return cached.conn; + } - try { - await mongoose.connect(process.envMONGODB_URI) + if (!cached.promise) { + const opts = { + useNewUrlParser: true, + useUnifiedTopology: true, + dbName: 'devdb', // Ensures the correct database is used + }; - isConnected = true; - console.log('Connected to MongoDB via Mongoose'); - } catch (error) { - console.error('Error connecting to MongoDB:', error); - throw new Error('Failed to connect to MongoDB'); + cached.promise = mongoose.connect(MONGODB_URI, opts).then((mongoose) => { + console.log('Connected to MongoDB:', mongoose.connection.db.databaseName); // This should log 'devdb' + return mongoose; + }); + } + + cached.conn = await cached.promise; + return cached.conn; } -}; + + +export default connectToDatabase; diff --git a/models/Recipe.js b/models/Recipe.js index 0e4c2fc..0b5a60b 100644 --- a/models/Recipe.js +++ b/models/Recipe.js @@ -1,4 +1,3 @@ - import mongoose from 'mongoose'; const RecipeSchema = new mongoose.Schema({ @@ -29,6 +28,11 @@ const RecipeSchema = new mongoose.Schema({ sugar: String, protein: String, }, -}); +}, {collection: 'recipes'}); + +// Use 'Recipe' as the model name +const Recipe = mongoose.models.Recipe || mongoose.model('Recipe', RecipeSchema); + + +export default Recipe; -export default mongoose.models.Recipe || mongoose.model('recipe', RecipeSchema); From 5ea257f6584eb6ac40ff34b96264cac0747621ca Mon Sep 17 00:00:00 2001 From: phillip-tech Date: Wed, 23 Oct 2024 11:06:16 +0200 Subject: [PATCH 4/9] Added mobile menu and drag functionality to Navbar component --- app/components/Navbar.jsx | 85 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 80 insertions(+), 5 deletions(-) diff --git a/app/components/Navbar.jsx b/app/components/Navbar.jsx index 036dff6..b281564 100644 --- a/app/components/Navbar.jsx +++ b/app/components/Navbar.jsx @@ -1,11 +1,15 @@ -'use client'; - -import React, { useState, useEffect } from 'react'; +'use client' +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; @@ -25,6 +29,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: '/' }, { @@ -53,7 +77,15 @@ const Navbar = ({ position }) => { <> + + {/* Search Overlay */}
Date: Wed, 23 Oct 2024 11:07:51 +0200 Subject: [PATCH 5/9] Fetch data from database(MongoDb) - Fixed title, prep and cook time display --- app/api/recipe/route.js | 4 +++- app/components/RecipeCard.jsx | 8 ++++---- app/components/RecipeGrid.jsx | 8 ++++++-- lib/connectMongoose.js | 2 +- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/app/api/recipe/route.js b/app/api/recipe/route.js index f18e626..1adc1c4 100644 --- a/app/api/recipe/route.js +++ b/app/api/recipe/route.js @@ -3,8 +3,10 @@ import Recipe from "../../../models/Recipe"; import { NextResponse } from "next/server"; export async function GET(req) { + console.log('cjsd csdcdsc') try { - await connectToDatabase(); + let db = await connectToDatabase(); + console.log('mdcakmdcma') const recipes = await Recipe.find({}).limit(50); console.log(recipes) return NextResponse.json({ recipes }); diff --git a/app/components/RecipeCard.jsx b/app/components/RecipeCard.jsx index bd4ff34..23eb6e7 100644 --- a/app/components/RecipeCard.jsx +++ b/app/components/RecipeCard.jsx @@ -5,12 +5,12 @@ 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}

+

Prep time: {recipe.prep} mins

+

Cook time: {recipe.cook} mins

diff --git a/app/components/RecipeGrid.jsx b/app/components/RecipeGrid.jsx index 855950b..eeb96cf 100644 --- a/app/components/RecipeGrid.jsx +++ b/app/components/RecipeGrid.jsx @@ -9,9 +9,13 @@ const RecipeGrid = () => { useEffect(() => { const fetchRecipes = async () => { + console.log('hdbachbdashcb') try { - const response = await fetch('https://dummyjson.com/recipes',{cache:"no-store"}); + 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); @@ -27,7 +31,7 @@ const RecipeGrid = () => { return (
{recipes.map(recipe => ( - + ))}
); diff --git a/lib/connectMongoose.js b/lib/connectMongoose.js index b4ef9f3..c7beb3c 100644 --- a/lib/connectMongoose.js +++ b/lib/connectMongoose.js @@ -1,4 +1,4 @@ -import mongoose from 'mongoose'; +import mongoose from "mongoose"; const MONGODB_URI = process.env.MONGODB_URI; console.log(process.env.MONGODB_URI) From d8a18caf48b4b95edb3e6a71c0c87711ad9fb57b Mon Sep 17 00:00:00 2001 From: phillip-tech Date: Wed, 23 Oct 2024 11:31:47 +0200 Subject: [PATCH 6/9] Updated Navbar component with drag functionality, added mobile menu and search overlay, and refactored code organization --- app/api/recipe/route.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/api/recipe/route.js b/app/api/recipe/route.js index 1adc1c4..9adb9de 100644 --- a/app/api/recipe/route.js +++ b/app/api/recipe/route.js @@ -8,7 +8,7 @@ export async function GET(req) { let db = await connectToDatabase(); console.log('mdcakmdcma') const recipes = await Recipe.find({}).limit(50); - console.log(recipes) + //console.log(recipes) return NextResponse.json({ recipes }); } catch (error) { console.error(error); From 5faea70ef7a573f8a34f6855cf14228c0bd89d5b Mon Sep 17 00:00:00 2001 From: phillip-tech Date: Wed, 23 Oct 2024 11:32:56 +0200 Subject: [PATCH 7/9] Factored mobile menu and drag functionality to Navbar component" --- app/components/Navbar.jsx | 82 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 79 insertions(+), 3 deletions(-) diff --git a/app/components/Navbar.jsx b/app/components/Navbar.jsx index 036dff6..329c7f5 100644 --- a/app/components/Navbar.jsx +++ b/app/components/Navbar.jsx @@ -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; @@ -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: '/' }, { @@ -53,7 +78,15 @@ const Navbar = ({ position }) => { <> + + {/* Search Overlay */}
Date: Wed, 23 Oct 2024 18:19:37 +0200 Subject: [PATCH 8/9] "Refactored RecipeDetail component: updated console logs, modified recipe data rendering, and removed nutrition tab" --- app/api/recipe/[id]/route.js | 12 ++- app/api/recipe/route.js | 4 +- app/components/RecipeCard.jsx | 7 +- app/components/RecipeGrid.jsx | 9 +- app/recipes/[id]/page.jsx | 100 +++++++++++------- models/Recipe.js | 4 + package-lock.json | 186 +++++++++++++++++++++++++++++++++- package.json | 1 + 8 files changed, 272 insertions(+), 51 deletions(-) diff --git a/app/api/recipe/[id]/route.js b/app/api/recipe/[id]/route.js index 402d31b..858665c 100644 --- a/app/api/recipe/[id]/route.js +++ b/app/api/recipe/[id]/route.js @@ -1,6 +1,7 @@ -import connectToDatabase from "../../../lib/connectMongoose"; -import Recipe from "../../../models/Recipe"; +import connectToDatabase from "../../../../lib/connectMongoose"; +import Recipe from "../../../../models/Recipe"; import { NextResponse } from "next/server"; +import mongoose from "mongoose"; /** * @@ -12,9 +13,12 @@ import { NextResponse } from "next/server"; 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 }); - + const recipe = await Recipe.findOne({_id: id}).lean(); + console.log(recipe,'123456789df') return NextResponse.json({ recipe }, { status: 200 }); } catch (error) { console.error(error); diff --git a/app/api/recipe/route.js b/app/api/recipe/route.js index 9adb9de..a376384 100644 --- a/app/api/recipe/route.js +++ b/app/api/recipe/route.js @@ -7,8 +7,8 @@ export async function GET(req) { try { let db = await connectToDatabase(); console.log('mdcakmdcma') - const recipes = await Recipe.find({}).limit(50); - //console.log(recipes) + 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(error); diff --git a/app/components/RecipeCard.jsx b/app/components/RecipeCard.jsx index 23eb6e7..f8cdb78 100644 --- a/app/components/RecipeCard.jsx +++ b/app/components/RecipeCard.jsx @@ -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 ( -
+
{recipe.title}

{recipe.title}

Prep time: {recipe.prep} mins

Cook time: {recipe.cook} mins

-
@@ -28,4 +27,4 @@ const RecipeCard = ({ recipe }) => { ); }; -export default RecipeCard; \ No newline at end of file +export default RecipeCard; diff --git a/app/components/RecipeGrid.jsx b/app/components/RecipeGrid.jsx index f90df37..eeb96cf 100644 --- a/app/components/RecipeGrid.jsx +++ b/app/components/RecipeGrid.jsx @@ -1,3 +1,4 @@ +// app/components/RecipeGrid.jsx "use client" import React, { useEffect, useState } from 'react'; import RecipeCard from './RecipeCard'; // Update this import @@ -10,7 +11,9 @@ const RecipeGrid = () => { const fetchRecipes = async () => { console.log('hdbachbdashcb') try { - const response = await fetch('https://dummyjson.com/recipes',{cache:"no-store"}); + 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); @@ -28,10 +31,10 @@ const RecipeGrid = () => { return (
{recipes.map(recipe => ( - + ))}
); }; -export default RecipeGrid; +export default RecipeGrid; \ No newline at end of file diff --git a/app/recipes/[id]/page.jsx b/app/recipes/[id]/page.jsx index e2f524d..59c2473 100644 --- a/app/recipes/[id]/page.jsx +++ b/app/recipes/[id]/page.jsx @@ -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; @@ -13,78 +11,83 @@ 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(); + + + console.log("Recipe ID from params:", id); 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 + return ; } const totalTime = recipe.prepTimeMinutes + recipe.cookTimeMinutes; return (
- -
{recipe.name}
- -

- {recipe.name} -

+

{recipe.title}

-

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

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

-

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

- Total Time: {formatTime(totalTime)} + Cook Time: {formatTime(recipe.cook)}

+

Category: {recipe.category}

Servings: {recipe.servings} servings

+

Published: {new Date(recipe.published).toLocaleDateString()}

- -
    +
    • { > Instructions
    • +
    • setActiveTab("nutrition")} + > + Nutrition +
    -
    {activeTab === "ingredients" ? (

    Ingredients

    -
      - {recipe.ingredients.map((ingredient, index) => ( -
    • {ingredient}
    • +
        + {Object.entries(recipe.ingredients).map(([ingredient, quantity], index) => ( +
      • + {ingredient}: {quantity} +
      • ))}
    - ) : ( + ) : activeTab === "instructions" ? (

    Instructions

    -
      +
        {recipe.instructions.map((instruction, index) => (
      • {instruction}
      • ))}
    + ) : ( +
    +

    Nutrition Information

    +
      +
    • Calories: {recipe.nutrition.calories}
    • +
    • Fat: {recipe.nutrition.fat}g
    • +
    • Saturated Fat: {recipe.nutrition.saturated}g
    • +
    • Sodium: {recipe.nutrition.sodium}mg
    • +
    • Carbohydrates: {recipe.nutrition.carbohydrates}g
    • +
    • Fiber: {recipe.nutrition.fiber}g
    • +
    • Sugar: {recipe.nutrition.sugar}g
    • +
    • Protein: {recipe.nutrition.protein}g
    • +
    +
    )}
@@ -131,4 +157,4 @@ const RecipeDetail = ({ params }) => { ); }; -export default RecipeDetail; \ No newline at end of file +export default RecipeDetail; diff --git a/models/Recipe.js b/models/Recipe.js index 0b5a60b..e992283 100644 --- a/models/Recipe.js +++ b/models/Recipe.js @@ -1,6 +1,10 @@ import mongoose from 'mongoose'; const RecipeSchema = new mongoose.Schema({ + _id: { + type: String, + required: true, + }, title: { type: String, required: true, diff --git a/package-lock.json b/package-lock.json index 181d379..c3ea9ab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "@fortawesome/react-fontawesome": "^0.2.2", "dotenv": "^16.4.5", "lucide-react": "^0.453.0", + "mongoose": "^8.7.2", "next": "14.2.15", "react": "^18", "react-dom": "^18", @@ -270,6 +271,15 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.9.tgz", + "integrity": "sha512-tVkljjeEaAhCqTzajSdgbQ6gE6f3oneVwa3iXR6csiEwXXOFsiC6Uh9iAjAhXPtqa/XMDHWjjeNH/77m/Yq2dw==", + "license": "MIT", + "dependencies": { + "sparse-bitfield": "^3.0.3" + } + }, "node_modules/@next/env": { "version": "14.2.15", "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.15.tgz", @@ -526,6 +536,21 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==", + "license": "MIT" + }, + "node_modules/@types/whatwg-url": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz", + "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==", + "license": "MIT", + "dependencies": { + "@types/webidl-conversions": "*" + } + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.10.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.10.0.tgz", @@ -1105,6 +1130,15 @@ "node": ">=8" } }, + "node_modules/bson": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.9.0.tgz", + "integrity": "sha512-X9hJeyeM0//Fus+0pc5dSUMhhrrmWwQUtdavaQeF3Ta6m69matZkGWV/MrBcnwUeLC8W9kwwc2hfkZgUuCX3Ig==", + "license": "Apache-2.0", + "engines": { + "node": ">=16.20.1" + } + }, "node_modules/busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -3204,6 +3238,7 @@ "version": "2.6.3", "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", "integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==", + "license": "Apache-2.0", "engines": { "node": ">=12.0.0" } @@ -3320,6 +3355,12 @@ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc" } }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "license": "MIT" + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -3377,6 +3418,105 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/mongodb": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.9.0.tgz", + "integrity": "sha512-UMopBVx1LmEUbW/QE0Hw18u583PEDVQmUmVzzBRH0o/xtE9DBRA5ZYLOjpLIa03i8FXjzvQECJcqoMvCXftTUA==", + "license": "Apache-2.0", + "dependencies": { + "@mongodb-js/saslprep": "^1.1.5", + "bson": "^6.7.0", + "mongodb-connection-string-url": "^3.0.0" + }, + "engines": { + "node": ">=16.20.1" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.1.0", + "gcp-metadata": "^5.2.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=6.0.0 <7", + "snappy": "^7.2.2", + "socks": "^2.7.1" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "gcp-metadata": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + }, + "socks": { + "optional": true + } + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.1.tgz", + "integrity": "sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg==", + "license": "Apache-2.0", + "dependencies": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^13.0.0" + } + }, + "node_modules/mongoose": { + "version": "8.7.2", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.7.2.tgz", + "integrity": "sha512-Ok4VzMds9p5G3ZSUhmvBm1GdxanbzhS29jpSn02SPj+IXEVFnIdfwAlHHXWkyNscZKlcn8GuMi68FH++jo0flg==", + "license": "MIT", + "dependencies": { + "bson": "^6.7.0", + "kareem": "2.6.3", + "mongodb": "6.9.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "17.1.3" + }, + "engines": { + "node": ">=16.20.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mongoose" + } + }, + "node_modules/mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "license": "MIT", + "dependencies": { + "debug": "4.x" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -4380,7 +4520,8 @@ "node_modules/sift": { "version": "17.1.3", "resolved": "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz", - "integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==" + "integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==", + "license": "MIT" }, "node_modules/signal-exit": { "version": "4.1.0", @@ -4404,6 +4545,15 @@ "node": ">=0.10.0" } }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "license": "MIT", + "dependencies": { + "memory-pager": "^1.0.2" + } + }, "node_modules/streamsearch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", @@ -4800,6 +4950,18 @@ "node": ">=8.0" } }, + "node_modules/tr46": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", + "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "license": "MIT", + "dependencies": { + "punycode": "^2.3.0" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/ts-api-utils": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", @@ -4990,6 +5152,28 @@ "dev": true, "license": "MIT" }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==", + "license": "MIT", + "dependencies": { + "tr46": "^4.1.1", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 26251e6..168d3f1 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "@fortawesome/react-fontawesome": "^0.2.2", "dotenv": "^16.4.5", "lucide-react": "^0.453.0", + "mongoose": "^8.7.2", "next": "14.2.15", "react": "^18", "react-dom": "^18", From d12f32c3e1a4a97cd3c5db4de864164b1d57de16 Mon Sep 17 00:00:00 2001 From: SABELOMAWELA Date: Wed, 23 Oct 2024 18:19:59 +0200 Subject: [PATCH 9/9] "Refactored RecipeDetail component: updated console logs, changed recipe data rendering, and removed nutrition tab" --- app/recipes/[id]/page.jsx | 59 ++++++++++++--------------------------- 1 file changed, 18 insertions(+), 41 deletions(-) diff --git a/app/recipes/[id]/page.jsx b/app/recipes/[id]/page.jsx index 59c2473..8c06f7d 100644 --- a/app/recipes/[id]/page.jsx +++ b/app/recipes/[id]/page.jsx @@ -11,13 +11,13 @@ const formatTime = (minutes) => { const RecipeDetail = ({ params }) => { const { id } = params; - const router = useRouter(); + const router = useRouter(); const [recipe, setRecipe] = useState(null); const [activeTab, setActiveTab] = useState("ingredients"); - - console.log("Recipe ID from params:", id); + // 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 () => { @@ -31,7 +31,7 @@ const RecipeDetail = ({ params }) => { throw new Error("Failed to fetch recipe"); } const data = await response.json(); - console.log(data.recipe, 'data') + console.log(data.recipe,'data') setRecipe(data.recipe); } catch (error) { console.error("Error fetching recipe:", error); @@ -69,25 +69,26 @@ const RecipeDetail = ({ params }) => {

{recipe.title}

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

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

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

+

+ Total Time: {formatTime(totalTime)}

-

Category: {recipe.category}

Servings: {recipe.servings} servings

-

Published: {new Date(recipe.published).toLocaleDateString()}

-
    +
    • { > Instructions
    • -
    • setActiveTab("nutrition")} - > - Nutrition -
    {activeTab === "ingredients" ? (

    Ingredients

    -
      - {Object.entries(recipe.ingredients).map(([ingredient, quantity], index) => ( -
    • - {ingredient}: {quantity} -
    • - ))} +
        + {/* {recipe.ingredients.map((ingredient, index) => ( +
      • {ingredient}
      • + ))} */}
    - ) : activeTab === "instructions" ? ( + ) : (

    Instructions

    -
      +
        {recipe.instructions.map((instruction, index) => (
      • {instruction}
      • ))}
    - ) : ( -
    -

    Nutrition Information

    -
      -
    • Calories: {recipe.nutrition.calories}
    • -
    • Fat: {recipe.nutrition.fat}g
    • -
    • Saturated Fat: {recipe.nutrition.saturated}g
    • -
    • Sodium: {recipe.nutrition.sodium}mg
    • -
    • Carbohydrates: {recipe.nutrition.carbohydrates}g
    • -
    • Fiber: {recipe.nutrition.fiber}g
    • -
    • Sugar: {recipe.nutrition.sugar}g
    • -
    • Protein: {recipe.nutrition.protein}g
    • -
    -
    )}