module 6a

This commit is contained in:
2026-07-27 17:48:40 -05:00
parent 6cb13650ed
commit e114490cde
20 changed files with 1875 additions and 116 deletions

View File

@@ -105,6 +105,11 @@ export interface NdaRound {
preferred_businesses_text: string | null;
total_purchase_price: string | null;
down_payment: string | null;
/** Set when the round came in through the NDA inbox. */
dropbox_sign_id: string | null;
signer_name: string | null;
/** A declined round stays SENT — it was never signed. */
declined: boolean;
deals: Deal[];
}
@@ -250,6 +255,53 @@ export interface Today {
counts: TodayCounts;
}
// ------------------------------------------------------------- NDA inbox
export type InboxStatus = 'pending' | 'signed' | 'declined';
export interface InboxRow {
signature_request_id: string;
title: string;
/** The title with the prefix and the signer's name stripped out. */
title_remainder: string;
/** Full ISO timestamp: Dropbox orders by date *and* time. */
created_at: string;
status: InboxStatus;
signer: { name: string; email: string };
/** Full ISO timestamp as well — the second the signature came in. */
signed_at: string | null;
imported: { nda_id: string; buyer_id: string } | null;
known_buyer: { buyer_id: string; company_name: string | null; contact_name: string } | null;
business_suggestions: { id: string; name: string; status: BusinessStatus }[];
}
export type RefreshState = 'idle' | 'running' | string;
export interface Inbox {
requests: InboxRow[];
/** ISO timestamp of the last completed background refresh, null if never. */
last_refresh_at: string | null;
refresh_state: RefreshState;
}
export interface ImportResult {
buyer_id: string;
nda_id: string;
deal_id: string | null;
created: { buyer: boolean; contact: boolean };
status: InboxStatus;
nas_path: string | null;
/** Set when the round was imported but the PDF could not be filed. */
warning: string | null;
}
export interface SyncResult {
checked: number;
signed: number;
declined: number;
failed: number;
warnings: string[];
}
export class ApiError extends Error {
constructor(readonly status: number, message: string) {
super(message);
@@ -352,14 +404,37 @@ export const api = {
business_id: businessId,
path: filePath,
}),
/** Reads the mirrored requests out of the database — never calls Dropbox. */
ndaInbox: (since: string) => request<Inbox>(`/api/nda-inbox?${qs({ since })}`),
/** Starts the background walk; resolves as soon as it is queued. */
refreshInbox: (since: string) =>
post<{ state: RefreshState }>(`/api/nda-inbox/refresh?${qs({ since })}`),
importInbox: (signatureRequestId: string, buyerId?: string, businessId?: string) =>
post<ImportResult>('/api/nda-inbox/import', {
signature_request_id: signatureRequestId,
buyer_id: buyerId,
business_id: businessId,
}),
syncInbox: () => post<SyncResult>('/api/nda-inbox/sync'),
};
/** Same-origin streaming URL of the PDF filed for one NDA round. */
export function ndaFileUrl(ndaId: string): string {
return `/api/ndas/${ndaId}/file`;
}
/** Same-origin streaming URL of one file inside a business directory. */
export function businessFileUrl(id: string, filePath: string): string {
return `/api/businesses/${id}/file?path=${encodeURIComponent(filePath)}`;
}
/** The standalone (unbundled) pdf.js viewer page, pointed at a business file. */
export function viewerUrl(id: string, filePath: string): string {
return `/viewer/index.html?file=${encodeURIComponent(businessFileUrl(id, filePath))}`;
/** The standalone (unbundled) pdf.js viewer page, pointed at any /api/ file URL. */
export function viewerUrlFor(apiPath: string): string {
return `/viewer/index.html?file=${encodeURIComponent(apiPath)}`;
}
/** The viewer, pointed at a business file. */
export function viewerUrl(id: string, filePath: string): string {
return viewerUrlFor(businessFileUrl(id, filePath));
}