import type { EventPackageLimits, LimitUsageSummary } from '../services/eventApi'; export type LimitTone = 'neutral' | 'warning' | 'danger'; export type LimitSummaryCard = { id: 'photos' | 'guests'; label: string; state: LimitUsageSummary['state']; tone: LimitTone; used: number; limit: number | null; remaining: number | null; progress: number | null; valueLabel: string; description: string; badgeLabel: string; }; type TranslateFn = (key: string, fallback?: string) => string; function resolveTone(state: LimitUsageSummary['state']): LimitTone { if (state === 'limit_reached') { return 'danger'; } if (state === 'warning') { return 'warning'; } return 'neutral'; } function buildCard( id: 'photos' | 'guests', summary: LimitUsageSummary, t: TranslateFn ): LimitSummaryCard { const labelKey = id === 'photos' ? 'upload.limitSummary.cards.photos.title' : 'upload.limitSummary.cards.guests.title'; const remainingKey = id === 'photos' ? 'upload.limitSummary.cards.photos.remaining' : 'upload.limitSummary.cards.guests.remaining'; const unlimitedKey = id === 'photos' ? 'upload.limitSummary.cards.photos.unlimited' : 'upload.limitSummary.cards.guests.unlimited'; const tone = resolveTone(summary.state); const progress = typeof summary.limit === 'number' && summary.limit > 0 ? Math.min(100, Math.round((summary.used / summary.limit) * 100)) : null; const valueLabel = typeof summary.limit === 'number' && summary.limit > 0 ? `${summary.used.toLocaleString()} / ${summary.limit.toLocaleString()}` : t('upload.limitSummary.badges.unlimited'); const description = summary.state === 'unlimited' ? t(unlimitedKey) : summary.remaining !== null && summary.limit !== null ? t(remainingKey) .replace('{remaining}', `${Math.max(0, summary.remaining)}`) .replace('{limit}', `${summary.limit}`) : valueLabel; const badgeKey = (() => { switch (summary.state) { case 'limit_reached': return 'upload.limitSummary.badges.limit_reached'; case 'warning': return 'upload.limitSummary.badges.warning'; case 'unlimited': return 'upload.limitSummary.badges.unlimited'; default: return 'upload.limitSummary.badges.ok'; } })(); return { id, label: t(labelKey), state: summary.state, tone, used: summary.used, limit: summary.limit, remaining: summary.remaining, progress, valueLabel, description, badgeLabel: t(badgeKey), }; } export function buildLimitSummaries(limits: EventPackageLimits | null | undefined, t: TranslateFn): LimitSummaryCard[] { if (!limits) { return []; } const cards: LimitSummaryCard[] = []; if (limits.photos) { cards.push(buildCard('photos', limits.photos, t)); } if (limits.guests) { cards.push(buildCard('guests', limits.guests, t)); } return cards; }