fix(uat): dashboard snapshots current-state, pulse-chip gate, phone display, chip width
All checks were successful
Build & Push Docker Images / lint (push) Successful in 2m54s
Build & Push Docker Images / build-and-push (push) Successful in 8m10s

- pipeline funnel: count active interests by current stage (drop created_at
  window) — backfill had collapsed it to early stages (UAT 2026-06-03)
- pipeline value tile: render current-state (don't thread the date range)
- deal pulse chip: gate on the pulse_enabled master toggle (default ON) —
  was rendering even when admin turned it off; useFeatureFlag gains a
  default arg + the feature-flag endpoint a ?default= param (default-ON safe)
- contact phone display: show international format + country flag (E164),
  not the bare national format that hid the country
- berths: remove the dead row-density toggle; widen "Under offer to" chip on
  desktop so client names aren't truncated

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-03 18:27:56 +02:00
parent 39c19b2340
commit 2a7f922a01
8 changed files with 59 additions and 48 deletions

View File

@@ -102,9 +102,16 @@ export async function computePipelineFunnel(
): Promise<PipelineFunnelData> {
const { from, to } = rangeToBounds(range);
// The pipeline funnel is a CURRENT-STATE snapshot: it shows the live
// distribution of active interests across stages, NOT a created-in-range
// cohort. We deliberately do NOT filter the stage counts by createdAt —
// doing so dropped older late-stage deals (reservation/contract) out of
// shorter windows once real origination dates were backfilled, collapsing
// the funnel to the early stages (UAT 2026-06-03). The selected date range
// still scopes the `lost` leakage block below.
//
// Stage counts EXCLUDE lost/cancelled outcomes - those never become
// conversions, so polluting the funnel with them gives meaningless math.
// Lost is reported separately in the `lost` block.
const stageRows = await db
.select({ stage: interests.pipelineStage, count: sql<number>`count(*)::int` })
.from(interests)
@@ -112,7 +119,6 @@ export async function computePipelineFunnel(
and(
eq(interests.portId, portId),
isNull(interests.archivedAt),
between(interests.createdAt, from, to),
sql`(${interests.outcome} IS NULL OR ${interests.outcome} = 'won')`,
),
)