69 lines
2.6 KiB
TypeScript
69 lines
2.6 KiB
TypeScript
'use client';
|
|
|
|
import {VStack} from '@astryxdesign/core/Layout';
|
|
import {Grid} from '@astryxdesign/core/Grid';
|
|
import {PanelCard} from '@/shared/components/patterns/PanelCard';
|
|
import {SkeletonCardGrid} from '@/shared/components/patterns/LoadingState';
|
|
import {EmptyPanel} from '@/shared/components/patterns/EmptyPanel';
|
|
import {ActivityCard} from './ActivityCard';
|
|
import {AttributionNote} from './AttributionNote';
|
|
import {ACTIVITY_GROUPS} from '@/features/dashboard/services/activityService';
|
|
import type {ActivityMetric} from '@/features/dashboard/types/intelligence';
|
|
import type {Resource} from '@/shared/hooks/useResource';
|
|
|
|
/**
|
|
* The complete ecosystem, grouped by the question each group answers.
|
|
*
|
|
* Ten activities laid out as one flat grid is a list of features. Split three
|
|
* ways it becomes a diagnosis: engagement says what customers are doing,
|
|
* growth says what is bringing people in, commerce says whether either turned
|
|
* into business. A merchant with a flat conversion number and a rising
|
|
* engagement number knows which of the three to look at.
|
|
*
|
|
* One resource, three panels. The panels share a single fetch, so the groups
|
|
* can never disagree about a total, and a group with nothing in it renders its
|
|
* own empty state rather than leaving a headed card with a void under it.
|
|
*/
|
|
export function ActivityGroups({
|
|
resource,
|
|
}: {
|
|
resource: Resource<ActivityMetric[]>;
|
|
}) {
|
|
const basis = resource.data?.[0]?.impact.attribution ?? 'estimated';
|
|
|
|
return (
|
|
<VStack gap={5}>
|
|
{ACTIVITY_GROUPS.map((group) => (
|
|
<PanelCard
|
|
key={group.id}
|
|
title={group.label}
|
|
subtitle={group.question}
|
|
actions={<AttributionNote basis={basis} />}
|
|
resource={resource}
|
|
loading={<SkeletonCardGrid count={4} height={128} minWidth={220} />}
|
|
empty={
|
|
<EmptyPanel
|
|
icon="activityVisit"
|
|
title={`No ${group.label.toLowerCase()} activity`}
|
|
description="Activities appear here once customers start taking part."
|
|
/>
|
|
}
|
|
>
|
|
{(metrics) => (
|
|
<Grid columns={{minWidth: 220, repeat: 'fit'}} gap={3}>
|
|
{metrics
|
|
.filter((m) => m.group === group.id)
|
|
.map((m) => (
|
|
// `catalogue` — this is the management view, so each card
|
|
// adds what the dashboard summary has no room for: status,
|
|
// LYTs issued, and the full impact chain.
|
|
<ActivityCard key={m.id} metric={m} variant="catalogue" />
|
|
))}
|
|
</Grid>
|
|
)}
|
|
</PanelCard>
|
|
))}
|
|
</VStack>
|
|
);
|
|
}
|