Skip to content

Commit ecc0fbe

Browse files
authored
Merge pull request #168 from CodeSpace-Academy/main
bringing over changes from old repo
2 parents 8e8919a + f06b3a9 commit ecc0fbe

26 files changed

+503
-79
lines changed

Public/ArejengLogo.png

29.3 KB
Loading

Public/apple-touch-icon.png

9.96 KB
Loading

Public/favicon-48x48.png

1.52 KB
Loading

Public/favicon.ico

14.7 KB
Binary file not shown.

Public/favicon.svg

Lines changed: 3 additions & 0 deletions
Loading

Public/site.webmanifest

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"name": "MyWebSite",
3+
"short_name": "MySite",
4+
"icons": [
5+
{
6+
"src": "/web-app-manifest-192x192.png",
7+
"sizes": "192x192",
8+
"type": "image/png",
9+
"purpose": "maskable"
10+
},
11+
{
12+
"src": "/web-app-manifest-512x512.png",
13+
"sizes": "512x512",
14+
"type": "image/png",
15+
"purpose": "maskable"
16+
}
17+
],
18+
"theme_color": "#ffffff",
19+
"background_color": "#ffffff",
20+
"display": "standalone"
21+
}

Public/web-app-manifest-192x192.png

11.1 KB
Loading

Public/web-app-manifest-512x512.png

50.3 KB
Loading

app/api/categories/route.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import clientPromise from "../../../lib/mongodb";
2+
3+
/**
4+
* API route handler for fetching all unique categories from the recipes collection.
5+
* File location: app/api/categories/route.js
6+
*
7+
* @async
8+
* @function
9+
* @returns {Promise<void>} Sends a JSON response containing all unique categories or an error message.
10+
*/
11+
export async function GET() {
12+
try {
13+
// Connect to MongoDB
14+
const client = await clientPromise;
15+
const db = client.db("devdb");
16+
17+
// Fetch all unique categories
18+
const categories = await db.collection("recipes").distinct("category");
19+
20+
// Log the results for debugging
21+
console.log('\n=== Categories Fetch Results ===');
22+
console.log('Total categories found:', categories.length);
23+
console.log('Categories:', categories);
24+
25+
// Return successful response
26+
return new Response(
27+
JSON.stringify({
28+
success: true,
29+
categories,
30+
total: categories.length
31+
}),
32+
{
33+
status: 200,
34+
headers: {
35+
'Content-Type': 'application/json'
36+
}
37+
}
38+
);
39+
40+
} catch (error) {
41+
// Log any errors
42+
console.error('Failed to fetch categories:', error);
43+
44+
// Return error response
45+
return new Response(
46+
JSON.stringify({
47+
success: false,
48+
error: "Failed to fetch categories",
49+
details: process.env.NODE_ENV === 'development' ? error.message : undefined
50+
}),
51+
{
52+
status: 500,
53+
headers: {
54+
'Content-Type': 'application/json'
55+
}
56+
}
57+
);
58+
}
59+
}

app/api/recipes/route.js

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,30 @@
11
import clientPromise from "../../../lib/mongodb";
22

33
/**
4-
* API route handler for fetching paginated recipes from the 'recipes' collection in MongoDB.
4+
* API route handler for fetching all recipes from the 'recipes' collection in MongoDB.
55
*
66
* @async
77
* @function
8-
* @param {Object} req - The request object containing query parameters for pagination.
9-
* @returns {Promise<void>} Sends a JSON response containing the paginated recipes or an error message.
8+
* @param {Object} _req - The request object (not used in this case).
9+
* @param {Object} res - The response object used to send back the result.
10+
* @returns {Promise<void>} Sends a JSON response containing the fetched recipes or an error message.
1011
*/
11-
export async function GET(req) {
12+
export async function GET (req) {
1213
try {
1314
// Await the MongoDB client connection
1415
const client = await clientPromise;
15-
const db = client.db("devdb"); // Connect to the 'devdb' database
16+
const db = client.db('devdb'); // Connect to the 'devdb' database
1617

17-
// Parse the 'page' and 'limit' query parameters from the URL, with defaults
18-
const url = new URL(req.url);
19-
const page = parseInt(url.searchParams.get("page") || "1", 10);
20-
const limit = parseInt(url.searchParams.get("limit") || "20", 10);
21-
22-
// Calculate the number of documents to skip for pagination
23-
const skip = (page - 1) * limit;
24-
25-
// Fetch the paginated recipes from the collection
26-
const recipes = await db.collection("recipes")
27-
.find({})
28-
.skip(skip)
29-
.limit(limit)
30-
.toArray();
18+
// Fetch all documents from the 'recipes' collection and convert them to an array
19+
const recipes = await db.collection('recipes').find({}).limit(100).toArray();
3120

3221
// Send a 200 (OK) response with the fetched recipes in JSON format
33-
return new Response(JSON.stringify({ recipes }), { status: 200 });
22+
return new Response(JSON.stringify({ recipes}), { status: 200 });
3423
} catch (e) {
35-
36-
37-
return new Response(JSON.stringify({ error: "Failed to fetch data" }), { status: 500 });
24+
// Log the error to the console for debugging
25+
console.error(e);
26+
27+
// Send a 500 (Internal Server Error) response with an error message
28+
return new Response(JSON.stringify({error: 'Failed to fetch data'}), { status: 500 });
3829
}
39-
}
30+
};

app/components/Recipes.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
"use client";
2+
3+
import React, { useEffect, useState } from 'react';
4+
5+
const Recipes = () => {
6+
const [recipes, setRecipes] = useState([]);
7+
const [loading, setLoading] = useState(true);
8+
const [error, setError] = useState(null);
9+
10+
// Fetch recipes from the API
11+
useEffect(() => {
12+
const fetchRecipes = async () => {
13+
try {
14+
console.log("Fetching recipes...");
15+
const response = await fetch('/api/recipes');
16+
17+
if (!response.ok) {
18+
throw new Error('Network response was not ok');
19+
}
20+
21+
const data = await response.json();
22+
console.log("Fetched recipes:", data);
23+
setRecipes(data);
24+
} catch (error) {
25+
console.error("Error fetching recipes:", error.message);
26+
setError(error.message);
27+
} finally {
28+
setLoading(false);
29+
}
30+
};
31+
32+
33+
fetchRecipes();
34+
}, []);
35+
36+
if (loading) {
37+
return <div>Loading...</div>;
38+
}
39+
40+
if (error) {
41+
return <div>Error: {error}</div>;
42+
}
43+
44+
if (recipes.length === 0) {
45+
return <div>No recipes found.</div>;
46+
}
47+
48+
return (
49+
<div>
50+
<h1>Recipes</h1>
51+
<ul>
52+
{recipes.map((recipe) => (
53+
<li key={recipe._id}>
54+
<h2>{recipe.title}</h2>
55+
<p>{recipe.description}</p>
56+
{/* Add more fields from your recipe object as needed */}
57+
</li>
58+
))}
59+
</ul>
60+
</div>
61+
);
62+
};
63+
64+
export default Recipes;

app/components/error.js

Lines changed: 47 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,9 @@
11
"use client";
22

3-
import { useEffect } from "react";
3+
import { useEffect, useState } from "react";
44
import { motion } from "framer-motion";
55

6-
/**
7-
* @typedef {Object} SpinningGearProps
8-
* @property {string} [className] - Additional CSS classes for the SVG.
9-
*/
10-
11-
/**
12-
* Renders a spinning gear SVG animation.
13-
* @function
14-
* @returns {JSX.Element} The SpinningGear component.
15-
*/
6+
// Component for the spinning gear animation
167
const SpinningGear = () => (
178
<motion.svg
189
xmlns="http://www.w3.org/2000/svg"
@@ -32,22 +23,8 @@ const SpinningGear = () => (
3223
</motion.svg>
3324
);
3425

35-
/**
36-
* @typedef {Object} ErrorProps
37-
* @property {Error} error - The error object.
38-
* @property {Function} reset - Function to reset the error state.
39-
*/
40-
41-
/**
42-
* Renders an error page with animation and a reset button.
43-
* @function
44-
* @param {ErrorProps} props - The component props.
45-
* @returns {JSX.Element} The Error component.
46-
*/
26+
// Component for handling and displaying errors
4727
export default function Error({ error, reset }) {
48-
/**
49-
* Logs the error to the console when the component mounts or the error changes.
50-
*/
5128
useEffect(() => {
5229
console.error(error);
5330
}, [error]);
@@ -77,15 +54,15 @@ export default function Error({ error, reset }) {
7754
animate={{ opacity: 1, y: 0 }}
7855
transition={{ delay: 0.4, duration: 0.5 }}
7956
>
80-
Something went wrong!
57+
Something went wrong while retrieving recipes!
8158
</motion.p>
8259
<motion.p
8360
className="mt-4 mb-8 text-teal-700"
8461
initial={{ opacity: 0 }}
8562
animate={{ opacity: 1 }}
8663
transition={{ delay: 0.6, duration: 0.5 }}
8764
>
88-
Don&apost t worry, try refreshing or return to the homepage.
65+
Dont worry, try refreshing or return to the homepage.
8966
</motion.p>
9067
<motion.div
9168
className="flex justify-center space-x-4"
@@ -107,3 +84,45 @@ export default function Error({ error, reset }) {
10784
</section>
10885
);
10986
}
87+
88+
// New component to fetch recipe data
89+
export function RecipeFetcher() {
90+
const [recipes, setRecipes] = useState([]);
91+
const [loading, setLoading] = useState(true);
92+
const [error, setError] = useState(null);
93+
94+
useEffect(() => {
95+
const fetchRecipes = async () => {
96+
try {
97+
const response = await fetch("API_URL_HERE"); // Replace with your API URL
98+
if (!response.ok) {
99+
throw new Error("Failed to fetch recipes");
100+
}
101+
const data = await response.json();
102+
setRecipes(data);
103+
} catch (err) {
104+
setError(err);
105+
} finally {
106+
setLoading(false);
107+
}
108+
};
109+
110+
fetchRecipes();
111+
}, []);
112+
113+
if (loading) {
114+
return <SpinningGear />;
115+
}
116+
117+
if (error) {
118+
return <Error error={error} reset={() => setError(null)} />;
119+
}
120+
121+
return (
122+
<div>
123+
{recipes.map(recipe => (
124+
<div key={recipe.id}>{recipe.name}</div> // Customize as per your recipe structure
125+
))}
126+
</div>
127+
);
128+
}

app/components/ui/card.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import * as React from "react"
2+
import { cn } from "../../../lib/utils"
3+
4+
const Card = React.forwardRef(({ className, ...props }, ref) => (
5+
<div
6+
ref={ref}
7+
className={cn("rounded-lg border bg-card text-card-foreground shadow-sm", className)}
8+
{...props}
9+
/>
10+
))
11+
Card.displayName = "Card"
12+
13+
const CardHeader = React.forwardRef(({ className, ...props }, ref) => (
14+
<div
15+
ref={ref}
16+
className={cn("flex flex-col space-y-1.5 p-6", className)}
17+
{...props}
18+
/>
19+
))
20+
CardHeader.displayName = "CardHeader"
21+
22+
const CardTitle = React.forwardRef(({ className, ...props }, ref) => (
23+
<h3
24+
ref={ref}
25+
className={cn("text-2xl font-semibold leading-none tracking-tight", className)}
26+
{...props}
27+
/>
28+
))
29+
CardTitle.displayName = "CardTitle"
30+
31+
const CardDescription = React.forwardRef(({ className, ...props }, ref) => (
32+
<p
33+
ref={ref}
34+
className={cn("text-sm text-muted-foreground", className)}
35+
{...props}
36+
/>
37+
))
38+
CardDescription.displayName = "CardDescription"
39+
40+
const CardContent = React.forwardRef(({ className, ...props }, ref) => (
41+
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
42+
))
43+
CardContent.displayName = "CardContent"
44+
45+
const CardFooter = React.forwardRef(({ className, ...props }, ref) => (
46+
<div
47+
ref={ref}
48+
className={cn("flex items-center p-6 pt-0", className)}
49+
{...props}
50+
/>
51+
))
52+
CardFooter.displayName = "CardFooter"
53+
54+
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }

0 commit comments

Comments
 (0)