From 1163407440b9a1690fb6c7708414439f0526fb7d Mon Sep 17 00:00:00 2001 From: BOHA Date: Sun, 7 Jun 2026 08:01:17 +0200 Subject: [PATCH] feat(mui): migrate WarehouseReceiptDetail onto MUI kit Co-Authored-By: Claude Opus 4.8 (1M context) --- src/admin/pages/WarehouseReceiptDetail.tsx | 610 ++++++++++++--------- 1 file changed, 340 insertions(+), 270 deletions(-) diff --git a/src/admin/pages/WarehouseReceiptDetail.tsx b/src/admin/pages/WarehouseReceiptDetail.tsx index 2086dbf..a37bc73 100644 --- a/src/admin/pages/WarehouseReceiptDetail.tsx +++ b/src/admin/pages/WarehouseReceiptDetail.tsx @@ -1,24 +1,41 @@ 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 IconButton from "@mui/material/IconButton"; 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 { warehouseReceiptDetailOptions, type WarehouseReceipt, + type WarehouseReceiptItem, + type WarehouseReceiptAttachment, } 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 = { @@ -33,6 +50,35 @@ function formatFileSize(bytes: number): string { return `${(bytes / (1024 * 1024)).toFixed(1)} MB`; } +const BackIcon = ( + + + +); + +const TrashIcon = ( + + + + +); + export default function WarehouseReceiptDetail() { const { id } = useParams(); const alert = useAlert(); @@ -122,44 +168,30 @@ export default function WarehouseReceiptDetail() { const cancelling = cancelMutation.isPending; if (isPending) { - return ( -
-
-
- ); + return ; } if (error || !receipt) { return ( -
-
-
- + - - - - -
-
-
-
-
-

Doklad nebyl nalezen.

-
-
-
-
+ Zpět + + } + /> + + + + ); } @@ -167,272 +199,310 @@ export default function WarehouseReceiptDetail() { const items = r.items ?? []; const attachments = r.attachments ?? []; + const itemColumns: DataColumn[] = [ + { + key: "item", + header: "Položka", + width: "25%", + bold: true, + render: (row) => row.item?.name || `ID: ${row.item_id}`, + }, + { + key: "quantity", + header: "Množství", + width: "12%", + mono: true, + render: (row) => String(Number(row.quantity)), + }, + { + key: "unit_price", + header: "Cena/ks", + width: "16%", + mono: true, + render: (row) => formatCurrency(Number(row.unit_price), "CZK"), + }, + { + key: "total", + header: "Celkem", + width: "16%", + mono: true, + bold: true, + render: (row) => + formatCurrency(Number(row.quantity) * Number(row.unit_price), "CZK"), + }, + { + key: "location", + header: "Lokace", + width: "16%", + mono: true, + render: (row) => row.location?.code || "—", + }, + { + key: "notes", + header: "Poznámka", + width: "15%", + render: (row) => row.notes || "—", + }, + ]; + + const attachmentColumns: DataColumn[] = [ + { + key: "file_name", + header: "Název souboru", + width: "45%", + bold: true, + render: (att) => ( + + {att.file_name} + + ), + }, + { + key: "file_size", + header: "Velikost", + width: "15%", + mono: true, + render: (att) => formatFileSize(att.file_size), + }, + { + key: "created_at", + header: "Datum", + width: "20%", + mono: true, + render: (att) => formatDate(att.created_at), + }, + { + key: "actions", + header: "Akce", + width: "20%", + render: (att) => + r.status === "DRAFT" && canOperate ? ( + handleDeleteAttachment(att.id)} + title="Smazat přílohu" + aria-label="Smazat přílohu" + color="error" + > + {TrashIcon} + + ) : null, + }, + ]; + return ( -
+ {/* Header */} -
- - - - - -
-

- {r.receipt_number || "Nový doklad"} -

- {r.supplier?.name && ( -

{r.supplier.name}

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

Základní údaje

-
-
- -
- {r.receipt_number || "—"} -
-
- -
- {r.supplier?.name || "—"} -
-
-
-
- -
- {r.delivery_note_number || "—"} -
-
- -
- {formatDate(r.delivery_note_date)} -
-
-
-
- -
- {r.received_by_user - ? `${r.received_by_user.first_name} ${r.received_by_user.last_name}` - : "—"} -
-
- -
{formatDate(r.created_at)}
-
-
+ + + Základní údaje + + + + + Číslo dokladu + + + {r.receipt_number || "—"} + + + + + Dodavatel + + + {r.supplier?.name || "—"} + + + + + Číslo dodacího listu + + + {r.delivery_note_number || "—"} + + + + + Datum dodacího listu + + + {formatDate(r.delivery_note_date)} + + + + + Přijal + + + {r.received_by_user + ? `${r.received_by_user.first_name} ${r.received_by_user.last_name}` + : "—"} + + + + + Vytvořeno + + + {formatDate(r.created_at)} + + {r.notes && ( - -
{r.notes}
-
+ + + Poznámky + + + {r.notes} + + )} -
-
+ +
{/* Lines table */} -
-

Položky

- {items.length === 0 ? ( -
Žádné řádky
- ) : ( -
- - - - - - - - - - - - - {items.map((item) => ( - - - - - - - - - ))} - -
PoložkaMnožstvíCena/ksCelkemLokacePoznámka
- {item.item?.name || `ID: ${item.item_id}`} - {Number(item.quantity)} - {formatCurrency(Number(item.unit_price), "CZK")} - - {formatCurrency( - Number(item.quantity) * Number(item.unit_price), - "CZK", - )} - - {item.location?.code || "—"} - {item.notes || "—"}
-
- )} -
+ + + Položky + + + columns={itemColumns} + rows={items} + rowKey={(row) => row.id} + empty={} + /> +
{/* Attachments */} -
-

Přílohy

- {attachments.length === 0 ? ( -
Žádné přílohy
- ) : ( -
- - - - - - - - - - - {attachments.map((att) => ( - - - - - - - ))} - -
Název souboruVelikostDatumAkce
- - {att.file_name} - - - {formatFileSize(att.file_size)} - - {formatDate(att.created_at)} - -
- {r.status === "DRAFT" && canOperate && ( - - )} -
-
-
- )} -
+ + + Přílohy + + + columns={attachmentColumns} + rows={attachments} + rowKey={(att) => att.id} + empty={} + /> +
- {/* Cancel confirmation modal */} - setCancelConfirm(false)} onConfirm={handleCancel} @@ -442,6 +512,6 @@ export default function WarehouseReceiptDetail() { confirmVariant="danger" loading={cancelling} /> -
+ ); }