# Profile Quota Display Feature

**Date**: 2025-11-26  
**Module**: `profile`  
**Status**: Production Ready

---

## Implementation Summary

| Component | File | Lines | Notes |
|-----------|------|-------|-------|
| QuotaDetailCard | `apps/web/src/modules/profile/components/QuotaDetailCard.vue` | 480 | Plan info, status badge, progress bars, upgrade CTA |
| useQuotaInfo | `apps/web/src/modules/profile/composables/useQuotaInfo.ts` | 98 | Fetches subscription summary, auto-refresh 5 min, retry |
| ProfilePage.web | `apps/web/src/modules/profile/pages/ProfilePage.web.vue` | Modified | Quota tab with loading/error states and retry |
| ProfilePage.mobile | `apps/web/src/modules/profile/pages/ProfilePage.mobile.vue` | Modified | Same quota tab UX on mobile toggle navigation |
| BillingController | `apps/api/src/modules/billing/billing.controller.ts` | Existing | Exposes `/api/billing/subscription` (+ legacy `/usage`) |
| E2E | `tests/e2e/profile-page.spec.ts` | New | Tab navigation + quota retry happy path |

---

## Feature Description

- Plan header shows tier chip, plan name, subscription status badge, and reset countdown.
- Four quota tracks (plans, AI calls, collaborators, storage) with percentage bars and remaining labels.
- Upgrade CTA appears when any quota dépasse 75% and tier n'est pas `pro`.
- Default limits derived from tier when backend returns `null` quota so the UI never breaks.
- Auto-refresh every 5 minutes (with cleanup) plus a manual "Réessayer" button when the API fails.
- Same experience sur desktop (tabs) et mobile (toggle horizontal).

---

## API Integration

- Endpoint: `GET /api/billing/subscription` → `BillingService.fetchSummary()` → `{ summary }` contenant `plan`, `quota`, `subscription`, et éventuellement `usageInsights` / `recommendations`.
- Fallback `/api/billing/usage` reste disponible mais n'est plus consommé par la page profile.
- `useQuotaInfo.error` alimente l'état d'erreur avec bouton `refetch()` pour relancer l'appel.

---

## Composable Output (`useQuotaInfo`)

- `quotaData`, `tier`, `planName`, `subscription` (normalisés avec valeurs par défaut sûres).
- `usageInsights`, `recommendations` (retransmis quand fournis par le backend).
- `loading`, `error`, `refetch`, `hasQuota`.
- Timer d'auto-refresh démarré au mount et annulé au unmount.

---

## QuotaDetailCard Props

```ts
interface Props {
  quota: UserQuota | null
  tier: PlanTier
  planName?: string
  subscriptionStatus?: string // défaut: 'active'
}
```

- Calcule le libellé de reset via `quota.window.periodEnd` ou fin de mois courante.
- `subscriptionStatus` pilote l'icône/couleur (`active`, `trialing`, `past_due`, `canceled`, `none`).

---

## Quota Types & Calculations

| Type | Source | Metric | Notes |
|------|--------|--------|-------|
| Plans | `quota.usage.plansGenerated` / `limits.plansPerMonth` | Entier | Valeurs par défaut si quota nul: free 3, premium 50, pro 999 |
| AI Calls | `quota.usage.aiCalls` / `limits.aiCallsPerMonth` | Entier | Couleurs changent à 75% / 90% |
| Collaborators | `quota.usage.collaborators` / `limits.collaborators` | Entier / Illimité | 999 affiché "Illimité" |
| Storage | `quota.usage.storageUsedMB` / `limits.storageGB` | GB (2 décimales) | Conversion MB → GB avant le pourcentage |

---

## Visual States

- Couleurs: `accent` (<75%), `warning` (75–89%), `negative` (≥90%).
- Texte "Limite atteinte" quand dépassement.
- CTA upgrade quand une barre ≥75% et tier ≠ `pro`.
- Loading: spinner; Erreur: "Quotas indisponibles" + `Réessayer`.
- Statut: `Abonnement actif` / `Période d'essai` / `Paiement en attente` / `Abonnement annulé`.

---

## Fiabilité & Qualité

- Logs sur succès/erreur avec message clair.
- Auto-refresh encapsulé via `safeOnMounted` / `safeOnUnmounted` pour éviter les timers orphelins.
- `BillingService.fetchSummary` normalise `plan`, `quota` et dates nulles avant exposition à l'UI.

---

## Integration Points

```ts
// ProfilePage.web.vue / ProfilePage.mobile.vue
const {
  quotaData,
  tier,
  planName,
  error,
  loading: quotaLoading,
  refetch,
  usageInsights,
  recommendations,
  subscription
} = useQuotaInfo()
```

```vue
<QuotaDetailCard
  v-if="!quotaLoading && !error"
  :quota="quotaData"
  :tier="tier"
  :plan-name="planName"
  :subscription-status="subscription?.status"
  @upgrade="handleUpgradeClick"
/>
<q-btn v-else flat dense color="accent" label="Réessayer" icon="refresh" @click="refetch" />
```

---

## Tests

- `tests/e2e/profile-page.spec.ts` :
  - Navigation entre onglets desktop/mobile (Stats, Badges, Quotas, Apparence...).
  - Force un `500` sur `/api/billing/subscription`, affiche "Réessayer", puis recharge avec succès après clic.

---

## Performance & Accessibilité

- Un appel réseau par cycle d'auto-refresh (5 minutes).
- Carte quota chargée en lazy via `defineAsyncComponent` pour alléger le bundle initial.
- Libellés textuels accompagnent les couleurs; boutons upgrade/retry accessibles clavier.

---

## Future Enhancements

- Afficher `usageInsights` et `recommendations` dans l'onglet quota.
- Ajouter un historique d'usage et des alertes proches des limites.
- Relier le CTA upgrade à une sélection de plan pré-remplie.
