diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 809e5ee..238304e 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -7,7 +7,7 @@ stages:
- deploy front
- deploy back
-stop-job:
+deploy-back-job:
stage: deploy back
only:
- back_release
@@ -18,5 +18,17 @@ stop-job:
- echo "Сборка образа докер"
- docker build -t my-bar .
- echo "Запуск докер контейнера"
- - docker run --name my-bar --restart=always -p 8091:8080 -d my-bar
- - echo "Деплой завершен"
\ No newline at end of file
+ - docker run --name my-bar --restart=always -p 8091:8080 -d -e COCKTAIL_PHOTO_PATH=/front/assets/cocktails -v /mnt/sdb1/my-bar-front/build:/front my-bar
+ - echo "Деплой завершен"
+
+deploy-front-job:
+ stage: deploy front
+ only:
+ - release_front
+ image: node:22.12
+ script:
+ - cd front
+ - npm install
+ - npm run build
+ - cp -r build /app
+ - echo "Деплой завершен"
diff --git a/front/package.json b/front/package.json
index 1034a42..27949b9 100644
--- a/front/package.json
+++ b/front/package.json
@@ -41,7 +41,7 @@
},
"scripts": {
"start": "react-scripts start",
- "build": "react-scripts build",
+ "build": "CI=false && react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
diff --git a/front/src/app/App.js b/front/src/app/App.js
index 3f99800..d741347 100644
--- a/front/src/app/App.js
+++ b/front/src/app/App.js
@@ -7,6 +7,7 @@ import {BrowserRouter as Router} from "react-router-dom";
import {NavigationRoutes} from "./NavigationRoutes";
import {SnackbarProvider} from 'notistack';
import {UserProvider} from "../context/UserContext";
+import {SelectProvider} from "../context/SelectContext";
function App() {
const theme = createTTheme();
@@ -36,10 +37,13 @@ function App() {
},
}}
/>
- {/*Маршрутизация*/}
-
-
-
+ {/*Провайдер выбора*/}
+
+ {/*Маршрутизация*/}
+
+
+
+
diff --git a/front/src/app/pages/cocktails/CocktailMenuBarPage.js b/front/src/app/pages/cocktails/CocktailMenuBarPage.js
index bef556f..531bfe8 100644
--- a/front/src/app/pages/cocktails/CocktailMenuBarPage.js
+++ b/front/src/app/pages/cocktails/CocktailMenuBarPage.js
@@ -16,6 +16,7 @@ import {requests} from "../../../requests";
import {api} from "../../../lib/clients/api";
import {useAlert} from "../../../hooks/useAlert";
import {CocktailInfoModal} from "../../../components/cocktails/CocktailInfoModal";
+import {useSelect} from "../../../hooks/useSelect";
export function CocktailMenuBarPage() {
const {createError} = useAlert();
@@ -23,8 +24,7 @@ export function CocktailMenuBarPage() {
const [findString, setFindString] = useState("");
const [loading, setLoading] = useState(true);
const [cocktails, setCocktails] = useState([]);
- const [openModal, setOpenModal] = useState(false);
- const [selected, setSelected] = useState(null);
+ const {setCocktail, state} = useSelect();
useEffect(() => {
api().get(`${requests.cocktails.menu}?all=true`)
@@ -38,12 +38,11 @@ export function CocktailMenuBarPage() {
const handleOpenModal = (row) => {
- setSelected(row)
- setOpenModal(true);
+ setCocktail(row);
}
const changeHandler = (row, value) => {
const newState = cocktails.map((r) => {
- if(r.id !== row.id) {
+ if (r.id !== row.id) {
return r;
}
return {
@@ -117,11 +116,7 @@ export function CocktailMenuBarPage() {
{/*Загрузчик*/}
{/*Модальное окно информации об ингредиенте*/}
- {
- setSelected(null);
- setOpenModal(false);
- }}/>
+
)
}
\ No newline at end of file
diff --git a/front/src/app/pages/cocktails/CocktailsPageContent.js b/front/src/app/pages/cocktails/CocktailsPageContent.js
index 428aa5e..176c480 100644
--- a/front/src/app/pages/cocktails/CocktailsPageContent.js
+++ b/front/src/app/pages/cocktails/CocktailsPageContent.js
@@ -14,57 +14,8 @@ import {useUser} from "../../../hooks/useUser";
import {blue} from "@mui/material/colors";
import UpIcon from "@mui/icons-material/KeyboardArrowUp";
import {sortList} from "../../../components/cocktails/sortingList";
-import {getComparator} from "../../../components/core/getComparator";
import Button from "@mui/material/Button";
-import Paper from "@mui/material/Paper";
-import CheckMarks from "../../../components/cocktails/CheckMarks";
-
-const filterList = (rows, filter, allowIngredients) => {
- let regExp = new RegExp("(.*?)" + filter.search + "(.*?)", "i");
- const sortingObj = sortList.find((s) => s.name === filter.sorting);
- const sortingValues = sortingObj.id.split("|");
- return rows
- .filter((row) => {
- const nameReg = row.name.split(" ").map((n) => n.match(regExp) !== null).includes(true);
- const ingredientReg = row.components
- .split(", ")
- .map((r) => r.match(regExp) !== null)
- .includes(true);
- return nameReg || ingredientReg;
- })
- .filter((row) => filter.onlyFavourite ? row.rating.favourite : true)
- .filter((row) => filter.glass.length === 0 || filter.glass.includes(row.glass))
- .filter((row) => filter.category.length === 0 || filter.category.includes(row.category))
- .filter((row) => filter.alcohol.length === 0 || filter.alcohol.includes(row.alcoholic))
- .filter((row) => {
- if (filter.tags.length === 0) {
- return true;
- }
-
- if (row.tags.length === 0) {
- return false;
- }
- return row.tags.split(",").find((tag) => filter.tags.includes(tag))
- })
- .filter((row) => {
- if (filter.iCount.length === 0) {
- return true;
- }
- const arr = row.components.split(", ");
- const count = arr.filter((n) => !allowIngredients.includes(n)).length;
- const filt = filter.ingredient.length === 0 || arr.filter((n) => filter.ingredient.includes(n)).length > 0;
-
- return filter.iCount === count && filt;
- })
- .filter((row) => {
- if (filter.inMenu === "") {
- return row;
- }
- const filterValue = filter.inMenu === "Есть в меню";
- return filterValue === row.inMenu;
- })
- .sort(getComparator(sortingValues[1], sortingValues[0], "name"))
-}
+import {useSelect} from "../../../hooks/useSelect";
const emptyFilter = {
search: "",
@@ -86,14 +37,14 @@ const CocktailsPageContent = ({all}) => {
const [allowIngredients, setAllowIngredients] = useState([])
const [rows, setRows] = useState([]);
const [filter, setFilter] = useState(emptyFilter)
- const [open, setOpen] = useState(false);
- const [selectedCocktail, setSelectedCocktail] = useState(null)
- const [chips, setChips] = useState([])
+ // const [chips, setChips] = useState([])
const [page, setPage] = useState(-1);
const [load, setLoad] = useState(false);
const [isEnd, setIsEnd] = useState(false);
const [isNew, setIsNew] = useState(true);
+ const {selectCocktail, getCocktail, getOpenCocktail} = useSelect();
+
const loading = useCallback(() => {
const size = Math.floor((window.innerWidth) / 350) * 5;
if (load || (!isNew && isEnd)) {
@@ -111,7 +62,7 @@ const CocktailsPageContent = ({all}) => {
api().post(requests.cocktails.menu, request)
.then((r) => {
if (r.data.length === 0) {
- if(isNew) {
+ if (isNew) {
setRows([]);
}
setIsEnd(true);
@@ -139,6 +90,7 @@ const CocktailsPageContent = ({all}) => {
}
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
+ // eslint-disable-next-line
}, [loading]);
useEffect(() => {
api().get(requests.bar.ingredientSimple)
@@ -152,6 +104,7 @@ const CocktailsPageContent = ({all}) => {
}, [])
useEffect(() => {
loading();
+ // eslint-disable-next-line
}, [filter])
useEffect(() => {
if (!all) {
@@ -164,7 +117,8 @@ const CocktailsPageContent = ({all}) => {
.filter((nhc) => nhc.length === 1)
.map((fc) => fc[0])
.forEach((i) => ingredients.add(i))
- setChips(Array.from(ingredients).sort(getComparator()));
+ // setChips(Array.from(ingredients).sort(getComparator()));
+ // eslint-disable-next-line
}, [rows, allowIngredients])
const renderSkeleton = () => {
@@ -230,12 +184,9 @@ const CocktailsPageContent = ({all}) => {
setFilter(emptyFilter);
}
const handleSelectCocktail = (row) => {
- setSelectedCocktail(row.id)
- setOpen(true)
- }
- const handleCloseCocktailModal = () => {
- setOpen(false);
- setSelectedCocktail(null);
+ selectCocktail(row.id)
+ // setSelectedCocktail(row.id)
+ // setOpen(true)
}
const handleEditMenu = (row, value) => {
const newState = rows.map((r) => {
@@ -271,8 +222,7 @@ const CocktailsPageContent = ({all}) => {
{/**/}
{/*Модальное окно информации о коктейле*/}
-
+
{/*Блок фильтров*/}
{
@@ -76,12 +76,7 @@ export function IngredientsPage() {
});
}
const handleOpenModal = (i) => {
- setOpenModal(true);
- setSelectedInfo(i);
- }
- const handleCloseModal = () => {
- setSelectedInfo(null);
- setOpenModal(false);
+ selectIngredient(i)
}
return (
@@ -147,7 +142,7 @@ export function IngredientsPage() {
{/*Загрузчик*/}
{/*Модальное окно информации об ингредиенте*/}
-
+
)
}
\ No newline at end of file
diff --git a/front/src/components/Ingredients/IngredientInfoModal.js b/front/src/components/Ingredients/IngredientInfoModal.js
index 75ce54f..103ab14 100644
--- a/front/src/components/Ingredients/IngredientInfoModal.js
+++ b/front/src/components/Ingredients/IngredientInfoModal.js
@@ -6,13 +6,34 @@ import Button from "@mui/material/Button";
import * as React from "react";
import Stack from "@mui/material/Stack";
import Typography from "@mui/material/Typography";
+import List from "@mui/material/List";
+import {useEffect, useState} from "react";
+import {api} from "../../lib/clients/api";
+import {requests} from "../../requests";
+import {useAlert} from "../../hooks/useAlert";
+import ListItem from "@mui/material/ListItem";
+import {useSelect} from "../../hooks/useSelect";
+
+export function IngredientInfoModal({ingredient}) {
+ const [cocktails, setCocktails] = useState([]);
+ const {closeIngredient, getOpenIngredient, selectCocktail} = useSelect();
+ const {createError} = useAlert();
+
+ useEffect(() => {
+ if(!ingredient) {
+ return
+ }
+ api().get(requests.cocktails.byIngredient + ingredient.id)
+ .then((r) => setCocktails(r.data))
+ .catch(() => createError())
+ // eslint-disable-next-line
+ }, [ingredient]);
-export function IngredientInfoModal({ingredient, open, closeHandler}) {
if (!ingredient) {
return null;
}
return (
-
);
diff --git a/front/src/components/cocktails/Cocktail.js b/front/src/components/cocktails/Cocktail.js
index 272da22..ddfb922 100644
--- a/front/src/components/cocktails/Cocktail.js
+++ b/front/src/components/cocktails/Cocktail.js
@@ -1,9 +1,6 @@
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";
@@ -14,6 +11,7 @@ import FavoriteIcon from '@mui/icons-material/Favorite';
import {api} from "../../lib/clients/api";
import Box from "@mui/material/Box";
import {useUser} from "../../hooks/useUser";
+import {CocktailDescription} from "./CocktailDescription";
function renderFavouriteBadge(handleFavourite, row) {
const childIcon = row.rating.favourite ? : ;
@@ -65,40 +63,13 @@ export function Cocktail({row, handleFavourite, handleChangeRating, handleSelect
alt={row.name}
height="300"
- image={`${row.image}/preview`}
+ image={row.image.includes("thecocktaildb") ? (row.image + "/preview") : row.image}
/>
{renderFavouriteBadge(handleFavourite, row)}
{renderRating(handleChangeRating, row)}
{row.name}
-
- {row.hasError && (
-
- Имеет ошибку в рецепте или ингредиентах
-
- )}
-
- {"Категория: " + row.category}
-
-
- {"Алкоголь: " + row.alcoholic}
-
- {row.volume !== null && (
-
- {"Крепость: ≈" + row.volume}
-
- )}
-
- {"Подача: " + row.glass}
-
-
- {"Состав: " + row.components}
-
- {(row.tags && row.tags.length > 0) && (
-
- {"Теги: " + row.tags.replaceAll(',', ', ')}
- )}
-
+
{(row.isAllowed && session.isActive && user.invited) &&
diff --git a/front/src/components/cocktails/CocktailDescription.js b/front/src/components/cocktails/CocktailDescription.js
new file mode 100644
index 0000000..db6b9e2
--- /dev/null
+++ b/front/src/components/cocktails/CocktailDescription.js
@@ -0,0 +1,36 @@
+import ListItem from "@mui/material/ListItem";
+import ListItemText from "@mui/material/ListItemText";
+import List from "@mui/material/List";
+
+export function CocktailDescription({row}) {
+ return (
+
+ {row.hasError && (
+
+ Имеет ошибку в рецепте или ингредиентах
+
+ )}
+
+ {"Категория: " + row.category}
+
+
+ {"Алкоголь: " + row.alcoholic}
+
+ {row.volume !== null && (
+
+ {"Крепость: ≈" + row.volume}
+
+ )}
+
+ {"Подача: " + row.glass}
+
+
+ {"Состав: " + row.components}
+
+ {(row.tags && row.tags.length > 0) && (
+
+ {"Теги: " + row.tags.replaceAll(',', ', ')}
+ )}
+
+ )
+}
\ No newline at end of file
diff --git a/front/src/components/cocktails/CocktailInfoModal.js b/front/src/components/cocktails/CocktailInfoModal.js
index 98a018c..afb6053 100644
--- a/front/src/components/cocktails/CocktailInfoModal.js
+++ b/front/src/components/cocktails/CocktailInfoModal.js
@@ -21,24 +21,20 @@ import {useAlert} from "../../hooks/useAlert";
import {paths} from "../../path";
import {Loading} from "../core/Loading";
import {useUser} from "../../hooks/useUser";
+import {useSelect} from "../../hooks/useSelect";
-export function CocktailInfoModal({open, row, closeHandler}) {
+export function CocktailInfoModal({row}) {
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 {closeCocktail, selectIngredient, getIngredient, getOpenCocktail} = useSelect();
const openIngredientModalHandler = (id) => {
api().get(`${requests.bar.ingredient}?id=${id}`)
.then((r) => {
- setSelectedIngredient(r.data)
- setOpenIngredientModal(true);
- }).catch(() => createError("Ошибка получения информации об ингредиенте"))
+ selectIngredient(r.data)
+ })
+ .catch(() => createError("Ошибка получения информации об ингредиенте"))
}
const selectIngredientHandler = (ingredient) => {
const url = `${requests.bar.ingredient}?id=${ingredient.id}`;
@@ -79,18 +75,17 @@ export function CocktailInfoModal({open, row, closeHandler}) {
.catch(() => {
getError();
setLoading(false)
- closeHandler();
+ closeCocktail();
})
+ // eslint-disable-next-line
}, [row]);
if (!row || !cocktail) {
return null;
}
- let alko = 0;
- let volume = 0;
return (
)
diff --git a/front/src/components/orders/OrderModal.js b/front/src/components/orders/OrderModal.js
index 53d4928..907842d 100644
--- a/front/src/components/orders/OrderModal.js
+++ b/front/src/components/orders/OrderModal.js
@@ -37,6 +37,7 @@ function renderButtons(row, my, handleChange) {
export default function OrderModal({row, handleClose, open, handleChange, my}) {
const [receipt, setReceipt] = useState([]);
+ const [instructions, setInstructions] = useState();
const {createError} = useAlert();
useEffect(() => {
@@ -46,6 +47,10 @@ export default function OrderModal({row, handleClose, open, handleChange, my}) {
api().get(requests.bar.receipts + row.cocktail.id)
.then((r) => setReceipt(r.data))
.catch(() => createError("Ошибка получения рецепта"))
+
+ api().get(requests.cocktails.instructions + row.cocktail.id)
+ .then((r) => setInstructions(r.data))
+ .catch(() => createError("Ошибка получения инструкции"))
// eslint-disable-next-line
}, [row]);
@@ -62,7 +67,6 @@ export default function OrderModal({row, handleClose, open, handleChange, my}) {
{"Заказ №" + row.id}
{row.cocktail.name}
- {row.cocktail.alcoholic + " " + row.cocktail.category}
{"для: " + row.visitor.name + " " + row.visitor.lastName}
@@ -74,8 +78,14 @@ export default function OrderModal({row, handleClose, open, handleChange, my}) {
return ({`${r.ingredient.name} - ${r.measure}`})
})}
- Инструкция:
- {row.cocktail.instructions}
+ {instructions &&
+ (
+ <>
+ Инструкция:
+ {instructions}
+ >
+ )
+ }
{row.cocktail.video && (