From ef4e87f5b8ecb85e77014dc021627e055aebd3a7 Mon Sep 17 00:00:00 2001 From: Amirhossein Khalili Date: Fri, 21 Aug 2026 07:49:04 +0800 Subject: [PATCH] fix: render completed growth reports reliably --- src/lib/components/GrowthInsights.svelte | 23 ++++++++++++++--------- src/lib/components/GrowthInsights.test.ts | 20 ++++++++++++++++++++ src/lib/components/GrowthPage.svelte | 9 +++++++-- 3 files changed, 41 insertions(+), 11 deletions(-) create mode 100644 src/lib/components/GrowthInsights.test.ts diff --git a/src/lib/components/GrowthInsights.svelte b/src/lib/components/GrowthInsights.svelte index c78a8fd..00ea3c2 100644 --- a/src/lib/components/GrowthInsights.svelte +++ b/src/lib/components/GrowthInsights.svelte @@ -25,14 +25,19 @@ peer, terminalScoped = false, }: { - wins?: Win[]; - opportunities?: Opportunity[]; - risks?: Risk[]; - briefs?: Brief[]; + wins?: Win[] | null; + opportunities?: Opportunity[] | null; + risks?: Risk[] | null; + briefs?: Brief[] | null; peer?: Peer | null; terminalScoped?: boolean; } = $props(); + const safeWins = $derived(wins ?? []); + const safeOpportunities = $derived(opportunities ?? []); + const safeRisks = $derived(risks ?? []); + const safeBriefs = $derived(briefs ?? []); + function dateLabel(value: string) { return new Intl.DateTimeFormat('fa-IR-u-ca-persian', { dateStyle: 'medium', @@ -54,7 +59,7 @@ > - {#each opportunities.slice(0, 5) as opportunity, index} + {#each safeOpportunities.slice(0, 5) as opportunity, index}
@@ -79,13 +84,13 @@ - {#if briefs.length} + {#if safeBriefs.length}

پیشنهادهای آماده‌سازی

- {#each briefs as brief} + {#each safeBriefs as brief}

{brief.headline}

@@ -130,7 +135,7 @@ > - {#each wins as win} + {#each safeWins as win}

{win.eventTitleFa}

{dateLabel(win.startDate)}

@@ -155,7 +160,7 @@ > - {#each risks.slice(0, 3) as risk} + {#each safeRisks.slice(0, 3) as risk}
{ + it('renders empty insight states when persisted API arrays are null', () => { + render(GrowthInsights, { + wins: null, + opportunities: null, + risks: null, + briefs: null, + peer: null, + }); + + expect(screen.getByText('در افق فعلی، فرصت رویدادی معناداری پیدا نشد.')).not.toBeNull(); + expect(screen.getByText('هنوز رویداد موفقی با شواهد کافی ثبت نشده است.')).not.toBeNull(); + expect(screen.getByText('افت معناداری برای هشدار پیدا نشد.')).not.toBeNull(); + }); +}); diff --git a/src/lib/components/GrowthPage.svelte b/src/lib/components/GrowthPage.svelte index 36d7d0f..c3af831 100644 --- a/src/lib/components/GrowthPage.svelte +++ b/src/lib/components/GrowthPage.svelte @@ -147,6 +147,7 @@ source.close(); schedulePoll(); }; + schedulePoll(); } function isGrowthReport(value: unknown): value is GrowthReport { @@ -165,9 +166,13 @@ if (polling) clearTimeout(polling); polling = setTimeout(async () => { if (!report) return; + const reportId = report.reportId; try { - report = await api.growthReport(report.reportId); - if (['QUEUED', 'ANALYZING', 'GENERATING'].includes(report.status)) schedulePoll(); + const next = await api.growthReport(reportId); + if (report?.reportId !== reportId) return; + report = next; + if (['QUEUED', 'ANALYZING', 'GENERATING'].includes(next.status)) schedulePoll(); + else closeRealtime(); } catch { schedulePoll(); }