Skip to content

Commit

Permalink
Replace restaurants with food options and update components styles
Browse files Browse the repository at this point in the history
  • Loading branch information
ameliedefrance authored and LedruRomane committed May 16, 2024
1 parent cae43f5 commit 82bb87d
Show file tree
Hide file tree
Showing 12 changed files with 488 additions and 0 deletions.
17 changes: 17 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import '@assets/app.scss'
import AppLayout from '@app/layouts/app-layout.tsx';
import { ThemeProvider } from '@mui/material/styles';
import { CssBaseline } from '@mui/material';
import { customTheme } from '@app/theme.ts';
import OptionsList from '@app/pages/options-list.tsx';

export default function App() {
return (
<ThemeProvider theme={customTheme}>
<CssBaseline />
<AppLayout>
<OptionsList />
</AppLayout>
</ThemeProvider>
)
}
27 changes: 27 additions & 0 deletions src/components/UI/Button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { PropsWithChildren } from 'react'
import { styled } from '@mui/material'

export default function Button({ children }: PropsWithChildren) {
return (
<Wrapper>
{children}
</Wrapper>
)
}

const Wrapper = styled('button')(({ theme }) => ({
height: '60px',
padding: `0 ${theme.spacing(2.5)}`,
fontSize: '18px',
color: theme.palette.text.primary,
fontWeight: 'bold',
background: theme.palette.primary.main,
border: 'none',
borderRadius: theme.shape.borderRadius,
cursor: 'pointer',
transition: 'all .2s',

'&:hover, &:focus': {
background: theme.palette.primary.dark,
},
}));
65 changes: 65 additions & 0 deletions src/components/UI/RestaurantCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { Button, Card, CardActions, CardContent, CardMedia, Typography } from '@mui/material'
import ToggleSwitch from '@app/components/UI/toggle-switch.tsx'

// TODO: Unused component, keep for future version ?
interface Props {
id: number
name: string
description: string
website: string
image: string
pickedRestaurantIds: number[]
setPickedRestaurantIds: (id: number[]) => void
}

export function RestaurantCard({
id,
name,
description,
website,
image,
pickedRestaurantIds,
setPickedRestaurantIds,
}: Props) {

function addRestaurantToPool (id: number) {
setPickedRestaurantIds([...pickedRestaurantIds, id]);
}

function removeRestaurantFromPool (id: number) {
setPickedRestaurantIds(pickedRestaurantIds.filter(restaurantId => id !== restaurantId));
}

const selected = pickedRestaurantIds.includes(id);

function toggleRestaurant (value: boolean) {
if (value) {
addRestaurantToPool(id);
} else {
removeRestaurantFromPool(id);
}
}

return <>
<Card sx={{ maxWidth: 345 }}>
<CardMedia
sx={{ height: 140 }}
component="img"
image={image}
alt={name}
/>
<CardContent>
<Typography gutterBottom variant="h5" component="div">
{name}
</Typography>
<Typography variant="body2" color="text.secondary">
{description}
</Typography>
</CardContent>
<CardActions>
<ToggleSwitch label="Ajouter au pool de selection" checked={selected} setChecked={toggleRestaurant} />
<Button size="small" href={website} target="_blank">Website</Button>
</CardActions>
</Card>
</>
}
63 changes: 63 additions & 0 deletions src/components/UI/food-option.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import React from 'react'
import { styled } from '@mui/material'

type Props = {
id: string
label: string
icon: string
pickedOptions: string[]
setPickedOptions: (options: string[]) => void
}

export default function FoodOption({ id, label, icon, pickedOptions, setPickedOptions }: Props) {
const checked = pickedOptions.includes(id);

function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
if (e.target.checked) {
setPickedOptions([...pickedOptions, id]);
} else {
setPickedOptions(pickedOptions.filter(option => id !== option));
}
}

return <>
<Input type="checkbox" id={label} onChange={handleChange} className={checked ? 'checked' : ''} />
<Label htmlFor={label} >
<Icon>{icon}</Icon>
{label}
</Label>
</>;
}

const Label = styled('label')(({ theme }) => ({
padding: theme.spacing(1.5),
height: '75px',
display: 'flex',
alignItems: 'center',
gap: '1rem',
fontSize: '1.1rem',
color: theme.palette.text.primary,
background: theme.palette.secondary.main,
border: 'solid 2px',
borderColor: theme.palette.secondary.light,
borderRadius: theme.shape.borderRadius,
cursor: 'pointer',
transition: 'all .2s',

'&:hover, &:focus': {
borderColor: theme.palette.primary.main,
},

'input:checked, .checked + &': {
background: theme.palette.primary.dark,
borderColor: theme.palette.primary.main,
},
}));

const Icon = styled('span')(() => ({
fontSize: '2rem',
}));

const Input = styled('input')(() => ({
display: 'none',
}));
39 changes: 39 additions & 0 deletions src/components/UI/toggle-switch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from 'react'
import { FormGroup, FormControlLabel, Switch, styled } from '@mui/material'

interface Props {
label: string
checked: boolean
setChecked: (value: boolean) => void
}

export default function ToggleSwitch({
label,
checked,
setChecked,
}: Props) {

const handleSwitch = (event: React.ChangeEvent<HTMLInputElement>) => {
setChecked(event.target.checked);
}

return (
<FormGroup>
<LabelStyled
control={
<Switch checked={checked} onChange={handleSwitch} />
}
label={label}
/>
</FormGroup>
);
}


const LabelStyled = styled(FormControlLabel)(({ theme }) => ({
color: theme.palette.text.primary,

'& .MuiSwitch-track': {
backgroundColor: theme.palette.text.primary,
},
}));
15 changes: 15 additions & 0 deletions src/components/footer/footer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { styled } from '@mui/material'

export default function Footer() {
return <Wrapper role="contentinfo">
Made with 🌮 at elao - © 2024
</Wrapper>;
}

const Wrapper = styled('footer')(({ theme }) => ({
marginTop: theme.spacing(2),
padding: `${theme.spacing(1)} 0`,
color: theme.palette.text.primary,
textAlign: 'center',
borderTop: 'solid 1px rgba(146, 148, 175, .2)',
}));
45 changes: 45 additions & 0 deletions src/components/header/header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { styled } from '@mui/material'

export default function Header() {
return <Wrapper>
<Title>
<span>Ça mâche</span>
<span>quoi ?</span>
</Title>
</Wrapper>;
}

const Wrapper = styled('header')(() => ({
padding: '100px 0 80px',
width: '60%',
}));

const Title = styled('h1')(({ theme }) => ({
margin: `0 0 0 ${theme.spacing(1)}`,
display: 'flex',
flexDirection: 'column',
alignItems: 'flex-start',
fontSize: '3.25rem',
lineHeight: '1.1',
color: theme.palette.text.primary,

'span': {
position: 'relative',
zIndex: '1',

'&::before': {
height: '2rem',
width: '100%',
position: 'absolute',
bottom: '.2rem',
left: '.5rem',
content: '""',
zIndex: '-1',
background: theme.palette.background.paper,
},

'&:last-of-type': {
marginLeft: '13rem',
},
},
}));
36 changes: 36 additions & 0 deletions src/data/food-options.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
const data = {
"foodOptions": [
{
"id": "1",
"label": "Sushi",
"icon": "🍣",
},
{
"id": "2",
"label": "Salade",
"icon": "🥬",
},
{
"id": "3",
"label": "Pizza",
"icon": "🍕",
},
{
"id": "4",
"label": "Burger",
"icon": "🍔",
},
{
"id": "5",
"label": "Kebab",
"icon": "🥙",
},
{
"id": "6",
"label": "Formule boulangerie",
"icon": "🥖",
},
],
};

export default data;
30 changes: 30 additions & 0 deletions src/layouts/app-layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { PropsWithChildren } from 'react'
import Header from '@app/components/header/header.tsx'
import Footer from '@app/components/footer/footer.tsx'
import { styled } from '@mui/material'
import background from '@images/background.svg'

export default function AppLayout({ children }: PropsWithChildren) {
return <Container>
<Header />
<Main>
{children}
</Main>
<Footer />
</Container>;
}

const Container = styled('div')(({ theme }) => ({
padding: `0 ${theme.spacing(4.5)}`,
display: 'flex',
flexDirection: 'column',
minHeight: '100vh',
height: '100vh',
minWidth: '100vw',
background: `${theme.palette.background.default} url(${background}) no-repeat right bottom`,
overflow: 'auto',
}));

const Main = styled('main')(() => ({
flex: '1',
}));
10 changes: 10 additions & 0 deletions src/main.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from '@app/App.tsx'
import '@assets/app.scss'

ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<App />
</React.StrictMode>,
)
Loading

0 comments on commit 82bb87d

Please sign in to comment.