feat(berth-deal-docs): clickable rows open in-page file preview
The Interest Documents tab on the berth detail page listed deal docs read-only with only an "Open" link to the interest detail page — forced reps to navigate away just to see the PDF. Now every row whose backing PDF exists opens the existing FilePreviewDialog inline. - Service: listDealDocumentsForBerth now joins files and returns fileId (COALESCE(signedFileId, fileId) so completed envelopes prefer the signed PDF), fileName, mimeType. Drafts without a blob yet still appear, just non-clickable. - UI: row title area is a button that triggers FilePreviewDialog; Eye affordance on hover. Falls back to a "no file yet" hint when the document has no backing blob. "Open" link stays as the secondary "go to interest" action. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -348,6 +348,13 @@ export interface BerthDealDoc {
|
||||
status: string;
|
||||
createdAt: Date;
|
||||
interestId: string;
|
||||
/** ID of the file blob backing this document (signed PDF if completed,
|
||||
* otherwise the source upload). Null when no file is attached yet
|
||||
* (e.g. a draft envelope before its PDF lands). Drives the in-page
|
||||
* preview affordance — rows without a fileId render as non-clickable. */
|
||||
fileId: string | null;
|
||||
fileName: string | null;
|
||||
mimeType: string | null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -365,6 +372,14 @@ export async function listDealDocumentsForBerth(
|
||||
portId: string,
|
||||
berthId: string,
|
||||
): Promise<BerthDealDoc[]> {
|
||||
// Resolve the preview-worthy file in SQL via COALESCE(signed_file_id,
|
||||
// file_id) so completed envelopes prefer their signed PDF while drafts
|
||||
// fall back to the source upload. LEFT JOIN files so envelopes without
|
||||
// any blob yet (drafts before placement) still appear, just without a
|
||||
// preview affordance.
|
||||
const previewFileId = sql<
|
||||
string | null
|
||||
>`COALESCE(${documents.signedFileId}, ${documents.fileId})`;
|
||||
const rows = await db
|
||||
.select({
|
||||
id: documents.id,
|
||||
@@ -373,10 +388,14 @@ export async function listDealDocumentsForBerth(
|
||||
status: documents.status,
|
||||
createdAt: documents.createdAt,
|
||||
interestId: documents.interestId,
|
||||
fileId: previewFileId,
|
||||
fileName: files.filename,
|
||||
mimeType: files.mimeType,
|
||||
})
|
||||
.from(documents)
|
||||
.innerJoin(interestBerths, eq(interestBerths.interestId, documents.interestId))
|
||||
.innerJoin(interests, eq(interests.id, documents.interestId))
|
||||
.leftJoin(files, and(eq(files.id, previewFileId), eq(files.portId, portId)))
|
||||
.where(
|
||||
and(
|
||||
eq(interestBerths.berthId, berthId),
|
||||
@@ -395,6 +414,9 @@ export async function listDealDocumentsForBerth(
|
||||
status: r.status,
|
||||
createdAt: r.createdAt,
|
||||
interestId: r.interestId,
|
||||
fileId: r.fileId ?? null,
|
||||
fileName: r.fileName ?? null,
|
||||
mimeType: r.mimeType ?? null,
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user