добавлена работа со списками продуктов, попытка оптимизировать запрос по поиску коктейлей

This commit is contained in:
Kayashov.SM
2025-05-03 01:36:17 +04:00
parent badd71545e
commit 9809a19762
13 changed files with 269 additions and 43 deletions

View File

@@ -12,6 +12,7 @@ import {MenuPage} from "./pages/cocktails/MenuPage";
import {EditIngredientPage} from "./pages/ingredients/EditIngredientPage";
import {EditCocktailPage} from "./pages/cocktails/EditCocktailPage";
import {useEffect, useState} from "react";
import {BarChangePage} from "./pages/BarChangePage";
export function NavigationRoutes() {
const {auth} = useAuth();
@@ -64,6 +65,11 @@ const authPages = [
children: (<MenuPage/>),
exact: true,
},
{
path: paths.bar.list,
isPrivate: true,
children: (<BarChangePage/>),
},
{
path: paths.bar.ingredients,
isPrivate: true,

View File

@@ -0,0 +1,111 @@
import Paper from "@mui/material/Paper";
import React, {useEffect, useState} from "react";
import {api} from "../../lib/clients/api";
import {requests} from "../../requests";
import {useAlert} from "../../hooks/useAlert";
import {Card} from "@mui/material";
import Stack from "@mui/material/Stack";
import Typography from "@mui/material/Typography";
import IconButton from "@mui/material/IconButton";
import Box from "@mui/material/Box";
import DeleteIcon from '@mui/icons-material/Delete';
import ElectricalServicesIcon from '@mui/icons-material/ElectricalServices';
import {getComparator} from "../../components/core/getComparator";
import Toolbar from "@mui/material/Toolbar";
import AddCircleIcon from '@mui/icons-material/AddCircle';
import {BarCreateModal} from "../../components/BarCreateModal";
import PowerIcon from '@mui/icons-material/Power';
export function BarChangePage() {
const [bars, setBars] = useState([])
const [open, setOpen] = useState(false)
const {createError, createSuccess, createWarning} = useAlert();
useEffect(() => {
api().get(requests.bar.list)
.then((r) => {
setBars(r.data.sort(getComparator("name")))
})
.catch(() => {
createError("Ошибка получения списков")
})
}, []);
const changeHandler = (bar) => {
createWarning("Дождитесь окончания операции")
api().post(`${requests.bar.change}/${bar.id}`)
.then(() => createSuccess("Список изменен"))
.catch(() => createError("Ошибка изменения активного списка"))
const newState = bars.map((b) => {
if (b.active) {
return {
...b, active: false
}
}
if (b.id === bar.id) {
return {
...b, active: true
}
}
return b;
})
setBars(newState);
}
const deleteHandler = (bar) => {
if (bar.active) {
createError("Нельзя удалить активный бар!")
return;
}
api().delete(requests.bar.crud + bar.id)
.then(() => createSuccess("Список удален"))
.catch(() => createError("Ошибка удаления. Обновите страницу"))
setBars(bars.filter((b) => b.id !== bar.id));
}
const createHandler = (name) => {
api().post(requests.bar.crud + name)
.then((r) => {
createSuccess("Cписок создан");
let state = bars;
state.push(r.data);
setBars(state)
setOpen(false)
}).catch(() => createError("Ошибка создания списка"))
}
function closeHandler() {
setOpen(false)
}
return (<>
<BarCreateModal open={open} close={closeHandler} create={createHandler}/>
<Paper sx={{p: 1}}>
<Toolbar>
<Typography variant='h6'>Списки ингредиентов (бары)</Typography>
<IconButton edge="end" onClick={() => setOpen(true)}>
<AddCircleIcon/>
</IconButton>
</Toolbar>
{bars.map((b) => {
return <Card key={b.id} sx={{m: 2, p: 2}}>
<Stack direction='row' justifyContent={'space-between'}>
<Typography>{b.name}</Typography>
{b.active && <IconButton disabled>
<PowerIcon/>
</IconButton>}
{!b.active && <Box>
<IconButton onClick={() => deleteHandler(b)}>
<DeleteIcon/>
</IconButton>
<IconButton onClick={() => changeHandler(b)}>
<ElectricalServicesIcon/>
</IconButton>
</Box>}
</Stack>
</Card>
})}
</Paper>
</>
)
}

View File

@@ -0,0 +1,39 @@
import Dialog from "@mui/material/Dialog";
import DialogTitle from "@mui/material/DialogTitle";
import * as React from "react";
import Typography from "@mui/material/Typography";
import DialogContent from "@mui/material/DialogContent";
import DialogActions from "@mui/material/DialogActions";
import Button from "@mui/material/Button";
import {useState} from "react";
import TextField from "@mui/material/TextField";
export function BarCreateModal({open, close, create}) {
const [value, setValue] = useState("");
return (
<Dialog fullWidth={true}
open={open} onClose={close}
sx={{
'& .MuiDialog-paper': {
margin: '8px',
},
'& .MuiPaper-root': {
width: 'calc(100% - 16px)',
}
}}>
<DialogTitle>
<Typography>Создать список</Typography>
</DialogTitle>
<DialogContent>
<TextField sx={{width: '75%'}}
label={"Название списка"} variant='outlined'
value={!value ? "" : value}
onChange={(e) => setValue(e.target.value)}
/>
</DialogContent>
<DialogActions>
<Button onClick={() => create(value)}>Создать</Button>
</DialogActions>
</Dialog>
)
}

View File

@@ -11,6 +11,7 @@ import EditIcon from '@mui/icons-material/Edit';
import DeleteIcon from '@mui/icons-material/Delete';
import LocalBarIcon from '@mui/icons-material/LocalBar';
import {paths} from "../../path";
import {useAlert} from "../../hooks/useAlert";
function renderFavouriteBadge(handleFavourite, row) {
const childIcon = row.rating.favourite ? <FavoriteIcon/> : <FavoriteBorderIcon/>;
@@ -33,6 +34,7 @@ function renderRating(handleChangeRating, row) {
}
export function Cocktail({row, handleFavourite, handleChangeRating, handleSelect, deleteHandler}) {
const {notImplement} = useAlert();
return (
<Grid item sx={{pr: 2}}>
<CocktailItemStyled>
@@ -55,24 +57,23 @@ export function Cocktail({row, handleFavourite, handleChangeRating, handleSelect
image={row.image.includes("thecocktaildb") ? (row.image + "/preview") : row.image}
/>
<CardActions>
<IconButton sx={{m: 0}} size='small'>
<IconButton sx={{m: 0}} size='small' onClick={() => notImplement()}>
<LocalBarIcon fontSize='small'/>
</IconButton>
{renderFavouriteBadge(handleFavourite, row)}
{renderRating(handleChangeRating, row)}
<IconButton size={'small'} href={`${paths.bar.cocktailEdit}?id=${row.id}`}>
<EditIcon fontSize={'small'}/>
<IconButton size='small' href={`${paths.bar.cocktailEdit}?id=${row.id}`}>
<EditIcon fontSize='small'/>
</IconButton>
<IconButton size={'small'} onClick={() => deleteHandler(row)}>
<DeleteIcon fontSize={'small'}/>
<IconButton size='small' onClick={() => deleteHandler(row)}>
<DeleteIcon fontSize='small'/>
</IconButton>
</CardActions>
<CardContent sx={{pb: 0, pl: 2, pt: 0}}>
<Typography variant="h5" minHeight={'50px'} mt={2}>{row.name} </Typography>
<CocktailDescription row={row}/>
</CardContent>
</Box>
</CocktailItemStyled>
</Grid>

View File

@@ -16,6 +16,10 @@ export function useAlert() {
createAlert("Данный функционал пока не реализован", {variant: 'warning'});
}
function createWarning(message) {
createAlert(message, {variant: 'warning'})
}
function createError(message) {
createAlert(message, {variant: "error"});
}
@@ -28,5 +32,5 @@ export function useAlert() {
createAlert(message, {variant: "success"});
}
return {createAlert, notImplement, createError, getError, createSuccess}
return {createAlert, notImplement, createError, getError, createSuccess, createWarning}
}

View File

@@ -2,6 +2,7 @@ import {paths} from "./path";
export const navItems = [
{key: 'menu', title: 'Меню', href: paths.dashboard.overview, icon: 'menu'},
{key: 'barList', title: 'Список баров', href: paths.bar.list, icon: 'basket', forBarmen: true},
{key: 'ingredients', title: 'Список ингредиентов', href: paths.bar.ingredients, icon: 'basket', forBarmen: true},
{key: 'ingredientEdit', title: 'Ингредиенты', href: paths.bar.ingredientEdit, icon: 'ingredients', forAdmin: true},
{key: 'cocktailEdit', title: 'Коктейли', href: paths.bar.cocktailEdit, icon: 'cocktail', forAdmin: true}

View File

@@ -36,7 +36,9 @@ export const requests = {
invite: routes.visitor + "/invite?"
},
bar: {
list: routes.bar + "list",
list: routes.bar + "all",
change: routes.bar + "change",
crud: routes.bar,
addToMyList: routes.bar + "addToMyList",
enter: routes.bar + "enter?id=",
pay: routes.order + "?",