103 lines
2.9 KiB
React
103 lines
2.9 KiB
React
import { useState } from 'react'
|
||
import { useSubscriptions } from '../context/SubscriptionsContext.jsx'
|
||
|
||
function formatEUR(n) {
|
||
return new Intl.NumberFormat('fr-FR', {
|
||
style: 'currency',
|
||
currency: 'EUR',
|
||
}).format(Number(n) || 0)
|
||
}
|
||
|
||
function formatDate(iso) {
|
||
try {
|
||
return new Intl.DateTimeFormat('fr-FR', {
|
||
dateStyle: 'long',
|
||
}).format(new Date(iso))
|
||
} catch {
|
||
return iso || '—'
|
||
}
|
||
}
|
||
|
||
export default function AbonnementPage() {
|
||
const { plans, subscription, subscribe, cancelSubscription, getPlanLabel } =
|
||
useSubscriptions()
|
||
const [err, setErr] = useState(null)
|
||
const [ok, setOk] = useState(null)
|
||
|
||
function handleSubscribe(planId) {
|
||
setErr(null)
|
||
setOk(null)
|
||
try {
|
||
subscribe(planId)
|
||
setOk('Abonnement pris en compte (POST /api/subscriptions en local).')
|
||
} catch (e) {
|
||
setErr(e?.message || 'Impossible de souscrire.')
|
||
}
|
||
}
|
||
|
||
return (
|
||
<div className="abonnement-page">
|
||
<h2 className="page-title">Abonnement</h2>
|
||
<p className="page-lead">
|
||
Équivalent local de <code>POST /api/subscriptions</code> · stockage{' '}
|
||
<code>librairie-subscriptions</code> · pas de paiement réel, c’est une
|
||
démo.
|
||
</p>
|
||
|
||
{err ? (
|
||
<p className="form-error" role="alert">
|
||
{err}
|
||
</p>
|
||
) : null}
|
||
{ok ? <p className="form-notice">{ok}</p> : null}
|
||
|
||
{subscription ? (
|
||
<section className="order-panel abo-active">
|
||
<h3 className="panel-title">Abonnement actif</h3>
|
||
<p>
|
||
Formule : <strong>{getPlanLabel(subscription.planId)}</strong>
|
||
</p>
|
||
<p className="book-section-lead">
|
||
Depuis le {formatDate(subscription.subscribedAt)}
|
||
</p>
|
||
<button
|
||
type="button"
|
||
className="btn danger"
|
||
onClick={() => {
|
||
cancelSubscription()
|
||
setOk('Abonnement annulé (local).')
|
||
}}
|
||
>
|
||
Résilier (local)
|
||
</button>
|
||
</section>
|
||
) : null}
|
||
|
||
<section className="order-panel">
|
||
<h3 className="panel-title">Choisir une formule</h3>
|
||
<ul className="abo-plans">
|
||
{plans.map((p) => (
|
||
<li key={p.id} className="abo-plan-card">
|
||
<p className="abo-plan-name">{p.label}</p>
|
||
<p className="abo-plan-price">{formatEUR(p.price)}</p>
|
||
<button
|
||
type="button"
|
||
className="btn primary small"
|
||
onClick={() => handleSubscribe(p.id)}
|
||
disabled={Boolean(subscription)}
|
||
>
|
||
Souscrire (POST)
|
||
</button>
|
||
</li>
|
||
))}
|
||
</ul>
|
||
{subscription ? (
|
||
<p className="book-section-lead">
|
||
Pour changer de formule, résilie d’abord puis reprends une offre.
|
||
</p>
|
||
) : null}
|
||
</section>
|
||
</div>
|
||
)
|
||
}
|