From 40a8b0f460f62612651416abc49493cec8c5596f Mon Sep 17 00:00:00 2001 From: romane-ledru Date: Sun, 31 Dec 2023 11:32:02 +0100 Subject: [PATCH] Change Restaurant button --- assets/app.scss | 6 - package-lock.json | 26 ++ package.json | 1 + src/components/UI/Button/RestaurantButton.tsx | 247 ++++++++++++++++++ src/components/UI/Button/ValidateButton.tsx | 18 ++ src/components/UI/ToggleSwitch.tsx | 38 +-- src/data/restaurants.ts | 3 - src/pages/RestaurantsOptions.tsx | 53 ++-- 8 files changed, 332 insertions(+), 60 deletions(-) create mode 100644 src/components/UI/Button/RestaurantButton.tsx create mode 100644 src/components/UI/Button/ValidateButton.tsx diff --git a/assets/app.scss b/assets/app.scss index 7e3e6bb..bd2ec3f 100644 --- a/assets/app.scss +++ b/assets/app.scss @@ -3,9 +3,3 @@ body { flex: 1; height: 100vh; } - -#root { - display: flex; - flex: 1; -} - diff --git a/package-lock.json b/package-lock.json index 1238b27..d05503d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "@emotion/react": "^11.11.3", "@emotion/styled": "^11.11.0", + "@mui/icons-material": "^5.15.2", "@mui/material": "^5.15.2", "react": "^18.2.0", "react-dom": "^18.2.0" @@ -1189,6 +1190,31 @@ "url": "https://opencollective.com/mui-org" } }, + "node_modules/@mui/icons-material": { + "version": "5.15.2", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.15.2.tgz", + "integrity": "sha512-Vs0Z6cd6ieTavMjqPvIJJfwsKaCLdRSErk5LjKdZlBqk7r2SR6roDyhVTQuZOeCzjEFj0qZ4iVPp2DJZRwuYbw==", + "dependencies": { + "@babel/runtime": "^7.23.6" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@mui/material": "^5.0.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@mui/material": { "version": "5.15.2", "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.2.tgz", diff --git a/package.json b/package.json index c26683e..9a1fd8a 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "dependencies": { "@emotion/react": "^11.11.3", "@emotion/styled": "^11.11.0", + "@mui/icons-material": "^5.15.2", "@mui/material": "^5.15.2", "react": "^18.2.0", "react-dom": "^18.2.0" diff --git a/src/components/UI/Button/RestaurantButton.tsx b/src/components/UI/Button/RestaurantButton.tsx new file mode 100644 index 0000000..4fa4e31 --- /dev/null +++ b/src/components/UI/Button/RestaurantButton.tsx @@ -0,0 +1,247 @@ +import { + Box, + Button, + ClickAwayListener, + Grow, + IconButton, MenuItem, + MenuList, + Paper, + Popper, + styled, + Typography +} from '@mui/material'; +import MoreVertIcon from '@mui/icons-material/MoreVert'; +import React from 'react'; + +interface Props { + id: number + name: string + website: string + image: string + pickedRestaurantIds: number[] + setPickedRestaurantIds: (id: number[]) => void +} + +export function RestaurantButton({ + id, + name, + website, + image, + pickedRestaurantIds, + setPickedRestaurantIds, +}: Props) { + const selected = pickedRestaurantIds.includes(id); + const selectedStyle = selected ? + { + width: '300px', + margin: '20px', + border: '4px solid currentColor' + } : { + width: '300px', + margin: '20px', + }; + const [open, setOpen] = React.useState(false); + const anchorRef = React.useRef(null); + + function addRestaurantToPool (id: number) { + setPickedRestaurantIds([...pickedRestaurantIds, id]); + } + + function removeRestaurantFromPool (id: number) { + setPickedRestaurantIds(pickedRestaurantIds.filter(restaurantId => id !== restaurantId)); + } + + function toggleRestaurant (value: boolean) { + if (value) { + addRestaurantToPool(id); + } else { + removeRestaurantFromPool(id); + } + } + + function handleClick () { + toggleRestaurant(!selected); + } + + const handleToggle = () => { + setOpen((prevOpen) => !prevOpen); + }; + + const handleClose = (event: Event) => { + if ( + anchorRef.current && + anchorRef.current.contains(event.target as HTMLElement) + ) { + return; + } + + setOpen(false); + }; + + const handleMenuItemClick = ( + website: string, + ) => { + window.open(website, '_blank'); + setOpen(false); + }; + + return + + + + + `calc(${theme.spacing(1)} + 6px)`, + }} + > + {name} + + + + + + + + + {({ TransitionProps }) => ( + + + + + handleMenuItemClick(website)} + > + Visit website + + + + + + )} + + +} + +const StyledMenuList = styled(MenuList)(({ theme }) => ({ + color: theme.palette.text.primary, + backgroundColor: theme.palette.primary.main, + marginTop: '-20px', +})); + +const StyledMenuItem = styled(MenuItem)(({ theme }) => ({ + color: theme.palette.secondary.contrastText, + '&:hover': { + color: theme.palette.common.white, + }, +})); + +const StyledIconButton = styled(IconButton)(({ theme }) => ({ + color: theme.palette.common.white, + backgroundColor: theme.palette.primary.main, + width: '40px', + height: '40px', + position: 'absolute', + zIndex: 2, +})); + +const StyledBox = styled(Box)({ + display: 'flex', + flexDirection: 'column', +}); + +const StyledButton = styled(Button)(({ theme }) => ({ + position: 'relative', + height: 200, + [theme.breakpoints.down('sm')]: { + width: '100% !important', // Overrides inline-style + height: 100, + }, + '&:hover, &.Mui-focusVisible': { + zIndex: 1, + '& .MuiImageBackdrop-root': { + opacity: 0.15, + }, + '& .MuiImageMarked-root': { + opacity: 0, + }, + '& .MuiTypography-root': { + border: '4px solid currentColor', + }, + }, +})); + +const Image = styled('span')(({ theme }) => ({ + position: 'absolute', + left: 0, + right: 0, + top: 0, + bottom: 0, + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + color: theme.palette.common.white, +})); + +const ImageBackdrop = styled('span')(({ theme }) => ({ + position: 'absolute', + left: 0, + right: 0, + top: 0, + bottom: 0, + backgroundColor: theme.palette.common.black, + opacity: 0.4, + transition: theme.transitions.create('opacity'), +})); + +const ImageMarked = styled('span')(({ theme }) => ({ + height: 3, + width: 18, + backgroundColor: theme.palette.common.white, + position: 'absolute', + bottom: -2, + left: 'calc(50% - 9px)', + transition: theme.transitions.create('opacity'), +})); + +const ImageSrc = styled('span')({ + position: 'absolute', + left: 0, + right: 0, + top: 0, + bottom: 0, + backgroundSize: 'cover', + backgroundPosition: 'center 40%', +}); diff --git a/src/components/UI/Button/ValidateButton.tsx b/src/components/UI/Button/ValidateButton.tsx new file mode 100644 index 0000000..6dc2eb1 --- /dev/null +++ b/src/components/UI/Button/ValidateButton.tsx @@ -0,0 +1,18 @@ +import { Fab, styled } from '@mui/material' + +const FabStyled = styled(Fab)(({ theme }) => ({ + position: 'fixed', + right: 0, + backgroundColor: theme.palette.primary.main, + '&:hover': { + backgroundColor: theme.palette.primary.light, + }, +})); + +export default function ValidateButton() { + return ( + + Valider + + ) +} diff --git a/src/components/UI/ToggleSwitch.tsx b/src/components/UI/ToggleSwitch.tsx index 9904b50..de0d500 100644 --- a/src/components/UI/ToggleSwitch.tsx +++ b/src/components/UI/ToggleSwitch.tsx @@ -18,10 +18,14 @@ export default function ToggleSwitch({ } return ( - + + } label={label} /> @@ -31,32 +35,8 @@ export default function ToggleSwitch({ const LabelStyled = styled(FormControlLabel)(({ theme }) => ({ - '.MuiSwitch-root': { - height: '55px', - borderWidth: '2px', - borderColor: theme.palette.mode === 'dark' ? '#fff' : theme.palette.primary.main, - opacity: '1', - '&:before, &:after': { - content: '""', - color: theme.palette.mode === 'dark' ? '#fff' : theme.palette.primary.main, - textTransform: 'uppercase', - fontSize: '.9rem', - fontWeight: '600', - position: 'absolute', - top: 18, - }, - }, - '&:has(.on) .MuiSwitch-track:before': { - content: '"Off"', - left: 20, - }, - '&:has(.off) .MuiSwitch-track:after': { - content: '"On"', - right: 20, - }, - '.MuiButtonBase-root.MuiSwitch-switchBase.Mui-checked + .MuiSwitch-track': { - opacity: '1', - height: '19px', - width: '19px', + color: theme.palette.secondary.contrastText, + '& .MuiSwitch-track': { + backgroundColor: theme.palette.secondary.contrastText, }, })); diff --git a/src/data/restaurants.ts b/src/data/restaurants.ts index 89c5624..d2bde54 100644 --- a/src/data/restaurants.ts +++ b/src/data/restaurants.ts @@ -3,21 +3,18 @@ const data = { { "id": 1, "name": "Restaurant 1", - "description": "Restaurant 1 description", "website": "https://mui.com/material-ui/react-card/", "image": "https://mui.com/static/images/cards/contemplative-reptile.jpg" }, { "id": 2, "name": "Restaurant 2", - "description": "Restaurant 2 description", "website": "https://mui.com/material-ui/react-card/", "image": "https://mui.com/static/images/cards/contemplative-reptile.jpg" }, { "id": 3, "name": "Restaurant 3", - "description": "Restaurant 3 description", "website": "https://mui.com/material-ui/react-card/", "image": "https://mui.com/static/images/cards/contemplative-reptile.jpg" } diff --git a/src/pages/RestaurantsOptions.tsx b/src/pages/RestaurantsOptions.tsx index 56dfff2..1826890 100644 --- a/src/pages/RestaurantsOptions.tsx +++ b/src/pages/RestaurantsOptions.tsx @@ -1,42 +1,51 @@ import { Box, styled } from '@mui/material'; -import { RestaurantCard } from '@app/components/UI/RestaurantCard.tsx'; -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import data from '@app/data/restaurants.ts'; +import { RestaurantButton } from '@app/components/UI/Button/RestaurantButton.tsx'; +import ToggleSwitch from '@app/components/UI/ToggleSwitch.tsx'; +import ValidateButton from '@app/components/UI/Button/ValidateButton.tsx'; export interface Restaurant { id: number name: string - description: string website: string image: string } export default function RestaurantsOptions() { const [pickedRestaurantIds, setPickedRestaurantIds] = useState([]); + const [allSelected, setAllSelected] = useState(false); const dataRestaurants = data.restaurants; - console.log(pickedRestaurantIds); - - return - {dataRestaurants && dataRestaurants.map((restaurant: Restaurant) => { - return - })} - - + useEffect(() => { + if (allSelected) { + setPickedRestaurantIds(dataRestaurants.map(restaurant => restaurant.id)); + } else { + setPickedRestaurantIds([]); + } + },[allSelected]); + + return <> + + + + {dataRestaurants && dataRestaurants.map((restaurant: Restaurant) => { + return + })} + + } const StyledContainer = styled(Box)(({ theme }) => theme.unstable_sx({ - - + display: 'flex', }));