source: CookCraft-FrontEnd/CookCraft-FrontEnd-master/cookcraft-app/src/components/RecipesComponents/Recipes.jsx@ d7b7f00

Last change on this file since d7b7f00 was d7b7f00, checked in by Gorazd Biskoski <gorazdbiskoskii@…>, 4 weeks ago

Add project

  • Property mode set to 100644
File size: 4.7 KB
RevLine 
[d7b7f00]1import React, { useState, useEffect } from 'react';
2import { useLocation, useNavigate } from 'react-router-dom';
3import styles from '../../css/RecipesCss/recipe-style.module.css';
4import Header from '../HomeComponents/Header';
5import Footer from '../HomeComponents/Footer';
6
7const Recipes = () => {
8 const [recipes, setRecipes] = useState([]);
9 const [page, setPage] = useState(0);
10 const [totalPages, setTotalPages] = useState(0);
11 const [loading, setLoading] = useState(false);
12
13 const location = useLocation();
14 const navigate = useNavigate();
15
16 const getSearchParams = (location) => {
17 const searchParams = new URLSearchParams(location.search);
18 const nationality = searchParams.get('nationality');
19 const category = searchParams.get('category');
20 const page = parseInt(searchParams.get('page'), 10);
21 const productIds = searchParams.getAll('productId').map(id => parseInt(id));
22 const searchTerm = searchParams.get('searchTerm');
23
24 return {
25 nationality,
26 category,
27 page: isNaN(page) ? 0 : page,
28 productIds,
29 searchTerm,
30 };
31 };
32 useEffect(() => {
33 const { nationality, category, page, productIds, searchTerm } = getSearchParams(location);
34
35 setPage(page);
36 loadRecipes(page, nationality, category, productIds, searchTerm);
37 }, [location]);
38
39 const loadRecipes = (page, nationality, category, productIds, searchTerm) => {
40 setLoading(true);
41
42 let url = `http://localhost:8080/api/recipes?page=${page}&size=9`;
43 if (searchTerm) {
44 url += `&searchTerm=${encodeURIComponent(searchTerm)}`;
45 }
46 if (nationality) {
47 url += `&nationality=${nationality}`;
48 }
49 if (category) {
50 url += `&category=${category}`;
51 }
52 if (productIds && productIds.length > 0) {
53 productIds.forEach(id => {
54 url += `&productId=${id}`;
55 });
56 }
57
58 fetch(url)
59 .then(response => response.json())
60 .then(data => {
61 setRecipes(data.content);
62 setTotalPages(data.totalPages);
63
64 setTimeout(() => {
65 setLoading(false);
66 }, 300);
67
68 window.scrollTo({ top: 0, behavior: 'smooth' });
69 })
70 .catch(error => {
71 console.error('Error fetching recipes:', error);
72 setLoading(false);
73 });
74};
75
76const handlePageChange = (newPage) => {
77 if (newPage !== page && newPage >= 0 && newPage < totalPages) {
78 setPage(newPage);
79
80 const searchParams = new URLSearchParams(location.search);
81 searchParams.set('page', newPage);
82
83 navigate(`/recipes?${searchParams.toString()}`);
84 }
85};
86
87const navigateToRecipe = (id) => {
88 const { nationality, category, productIds, page, searchTerm } = getSearchParams(location);
89
90 navigate(`/recipes/${id}`, {
91 state: {
92 category,
93 nationality,
94 productIds,
95 page,
96 searchTerm,
97 previousSearch: location.search,
98 },
99 });
100};
101
102 return (
103 <>
104 <Header />
105 <div className={styles.recipesPage}>
106 {loading && <div className={styles.loaderOverlay}><div className={styles.spinner}></div></div>}
107 <div className={styles.container}>
108 <h1 className={styles.sectionTitle}>Discover Your Next Favorite Dish</h1>
109 <button className={styles.addRecipeButton} onClick={() => navigate("/recipes/add")}>Add your recipe</button>
110 <div className={styles.recipeCards}>
111 {recipes.map(recipe => (
112 <div key={recipe.id} className={styles.recipeCard}>
113 <div
114 className={styles.recipeLink}
115 onClick={() => navigateToRecipe(recipe.id)}
116 >
117 <img src={recipe.strMealThumb} alt={recipe.strMeal} className={styles.recipeImage} />
118 <h2 className={styles.recipeTitle}>{recipe.strMeal}</h2>
119 <div className={styles.recipeDetails}>
120 <span className={styles.category}>{recipe.strCategory}</span>
121 <span className={styles.origin}>{recipe.strArea}</span>
122 </div>
123 </div>
124 </div>
125 ))}
126 </div>
127 <div className={styles.pagination}>
128 {page > 0 && (
129 <button
130 onClick={() => handlePageChange(page - 1)}
131 className={styles.pageButton}
132 >
133 &larr;
134 </button>
135 )}
136 <span className={styles.currentPage}>
137 Page {page + 1} of {totalPages}
138 </span>
139 {page < totalPages - 1 && (
140 <button
141 onClick={() => handlePageChange(page + 1)}
142 className={styles.pageButton}
143 >
144 &rarr;
145 </button>
146 )}
147 </div>
148 </div>
149 </div>
150 <Footer />
151 </>
152 );
153};
154
155export default Recipes;
Note: See TracBrowser for help on using the repository browser.