diff --git a/local_backend/routers/orders.py b/local_backend/routers/orders.py index 3e76777..a4177d5 100644 --- a/local_backend/routers/orders.py +++ b/local_backend/routers/orders.py @@ -8,7 +8,7 @@ from database import get_db from models.order import Order, OrderItem, OrderWaiter from models.user import User, AssistantAssignment from models.product import Product -from schemas.order import OrderCreate, OrderOut, OrderItemOut, AddItemsRequest, PayItemsRequest, AssignWaiterRequest +from schemas.order import OrderCreate, OrderOut, OrderItemOut, AddItemsRequest, PayItemsRequest, AssignWaiterRequest, OrderWaiterOut from routers.deps import get_current_user, require_manager from services.printer_service import route_and_print diff --git a/local_backend/schemas/order.py b/local_backend/schemas/order.py index 5b7521d..fdcc527 100644 --- a/local_backend/schemas/order.py +++ b/local_backend/schemas/order.py @@ -15,10 +15,17 @@ class AddItemsRequest(BaseModel): items: List[OrderItemInput] +class ProductNameOut(BaseModel): + id: int + name: str + model_config = {"from_attributes": True} + + class OrderItemOut(BaseModel): id: int order_id: int product_id: int + product: Optional[ProductNameOut] = None added_by: int quantity: int unit_price: float @@ -44,6 +51,11 @@ class AssignWaiterRequest(BaseModel): waiter_id: int +class OrderWaiterOut(BaseModel): + waiter_id: int + model_config = {"from_attributes": True} + + class OrderOut(BaseModel): id: int table_id: int @@ -54,5 +66,6 @@ class OrderOut(BaseModel): closed_by: Optional[int] = None notes: Optional[str] = None items: List[OrderItemOut] = [] + waiters: List[OrderWaiterOut] = [] model_config = {"from_attributes": True} diff --git a/waiter_pwa/src/pages/TableDetailPage.jsx b/waiter_pwa/src/pages/TableDetailPage.jsx index 2369195..0ed961e 100644 --- a/waiter_pwa/src/pages/TableDetailPage.jsx +++ b/waiter_pwa/src/pages/TableDetailPage.jsx @@ -4,6 +4,10 @@ import OrderSummary from '../components/OrderSummary' import useAuthStore from '../store/authStore' import client from '../api/client' +function fmtPrice(v) { + return Number(v).toFixed(2) + ' €' +} + export default function TableDetailPage() { const { tableId } = useParams() const { user } = useAuthStore() @@ -15,6 +19,7 @@ export default function TableDetailPage() { const [paying, setPaying] = useState(false) const [selectedIds, setSelectedIds] = useState([]) const [confirmClose, setConfirmClose] = useState(false) + const [confirmPay, setConfirmPay] = useState(false) const [error, setError] = useState('') async function load() { @@ -28,7 +33,7 @@ export default function TableDetailPage() { } else { setOrder(null) } - } catch (err) { + } catch { setError('Σφάλμα φόρτωσης') } finally { setLoading(false) @@ -37,6 +42,9 @@ export default function TableDetailPage() { useEffect(() => { load() }, [tableId]) + const activeItems = order?.items?.filter(i => i.status === 'active') || [] + const allPaid = order && activeItems.length === 0 + const isMyOrder = order && ( order.opened_by === user?.id || order.waiters?.some(w => w.waiter_id === user?.id) ) @@ -51,8 +59,8 @@ export default function TableDetailPage() { } async function paySelected() { - if (selectedIds.length === 0) return setPaying(true) + setConfirmPay(false) try { await client.post(`/api/orders/${order.id}/pay`, { item_ids: selectedIds }) setSelectedIds([]) @@ -78,8 +86,17 @@ export default function TableDetailPage() { setSelectedIds(prev => prev.includes(id) ? prev.filter(x => x !== id) : [...prev, id]) } - const allPaid = order && order.items?.filter(i => i.status === 'active').length === 0 - && order.items?.some(i => i.status === 'paid') + function selectAll() { + const allActive = activeItems.map(i => i.id) + const allSelected = allActive.every(id => selectedIds.includes(id)) + setSelectedIds(allSelected ? [] : allActive) + } + + const selectedTotal = activeItems + .filter(i => selectedIds.includes(i.id)) + .reduce((s, i) => s + i.unit_price * i.quantity, 0) + + const allActiveSelected = activeItems.length > 0 && activeItems.every(i => selectedIds.includes(i.id)) if (loading) return
Φόρτωση…
+ {selectedIds.length} αντικείμενο{selectedIds.length !== 1 ? 'α' : ''} +
++ {fmtPrice(selectedTotal)} +
+