// Shared fetch + derivations for partner MRR from /api/partner/mrr // (platform-api /me/partner/mrr). Like usePartnerTenants, the dashboard, // customers, and billing pages all read this under the 'partner-mrr' key, so // one cached payload serves all of them. This composable also owns the // derivations that were duplicated per page: the per-tenant lookup Map and the // per-currency display totals (amounts are never FX-summed across currencies). // // const { mrr, mrrByTenant, totalsDisplay, refresh } = usePartnerMrr() // // Synchronous (non-async) so `useFetch` runs in the caller's setup context even // when called after another await. Call WITHOUT await. import type { MrrBreakdownRow, MrrResponse } from '~/types/partner' export function usePartnerMrr() { const { data: mrr, refresh, error, pending } = useFetch('/api/partner/mrr', { key: 'partner-mrr', default: () => ({ totals: [], breakdown: [] }), }) // tenantId → its subscription's MRR row, for O(1) per-row lookups in the // customers table without a second fetch. const mrrByTenant = computed(() => { const m = new Map() for (const row of mrr.value?.breakdown ?? []) m.set(row.tenantId, row) return m }) // Per-currency totals in major units (minor / 100), e.g. { DKK: 55_750 }. const totalsDisplay = computed(() => (mrr.value?.totals ?? []).map((t) => ({ currency: t.currency, majorAmount: Math.round(t.monthlyMinor / 100), })), ) // Compact one-line summary, e.g. "55.750 DKK + 1.200 EUR / mo". const totalsLine = computed(() => { const parts = totalsDisplay.value.map( (t) => `${t.majorAmount.toLocaleString('da-DK')} ${t.currency}`, ) if (parts.length === 0) return '0 DKK / mo' return parts.join(' + ') + ' / mo' }) // True when any subscription is custom/Enterprise-priced (renders as // "custom" rather than a misleading 0 in the totals). const hasCustomPriced = computed(() => (mrr.value?.breakdown ?? []).some((b) => b.custom)) return { mrr, mrrByTenant, totalsDisplay, totalsLine, hasCustomPriced, refresh, error, pending } }