From e2f1fa6d50a9b56eb6ed7311647cd5ef921b29a0 Mon Sep 17 00:00:00 2001 From: "Claude (auto-fix)" Date: Fri, 19 Jun 2026 04:30:08 +0530 Subject: [PATCH] feat(po-detail): show all attachments grouped by type Split the flat document list into two labeled sections: Submission (po-document/* keys) and Delivery Receipt (receipt/* keys). Delivery notes from the Receipt record are also surfaced under that section. Added `receipt` to the PoWithRelations type so the field is available inside the component. Fixes #10 --- App/components/po/po-detail.tsx | 47 ++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/App/components/po/po-detail.tsx b/App/components/po/po-detail.tsx index 21288b0..5885257 100644 --- a/App/components/po/po-detail.tsx +++ b/App/components/po/po-detail.tsx @@ -65,6 +65,7 @@ type PoWithRelations = { sortOrder: number; }[]; documents: { id: string; fileName: string; fileSize: number; storageKey: string; uploadedAt: Date }[]; + receipt: { id: string; storageKey: string; fileName: string; notes: string | null; confirmedAt: Date } | null; actions: { id: string; actionType: string; note: string | null; metadata: import("@prisma/client").Prisma.JsonValue; createdAt: Date; actor: { name: string } }[]; }; @@ -149,9 +150,10 @@ export async function PoDetail({ po, currentUserId, currentRole, readOnly = fals ? "Submitter updated these line items after edits were requested. Previous values shown with strikethrough." : "Line items were amended by manager. Current values shown; original values shown with strikethrough."; - const downloadUrls = await Promise.all( + const downloadUrlList = await Promise.all( po.documents.map((doc) => generateDownloadUrl(doc.storageKey)) ); + const urlByDocId = new Map(po.documents.map((doc, i) => [doc.id, downloadUrlList[i]])); const canConfirmReceipt = (po.status === "PAID_DELIVERED" || po.status === "PARTIALLY_CLOSED" || po.status === "PARTIALLY_PAID") && @@ -399,15 +401,19 @@ export async function PoDetail({ po, currentUserId, currentRole, readOnly = fals )} - {/* Documents */} - {po.documents.length > 0 && ( -
-

Attachments

+ {/* Documents — grouped by type */} + {(() => { + const submissionDocs = po.documents.filter((d) => !d.storageKey.startsWith("receipt/")); + const receiptDocs = po.documents.filter((d) => d.storageKey.startsWith("receipt/")); + const hasDeliverySection = receiptDocs.length > 0 || !!po.receipt?.notes; + if (submissionDocs.length === 0 && !hasDeliverySection) return null; + + const renderDocList = (docs: typeof po.documents) => ( -
- )} + ); + + return ( +
+

Attachments

+
+ {submissionDocs.length > 0 && ( +
+

Submission

+ {renderDocList(submissionDocs)} +
+ )} + {hasDeliverySection && ( +
+

Delivery Receipt

+ {po.receipt?.notes && ( +

“{po.receipt.notes}”

+ )} + {receiptDocs.length > 0 && renderDocList(receiptDocs)} +
+ )} +
+
+ ); + })()} {/* Confirm receipt CTA */} {canConfirmReceipt && (