feat(07-02): wire agentDownloadUrl to doc detail page, add signedAt to dashboard and client profile

- document detail page: import createAgentDownloadToken, generate agentDownloadUrl server-side for
  signed docs (signedFilePath present), pass agentDownloadUrl and signedAt props to PreparePanel
- DocumentsTable: add signedAt to DocumentRow type, add Date Signed column header and cell
- dashboard page: add signedAt to db select so allRows includes signed date for Signed documents
- ClientProfileClient: add signedAt to local DocumentRow type (fixes type mismatch with DocumentsTable)
- clients/[id]/page: add signedAt to query select to satisfy updated DocumentRow type
This commit is contained in:
Chandler Copeland
2026-03-21 10:39:03 -06:00
parent b823ae5c58
commit 68d94a779f
5 changed files with 35 additions and 7 deletions

View File

@@ -20,6 +20,7 @@ export default async function ClientProfilePage({
name: documents.name, name: documents.name,
status: documents.status, status: documents.status,
sentAt: documents.sentAt, sentAt: documents.sentAt,
signedAt: documents.signedAt,
clientId: documents.clientId, clientId: documents.clientId,
clientName: sql<string>`${clients.name}`, clientName: sql<string>`${clients.name}`,
}) })

View File

@@ -22,6 +22,7 @@ export default async function DashboardPage({
name: documents.name, name: documents.name,
status: documents.status, status: documents.status,
sentAt: documents.sentAt, sentAt: documents.sentAt,
signedAt: documents.signedAt,
clientName: clients.name, clientName: clients.name,
clientId: documents.clientId, clientId: documents.clientId,
}) })
@@ -38,16 +39,18 @@ export default async function DashboardPage({
return ( return (
<div> <div>
<div className="flex items-center justify-between mb-6"> <div style={{ marginBottom: "1.5rem" }}>
<h1 className="text-[var(--navy)] text-2xl font-semibold"> <h1 style={{ color: "#1B2B4B", fontSize: "1.5rem", fontWeight: 700, marginBottom: "0.25rem" }}>
Welcome back, {firstName} Welcome back, {firstName}
</h1> </h1>
<p style={{ color: "#6B7280", fontSize: "0.875rem" }}>All documents across your clients</p>
</div> </div>
<div className="flex items-center gap-4 mb-6">
<span className="text-sm text-gray-600">Filter by status:</span> <div style={{ backgroundColor: "white", borderRadius: "1rem", boxShadow: "0 1px 4px rgba(0,0,0,0.07)", overflow: "hidden" }}>
<div style={{ display: "flex", alignItems: "center", gap: "0.75rem", padding: "1rem 1.5rem", borderBottom: "1px solid #F3F4F6" }}>
<span style={{ fontSize: "0.875rem", color: "#6B7280" }}>Filter by status:</span>
<DashboardFilters currentStatus={status} /> <DashboardFilters currentStatus={status} />
</div> </div>
<div className="bg-white rounded-xl shadow-sm overflow-hidden">
<DocumentsTable rows={filteredRows} showClientColumn={true} /> <DocumentsTable rows={filteredRows} showClientColumn={true} />
</div> </div>
</div> </div>

View File

@@ -6,6 +6,7 @@ import { eq } from 'drizzle-orm';
import Link from 'next/link'; import Link from 'next/link';
import { PdfViewerWrapper } from './_components/PdfViewerWrapper'; import { PdfViewerWrapper } from './_components/PdfViewerWrapper';
import { PreparePanel } from './_components/PreparePanel'; import { PreparePanel } from './_components/PreparePanel';
import { createAgentDownloadToken } from '@/lib/signing/token';
export default async function DocumentPage({ export default async function DocumentPage({
params, params,
@@ -29,6 +30,12 @@ export default async function DocumentPage({
if (!doc) redirect('/portal/dashboard'); if (!doc) redirect('/portal/dashboard');
// Generate agent download URL server-side for Signed documents
// Must be done here (server component) — PreparePanel is 'use client' and cannot call createAgentDownloadToken
const agentDownloadUrl = doc.signedFilePath
? `/api/documents/${docId}/download?adt=${await createAgentDownloadToken(docId)}`
: null;
return ( return (
<div className="max-w-5xl mx-auto px-4 py-6"> <div className="max-w-5xl mx-auto px-4 py-6">
<div className="mb-4 flex items-center justify-between"> <div className="mb-4 flex items-center justify-between">
@@ -56,6 +63,8 @@ export default async function DocumentPage({
defaultEmail={docClient?.email ?? ''} defaultEmail={docClient?.email ?? ''}
clientName={docClient?.name ?? ''} clientName={docClient?.name ?? ''}
currentStatus={doc.status} currentStatus={doc.status}
agentDownloadUrl={agentDownloadUrl}
signedAt={doc.signedAt ?? null}
/> />
</div> </div>
</div> </div>

View File

@@ -15,6 +15,7 @@ type DocumentRow = {
clientName: string | null; clientName: string | null;
status: "Draft" | "Sent" | "Viewed" | "Signed"; status: "Draft" | "Sent" | "Viewed" | "Signed";
sentAt: Date | null; sentAt: Date | null;
signedAt: Date | null;
clientId: string; clientId: string;
}; };

View File

@@ -7,6 +7,7 @@ type DocumentRow = {
clientName: string | null; clientName: string | null;
status: "Draft" | "Sent" | "Viewed" | "Signed"; status: "Draft" | "Sent" | "Viewed" | "Signed";
sentAt: Date | null; sentAt: Date | null;
signedAt: Date | null;
clientId: string; clientId: string;
}; };
@@ -39,6 +40,9 @@ export function DocumentsTable({ rows, showClientColumn = true }: Props) {
<th style={{ textAlign: "left", fontSize: "0.75rem", fontWeight: 600, color: "#6B7280", textTransform: "uppercase", letterSpacing: "0.05em", padding: "0.75rem 1.5rem" }}> <th style={{ textAlign: "left", fontSize: "0.75rem", fontWeight: 600, color: "#6B7280", textTransform: "uppercase", letterSpacing: "0.05em", padding: "0.75rem 1.5rem" }}>
Date Sent Date Sent
</th> </th>
<th style={{ textAlign: "left", fontSize: "0.75rem", fontWeight: 600, color: "#6B7280", textTransform: "uppercase", letterSpacing: "0.05em", padding: "0.75rem 1.5rem" }}>
Date Signed
</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@@ -64,6 +68,16 @@ export function DocumentsTable({ rows, showClientColumn = true }: Props) {
? new Date(row.sentAt).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" }) ? new Date(row.sentAt).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" })
: "—"} : "—"}
</td> </td>
<td style={{ padding: "0.875rem 1.5rem", color: "#6B7280" }}>
{row.signedAt
? new Date(row.signedAt).toLocaleDateString("en-US", {
timeZone: "America/Denver",
month: "short",
day: "numeric",
year: "numeric",
})
: "—"}
</td>
</tr> </tr>
))} ))}
</tbody> </tbody>