feat(03-02): add StatusBadge and DocumentsTable shared portal components
- StatusBadge: color-coded pill for Draft=gray, Sent=blue, Viewed=amber, Signed=green - DocumentsTable: reusable table with optional Client column, StatusBadge integration - Date format: toLocaleDateString en-US short month; null sentAt renders as em-dash
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
import { StatusBadge } from "./StatusBadge";
|
||||
|
||||
type DocumentRow = {
|
||||
id: string;
|
||||
name: string;
|
||||
clientName: string | null;
|
||||
status: "Draft" | "Sent" | "Viewed" | "Signed";
|
||||
sentAt: Date | null;
|
||||
clientId: string;
|
||||
};
|
||||
|
||||
type Props = { rows: DocumentRow[]; showClientColumn?: boolean };
|
||||
|
||||
export function DocumentsTable({ rows, showClientColumn = true }: Props) {
|
||||
return (
|
||||
<table className="w-full text-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="text-left text-xs font-medium text-gray-500 uppercase px-4 py-3">
|
||||
Document Name
|
||||
</th>
|
||||
{showClientColumn && (
|
||||
<th className="text-left text-xs font-medium text-gray-500 uppercase px-4 py-3">
|
||||
Client
|
||||
</th>
|
||||
)}
|
||||
<th className="text-left text-xs font-medium text-gray-500 uppercase px-4 py-3">
|
||||
Status
|
||||
</th>
|
||||
<th className="text-left text-xs font-medium text-gray-500 uppercase px-4 py-3">
|
||||
Date Sent
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{rows.map((row) => (
|
||||
<tr key={row.id}>
|
||||
<td className="px-4 py-3 border-t border-gray-100">{row.name}</td>
|
||||
{showClientColumn && (
|
||||
<td className="px-4 py-3 border-t border-gray-100">
|
||||
{row.clientName ?? "—"}
|
||||
</td>
|
||||
)}
|
||||
<td className="px-4 py-3 border-t border-gray-100">
|
||||
<StatusBadge status={row.status} />
|
||||
</td>
|
||||
<td className="px-4 py-3 border-t border-gray-100">
|
||||
{row.sentAt
|
||||
? row.sentAt.toLocaleDateString("en-US", {
|
||||
month: "short",
|
||||
day: "numeric",
|
||||
year: "numeric",
|
||||
})
|
||||
: "—"}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
type DocumentStatus = "Draft" | "Sent" | "Viewed" | "Signed";
|
||||
|
||||
const STATUS_STYLES: Record<DocumentStatus, string> = {
|
||||
Draft: "bg-gray-100 text-gray-600",
|
||||
Sent: "bg-blue-100 text-blue-700",
|
||||
Viewed: "bg-amber-100 text-amber-700",
|
||||
Signed: "bg-green-100 text-green-700",
|
||||
};
|
||||
|
||||
export function StatusBadge({ status }: { status: DocumentStatus }) {
|
||||
return (
|
||||
<span
|
||||
className={`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${STATUS_STYLES[status]}`}
|
||||
>
|
||||
{status}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user