feat: odebírání položek objednávky ve sloupci Z nabídky
CI / Generate TypeScript types (push) Successful in 10s
CI / Server unit tests (push) Successful in 26s
CI / Build server (push) Successful in 58s
CI / Build client (push) Successful in 1m4s
CI / Playwright E2E tests (push) Successful in 1m47s
CI / Build and push Docker image (push) Successful in 45s
CI / Notify (push) Successful in 2s

This commit is contained in:
2026-09-23 16:26:10 +02:00
parent bd52ae071e
commit f9a7b791a0
4 changed files with 94 additions and 3 deletions
+20 -2
View File
@@ -2,7 +2,7 @@ import { useMemo } from "react";
import { OverlayTrigger, Tooltip } from "react-bootstrap";
import SelectSearch, { SelectedOptionValue, SelectSearchOption } from "react-select-search";
import { StoreMenuDish } from "../../../types";
import { matchNoteToMenu } from "../utils/menuMatch";
import { matchNoteToMenu, splitNoteItems } from "../utils/menuMatch";
import "./MenuHintCell.scss";
type Props = {
@@ -14,6 +14,8 @@ type Props = {
canEdit: boolean,
onPick: (dish: StoreMenuDish) => void,
onUsePrice: (priceKc: number) => void,
/** Odebere jeden kus položky poznámky na daném indexu (a odečte její cenu) */
onRemoveItem: (index: number) => void,
};
const formatDish = (d: StoreMenuDish) => d.price != null ? `${d.name} (${d.price} Kč)` : d.name;
@@ -22,7 +24,7 @@ const formatDish = (d: StoreMenuDish) => d.price != null ? `${d.name} (${d.price
* Buňka „Z nabídky" ve skupinové objednávce: výběr položky ze stažené nabídky podniku
* (doplní poznámku i částku) a kontrola ceny rozpoznané z poznámky proti zadané částce.
*/
export default function MenuHintCell({ menu, note, amount, canEdit, onPick, onUsePrice }: Readonly<Props>) {
export default function MenuHintCell({ menu, note, amount, canEdit, onPick, onUsePrice, onRemoveItem }: Readonly<Props>) {
const options = useMemo<SelectSearchOption[]>(() => {
if (!menu?.length) return [];
const groups = new Map<string, SelectSearchOption[]>();
@@ -35,6 +37,7 @@ export default function MenuHintCell({ menu, note, amount, canEdit, onPick, onUs
}, [menu]);
const match = useMemo(() => menu ? matchNoteToMenu(note, menu) : undefined, [menu, note]);
const items = useMemo(() => splitNoteItems(note, menu), [note, menu]);
if (!menu?.length) {
return <small className="text-muted">—</small>;
@@ -60,6 +63,21 @@ export default function MenuHintCell({ menu, note, amount, canEdit, onPick, onUs
}}
/>
)}
{canEdit && items.length > 0 && (
<div className="menu-hint-items">
{items.map((text, i) => {
// Rozpoznaná položka ze stejného rozdělení poznámky — kvůli ceně na čipu
const part = match && match.parts.length === items.length ? match.parts[i] : undefined;
const price = part?.dish?.price;
return (
<span key={`${i}-${text}`} className="menu-hint-item">
{text}{price != null && <small> {price} Kč</small>}
<button type="button" onClick={() => onRemoveItem(i)} title={`Odebrat 1× ${text}`} aria-label={`Odebrat ${text}`}>×</button>
</span>
);
})}
</div>
)}
{match && (
<OverlayTrigger
placement="top"