Skip to content

Commit

Permalink
Merge pull request #78 from Hello-Kitchen/49-dynamic-loading-of-content
Browse files Browse the repository at this point in the history
feat: dynamic loading of categories and foods
  • Loading branch information
JulesGresset authored Jan 10, 2025
2 parents 391dfef + 286b2d5 commit 47dced3
Showing 1 changed file with 162 additions and 39 deletions.
201 changes: 162 additions & 39 deletions src/Pages/Dashboard/Dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,71 +2,194 @@ import React, { useEffect, useState } from "react";
import { useOutletContext } from "react-router-dom";
import PropTypes from "prop-types";

import CategoryButton from '../../Components/CategoryButton/CategoryButton';
import CategoryButton from "../../Components/CategoryButton/CategoryButton";
import FoodList from "../../Components/FoodList/FoodList";

/**
* Component : Page, Displays all the food categories of the restaurant
*
*
* @component Dashboard
* @param {function} setOrders state function used to update the current order when the food is added
* @param {Object} orderDetails Object used to persist detail and ingredient choices of a current food
* @param {function} setOrderDetails state function to update the orderDetails object
*/
function Dashboard({ setOrders, orderDetails, setOrderDetails }) {
const data = localStorage.getItem("data");
const { setPriceLess, price, setPayList } = useOutletContext();
const [ selectedCategory, setSelectedCategory ] = useState();
const [ categoryFood, setCategoryFood ] = useState();
const data = localStorage.getItem("data");
const { setPriceLess, price, setPayList } = useOutletContext();
const [selectedCategory, setSelectedCategory] = useState();
const [categoryFood, setCategoryFood] = useState();

useEffect(() => {
setPriceLess(price);
setPayList([]);
}, [price, setPriceLess, setPayList]);
useEffect(() => {
setPriceLess(price);
setPayList([]);
}, [price, setPriceLess, setPayList]);

const handleCategoryClick = async (id) => {
const tmp = await JSON.parse(data).find((elem) => elem.id === id).food;
setCategoryFood(tmp);
setSelectedCategory(id);
const handleCategoryClick = async (id) => {
const localFoods = JSON.parse(data).find((elem) => elem.id === id).food;

setCategoryFood(localFoods);
setSelectedCategory(id);

try {
const response = await fetch(
`http://${process.env.REACT_APP_BACKEND_URL}:${process.env.REACT_APP_BACKEND_PORT}/api/${process.env.REACT_APP_NBR_RESTAURANT}/food?foodCategory=${id}`,
{
headers: {
Authorization: `Bearer ${localStorage.getItem("token")}`,
},
}
);

if (response.status === 401) {
throw new Error("Unauthorized access. Please log in.");
}

const apiFoods = await response.json();
const localData = JSON.parse(localStorage.getItem("data")) || [];

const updatedFoods = await Promise.all(
apiFoods.map(async (apiFood) => {
const localFood = localFoods.find(
(localFood) => localFood.id === apiFood.id
);

// If food already exists in the cache
if (localFood) {
return {
...apiFood,
details: localFood.details,
ingredients: localFood.ingredients,
};
}

// If food is new
const foodDetailsResponse = await fetch(
`http://${process.env.REACT_APP_BACKEND_URL}:${process.env.REACT_APP_BACKEND_PORT}/api/${process.env.REACT_APP_NBR_RESTAURANT}/food/${apiFood.id}?useCase=POS`,
{
headers: {
Authorization: `Bearer ${localStorage.getItem("token")}`,
},
}
);

if (foodDetailsResponse.status === 401) {
throw new Error("Unauthorized access. Please log in.");
}

const newFoodDetails = await foodDetailsResponse.json();
return newFoodDetails;
})
);

const updatedLocalData = localData.map((category) => {
if (category.id === id) {
return { ...category, food: updatedFoods };
}
return category;
});

setCategoryFood(updatedFoods);
localStorage.setItem("data", JSON.stringify(updatedLocalData));
} catch (error) {
console.log(error);
}
};

const colors = [
"bg-category-red",
"bg-category-purple",
"bg-category-orange",
"bg-category-green",
"bg-category-blue",
"bg-category-cyan"
]
const buttons = JSON.parse(data).map((elem) =>
<CategoryButton key={elem.id} id={elem.id} name={elem.name} food={elem.food} color={colors[elem.id] != null ? colors[elem.id] : colors[0]} handleClick={(id) => handleCategoryClick(id)}/>
);
const colors = [
"bg-category-red",
"bg-category-purple",
"bg-category-orange",
"bg-category-green",
"bg-category-blue",
"bg-category-cyan",
];

const buttons = JSON.parse(data).map((elem) => (
<CategoryButton
key={elem.id}
id={elem.id}
name={elem.name}
food={elem.food}
color={colors[elem.id] != null ? colors[elem.id] : colors[0]}
handleClick={(id) => handleCategoryClick(id)}
/>
));

useEffect(() => {
fetch(
`http://${process.env.REACT_APP_BACKEND_URL}:${process.env.REACT_APP_BACKEND_PORT}/api/${process.env.REACT_APP_NBR_RESTAURANT}/food_category`,
{
headers: {
Authorization: `Bearer ${localStorage.getItem("token")}`,
},
}
)
.then((response) => {
if (response.status === 401) {
throw new Error("Unauthorized access. Please log in.");
}
return response.json();
})
.then((data) => {
const localData = JSON.parse(localStorage.getItem("data")) || [];

const updatedData = data.map((apiCategory) => {
const localCategory = localData.find(
(localCategory) => localCategory.id === apiCategory.id
);
// If the category already exists
if (localCategory) {
return {
...apiCategory,
food: localCategory.food || [], // The food array is not changed (not in the API call)
};
}
// If it's a new category
return {
...apiCategory,
food: [], // The food array will be loaded when the user clicks on the category
};
});
localStorage.setItem("data", JSON.stringify(updatedData));
})
.catch((error) => {
console.log(error);
});
}, []);

return (
<div className="h-full w-3/4">
{ selectedCategory ?
<div className="h-full w-full">
<div className="h-5 w-full bg-black text-white" onClick={() => setSelectedCategory(null)}>
TMP BACK BTN
</div>
{selectedCategory ? (
<div className="h-full w-full">
<FoodList foods={categoryFood} color={colors[selectedCategory]} setOrders={setOrders} orderDetails={orderDetails} setOrderDetails={setOrderDetails}/>
<div
className="h-5 w-full bg-black text-white"
onClick={() => setSelectedCategory(null)}
>
TMP BACK BTN
</div>
<div className="h-full w-full">
<FoodList
foods={categoryFood}
color={colors[selectedCategory]}
setOrders={setOrders}
orderDetails={orderDetails}
setOrderDetails={setOrderDetails}
/>
</div>
</div>
</div>
:
) : (
<div className="h-full grid grid-cols-2 grid-rows-8 content-start">
{buttons}
{buttons}
</div>
}
)}
</div>
);
}


Dashboard.propTypes = {
setOrders: PropTypes.func.isRequired,
orderDetails: PropTypes.object.isRequired,
setOrderDetails: PropTypes.func.isRequired,
setOrders: PropTypes.func.isRequired,
orderDetails: PropTypes.object.isRequired,
setOrderDetails: PropTypes.func.isRequired,
};

export default Dashboard;

0 comments on commit 47dced3

Please sign in to comment.