Ajout fidelite_abo_pret_commande_groupe

This commit is contained in:
Aubert Marvin
2026-05-10 12:44:52 +02:00
parent d1f880cfbb
commit f80dfdcdb5
16 changed files with 1172 additions and 7 deletions
+155
View File
@@ -0,0 +1,155 @@
import { useMemo, useState } from 'react'
import { Link, useParams } from 'react-router-dom'
import { useGroups } from '../context/GroupsContext.jsx'
function formatEUR(n) {
return new Intl.NumberFormat('fr-FR', {
style: 'currency',
currency: 'EUR',
maximumFractionDigits: 2,
}).format(Number(n) || 0)
}
function formatDate(iso) {
try {
return new Intl.DateTimeFormat('fr-FR', {
dateStyle: 'short',
timeStyle: 'short',
}).format(new Date(iso))
} catch {
return iso || '—'
}
}
export default function GroupDetailPage() {
const { groupId } = useParams()
const {
groups,
addGroupOrder,
getOrdersForGroup,
groupTotalEuros,
} = useGroups()
const group = useMemo(
() => groups.find((g) => g.id === String(groupId)),
[groups, groupId],
)
const lines = group ? getOrdersForGroup(group.id) : []
const total = group ? groupTotalEuros(group.id) : 0
const [contributor, setContributor] = useState('')
const [amount, setAmount] = useState('')
const [note, setNote] = useState('')
const [err, setErr] = useState(null)
const [ok, setOk] = useState(null)
function handleSubmit(e) {
e.preventDefault()
setErr(null)
setOk(null)
if (!group) return
try {
addGroupOrder(group.id, {
contributor,
amount,
note,
})
setContributor('')
setAmount('')
setNote('')
setOk('Contribution enregistrée (POST /api/groups/:id/orders en local).')
} catch (ex) {
setErr(ex?.message || 'Impossible denregistrer.')
}
}
if (!group) {
return (
<div className="groupes-page">
<p className="empty-state">Groupe introuvable.</p>
<Link to="/groupes" className="nav-link">
Liste des groupes
</Link>
</div>
)
}
return (
<div className="groupes-page">
<Link to="/groupes" className="nav-link book-detail-back">
Tous les groupes
</Link>
<h2 className="page-title">{group.name}</h2>
<p className="page-lead">
Pool actuel : <strong>{formatEUR(total)}</strong> · id{' '}
<code>{group.id.slice(0, 8)}</code>
</p>
{err ? (
<p className="form-error" role="alert">
{err}
</p>
) : null}
{ok ? <p className="form-notice">{ok}</p> : null}
<section className="order-panel">
<h3 className="panel-title">Participer à la commande groupée</h3>
<form className="review-form" onSubmit={handleSubmit}>
<label>
Pseudo / prénom
<input
value={contributor}
onChange={(e) => setContributor(e.target.value)}
placeholder="Marvin"
/>
</label>
<label>
Montant () optionnel pour la démo
<input
type="number"
min={0}
step="0.5"
value={amount}
onChange={(e) => setAmount(e.target.value)}
placeholder="12.5"
/>
</label>
<label>
Note (ex. titres souhaités)
<textarea
rows={2}
value={note}
onChange={(e) => setNote(e.target.value)}
placeholder="2 romans SF…"
/>
</label>
<button type="submit" className="btn primary">
Envoyer ma participation (POST)
</button>
</form>
</section>
<section className="order-panel">
<h3 className="panel-title">Contributions</h3>
{lines.length === 0 ? (
<p className="empty-state">Personne na encore participé.</p>
) : (
<ul className="reviews-list">
{lines.map((o) => (
<li key={o.id} className="reviews-item">
<p className="reviews-meta">
<strong>{o.contributor}</strong> · {formatDate(o.createdAt)} ·{' '}
{formatEUR(o.amountEuros)}
</p>
{o.note ? (
<p className="reviews-text">{o.note}</p>
) : null}
</li>
))}
</ul>
)}
</section>
</div>
)
}