diff --git a/src/Components/FoodElem/FoodDetail/FoodDetail.js b/src/Components/FoodElem/FoodDetail/FoodDetail.js
index 7b097ff..fb4b2b8 100644
--- a/src/Components/FoodElem/FoodDetail/FoodDetail.js
+++ b/src/Components/FoodElem/FoodDetail/FoodDetail.js
@@ -1,117 +1,86 @@
-import React from 'react';
+import React, { useState } from 'react';
import PropTypes from 'prop-types';
-import { useState } from "react";
-
/**
* Component : Component handling a specific detail of a food, user inputs, and displays the choices
*
* @component FoodDetail
* @param {String} name Name of the food detail
* @param {[Object]} data Object Array of the current detail information of a food
- * @param {Object} multiple Boolean, used to know if multiple detail options can be chosen
+ * @param {Boolean} multiple Boolean, used to know if multiple detail options can be chosen
* @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 FoodDetail({name, data, multiple, orderDetails, setOrderDetails}) {
+function FoodDetail({ name, data, multiple, orderDetails, setOrderDetails }) {
+ // Initialize data based on the previous state of the details buttons
+ const initializeData = () => {
+ const existingDetail = orderDetails.details.find(detail => detail.name === name);
+ const selectedItems = existingDetail ? existingDetail.list : [];
+ return data.map(item => ({
+ name: item,
+ selected: selectedItems.includes(item),
+ color: selectedItems.includes(item)
+ ? 'bg-kitchen-food-detail-selected'
+ : 'bg-kitchen-food-detail',
+ }));
+ };
- let detailObj = {name: name, list: []};
- //map function to parse the data of a detail, to add a button color and a boolean
- //uses current order details to update data, preventing resets between page change
- const [fullData, setFullData] = useState(data.map((elem => {
- let color = 'bg-kitchen-food-detail';
- let selected = false;
- let copy = orderDetails.details;
- let check = copy.filter(e => e.name === name);
- if (check.length !== 0 && check[0].list.find(e => e === elem)) {
- color = 'bg-kitchen-food-detail-selected';
- selected = true;
- }
- return {
- name: elem,
- color: color,
- selected: selected
+ const [fullData, setFullData] = useState(initializeData);
+
+ // Update order details object with the new details
+ const updateOrderDetails = (updatedItems) => {
+ const updatedDetails = orderDetails.details.filter(detail => detail.name !== name);
+ if (updatedItems.length > 0) {
+ updatedDetails.push({name, list: updatedItems});
}
- })));
+ setOrderDetails({...orderDetails, details: updatedDetails});
+ };
- //function called when a choice of a detail is clicked :
- //updates the button based on user inputs
- const handleClick = (name) => {
- setFullData(null)
- setFullData(fullData.map((data => {
- let color = data.color;
- let selected = data.selected;
- if (multiple === false) {
- color = 'bg-kitchen-food-detail';
- selected = false;
+ // Handle click on a detail choice
+ const handleClick = (clickedName) => {
+ const updatedData = fullData.map(item => {
+ // if multiple is false, will deselects other options
+ if (!multiple && item.name !== clickedName) {
+ return {...item, selected: false, color: 'bg-kitchen-food-detail'};
}
- if (data.name === name) {
- selected = data.selected ? false : true;
- let copy = orderDetails.details;
- //adds the user choices to an object, else remove it
- if (selected) {
- color = 'bg-kitchen-food-detail-selected';
- copy = copy.filter(e => e.name === detailObj.name);
- let temp = detailObj.list;
- if (copy.length !== 0) {
- temp = copy[0].list;
- }
- //If the detail is a single choice, will erase previous one, otherwise add it to a list
- if (multiple === false) {
- temp = [data.name];
- } else {
- temp.push(data.name);
- }
- detailObj = {name: detailObj.name, list: temp};
- } else {
- copy = copy.filter(e => e.name === detailObj.name);
- let temp = detailObj.list;
- if (copy.length !== 0) {
- temp = copy[0].list;
- temp = temp.filter(e => e !== data.name);
- detailObj = {name: detailObj.name, list: temp};
- }
- color = 'bg-kitchen-food-detail';
- }
- //adds the new detail to the current order
- let arr = orderDetails.details;
- arr = arr.filter(e => e.name !== detailObj.name);
- let sups = orderDetails.sups;
- arr.push(detailObj);
- setOrderDetails({details: arr, sups: sups});
+ if (item.name === clickedName) {
+ const isSelected = !item.selected;
+ return {
+ ...item,
+ selected: isSelected,
+ color: isSelected ? 'bg-kitchen-food-detail-selected' : 'bg-kitchen-food-detail',
+ };
}
- return {
- name: data.name,
- color: color,
- selected: selected
- }
- })))
- }
+ return item;
+ });
+ const selectedItems = updatedData.filter(item => item.selected).map(item => item.name);
+ setFullData(updatedData);
+ updateOrderDetails(selectedItems);
+ };
- //map function to display all choices of a detail
- const choice = fullData.map((elem) =>
+ const choice = fullData.map((elem) => (
-
-
{name}
+
+
+ {name}
+
{choice}
- )
+ );
}
FoodDetail.propTypes = {
@@ -122,5 +91,4 @@ FoodDetail.propTypes = {
setOrderDetails: PropTypes.func.isRequired
}
-
export default FoodDetail;
diff --git a/src/__tests__/Components/FoodElem/FoodDetail.test.js b/src/__tests__/Components/FoodElem/FoodDetail.test.js
index 4ee1041..a1733d2 100644
--- a/src/__tests__/Components/FoodElem/FoodDetail.test.js
+++ b/src/__tests__/Components/FoodElem/FoodDetail.test.js
@@ -1,109 +1,125 @@
import React from 'react';
-import { render, screen, fireEvent } from '@testing-library/react';
+import { render, fireEvent } from '@testing-library/react';
import FoodDetail from '../../../Components/FoodElem/FoodDetail/FoodDetail';
describe('FoodDetail Component', () => {
const mockSetOrderDetails = jest.fn();
- const name = "Accompagnement";
- const data = ["Frite", "Salade", "Riz", "Pâte", "Semoule"];
- const orderDetails = {details: [], sups: []};
- beforeEach(() => {
+ const defaultProps = {
+ name: 'Accompagnement',
+ data: ['Frite', 'Salade', 'Riz', "Pâte"],
+ multiple: true,
+ orderDetails: {
+ details: [],
+ sups: [],
+ },
+ setOrderDetails: mockSetOrderDetails,
+ };
+
+ afterEach(() => {
jest.clearAllMocks();
});
- test('renders FoodDetail', () => {
- render(
-
- );
-
- expect(screen.getByText(name)).toBeInTheDocument();
- data.forEach(item => {
- expect(screen.getByText(item)).toBeInTheDocument();
+ test('renders component', () => {
+ const { getByText } = render(
);
+
+ expect(getByText('Accompagnement')).toBeInTheDocument();
+ defaultProps.data.forEach((item) => {
+ expect(getByText(item)).toBeInTheDocument();
});
});
- test('updates an option when multiple = false', () => {
- render(
-
- );
+ test('initializes data with orderDetails', () => {
+ const customProps = {
+ ...defaultProps,
+ orderDetails: {
+ details: [{name: 'Accompagnement', list: ['Riz']}],
+ sups: [],
+ },
+ };
- const selectedButton = screen.getByText("Frite").closest('div');
- fireEvent.click(selectedButton.querySelector('button'));
+ const { getByText } = render(
);
+ const selectedButton = getByText('Riz').closest('div');
expect(selectedButton).toHaveClass('bg-kitchen-food-detail-selected');
+ });
+
+ test('handles selection', () => {
+ const singleChoiceProps = {...defaultProps, multiple: false};
+ const { getByText } = render(
);
+
+ const selectedButton = getByText('Riz').closest('button');
+ const secondButton = getByText('Frite').closest('button');
+
+ fireEvent.click(selectedButton);
expect(mockSetOrderDetails).toHaveBeenCalledWith({
- details: [{ name: name, list: ["Frite"] }],
- sups: []
+ details: [{name: 'Accompagnement', list: ['Riz']}],
+ sups: [],
+ });
+
+ fireEvent.click(secondButton);
+ expect(mockSetOrderDetails).toHaveBeenCalledWith({
+ details: [{name: 'Accompagnement', list: ['Frite']}],
+ sups: [],
});
});
- test('updates an option when mutiple = true', () => {
- render(
-
- );
-
- const firstButton = screen.getByText("Frite").closest('div');
- fireEvent.click(firstButton.querySelector('button'));
+ test('handles multiple selection', () => {
+ const { getByText } = render(
);
- const secondButton = screen.getByText("Semoule").closest('div');
- fireEvent.click(secondButton.querySelector('button'));
+ const firstButton = getByText('Riz').closest('button');
+ const secondButton = getByText('Frite').closest('button');
- expect(firstButton).toHaveClass('bg-kitchen-food-detail-selected');
- expect(secondButton).toHaveClass('bg-kitchen-food-detail-selected');
+ fireEvent.click(firstButton);
+ expect(mockSetOrderDetails).toHaveBeenCalledWith({
+ details: [{name: 'Accompagnement', list: ['Riz']}],
+ sups: [],
+ });
+ fireEvent.click(secondButton);
expect(mockSetOrderDetails).toHaveBeenCalledWith({
- details: [{ name: name, list: expect.arrayContaining(["Frite"]) }],
- sups: []
+ details: [{name: 'Accompagnement', list: ['Frite', 'Riz']}],
+ sups: [],
});
+
+ fireEvent.click(firstButton);
expect(mockSetOrderDetails).toHaveBeenCalledWith({
- details: [{ name: name, list: expect.arrayContaining(["Semoule"]) }],
- sups: []
+ details: [{name: 'Accompagnement', list: ['Frite']}],
+ sups: [],
});
});
- test('deselects an option', () => {
- const orderDetailsWithSelection = {
- details: [{ name: name, list: ["Frite"] }],
- sups: []
+ test('removes details', () => {
+ const initialProps = {
+ ...defaultProps,
+ orderDetails: {
+ details: [{name: 'Accompagnement', list: ['Riz']}],
+ sups: [],
+ },
};
- render(
-
- );
-
- const selectedButton = screen.getByText("Frite").closest('div');
- expect(selectedButton).toHaveClass('bg-kitchen-food-detail-selected');
- fireEvent.click(selectedButton.querySelector('button'));
+ const { getByText } = render(
);
- expect(selectedButton).toHaveClass('bg-kitchen-food-detail');
+ const firstButton = getByText('Riz').closest('button');
+
+ fireEvent.click(firstButton);
expect(mockSetOrderDetails).toHaveBeenCalledWith({
- details: [{ name: name, list: [] }],
- sups: []
+ details: [],
+ sups: [],
});
});
-});
\ No newline at end of file
+
+ test('updates color', () => {
+ const { getByText } = render(
);
+
+ const firstButton = getByText('Riz').closest('div');
+ const secondButton = getByText('Frite').closest('div');
+
+ expect(firstButton).toHaveClass('bg-kitchen-food-detail');
+ expect(secondButton).toHaveClass('bg-kitchen-food-detail');
+
+ fireEvent.click(firstButton.querySelector('button'));
+ expect(firstButton).toHaveClass('bg-kitchen-food-detail-selected');
+ expect(secondButton).toHaveClass('bg-kitchen-food-detail');
+ });
+});