feat(ux): P-4.5 inquiry linkage + docs N+1 parallelization

Step 4 (in progress) — first slice of UX features.

P-4.5: inquiry → client linkage now survives the triage conversion.

- inquiry-inbox.tsx adds `?create=1` to the redirect so the new-client
  sheet auto-opens (the existing prefill_* params were already being
  written but the form never opened).
- client-list.tsx reads prefill_name / prefill_email / prefill_phone /
  prefill_source / prefill_inquiry_id from useSearchParams and passes
  them to ClientForm via a typed `prefill` prop.
- ClientForm hydrates the create-flow initial values from the prefill
  AND threads `sourceInquiryId` through to the createClient mutation.
- createClientSchema accepts `sourceInquiryId`; the existing service
  spread already passes it to drizzle's insert.

Net effect: a website inquiry that gets converted now lands as a
client row with `clients.source_inquiry_id` populated. The conversion
funnel-by-source chart (Step 6) can attribute the win back to the
originating inquiry.

Documents tab N+1: `listInflightWorkflowsAggregatedByEntity` previously
walked direct + every company + every yacht + every related client
sequentially. On a busy client (~25 related entities) this was ~50
sequential round-trips with cumulative latency. Replaced with a single
`Promise.all` over the four lookup groups + nested Promise.all over
the per-entity queries within each group. Same query count, but wall-
clock collapses from "sum of every query" to "max single round-trip"
(typically <100ms now vs >1s before).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-14 15:37:23 +02:00
parent e933e32dbd
commit a77b3c670a
5 changed files with 124 additions and 26 deletions

View File

@@ -34,6 +34,10 @@ export const createClientSchema = z.object({
timezone: optionalIanaTimezoneSchema.optional(),
source: z.enum(['website', 'manual', 'referral', 'broker', 'other']).optional(),
sourceDetails: z.string().optional(),
/** When the client was created from a website-inquiry triage, points
* back at the originating `website_submissions.id`. Drives the
* conversion-funnel-by-source chart. Migration 0065 installs the FK. */
sourceInquiryId: z.string().optional(),
tagIds: z.array(z.string()).optional().default([]),
});