108 lines
2.9 KiB
TypeScript
108 lines
2.9 KiB
TypeScript
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;
|
|
}
|