diff --git a/src/admin/pages/WarehouseIssueDetail.tsx b/src/admin/pages/WarehouseIssueDetail.tsx index 8f8cfef..d08b697 100644 --- a/src/admin/pages/WarehouseIssueDetail.tsx +++ b/src/admin/pages/WarehouseIssueDetail.tsx @@ -1,24 +1,39 @@ import { useState } from "react"; -import { useParams, useNavigate, Link } from "react-router-dom"; +import { useParams, useNavigate, Link as RouterLink } from "react-router-dom"; import { useQuery } from "@tanstack/react-query"; +import { motion } from "framer-motion"; +import Box from "@mui/material/Box"; +import Typography from "@mui/material/Typography"; import { useAlert } from "../context/AlertContext"; import { useAuth } from "../context/AuthContext"; import Forbidden from "../components/Forbidden"; -import { motion } from "framer-motion"; -import ConfirmModal from "../components/ConfirmModal"; -import FormField from "../components/FormField"; import { formatCurrency, formatDate } from "../utils/formatters"; import { warehouseIssueDetailOptions, type WarehouseIssue, + type WarehouseIssueItem, } from "../lib/queries/warehouse"; import { useApiMutation } from "../lib/queries/mutations"; +import { + Button, + Card, + DataTable, + StatusChip, + EmptyState, + LoadingState, + PageHeader, + ConfirmDialog, + type DataColumn, +} from "../ui"; -const STATUS_BADGE: Record = { - DRAFT: "admin-badge-warning", - CONFIRMED: "admin-badge-active", - CANCELLED: "admin-badge-danger", +const STATUS_COLOR: Record< + string, + "default" | "success" | "error" | "warning" | "info" +> = { + DRAFT: "warning", + CONFIRMED: "success", + CANCELLED: "error", }; const STATUS_LABEL: Record = { @@ -27,6 +42,19 @@ const STATUS_LABEL: Record = { CANCELLED: "Zrušeno", }; +const BackIcon = ( + + + +); + export default function WarehouseIssueDetail() { const { id } = useParams(); const alert = useAlert(); @@ -92,257 +120,290 @@ export default function WarehouseIssueDetail() { const cancelling = cancelMutation.isPending; if (isPending) { - return ( -
-
-
- ); + return ; } if (error || !issue) { return ( -
-
-
- + - - - - -
-
-
-
-
-

Výdejka nebyla nalezena.

-
-
-
-
+ Zpět + + } + /> + + + + ); } const iss = issue as WarehouseIssue; const items = iss.items ?? []; + const itemColumns: DataColumn[] = [ + { + key: "item", + header: "Položka", + width: "20%", + bold: true, + render: (row) => row.item?.name || `ID: ${row.item_id}`, + }, + { + key: "batch", + header: "Šarže", + width: "18%", + mono: true, + render: (row) => + row.batch + ? `${formatDate(row.batch.received_at)} – ${formatCurrency(Number(row.batch.unit_price), "CZK")}` + : "—", + }, + { + key: "quantity", + header: "Množství", + width: "10%", + mono: true, + render: (row) => String(Number(row.quantity)), + }, + { + key: "unit_price", + header: "Cena/ks", + width: "13%", + mono: true, + render: (row) => + row.batch ? formatCurrency(Number(row.batch.unit_price), "CZK") : "—", + }, + { + key: "total", + header: "Celkem", + width: "13%", + mono: true, + bold: true, + render: (row) => + row.batch + ? formatCurrency( + Number(row.quantity) * Number(row.batch.unit_price), + "CZK", + ) + : "—", + }, + { + key: "location", + header: "Lokace", + width: "10%", + mono: true, + render: (row) => row.location?.code || "—", + }, + { + key: "reservation", + header: "Rezervace", + width: "10%", + mono: true, + render: (row) => + row.reservation + ? `ID: ${row.reservation.id} (${Number(row.reservation.remaining_qty)} ks)` + : "—", + }, + { + key: "notes", + header: "Poznámka", + width: "6%", + render: (row) => row.notes || "—", + }, + ]; + return ( -
+ {/* Header */} -
- - - - - -
-

- {iss.issue_number || "Nová výdejka"} -

- {iss.project && ( -

- {iss.project.project_number} – {iss.project.name} -

- )} -
- - {STATUS_LABEL[iss.status] ?? iss.status} - -
- {canOperate && ( -
- {iss.status === "DRAFT" && ( - <> - - - + + {canOperate && iss.status === "DRAFT" && ( + <> + + + + + )} + {canOperate && iss.status === "CONFIRMED" && ( + - - )} - {iss.status === "CONFIRMED" && ( - - )} -
- )} + + )} +
+ } + /> - {/* Header info */} + {/* Basic info */} -
-

Základní údaje

-
-
- -
- {iss.issue_number || "—"} -
-
- -
- {iss.project ? ( - - {iss.project.project_number} – {iss.project.name} - - ) : ( - "—" - )} -
-
- -
- {iss.issued_by_user - ? `${iss.issued_by_user.first_name} ${iss.issued_by_user.last_name}` - : "—"} -
-
-
-
- -
{formatDate(iss.created_at)}
-
-
+ + + Základní údaje + + + + + Číslo dokladu + + + {iss.issue_number || "—"} + + + + + Projekt + + {iss.project ? ( + + {iss.project.project_number} – {iss.project.name} + + ) : ( + + )} + + + + Vydal + + + {iss.issued_by_user + ? `${iss.issued_by_user.first_name} ${iss.issued_by_user.last_name}` + : "—"} + + + + + Vytvořeno + + + {formatDate(iss.created_at)} + + {iss.notes && ( - -
{iss.notes}
-
+ + + Poznámky + + + {iss.notes} + + )} -
-
+ +
{/* Lines table */} -
-

Položky

- {items.length === 0 ? ( -
Žádné řádky
- ) : ( -
- - - - - - - - - - - - - - - {items.map((item) => ( - - - - - - - - - - - ))} - -
PoložkaŠaržeMnožstvíCena/ksCelkemLokaceRezervacePoznámka
- {item.item?.name || `ID: ${item.item_id}`} - - {item.batch - ? `${formatDate(item.batch.received_at)} – ${formatCurrency(Number(item.batch.unit_price), "CZK")}` - : "—"} - {Number(item.quantity)} - {item.batch - ? formatCurrency(Number(item.batch.unit_price), "CZK") - : "—"} - - {item.batch - ? formatCurrency( - Number(item.quantity) * - Number(item.batch.unit_price), - "CZK", - ) - : "—"} - - {item.location?.code || "—"} - - {item.reservation - ? `ID: ${item.reservation.id} (${Number(item.reservation.remaining_qty)} ks)` - : "—"} - {item.notes || "—"}
-
- )} -
+ + + Položky + + + columns={itemColumns} + rows={items} + rowKey={(row) => row.id} + empty={} + /> +
- {/* Cancel confirmation modal */} - setCancelConfirm(false)} onConfirm={handleCancel} @@ -352,6 +413,6 @@ export default function WarehouseIssueDetail() { confirmVariant="danger" loading={cancelling} /> -
+ ); }