Initial commit

This commit is contained in:
Kayashov.SM
2025-03-12 17:54:16 +04:00
commit b6d8a3cebd
254 changed files with 29963 additions and 0 deletions

View File

@@ -0,0 +1,68 @@
import * as React from 'react';
import OutlinedInput from '@mui/material/OutlinedInput';
import InputLabel from '@mui/material/InputLabel';
import MenuItem from '@mui/material/MenuItem';
import FormControl from '@mui/material/FormControl';
import ListItemText from '@mui/material/ListItemText';
import Select from '@mui/material/Select';
import Checkbox from '@mui/material/Checkbox';
const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
const MenuProps = {
PaperProps: {
style: {
maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
width: 250,
},
},
};
export default function CheckMarks({rows, name, filterValue, handleChange, filterName, width, nonMulti, nullValue, identity}) {
const realValue = !nonMulti ? filterValue.filter((v) => v.length > 0) : filterValue;
return (
<div>
<FormControl sx={{m: 1, width: !width ? 300 : width}}>
<InputLabel>{name}</InputLabel>
<Select
multiple={!nonMulti}
value={realValue}
onChange={(e) => handleChange(filterName, e.target.value)}
input={<OutlinedInput label={name}/>}
renderValue={(selected) => !nonMulti ? selected.join(", ") : selected}
MenuProps={MenuProps}
defaultChecked={nonMulti && rows[0]}
variant="filled">
{(nonMulti && nullValue) && (
<MenuItem value={""}>
<em>Не выбрано</em>
</MenuItem>
)}
{rows.map((value) => {
if(identity) {
return (
<MenuItem key={"menuItemIn" + value} value={value}>
{!nonMulti && (
<Checkbox
checked={realValue.includes(value)}/>
)}
<ListItemText primary={value}/>
</MenuItem>
)
} else {
return (
<MenuItem key={value.id} value={value.name}>
{!nonMulti && (
<Checkbox
checked={realValue.includes(value.name)}/>
)}
<ListItemText primary={value.name}/>
</MenuItem>
)
}
})}
</Select>
</FormControl>
</div>
);
}

View File

@@ -0,0 +1,113 @@
import {CardActions, CardContent, CardMedia, Rating} from "@mui/material";
import {useAlert} from "../../hooks/useAlert";
import Typography from "@mui/material/Typography";
import List from "@mui/material/List";
import ListItem from "@mui/material/ListItem";
import ListItemText from "@mui/material/ListItemText";
import Button from "@mui/material/Button";
import Grid from "@mui/material/Grid";
import {requests} from "../../requests";
import {CocktailItemStyled} from "./CocktailItemStyled";
import IconButton from "@mui/material/IconButton";
import FavoriteBorderIcon from '@mui/icons-material/FavoriteTwoTone';
import FavoriteIcon from '@mui/icons-material/Favorite';
import {api} from "../../lib/clients/api";
import Box from "@mui/material/Box";
import {useUser} from "../../hooks/useUser";
function renderFavouriteBadge(handleFavourite, row) {
const childIcon = row.rating.favourite ? <FavoriteIcon color='error'/> : <FavoriteBorderIcon color={'warning'}/>;
return (
<IconButton sx={{position: 'absolute', top: "15px", right: "15px"}} onClick={() => handleFavourite(row)}>
{childIcon}
</IconButton>
)
}
function renderRating(handleChangeRating, row) {
return (
<Rating
sx={{position: 'absolute', top: '310px', right: '85px'}}
name="simple-controlled"
size="large"
value={row.rating.rating}
onChange={(event, newValue) => handleChangeRating(row, newValue)}
/>
)
}
export function Cocktail({row, handleFavourite, handleChangeRating, handleSelect, editMenuBlock}) {
const {createAlert, createError} = useAlert();
const {session, user} = useUser();
function pay(cocktailId) {
api().post(`${requests.bar.pay}cocktail=${cocktailId}`)
.then(() => createAlert("Ожидайте свой заказ", "success"))
.catch(() => createError("Ошибка во время создания заказа"))
}
return (
<Grid item sx={{pr: 2}}>
<CocktailItemStyled>
<Box sx={{
p: '4px 4px',
m: 1,
width: '320px',
position: 'relative',
}}>
<CardMedia
sx={{
loading: "eager",
borderRadius: 2
}}
onClick={() => handleSelect(row)}
component="img"
alt={row.name}
height="300"
image={`${row.image}/preview`}
/>
{renderFavouriteBadge(handleFavourite, row)}
{renderRating(handleChangeRating, row)}
<CardContent sx={{pb: '4px', pl: 2}}>
<Typography variant="h5" minHeight={'50px'} mt={2}>{row.name} </Typography>
<List sx={{py: '0px'}}>
{row.hasError && (
<ListItem sx={{p: '2px 12px 0px 0px', m: '0px'}}>
<ListItemText color={'red'}>Имеет ошибку в рецепте или ингредиентах</ListItemText>
</ListItem>
)}
<ListItem sx={{p: '2px 12px 0px 0px', m: '0px'}}>
<ListItemText>{"Категория: " + row.category}</ListItemText>
</ListItem>
<ListItem sx={{p: '2px 12px 0px 0px', m: '0px'}}>
<ListItemText>{"Алкоголь: " + row.alcoholic}</ListItemText>
</ListItem>
{row.volume !== null && (
<ListItem sx={{p: '2px 12px 0px 0px', m: '0px'}}>
<ListItemText>{"Крепость: ≈" + row.volume}</ListItemText>
</ListItem>
)}
<ListItem sx={{p: '2px 12px 0px 0px', m: '0px'}}>
<ListItemText>{"Подача: " + row.glass}</ListItemText>
</ListItem>
<ListItem sx={{p: '2px 12px 0px 0px', m: '0px'}}>
<ListItemText>{"Состав: " + row.components}</ListItemText>
</ListItem>
{(row.tags && row.tags.length > 0) && (
<ListItem sx={{p: '2px 12px 0px 0px', m: '0px'}}>
<ListItemText>{"Теги: " + row.tags.replaceAll(',', ', ')}</ListItemText>
</ListItem>)}
</List>
</CardContent>
<CardActions>
{(row.isAllowed && session.isActive && user.invited) &&
<Button variant="contained" onClick={() => pay(row.id)}>Заказать</Button>
}
{editMenuBlock(row)}
</CardActions>
</Box>
</CocktailItemStyled>
</Grid>
)
}

View File

@@ -0,0 +1,180 @@
import DialogTitle from "@mui/material/DialogTitle";
import DialogContent from "@mui/material/DialogContent";
import Stack from "@mui/material/Stack";
import Typography from "@mui/material/Typography";
import DialogActions from "@mui/material/DialogActions";
import Button from "@mui/material/Button";
import Dialog from "@mui/material/Dialog";
import * as React from "react";
import {useEffect, useState} from "react";
import {CardMedia} from "@mui/material";
import Paper from "@mui/material/Paper";
import Box from "@mui/material/Box";
import StarBorderIcon from '@mui/icons-material/StarBorder';
import IconButton from "@mui/material/IconButton";
import ShoppingCartIcon from '@mui/icons-material/ShoppingCart';
import DeleteIcon from '@mui/icons-material/Delete';
import {IngredientInfoModal} from "../Ingredients/IngredientInfoModal";
import {api} from "../../lib/clients/api";
import {requests} from "../../requests";
import {useAlert} from "../../hooks/useAlert";
import {paths} from "../../path";
import {Loading} from "../core/Loading";
import {useUser} from "../../hooks/useUser";
export function CocktailInfoModal({open, row, closeHandler}) {
const {user} = useUser();
const {getError, createError, createSuccess} = useAlert();
const [cocktail, setCocktail] = useState(null)
const [loading, setLoading] = useState(false);
const [selectedIngredient, setSelectedIngredient] = useState(null);
const [openIngredientModal, setOpenIngredientModal] = useState(false)
const closeIngredientHandler = () => {
setOpenIngredientModal(false);
setSelectedIngredient(null);
}
const openIngredientModalHandler = (id) => {
api().get(`${requests.bar.ingredient}?id=${id}`)
.then((r) => {
setSelectedIngredient(r.data)
setOpenIngredientModal(true);
}).catch(() => createError("Ошибка получения информации об ингредиенте"))
}
const selectIngredientHandler = (ingredient) => {
const url = `${requests.bar.ingredient}?id=${ingredient.id}`;
const request = ingredient.isHave ? api().delete(url) : api().put(url);
const value = !ingredient.isHave;
request.then(() => {
const newReceipts = cocktail.receipt.map((r) => {
if (r.ingredient.id !== ingredient.id) {
return r;
}
return {
...r,
ingredient: {
...ingredient,
isHave: value
}
}
})
setCocktail({
...cocktail,
receipt: newReceipts
})
createSuccess("Сохранено")
}).catch(() => createError("Ошибка сохранения"))
}
useEffect(() => {
setLoading(true)
if (!row) {
setLoading(false)
return;
}
api().get(requests.cocktails.modal + row)
.then((r) => {
setCocktail(r.data)
setLoading(false)
})
.catch(() => {
getError();
setLoading(false)
closeHandler();
})
}, [row]);
if (!row || !cocktail) {
return null;
}
let alko = 0;
let volume = 0;
return (
<Dialog fullWidth={true}
open={open} onClose={closeHandler}
sx={{
'& .MuiDialog-paper': {
margin: '8px',
},
'& .MuiPaper-root': {
width: 'calc(100% - 16px)',
}
}}>
<IngredientInfoModal ingredient={selectedIngredient} open={openIngredientModal}
closeHandler={closeIngredientHandler}/>
<Loading loading={loading}/>
<DialogTitle>
<Stack direction='row' justifyContent={'space-between'}>
<Box>{cocktail.name}</Box>
{cocktail.rating.rating > 0 &&
(
<Stack ml={3} direction='row'>
{`${cocktail.rating.rating}/5`}
<StarBorderIcon sx={{pb: "2px"}}/>
</Stack>
)
}
</Stack>
</DialogTitle>
<DialogContent>
<CardMedia
image={`${cocktail.image}/preview`}
sx={{
loading: "eager",
borderRadius: 2
}}
component="img"
alt={cocktail.name}
height="300"
/>
<Box mt={1}>
<Typography>Ингредиенты:</Typography>
<Paper sx={{p: 1}} elevation={3}>
<Stack>
{cocktail.receipt.map((r) => {
const hasError = r.count === null || r.unit === null;
const measure = hasError ? r.measure : (r.count + " " + r.unit.name)
if(alko !== null && volume !== null) {
console.log(r)
}
return (
<Stack key={r.ingredient.id} direction='row' justifyContent={'space-between'}
mt={1}>
<Stack direction='row'>
{user.role !== "USER" && (
<IconButton size="small" sx={{pb: "2px"}}
onClick={() => selectIngredientHandler(r.ingredient)}>
{r.ingredient.isHave
? (<DeleteIcon fontSize="small"/>)
: (<ShoppingCartIcon fontSize="small"/>)
}
</IconButton>
)}
<Typography
onClick={() => openIngredientModalHandler(r.ingredient.id)}>{r.ingredient.name}</Typography>
</Stack>
<Typography color={hasError && 'red'}>{measure}</Typography>
</Stack>
)
})}
</Stack>
</Paper>
</Box>
<Box>
<Typography mt={2}>Инструкция:</Typography>
<Paper sx={{p: 1}} elevation={3}>
<Box>
{cocktail.instructions}
</Box>
</Paper>
</Box>
</DialogContent>
<DialogActions>
{user.role.includes("ADMIN") && (
<Button href={`${paths.bar.cocktailEdit}?id=${cocktail.id}`}>Редактировать</Button>
)}
<Button onClick={closeHandler}>Закрыть</Button>
</DialogActions>
</Dialog>
)
}

View File

@@ -0,0 +1,12 @@
import {styled} from "@mui/material/styles";
import {Card} from "@mui/material";
export const CocktailItemStyled = styled(Card)(({theme}) => ({
backgroundColor: '#fff',
...theme.typography.body2,
padding: theme.spacing(1),
color: theme.palette.text.secondary,
...theme.applyStyles('dark', {
backgroundColor: '#1A2027',
})
}));

View File

@@ -0,0 +1,44 @@
import {Card, FormControlLabel} from "@mui/material";
import Stack from "@mui/material/Stack";
import Box from "@mui/material/Box";
import IconButton from "@mui/material/IconButton";
import InfoRoundedIcon from "@mui/icons-material/InfoRounded";
import {paths} from "../../path";
import EditIcon from "@mui/icons-material/Edit";
import React from "react";
import Switch from "@mui/material/Switch";
export function CocktailListCard({row, changeHandler, infoHandler}) {
return (
<Card sx={{mb: 1, height: '130px', display: 'relative', pt: 1, borderRadius: '15px'}}>
<Stack direction='row' justifyContent='start' alignItems='start'>
<Box sx={{width: '100px', height: '100px', ml: 1}}>
<img src={row.image} loading='eager' height={'100px'} width={'100px'} alt={row.id}
style={{borderRadius: '20%'}}/>
</Box>
<Stack sx={{width: 'calc(95% - 100px)', pr: 2, ml: 1}}>
<Box>{row.name}</Box>
<FormControlLabel sx={{mt: 5, pr: 2}}
onClick={() => changeHandler(row, !row.inMenu)}
value="bottom"
control={
<Switch color="primary" checked={row.inMenu}/>
}
label="В меню"
labelPlacement="start"
/>
</Stack>
<Stack direction='row'>
<Stack sx={{width: '5%', mt: 2}} spacing={1} justifyContent='flex-start'>
<IconButton size='small' onClick={() => infoHandler(row)}>
<InfoRoundedIcon/>
</IconButton>
<IconButton size='small' href={`${paths.bar.cocktailEdit}?id=${row.id}`}>
<EditIcon/>
</IconButton>
</Stack>
</Stack>
</Stack>
</Card>
)
}

View File

@@ -0,0 +1,76 @@
import {useMemo, useState} from "react";
import {getComparator} from "../core/getComparator";
import {Accordion, AccordionDetails, AccordionSummary} from "@mui/material";
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
import Typography from "@mui/material/Typography";
import Box from "@mui/material/Box";
import {CocktailListCard} from "./CocktailListCard";
import {groupByForLoop} from "../core/groupByForLoop";
export function CocktailsList({rows, grouping, changeHandler, infoHandler}) {
const [size, setSize] = useState(20);
window.addEventListener('scroll', () => {
if (window.innerHeight + window.scrollY >= (document.documentElement.scrollHeight - 100)) {
if (!grouping) {
setSize(size + 10)
}
}
});
const visibleRows = useMemo(() => {
let res = [];
if (rows.length === 0) {
return null;
}
if (!grouping) {
return rows
.sort(getComparator("asc", "name"))
.slice(0, size)
.map((row) => {
return (
<CocktailListCard row={row} key={row.id}
changeHandler={changeHandler} infoHandler={infoHandler}/>
)
})
}
const group = groupByForLoop(rows, "category")
if (!group || group.size === 0) {
return null;
}
Array.from(group.keys())
.sort(getComparator())
.map((key) => {
const list = group.get(key);
res.push(
<Accordion key={key} sx={{borderRadius: '5px', mb: 1}}>
<AccordionSummary
expandIcon={<ExpandMoreIcon/>}
aria-controls="panel1-content"
id="panel1-header"
>
<Typography component="span">{key}</Typography>
</AccordionSummary>
<AccordionDetails sx={{p: 1}}>
{list.sort(getComparator("asc", "name"))
.map((row) => {
return (
<CocktailListCard row={row} key={row.id}
changeHandler={changeHandler} infoHandler={infoHandler}/>
)
})}
</AccordionDetails>
</Accordion>
)
})
return res;
// eslint-disable-next-line
}, [size, rows])
return (
<Box mt={2}>
{visibleRows}
</Box>
)
}

View File

@@ -0,0 +1,167 @@
import Box from "@mui/material/Box";
import Stack from "@mui/material/Stack";
import Typography from "@mui/material/Typography";
import IconButton from "@mui/material/IconButton";
import AddIcon from "@mui/icons-material/Add";
import * as React from "react";
import {useEffect, useState} from "react";
import {useAlert} from "../../hooks/useAlert";
import {api} from "../../lib/clients/api";
import {requests} from "../../requests";
import {getComparator} from "../core/getComparator";
import {Card} from "@mui/material";
import {SelectEdit} from "./SelectEdit";
import TextField from "@mui/material/TextField";
import DeleteForeverIcon from '@mui/icons-material/DeleteForever';
export function EditCocktailReceipt({receipt, handler}) {
const {createError} = useAlert()
const [ingredients, setIngredients] = useState([]);
const [units, setUnits] = useState([])
useEffect(() => {
api().get(requests.bar.ingredientList)
.then((r) => setIngredients(r.data.sort(getComparator("asc", "name"))))
.catch(() => createError("Ошибка получения списка ингредиентов"))
api().get(requests.bar.unit)
.then((r) => setUnits(r.data.sort(getComparator("asc", "name"))))
.catch(() => createError("Ошибка получения единиц измерения"))
}, []);
const selectHandler = (name, value) => {
const ing = ingredients.find((i) => i.name === value)
const newState = receipt.map((r, i) => {
if (i !== name) {
return r;
}
return {
id: r.id,
ingredient: {
id: ing.id,
isHave: ing.have,
name: ing.name
},
measure: r.measure
}
})
handler("receipt", newState);
checkAllowed(newState);
}
const unitHandler = (name, value) => {
const ing = units.find((i) => i.name === value)
const newState = receipt.map((r, i) => {
if (i !== name) {
return r;
}
return {
id: r.id,
ingredient: r.ingredient,
unit: ing,
count: r.count,
measure: r.measure
}
})
handler("receipt", newState);
checkAllowed(newState);
}
const removeHandler = (index) => {
const arr = receipt.filter((r, i) => i !== index)
handler("receipt", arr)
checkAllowed(arr)
}
const addHandler = () => {
const oldState = receipt;
oldState.push({
id: null,
ingredient: {
id: null,
isHave: false,
name: ""
},
measure: ""
});
handler("receipt", oldState);
checkAllowed(oldState);
}
const checkAllowed = (state) => {
handler("isAllowed", !state.map((r) => r.ingredient.isHave).includes(false))
}
const measureHandler = (index, value) => {
const newState = receipt.map((r, i) => {
if (index !== i) {
return r
}
return {
...r,
measure: value
}
})
handler("receipt", newState)
}
const countHandler = (index, value) => {
const newState = receipt.map((r, i) => {
if (index !== i) {
return r
}
return {
...r,
count: value
}
})
handler("receipt", newState)
}
return (
<Box mb={2}>
{/*Заголовок*/}
<Stack direction='row' justifyContent={'space-between'} sx={{mr: 1}}>
<Typography ml={1} mt={1}>Рецепт</Typography>
<IconButton onClick={() => addHandler()}>
<AddIcon/>
</IconButton>
</Stack>
{/*Рецепт*/}
<Stack sx={{mr: 1}}>
{receipt.map((r, i) => {
return (
<Card key={i} sx={{ml: 0, mb: 1}}>
<Stack>
<Stack direction='row'>
<SelectEdit width={'calc(65% - 28px)'} array={ingredients} value={r.ingredient.name}
handler={selectHandler} label={"Ингредиент"}
margin={1} attributeName={i}
/>
<TextField sx={{width: 'calc(35% - 28px)', mt: 1}}
label={"Кол-во"}
variant="outlined"
disabled
value={r.measure}
onChange={(e) => measureHandler(i, e.target.value)}
/>
<IconButton sx={{mt: 2}}
onClick={() => removeHandler(i)}
>
<DeleteForeverIcon/>
</IconButton>
</Stack>
<Stack direction='row' ml={1} mb={1}>
<TextField sx={{width: 'calc(35% - 28px)', mt: 1}}
label={"Кол-во"}
variant="outlined"
value={r.count}
onChange={(e) => countHandler(i, e.target.value)}
/>
<SelectEdit width={'calc(65% - 28px)'} array={units} value={!r.unit ? null : r.unit.name}
handler={unitHandler} label={"Ед."}
margin={1} attributeName={i}
/>
</Stack>
</Stack>
</Card>
)
})}
</Stack>
</Box>
)
}

View File

@@ -0,0 +1,160 @@
import {Card, FormControl, FormControlLabel, InputAdornment, InputLabel, OutlinedInput} from "@mui/material";
import IconButton from "@mui/material/IconButton";
import SearchIcon from "@mui/icons-material/Search";
import Tooltip from "@mui/material/Tooltip";
import FilterListIcon from "@mui/icons-material/FilterList";
import Box from "@mui/material/Box";
import Grid from "@mui/material/Grid";
import Switch from "@mui/material/Switch";
import CheckMarks from "./CheckMarks";
import Button from "@mui/material/Button";
import * as React from "react";
import {useEffect, useState} from "react";
import {requests} from "../../requests";
import {useAlert} from "../../hooks/useAlert";
import {api} from "../../lib/clients/api";
import {sortList} from "./sortingList";
const inMenuFilter = [
{
id: true,
name: "Есть в меню"
},
{
id: false,
name: "Нет в меню"
}
]
export function FilterBlock({filter, handleFilterChange, handleClearFilter, barmen, all}) {
const {createError} = useAlert();
const [glass, setGlass] = useState([]);
const [category, setCategory] = useState([]);
const [tags, setTags] = useState([])
const alcohol = [
{
name: "Алкогольный",
id: "alcohol1"
},
{
name: "Безалкогольный",
id: "alcohol2"
},
{
name: "Опционально",
id: "alcohol3"
}];
const ingredientCount = [
{
id: "1IngredientCount",
name: 1
},
{
id: "2IngredientCount",
name: 2
},
{
id: "3IngredientCount",
name: 3
},
{
id: "4IngredientCount",
name: 4
},
{
id: "5IngredientCount",
name: 5
}]
useEffect(() => {
api().get(requests.bar.category)
.then((r) => setCategory(r.data))
.catch(() => createError("Ошибка получения категорий"))
api().get(requests.bar.glass)
.then((r) => setGlass(r.data))
.catch(() => createError("Ошибка получения посуды"))
api().get(requests.bar.tags)
.then((r) => setTags(r.data))
.catch(() => createError("Ошибка получения тегов"))
// eslint-disable-next-line
}, []);
return (
<Card>
{/*Строка поиска*/}
<FormControl sx={{m: 1, width: '300px'}}>
<InputLabel htmlFor="outlined-adornment-amount">Поиск</InputLabel>
<OutlinedInput
onChange={(e) => handleFilterChange("search", e.target.value)}
label="With normal TextField"
startAdornment={
<InputAdornment position="start">
<IconButton edge="end">
<SearchIcon/>
</IconButton>
</InputAdornment>
}
/>
</FormControl>
{/*Кнопка открытия фильтров*/}
<Tooltip title="Filter list">
<IconButton onClick={() => handleFilterChange("hidden", !filter.hidden)}>
<FilterListIcon/>
</IconButton>
</Tooltip>
{/*Блок сортировки*/}
<Box hidden={filter.hidden}>
<Grid container>
{/*Фильтр по алкогольности*/}
<CheckMarks rows={sortList} name={"Сортировать по..."} handleChange={handleFilterChange}
filterValue={filter.sorting} filterName={"sorting"} nonMulti/>
</Grid>
</Box>
{/*Блок фильтров*/}
<Box hidden={filter.hidden}>
<Grid container>
{/*Фильтр по меню*/}
{(barmen && all) && (
<CheckMarks rows={inMenuFilter} name={"Есть в меню"} filterName={"inMenu"}
filterValue={filter.inMenu}
handleChange={handleFilterChange}
nonMulti nullValue
/>
)}
{/*Фильтр по избранным*/}
<FormControlLabel
control={
<Switch inputProps={{'aria-label': 'controlled'}}
onChange={() => handleFilterChange("onlyFavourite", !filter.onlyFavourite)}
/>
}
label="Только избранные"
sx={{ml: 1}}
/>
{/*Фильтр по алкогольности*/}
<CheckMarks rows={alcohol} name={"Алкогольность"} handleChange={handleFilterChange}
filterValue={filter.alcohol} filterName={"alcohol"}/>
{/*Фильтр по категории*/}
{category.length > 0 && (
<CheckMarks rows={category} name={"Категории"} filterValue={filter.category}
filterName={"category"} handleChange={handleFilterChange}/>)}
{/*Фильтр по посуде*/}
{glass.length > 0 && (<CheckMarks rows={glass} name={"Подача"} handleChange={handleFilterChange}
filterValue={filter.glass} filterName={"glass"}/>)}
{/*Фильтр по тегам*/}
{tags.length > 0 && (<CheckMarks rows={tags} name={"Теги"} handleChange={handleFilterChange}
filterValue={filter.tags} filterName={"tags"}/>)}
{/*Фильтр по нехватке ингредиентов*/}
{/*todo: доделать эти фильтры в беке*/}
{/*{(barmen && all) && (<CheckMarks rows={ingredientCount} name={"Не хватает ингредиентов"}*/}
{/* handleChange={handleFilterChange}*/}
{/* nonMulti nullValue*/}
{/* filterValue={filter.iCount} filterName={"iCount"}/>)}*/}
<Button onClick={() => handleClearFilter()}>Сбросить</Button>
</Grid>
</Box>
</Card>
)
}

View File

@@ -0,0 +1,17 @@
import Grid from "@mui/material/Grid";
import {Stack} from "@mui/material";
import Typography from "@mui/material/Typography";
import {CocktailItemStyled} from "./CocktailItemStyled";
export function NoResult({load}) {
return (
<Grid item lg={4} md={6} sm={12} xl={3} hidden={!load}>
<CocktailItemStyled>
<Stack align="center" sx={{width: "350px"}}>
<Typography variant="h5" minHeight={'50px'} mt={2}>Нет результатов</Typography>
<Typography>Попробуйте заглянуть позднее</Typography>
</Stack>
</CocktailItemStyled>
</Grid>
)
}

View File

@@ -0,0 +1,25 @@
import {FormControl, InputLabel} from "@mui/material";
import Select from "@mui/material/Select";
import MenuItem from "@mui/material/MenuItem";
import * as React from "react";
export function SelectEdit({label, value, array, handler, attributeName, width, margin}) {
return (
<FormControl sx={{width: width, m: margin}}>
<InputLabel>{label}</InputLabel>
<Select
autoWidth
label={label}
value={!value ? "" : value}
onChange={(e) => handler(attributeName, e.target.value)}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
{array.map((c) => {
return (<MenuItem key={c.id} value={c.name}>{c.name}</MenuItem>)
})}
</Select>
</FormControl>
)
}

View File

@@ -0,0 +1,27 @@
export const sortList = [
{
id: "name|asc",
name: "Название по возрастанию"
},
{
id: "name|desc",
name: "Название по убыванию"
},
// todo: добавить сортировки в беке
// {
// id: "rating.rating|desc",
// name: "Сначала с оценкой"
// },
// {
// id: "rating.rating|asc",
// name: "Сначала без оценки"
// },
// {
// id: "rating.favourite|desc",
// name: "Сначала избранные"
// },
// {
// id: "rating.favourite|asc",
// name: "Сначала не избранные"
// }
]