diff --git a/client/src/App.tsx b/client/src/App.tsx index 34f8748..5a1451d 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -18,18 +18,20 @@ import './themes/bocchi.scss'; import { faCircleCheck, faNoteSticky, faTrashCan, faComment } from '@fortawesome/free-regular-svg-icons'; import { useSettings } from './context/settings'; import Footer from './components/Footer'; -import { faArrowUpRightFromSquare, faBasketShopping, faChainBroken, faChevronLeft, faChevronRight, faDharmachakra, faGear, faMoneyBillTransfer, faSatelliteDish, faSearch, faTriangleExclamation } from '@fortawesome/free-solid-svg-icons'; +import { faArrowUpRightFromSquare, faBasketShopping, faTag, faChainBroken, faChevronLeft, faChevronRight, faDharmachakra, faGear, faMoneyBillTransfer, faSatelliteDish, faSearch, faTriangleExclamation } from '@fortawesome/free-solid-svg-icons'; import { useNavigate } from 'react-router-dom'; import Loader from './components/Loader'; import { getHumanDateTime, isInTheFuture } from './Utils'; import NoteModal from './components/modals/NoteModal'; +import PriceModal from './components/modals/PriceModal'; +import { parsePriceCzk } from './utils/parsePrice'; import PayForAllModal from './components/modals/PayForAllModal'; import SpinWheelModal, { WheelPick } from './components/modals/SpinWheelModal'; import EaterBadge from './components/EaterBadge'; import PendingPayments from './components/PendingPayments'; import { useEasterEgg } from './context/eggs'; -import { ClientData, Food, MealSlot, PendingQr, PizzaOrder, DepartureTime, PizzaDayState, Restaurant, RestaurantDayMenu, RestaurantDayMenuMap, LunchChoice, LocationLunchChoicesMap, UserLunchChoice, PizzaVariant, getData, getEasterEggImage, addPizza, removePizza, updatePizzaDayNote, createPizzaDay, deletePizzaDay, lockPizzaDay, unlockPizzaDay, finishOrder, finishDelivery, addChoice, jdemeObed, removeChoices, removeChoice, updateNote, changeDepartureTime, setBuyer, generateQr } from '../../types'; -import { getLunchChoiceName } from './enums'; +import { ClientData, Food, MealSlot, PendingQr, PizzaOrder, DepartureTime, PizzaDayState, Restaurant, RestaurantDayMenu, RestaurantDayMenuMap, LunchChoice, LocationLunchChoicesMap, UserLunchChoice, PizzaVariant, getData, getEasterEggImage, addPizza, removePizza, updatePizzaDayNote, createPizzaDay, deletePizzaDay, lockPizzaDay, unlockPizzaDay, finishOrder, finishDelivery, addChoice, jdemeObed, removeChoices, removeChoice, updateNote, updatePrice, changeDepartureTime, setBuyer, generateQr } from '../../types'; +import { CHOICES_WITHOUT_PRICE, getLunchChoiceName } from './enums'; import { isArrowNavigationBlocked } from './utils/arrowNavigation'; // import FallingLeaves, { LEAF_PRESETS, LEAF_COLOR_THEMES } from './FallingLeaves'; // import './FallingLeaves.scss'; @@ -88,6 +90,7 @@ function App() { const [dayIndex, setDayIndex] = useState(); const [loadingPizzaDay, setLoadingPizzaDay] = useState(false); const [noteModalOpen, setNoteModalOpen] = useState(false); + const [priceModalOpen, setPriceModalOpen] = useState(false); const [payForAllLocationKey, setPayForAllLocationKey] = useState(null); const [spinWheelOpen, setSpinWheelOpen] = useState(false); const [eggImage, setEggImage] = useState(); @@ -443,6 +446,13 @@ function App() { } } + const savePrice = async (price?: number) => { + if (auth?.login) { + await updatePrice({ body: { price, dayIndex } }); + setPriceModalOpen(false); + } + } + const copyNote = async (note: string) => { if (auth?.login && note) { await updateNote({ body: { note, dayIndex } }); @@ -666,6 +676,15 @@ function App() { const noOrders = data?.pizzaDay?.orders?.length === 0; const canChangeChoice = dayIndex == null || data.todayDayIndex == null || dayIndex >= data.todayDayIndex; + const ownChoice = auth?.login ? Object.entries(data.choices) + .map(([locationKey, loginMap]) => ({ locationKey: locationKey as LunchChoice, choice: loginMap?.[auth.login!] })) + .find(entry => entry.choice != null) as { locationKey: LunchChoice, choice: UserLunchChoice } | undefined : undefined; + // Součet cen vybraných jídel z menu jako návrh ceny; pokud některou cenu nelze přečíst, nenavrhujeme nic + const ownFoodPrices = ownChoice?.choice.selectedFoods?.map(index => parsePriceCzk(food[ownChoice.locationKey as Restaurant]?.food?.[index]?.price)) ?? []; + const ownSuggestedPrice = ownFoodPrices.length && !ownFoodPrices.includes(null) + ? Math.round((ownFoodPrices as number[]).reduce((sum, price) => sum + price, 0) * 100) + : undefined; + const { path, url, startOffset, endOffset, duration, ...style } = easterEgg || {}; return ( @@ -781,6 +800,7 @@ function App() { {login} {userPayload.departureTime && ({userPayload.departureTime})} {userPayload.note && ({userPayload.note})} + {login === auth.login && userPayload.price != null && {userPayload.price / 100} Kč}
{login === auth.login && canChangeChoice && locationKey === LunchChoice.OBJEDNAVAM && @@ -804,6 +824,9 @@ function App() { {login === auth.login && canChangeChoice && locationKey === LunchChoice.ROZHODUJI && setSpinWheelOpen(true)} className='action-icon spin-wheel-icon' icon={faDharmachakra} /> } + {login === auth.login && canChangeChoice && !CHOICES_WITHOUT_PRICE.includes(locationKey) && + setPriceModalOpen(true)} className='action-icon' icon={faTag} /> + } {login === auth.login && canChangeChoice && { setNoteModalOpen(true); @@ -969,6 +992,13 @@ function App() {