correction des bugue front end

This commit is contained in:
Emma781227
2026-08-20 21:49:36 +02:00
parent e895325254
commit 2cf399d6d0
16 changed files with 70 additions and 65 deletions

View File

@@ -20,7 +20,7 @@ export default function Footer() {
{/* Partie principale */} {/* Partie principale */}
<div className="max-w-7xl mx-auto px-6 py-10 grid grid-cols-2 md:grid-cols-4 gap-8"> <div className="max-w-7xl mx-auto px-6 py-10 grid grid-cols-1 sm:grid-cols-2 md:grid-cols-4 gap-8">
{/* Logo */} {/* Logo */}
@@ -185,7 +185,7 @@ export default function Footer() {
01 84 80 20 34 01 84 80 20 34
</a> </a>
<a href="mailto:contact@thetiptop.fr" className="inline-block mt-3 font-medium hover:text-teal-300"> <a href="mailto:contact@thetiptop.fr" className="inline-block mt-3 font-medium break-all hover:text-teal-300">
contact@thetiptop.fr contact@thetiptop.fr
</a> </a>

View File

@@ -9,7 +9,7 @@ export default function Header() {
const navigate = useNavigate() const navigate = useNavigate()
const { user, logout } = useAuth() const { user, logout } = useAuth()
const isLoggedIn = !!user const isLoggedIn = !!user
const logoContent = <img src={logo} alt="Logo de Thé Tip Top" className="h-10 sm:h-12 w-auto" /> const logoContent = <img src={logo} alt="Logo de Thé Tip Top" className="h-7 sm:h-8 md:h-9 lg:h-12 w-auto" />
const handleLogout = () => { const handleLogout = () => {
logout() logout()
@@ -40,12 +40,12 @@ export default function Header() {
)} )}
{/* Nav desktop */} {/* Nav desktop */}
<nav className="hidden md:flex items-center gap-6"> <nav className="hidden md:flex items-center gap-4 lg:gap-6">
{navLinks.map((link) => ( {navLinks.map((link) => (
<Link <Link
key={link.to} key={link.to}
to={link.to} to={link.to}
className={`font-medium transition-colors ${ className={`font-medium whitespace-nowrap transition-colors ${
pathname === link.to ? 'text-[#006B6B]' : 'text-gray-700 hover:text-[#006B6B]' pathname === link.to ? 'text-[#006B6B]' : 'text-gray-700 hover:text-[#006B6B]'
}`} }`}
> >
@@ -59,21 +59,21 @@ export default function Header() {
<div className="w-8 h-8 rounded-full bg-[#006B6B] flex items-center justify-center text-white text-xs font-bold"> <div className="w-8 h-8 rounded-full bg-[#006B6B] flex items-center justify-center text-white text-xs font-bold">
{initials} {initials}
</div> </div>
<span>{user.firstname}</span> <span className="whitespace-nowrap">{user.firstname}</span>
</Link> </Link>
<button <button
onClick={handleLogout} onClick={handleLogout}
className="text-sm text-gray-400 hover:text-red-500 transition-colors font-medium" className="text-sm text-gray-500 hover:text-red-500 transition-colors font-medium whitespace-nowrap"
> >
Déconnexion Déconnexion
</button> </button>
</div> </div>
) : ( ) : (
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Link to="/connexion" className="bg-[#006B6B] text-white px-4 py-2 rounded-lg hover:bg-[#005a5a] transition-colors text-sm"> <Link to="/connexion" className="bg-[#006B6B] border border-transparent text-white px-4 py-2 rounded-lg hover:bg-[#005a5a] transition-colors text-sm whitespace-nowrap">
Connexion Connexion
</Link> </Link>
<Link to="/inscription" className="border border-[#006B6B] text-[#006B6B] px-4 py-2 rounded-lg hover:bg-[#006B6B] hover:text-white transition-colors text-sm"> <Link to="/inscription" className="border border-[#006B6B] text-[#006B6B] px-4 py-2 rounded-lg hover:bg-[#006B6B] hover:text-white transition-colors text-sm whitespace-nowrap">
Inscription Inscription
</Link> </Link>
</div> </div>

View File

@@ -6,6 +6,7 @@ export default function UserNav({ active }) {
key: 'code', key: 'code',
to: '/saisir-code-unique', to: '/saisir-code-unique',
label: 'Saisir un code', label: 'Saisir un code',
shortLabel: 'Code',
icon: ( icon: (
<svg className="w-4 h-4" fill="none" stroke="currentColor" strokeWidth={2} viewBox="0 0 24 24"> <svg className="w-4 h-4" fill="none" stroke="currentColor" strokeWidth={2} viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" d="M15 5v2m0 4v2m0 4v2M5 5a2 2 0 00-2 2v3a2 2 0 110 4v3a2 2 0 002 2h14a2 2 0 002-2v-3a2 2 0 110-4V7a2 2 0 00-2-2H5z" /> <path strokeLinecap="round" strokeLinejoin="round" d="M15 5v2m0 4v2m0 4v2M5 5a2 2 0 00-2 2v3a2 2 0 110 4v3a2 2 0 002 2h14a2 2 0 002-2v-3a2 2 0 110-4V7a2 2 0 00-2-2H5z" />
@@ -16,6 +17,7 @@ export default function UserNav({ active }) {
key: 'gains', key: 'gains',
to: '/mes-gains', to: '/mes-gains',
label: 'Mes gains', label: 'Mes gains',
shortLabel: 'Mes gains',
icon: ( icon: (
<svg className="w-4 h-4" fill="none" stroke="currentColor" strokeWidth={2} viewBox="0 0 24 24"> <svg className="w-4 h-4" fill="none" stroke="currentColor" strokeWidth={2} viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" d="M20 12V22H4V12M22 7H2v5h20V7zM12 22V7M12 7H7.5a2.5 2.5 0 010-5C11 2 12 7 12 7zM12 7h4.5a2.5 2.5 0 000-5C13 2 12 7 12 7z" /> <path strokeLinecap="round" strokeLinejoin="round" d="M20 12V22H4V12M22 7H2v5h20V7zM12 22V7M12 7H7.5a2.5 2.5 0 010-5C11 2 12 7 12 7zM12 7h4.5a2.5 2.5 0 000-5C13 2 12 7 12 7z" />
@@ -26,6 +28,7 @@ export default function UserNav({ active }) {
key: 'profile', key: 'profile',
to: '/profile', to: '/profile',
label: 'Profil', label: 'Profil',
shortLabel: 'Profil',
icon: ( icon: (
<svg className="w-4 h-4" fill="none" stroke="currentColor" strokeWidth={2} viewBox="0 0 24 24"> <svg className="w-4 h-4" fill="none" stroke="currentColor" strokeWidth={2} viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" /> <path strokeLinecap="round" strokeLinejoin="round" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" />
@@ -43,12 +46,12 @@ export default function UserNav({ active }) {
className={`flex-1 flex items-center justify-center gap-1.5 py-3 text-xs sm:text-sm font-medium transition-colors border-b-2 ${ className={`flex-1 flex items-center justify-center gap-1.5 py-3 text-xs sm:text-sm font-medium transition-colors border-b-2 ${
active === tab.key active === tab.key
? 'text-[#006B6B] border-[#006B6B]' ? 'text-[#006B6B] border-[#006B6B]'
: 'text-gray-400 border-transparent hover:text-gray-600' : 'text-gray-500 border-transparent hover:text-gray-600'
}`} }`}
> >
{tab.icon} {tab.icon}
<span className="hidden sm:inline">{tab.label}</span> <span className="hidden sm:inline">{tab.label}</span>
<span className="sm:hidden">{tab.label.split(' ')[0]}</span> <span className="sm:hidden whitespace-nowrap">{tab.shortLabel}</span>
</Link> </Link>
))} ))}
</div> </div>

View File

@@ -1,3 +1,5 @@
/* eslint-disable react-refresh/only-export-components */
import { createContext, useContext, useState } from 'react' import { createContext, useContext, useState } from 'react'
const AuthContext = createContext(null) const AuthContext = createContext(null)

View File

@@ -8,7 +8,7 @@ function StatCard({ label, value, sub }) {
<div className="bg-white rounded-xl shadow p-4 text-center"> <div className="bg-white rounded-xl shadow p-4 text-center">
<p className="text-2xl sm:text-3xl font-bold text-[#006B6B]">{value ?? '—'}</p> <p className="text-2xl sm:text-3xl font-bold text-[#006B6B]">{value ?? '—'}</p>
<p className="text-xs sm:text-sm text-gray-500 mt-1">{label}</p> <p className="text-xs sm:text-sm text-gray-500 mt-1">{label}</p>
{sub && <p className="text-xs text-gray-400 mt-0.5">{sub}</p>} {sub && <p className="text-xs text-gray-500 mt-0.5">{sub}</p>}
</div> </div>
) )
} }
@@ -145,6 +145,9 @@ export default function Admin() {
const csv = [header, ...rows] const csv = [header, ...rows]
.map((row) => row.map((cell) => `"${String(cell).replace(/"/g, '""')}"`).join(';')) .map((row) => row.map((cell) => `"${String(cell).replace(/"/g, '""')}"`).join(';'))
.join('\n') .join('\n')
// Le BOM en tete du fichier est indispensable : sans lui, Excel ouvre le
// CSV en ANSI et casse tous les accents. Ne pas le supprimer.
// eslint-disable-next-line no-irregular-whitespace
const blob = new Blob([`${csv}`], { type: 'text/csv;charset=utf-8;' }) const blob = new Blob([`${csv}`], { type: 'text/csv;charset=utf-8;' })
const url = URL.createObjectURL(blob) const url = URL.createObjectURL(blob)
const link = document.createElement('a') const link = document.createElement('a')
@@ -196,7 +199,7 @@ export default function Admin() {
if (loading) return ( if (loading) return (
<div className="min-h-screen bg-gray-50 flex items-center justify-center"> <div className="min-h-screen bg-gray-50 flex items-center justify-center">
<p className="text-gray-400">Chargement...</p> <p className="text-gray-500">Chargement...</p>
</div> </div>
) )
@@ -264,7 +267,7 @@ export default function Admin() {
</button> </button>
</form> </form>
<p className="text-xs text-gray-400 mt-2"> <p className="text-xs text-gray-500 mt-2">
Les participations durent 30 jours, puis 30 jours supplémentaires sont laissés pour retirer les lots. Les participations durent 30 jours, puis 30 jours supplémentaires sont laissés pour retirer les lots.
</p> </p>
@@ -393,7 +396,7 @@ export default function Admin() {
<tbody> <tbody>
{emailingContacts.length === 0 && ( {emailingContacts.length === 0 && (
<tr> <tr>
<td colSpan={3} className="py-6 text-center text-gray-400 text-sm"> <td colSpan={3} className="py-6 text-center text-gray-500 text-sm">
Aucun contact n'a accepté l'emailing pour le moment Aucun contact n'a accepté l'emailing pour le moment
</td> </td>
</tr> </tr>
@@ -428,7 +431,7 @@ export default function Admin() {
onChange={(e) => setTicketCode(e.target.value.toUpperCase())} onChange={(e) => setTicketCode(e.target.value.toUpperCase())}
placeholder="Code ticket (10 caractères)" placeholder="Code ticket (10 caractères)"
maxLength={10} maxLength={10}
className="flex-1 border border-gray-200 rounded-lg px-4 py-2.5 text-sm font-mono uppercase tracking-widest focus:outline-none focus:ring-2 focus:ring-[#006B6B] focus:border-[#006B6B]" className="flex-1 min-w-0 border border-gray-200 rounded-lg px-4 py-2.5 text-sm font-mono uppercase tracking-widest focus:outline-none focus:ring-2 focus:ring-[#006B6B] focus:border-[#006B6B]"
/> />
<button <button
type="submit" type="submit"
@@ -457,7 +460,7 @@ export default function Admin() {
<div className="px-4 py-3 flex items-start justify-between gap-3 border-b border-gray-100"> <div className="px-4 py-3 flex items-start justify-between gap-3 border-b border-gray-100">
<div> <div>
<p className="font-semibold text-gray-900 text-sm">{ticketResult.lot.name}</p> <p className="font-semibold text-gray-900 text-sm">{ticketResult.lot.name}</p>
<p className="text-gray-400 text-xs mt-0.5">{ticketResult.lot.description}</p> <p className="text-gray-500 text-xs mt-0.5">{ticketResult.lot.description}</p>
{ticketResult.lot.value && <p className="text-[#006B6B] text-xs font-semibold mt-1">{ticketResult.lot.value} €</p>} {ticketResult.lot.value && <p className="text-[#006B6B] text-xs font-semibold mt-1">{ticketResult.lot.value} €</p>}
</div> </div>
<span className={`flex-shrink-0 text-xs font-semibold px-2.5 py-1 rounded-full ${ <span className={`flex-shrink-0 text-xs font-semibold px-2.5 py-1 rounded-full ${
@@ -527,7 +530,7 @@ export default function Admin() {
</div> </div>
</div> </div>
{winner?.winner?.createdAt && ( {winner?.winner?.createdAt && (
<p className="text-xs text-gray-400 text-right"> <p className="text-xs text-gray-500 text-right">
Tirage effectué le {formatDate(winner.winner.createdAt)} Tirage effectué le {formatDate(winner.winner.createdAt)}
</p> </p>
)} )}
@@ -572,7 +575,7 @@ export default function Admin() {
{/* Liste participants */} {/* Liste participants */}
<div className="bg-white rounded-xl shadow p-4 sm:p-6"> <div className="bg-white rounded-xl shadow p-4 sm:p-6">
<h2 className="text-base sm:text-lg font-bold text-gray-800 mb-4"> <h2 className="text-base sm:text-lg font-bold text-gray-800 mb-4">
Participants <span className="text-gray-400 font-normal text-sm">({users.length})</span> Participants <span className="text-gray-500 font-normal text-sm">({users.length})</span>
</h2> </h2>
<div className="overflow-x-auto -mx-4 sm:mx-0"> <div className="overflow-x-auto -mx-4 sm:mx-0">
<table className="w-full text-sm min-w-[400px]"> <table className="w-full text-sm min-w-[400px]">
@@ -586,7 +589,7 @@ export default function Admin() {
<tbody> <tbody>
{users.length === 0 && ( {users.length === 0 && (
<tr> <tr>
<td colSpan={3} className="py-6 text-center text-gray-400 text-sm"> <td colSpan={3} className="py-6 text-center text-gray-500 text-sm">
Aucun participant pour le moment Aucun participant pour le moment
</td> </td>
</tr> </tr>

View File

@@ -72,7 +72,7 @@ export default function Connexion() {
onChange={handleChange} onChange={handleChange}
required required
placeholder="Votre email" placeholder="Votre email"
className="w-full border border-gray-200 rounded-lg px-4 py-3 text-sm text-gray-700 placeholder-gray-300 focus:outline-none focus:ring-1 focus:ring-[#006B6B] focus:border-[#006B6B]" className="w-full border border-gray-200 rounded-lg px-4 py-3 text-sm text-gray-700 placeholder-gray-500 focus:outline-none focus:ring-1 focus:ring-[#006B6B] focus:border-[#006B6B]"
/> />
</div> </div>
@@ -89,12 +89,12 @@ export default function Connexion() {
onChange={handleChange} onChange={handleChange}
required required
placeholder="Votre mot de passe" placeholder="Votre mot de passe"
className="w-full border border-gray-200 rounded-lg px-4 py-3 pr-12 text-sm text-gray-700 placeholder-gray-300 focus:outline-none focus:ring-1 focus:ring-[#006B6B] focus:border-[#006B6B]" className="w-full border border-gray-200 rounded-lg px-4 py-3 pr-12 text-sm text-gray-700 placeholder-gray-500 focus:outline-none focus:ring-1 focus:ring-[#006B6B] focus:border-[#006B6B]"
/> />
<button <button
type="button" type="button"
onClick={() => setShowPassword(!showPassword)} onClick={() => setShowPassword(!showPassword)}
className="absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600" className="absolute right-3 top-1/2 -translate-y-1/2 text-gray-500 hover:text-gray-600"
aria-label="Afficher/masquer le mot de passe" aria-label="Afficher/masquer le mot de passe"
> >
<div className="w-6 h-6 rounded-full border-2 border-gray-400 flex items-center justify-center"> <div className="w-6 h-6 rounded-full border-2 border-gray-400 flex items-center justify-center">
@@ -105,7 +105,7 @@ export default function Connexion() {
</button> </button>
</div> </div>
<div className="text-right mt-1"> <div className="text-right mt-1">
<button type="button" className="text-xs text-gray-400 hover:text-[#006B6B] hover:underline"> <button type="button" className="text-xs text-gray-500 hover:text-[#006B6B] hover:underline">
Mot de passe oublié ? Mot de passe oublié ?
</button> </button>
</div> </div>
@@ -144,7 +144,7 @@ export default function Connexion() {
type="button" type="button"
disabled disabled
title="Connexion Facebook bientôt disponible" title="Connexion Facebook bientôt disponible"
className="flex items-center justify-center gap-2 border border-gray-200 rounded-lg py-3 text-sm text-gray-400 cursor-not-allowed opacity-60" className="flex items-center justify-center gap-2 border border-gray-200 rounded-lg py-3 text-sm text-gray-500 cursor-not-allowed opacity-60"
> >
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" aria-hidden="true">
<circle cx="12" cy="12" r="12" fill="#1877F2" /> <circle cx="12" cy="12" r="12" fill="#1877F2" />

View File

@@ -31,7 +31,7 @@ export default function Contact() {
</section> </section>
{/* Image */} {/* Image */}
<section className="rounded-2xl shadow overflow-hidden h-64 sm:h-80 md:h-117 md:self-start"> <section className="rounded-2xl shadow overflow-hidden h-64 sm:h-80 md:h-[468px] md:self-start">
<img <img
src={imgContact} src={imgContact}
alt="Une personne savourant un thé" alt="Une personne savourant un thé"

View File

@@ -84,7 +84,7 @@ export default function DefinirMotDePasse() {
required required
minLength={8} minLength={8}
placeholder="8 caractères minimum" placeholder="8 caractères minimum"
className="w-full border border-gray-200 rounded-lg px-4 py-3 text-sm text-gray-700 placeholder-gray-300 focus:outline-none focus:ring-1 focus:ring-[#006B6B] focus:border-[#006B6B]" className="w-full border border-gray-200 rounded-lg px-4 py-3 text-sm text-gray-700 placeholder-gray-500 focus:outline-none focus:ring-1 focus:ring-[#006B6B] focus:border-[#006B6B]"
/> />
</div> </div>
@@ -100,7 +100,7 @@ export default function DefinirMotDePasse() {
onChange={handleChange} onChange={handleChange}
required required
placeholder="Saisissez-le à nouveau" placeholder="Saisissez-le à nouveau"
className="w-full border border-gray-200 rounded-lg px-4 py-3 text-sm text-gray-700 placeholder-gray-300 focus:outline-none focus:ring-1 focus:ring-[#006B6B] focus:border-[#006B6B]" className="w-full border border-gray-200 rounded-lg px-4 py-3 text-sm text-gray-700 placeholder-gray-500 focus:outline-none focus:ring-1 focus:ring-[#006B6B] focus:border-[#006B6B]"
/> />
</div> </div>
@@ -109,7 +109,7 @@ export default function DefinirMotDePasse() {
type="checkbox" type="checkbox"
checked={showPassword} checked={showPassword}
onChange={(e) => setShowPassword(e.target.checked)} onChange={(e) => setShowPassword(e.target.checked)}
className="w-4 h-4 accent-[#006B6B]" className="w-5 h-5 accent-[#006B6B]"
/> />
<span className="text-xs text-gray-500">Afficher les mots de passe</span> <span className="text-xs text-gray-500">Afficher les mots de passe</span>
</label> </label>

View File

@@ -94,7 +94,7 @@ export default function Employe() {
required required
placeholder="Code ticket (10 caractères)" placeholder="Code ticket (10 caractères)"
maxLength={10} maxLength={10}
className="flex-1 border border-gray-300 rounded-lg px-4 py-3 text-sm font-mono uppercase tracking-widest focus:outline-none focus:ring-2 focus:ring-[#006B6B] focus:border-[#006B6B]" className="flex-1 min-w-0 border border-gray-300 rounded-lg px-4 py-3 text-sm font-mono uppercase tracking-widest focus:outline-none focus:ring-2 focus:ring-[#006B6B] focus:border-[#006B6B]"
/> />
<button <button
type="submit" type="submit"
@@ -142,7 +142,7 @@ export default function Employe() {
{/* Infos client */} {/* Infos client */}
<div className="px-5 py-4 space-y-2 border-b border-gray-100"> <div className="px-5 py-4 space-y-2 border-b border-gray-100">
<p className="text-xs text-gray-400 font-medium uppercase tracking-wider mb-2">Client</p> <p className="text-xs text-gray-500 font-medium uppercase tracking-wider mb-2">Client</p>
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<div className="w-9 h-9 rounded-full bg-[#006B6B] flex items-center justify-center text-white text-sm font-bold flex-shrink-0"> <div className="w-9 h-9 rounded-full bg-[#006B6B] flex items-center justify-center text-white text-sm font-bold flex-shrink-0">
{(result.client.firstname?.[0] ?? '?').toUpperCase()}{(result.client.lastname?.[0] ?? '?').toUpperCase()} {(result.client.firstname?.[0] ?? '?').toUpperCase()}{(result.client.lastname?.[0] ?? '?').toUpperCase()}
@@ -158,7 +158,7 @@ export default function Employe() {
{/* Infos ticket */} {/* Infos ticket */}
<div className="px-5 py-4 space-y-1 border-b border-gray-100"> <div className="px-5 py-4 space-y-1 border-b border-gray-100">
<p className="text-xs text-gray-400 font-medium uppercase tracking-wider mb-2">Ticket</p> <p className="text-xs text-gray-500 font-medium uppercase tracking-wider mb-2">Ticket</p>
<p className="text-sm text-gray-700"> <p className="text-sm text-gray-700">
<span className="font-medium">Code :</span>{' '} <span className="font-medium">Code :</span>{' '}
<span className="font-mono">{result.ticket.code}</span> <span className="font-mono">{result.ticket.code}</span>

View File

@@ -154,7 +154,7 @@ export default function Inscription() {
</button> </button>
</form> </form>
<p className="text-center text-xs text-gray-400 mt-6"> <p className="text-center text-xs text-gray-500 mt-6">
Le code expire dans 15 minutes.{' '} Le code expire dans 15 minutes.{' '}
<button <button
type="button" type="button"
@@ -186,19 +186,19 @@ export default function Inscription() {
<div> <div>
<label htmlFor="reg-email" className="block text-sm font-medium text-gray-800 mb-1">Adresse email <span className="text-gray-800">*</span></label> <label htmlFor="reg-email" className="block text-sm font-medium text-gray-800 mb-1">Adresse email <span className="text-gray-800">*</span></label>
<input type="email" id="reg-email" name="email" value={form.email} onChange={handleChange} required placeholder="Votre email" <input type="email" id="reg-email" name="email" value={form.email} onChange={handleChange} required placeholder="Votre email"
className="w-full border border-gray-200 rounded-lg px-4 py-3 text-sm text-gray-700 placeholder-gray-300 focus:outline-none focus:ring-1 focus:ring-[#006B6B] focus:border-[#006B6B]" /> className="w-full border border-gray-200 rounded-lg px-4 py-3 text-sm text-gray-700 placeholder-gray-500 focus:outline-none focus:ring-1 focus:ring-[#006B6B] focus:border-[#006B6B]" />
</div> </div>
<div> <div>
<label htmlFor="reg-lastName" className="block text-sm font-medium text-gray-800 mb-1">Nom <span className="text-gray-800">*</span></label> <label htmlFor="reg-lastName" className="block text-sm font-medium text-gray-800 mb-1">Nom <span className="text-gray-800">*</span></label>
<input type="text" id="reg-lastName" name="lastName" value={form.lastName} onChange={handleChange} required placeholder="Votre nom" <input type="text" id="reg-lastName" name="lastName" value={form.lastName} onChange={handleChange} required placeholder="Votre nom"
className="w-full border border-gray-200 rounded-lg px-4 py-3 text-sm text-gray-700 placeholder-gray-300 focus:outline-none focus:ring-1 focus:ring-[#006B6B] focus:border-[#006B6B]" /> className="w-full border border-gray-200 rounded-lg px-4 py-3 text-sm text-gray-700 placeholder-gray-500 focus:outline-none focus:ring-1 focus:ring-[#006B6B] focus:border-[#006B6B]" />
</div> </div>
<div> <div>
<label htmlFor="reg-firstName" className="block text-sm font-medium text-gray-800 mb-1">Prénom <span className="text-gray-800">*</span></label> <label htmlFor="reg-firstName" className="block text-sm font-medium text-gray-800 mb-1">Prénom <span className="text-gray-800">*</span></label>
<input type="text" id="reg-firstName" name="firstName" value={form.firstName} onChange={handleChange} required placeholder="Votre prénom" <input type="text" id="reg-firstName" name="firstName" value={form.firstName} onChange={handleChange} required placeholder="Votre prénom"
className="w-full border border-gray-200 rounded-lg px-4 py-3 text-sm text-gray-700 placeholder-gray-300 focus:outline-none focus:ring-1 focus:ring-[#006B6B] focus:border-[#006B6B]" /> className="w-full border border-gray-200 rounded-lg px-4 py-3 text-sm text-gray-700 placeholder-gray-500 focus:outline-none focus:ring-1 focus:ring-[#006B6B] focus:border-[#006B6B]" />
</div> </div>
<div> <div>
@@ -222,9 +222,9 @@ export default function Inscription() {
<label htmlFor="reg-password" className="block text-sm font-medium text-gray-800 mb-1">Mot de passe <span className="text-gray-800">*</span></label> <label htmlFor="reg-password" className="block text-sm font-medium text-gray-800 mb-1">Mot de passe <span className="text-gray-800">*</span></label>
<div className="relative"> <div className="relative">
<input type={showPassword ? 'text' : 'password'} id="reg-password" name="password" value={form.password} onChange={handleChange} required placeholder="Votre mot de passe" <input type={showPassword ? 'text' : 'password'} id="reg-password" name="password" value={form.password} onChange={handleChange} required placeholder="Votre mot de passe"
className="w-full border border-gray-200 rounded-lg px-4 py-3 pr-12 text-sm text-gray-700 placeholder-gray-300 focus:outline-none focus:ring-1 focus:ring-[#006B6B] focus:border-[#006B6B]" /> className="w-full border border-gray-200 rounded-lg px-4 py-3 pr-12 text-sm text-gray-700 placeholder-gray-500 focus:outline-none focus:ring-1 focus:ring-[#006B6B] focus:border-[#006B6B]" />
<button type="button" onClick={() => setShowPassword(!showPassword)} <button type="button" onClick={() => setShowPassword(!showPassword)}
className="absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600" aria-label="Afficher/masquer"> className="absolute right-3 top-1/2 -translate-y-1/2 text-gray-500 hover:text-gray-600" aria-label="Afficher/masquer">
<div className="w-6 h-6 rounded-full border-2 border-gray-400 flex items-center justify-center"> <div className="w-6 h-6 rounded-full border-2 border-gray-400 flex items-center justify-center">
{showPassword && <div className="w-1.5 h-1.5 rounded-full bg-gray-400" />} {showPassword && <div className="w-1.5 h-1.5 rounded-full bg-gray-400" />}
</div> </div>
@@ -234,7 +234,7 @@ export default function Inscription() {
<label className="flex items-start gap-3 cursor-pointer"> <label className="flex items-start gap-3 cursor-pointer">
<input type="checkbox" checked={acceptedTerms} onChange={(e) => setAcceptedTerms(e.target.checked)} required <input type="checkbox" checked={acceptedTerms} onChange={(e) => setAcceptedTerms(e.target.checked)} required
className="mt-0.5 w-4 h-4 accent-[#006B6B] flex-shrink-0" /> className="mt-0.5 w-5 h-5 accent-[#006B6B] flex-shrink-0" />
<span className="text-xs text-gray-500 leading-relaxed"> <span className="text-xs text-gray-500 leading-relaxed">
J'accepte les{' '} J'accepte les{' '}
<Link to="/cgu" className="text-[#006B6B] hover:underline font-medium">conditions d'utilisation</Link>{' '} <Link to="/cgu" className="text-[#006B6B] hover:underline font-medium">conditions d'utilisation</Link>{' '}
@@ -246,10 +246,10 @@ export default function Inscription() {
<label className="flex items-start gap-3 cursor-pointer"> <label className="flex items-start gap-3 cursor-pointer">
<input type="checkbox" name="marketingOptIn" checked={marketingOptIn} <input type="checkbox" name="marketingOptIn" checked={marketingOptIn}
onChange={(e) => setMarketingOptIn(e.target.checked)} onChange={(e) => setMarketingOptIn(e.target.checked)}
className="mt-0.5 w-4 h-4 accent-[#006B6B] flex-shrink-0" /> className="mt-0.5 w-5 h-5 accent-[#006B6B] flex-shrink-0" />
<span className="text-xs text-gray-500 leading-relaxed"> <span className="text-xs text-gray-500 leading-relaxed">
J'accepte de recevoir les offres et actualités de Thé Tip Top par email. J'accepte de recevoir les offres et actualités de Thé Tip Top par email.
<span className="block text-gray-400 mt-0.5"> <span className="block text-gray-500 mt-0.5">
Facultatif — vous pouvez vous désinscrire à tout moment. Facultatif — vous pouvez vous désinscrire à tout moment.
</span> </span>
</span> </span>
@@ -277,7 +277,7 @@ export default function Inscription() {
</svg> </svg>
Google Google
</button> </button>
<button type="button" disabled title="Inscription Facebook bientôt disponible" className="flex items-center justify-center gap-2 border border-gray-200 rounded-lg py-3 text-sm text-gray-400 cursor-not-allowed opacity-60"> <button type="button" disabled title="Inscription Facebook bientôt disponible" className="flex items-center justify-center gap-2 border border-gray-200 rounded-lg py-3 text-sm text-gray-500 cursor-not-allowed opacity-60">
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" aria-hidden="true">
<circle cx="12" cy="12" r="12" fill="#1877F2" /> <circle cx="12" cy="12" r="12" fill="#1877F2" />
<path fill="#FFFFFF" d="M13.5 21v-8h2.7l.4-3h-3.1V8.1c0-.9.3-1.6 1.7-1.6h1.8V3.8c-.3 0-1.4-.1-2.6-.1-2.6 0-4.4 1.6-4.4 4.5V10H7.2v3H10v8h3.5z" /> <path fill="#FFFFFF" d="M13.5 21v-8h2.7l.4-3h-3.1V8.1c0-.9.3-1.6 1.7-1.6h1.8V3.8c-.3 0-1.4-.1-2.6-.1-2.6 0-4.4 1.6-4.4 4.5V10H7.2v3H10v8h3.5z" />

View File

@@ -70,7 +70,7 @@ export default function MesGains() {
</button> </button>
</div> </div>
{loading && <p className="text-center text-gray-400 text-sm mt-8">Chargement…</p>} {loading && <p className="text-center text-gray-500 text-sm mt-8">Chargement…</p>}
{error && ( {error && (
<div className="px-4 py-3 rounded-lg bg-red-50 border border-red-200 text-red-600 text-sm"> <div className="px-4 py-3 rounded-lg bg-red-50 border border-red-200 text-red-600 text-sm">
@@ -80,8 +80,8 @@ export default function MesGains() {
{!loading && !error && gains.length === 0 && ( {!loading && !error && gains.length === 0 && (
<div className="text-center mt-12"> <div className="text-center mt-12">
<p className="text-gray-400 text-sm">Aucun gain pour le moment.</p> <p className="text-gray-500 text-sm">Aucun gain pour le moment.</p>
<p className="text-gray-400 text-xs mt-1">Saisissez un code pour participer !</p> <p className="text-gray-500 text-xs mt-1">Saisissez un code pour participer !</p>
</div> </div>
)} )}
@@ -105,7 +105,7 @@ export default function MesGains() {
</div> </div>
<p className="text-gray-500 text-xs mt-1 leading-relaxed">{gain.description}</p> <p className="text-gray-500 text-xs mt-1 leading-relaxed">{gain.description}</p>
{gain.value && ( {gain.value && (
<p className="text-gray-400 text-xs mt-0.5">Valeur : {gain.value} €</p> <p className="text-gray-500 text-xs mt-0.5">Valeur : {gain.value} €</p>
)} )}
<div className="flex items-center gap-2 mt-2 flex-wrap"> <div className="flex items-center gap-2 mt-2 flex-wrap">
<p className="text-[#006B6B] text-xs">Gagné le {formatDate(gain.wonAt)}</p> <p className="text-[#006B6B] text-xs">Gagné le {formatDate(gain.wonAt)}</p>
@@ -115,7 +115,7 @@ export default function MesGains() {
</span> </span>
)} )}
</div> </div>
<p className="text-gray-400 text-[10px] mt-1"> <p className="text-gray-500 text-[10px] mt-1">
Code utilisé :{' '} Code utilisé :{' '}
<span className="font-mono tracking-widest text-gray-600">{gain.ticketCode}</span> <span className="font-mono tracking-widest text-gray-600">{gain.ticketCode}</span>
</p> </p>

View File

@@ -10,7 +10,7 @@ export default function NotFound() {
Page introuvable Page introuvable
</h1> </h1>
<p className="text-gray-400 text-sm sm:text-base max-w-xs mb-8"> <p className="text-gray-500 text-sm sm:text-base max-w-xs mb-8">
La page que vous recherchez n'existe pas ou a été déplacée. La page que vous recherchez n'existe pas ou a été déplacée.
</p> </p>

View File

@@ -9,7 +9,7 @@ export default function Perdu() {
<div className="min-h-screen bg-gray-50 flex flex-col items-center justify-center px-8 max-w-sm mx-auto text-center"> <div className="min-h-screen bg-gray-50 flex flex-col items-center justify-center px-8 max-w-sm mx-auto text-center">
<div className="w-20 h-20 bg-gray-200 rounded-full flex items-center justify-center mb-6"> <div className="w-20 h-20 bg-gray-200 rounded-full flex items-center justify-center mb-6">
<svg className="w-10 h-10 text-gray-400" fill="none" stroke="currentColor" strokeWidth={2} viewBox="0 0 24 24"> <svg className="w-10 h-10 text-gray-500" fill="none" stroke="currentColor" strokeWidth={2} viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" d="M9.172 16.172a4 4 0 015.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /> <path strokeLinecap="round" strokeLinejoin="round" d="M9.172 16.172a4 4 0 015.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg> </svg>
</div> </div>
@@ -22,7 +22,7 @@ export default function Perdu() {
{message || 'Ce code est invalide ou a déjà été utilisé.'} {message || 'Ce code est invalide ou a déjà été utilisé.'}
</p> </p>
<p className="text-gray-400 text-xs mb-8"> <p className="text-gray-500 text-xs mb-8">
Vérifiez le code présent sur votre ticket et réessayez. Vérifiez le code présent sur votre ticket et réessayez.
</p> </p>

View File

@@ -102,19 +102,19 @@ export default function Profile() {
{/* Infos du compte (lecture seule) */} {/* Infos du compte (lecture seule) */}
<div className="space-y-4 mb-8"> <div className="space-y-4 mb-8">
<div> <div>
<label className="block text-xs font-medium text-gray-400 uppercase tracking-wider mb-1">Adresse email</label> <label className="block text-xs font-medium text-gray-500 uppercase tracking-wider mb-1">Adresse email</label>
<div className="w-full border border-gray-100 rounded-lg px-4 py-3 text-sm text-gray-400 bg-gray-50 cursor-not-allowed select-none"> <div className="w-full border border-gray-100 rounded-lg px-4 py-3 text-sm text-gray-500 bg-gray-50 cursor-not-allowed select-none">
{user.email || '—'} {user.email || '—'}
</div> </div>
</div> </div>
<div> <div>
<label className="block text-xs font-medium text-gray-400 uppercase tracking-wider mb-1">Nom</label> <label className="block text-xs font-medium text-gray-500 uppercase tracking-wider mb-1">Nom</label>
<div className="w-full border border-gray-100 rounded-lg px-4 py-3 text-sm text-gray-500 bg-gray-50"> <div className="w-full border border-gray-100 rounded-lg px-4 py-3 text-sm text-gray-500 bg-gray-50">
{user.lastname || '—'} {user.lastname || '—'}
</div> </div>
</div> </div>
<div> <div>
<label className="block text-xs font-medium text-gray-400 uppercase tracking-wider mb-1">Prénom</label> <label className="block text-xs font-medium text-gray-500 uppercase tracking-wider mb-1">Prénom</label>
<div className="w-full border border-gray-100 rounded-lg px-4 py-3 text-sm text-gray-500 bg-gray-50"> <div className="w-full border border-gray-100 rounded-lg px-4 py-3 text-sm text-gray-500 bg-gray-50">
{user.firstname || '—'} {user.firstname || '—'}
</div> </div>
@@ -189,12 +189,12 @@ export default function Profile() {
onChange={handlePwChange} onChange={handlePwChange}
required required
placeholder="••••••••" placeholder="••••••••"
className="w-full border border-gray-200 rounded-lg px-4 py-3 pr-11 text-sm text-gray-700 placeholder-gray-300 focus:outline-none focus:ring-1 focus:ring-[#006B6B] focus:border-[#006B6B]" className="w-full border border-gray-200 rounded-lg px-4 py-3 pr-11 text-sm text-gray-700 placeholder-gray-500 focus:outline-none focus:ring-1 focus:ring-[#006B6B] focus:border-[#006B6B]"
/> />
<button <button
type="button" type="button"
onClick={() => setShowPw((s) => ({ ...s, [key]: !s[key] }))} onClick={() => setShowPw((s) => ({ ...s, [key]: !s[key] }))}
className="absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600" className="absolute right-3 top-1/2 -translate-y-1/2 text-gray-500 hover:text-gray-600"
aria-label="Afficher/masquer" aria-label="Afficher/masquer"
> >
<EyeIcon visible={showPw[key]} /> <EyeIcon visible={showPw[key]} />

View File

@@ -17,7 +17,6 @@ export default function SaisirCodeUnique() {
const [code, setCode] = useState('') const [code, setCode] = useState('')
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false)
const [gain, setGain] = useState(null) const [gain, setGain] = useState(null)
const [claim, setClaim] = useState(null)
const [wonAt, setWonAt] = useState(null) const [wonAt, setWonAt] = useState(null)
const [showDetail, setShowDetail] = useState(false) const [showDetail, setShowDetail] = useState(false)
@@ -27,7 +26,6 @@ export default function SaisirCodeUnique() {
try { try {
const data = await participateApi(code.trim().toUpperCase()) const data = await participateApi(code.trim().toUpperCase())
setGain(data.gain) setGain(data.gain)
setClaim(data.claim)
setWonAt(new Date()) setWonAt(new Date())
} catch (err) { } catch (err) {
if (!handleAuthError(err)) { if (!handleAuthError(err)) {
@@ -40,7 +38,6 @@ export default function SaisirCodeUnique() {
const handleClose = () => { const handleClose = () => {
setGain(null) setGain(null)
setClaim(null)
setWonAt(null) setWonAt(null)
setShowDetail(false) setShowDetail(false)
setCode('') setCode('')
@@ -65,7 +62,7 @@ export default function SaisirCodeUnique() {
placeholder="Votre code" placeholder="Votre code"
maxLength={10} maxLength={10}
required required
className="w-full border border-gray-200 rounded-lg px-4 py-3 text-sm text-gray-700 placeholder-gray-300 bg-white focus:outline-none focus:ring-1 focus:ring-[#006B6B] focus:border-[#006B6B]" className="w-full border border-gray-200 rounded-lg px-4 py-3 text-sm text-gray-700 placeholder-gray-500 bg-white focus:outline-none focus:ring-1 focus:ring-[#006B6B] focus:border-[#006B6B]"
/> />
<button <button
type="submit" type="submit"
@@ -147,28 +144,28 @@ export default function SaisirCodeUnique() {
{/* Valeur */} {/* Valeur */}
{gain.value && ( {gain.value && (
<div className="flex items-center justify-between py-2 border-b border-gray-100"> <div className="flex items-center justify-between py-2 border-b border-gray-100">
<span className="text-xs text-gray-400 uppercase tracking-wider">Valeur estimée</span> <span className="text-xs text-gray-500 uppercase tracking-wider">Valeur estimée</span>
<span className="text-sm font-semibold text-[#006B6B]">{gain.value} €</span> <span className="text-sm font-semibold text-[#006B6B]">{gain.value} €</span>
</div> </div>
)} )}
{/* Code utilisé */} {/* Code utilisé */}
<div className="flex items-center justify-between py-2 border-b border-gray-100"> <div className="flex items-center justify-between py-2 border-b border-gray-100">
<span className="text-xs text-gray-400 uppercase tracking-wider">Code utilisé</span> <span className="text-xs text-gray-500 uppercase tracking-wider">Code utilisé</span>
<span className="font-mono text-sm tracking-widest text-gray-700">{code}</span> <span className="font-mono text-sm tracking-widest text-gray-700">{code}</span>
</div> </div>
{/* Date & heure */} {/* Date & heure */}
{wonAt && ( {wonAt && (
<div className="flex items-center justify-between py-2 border-b border-gray-100"> <div className="flex items-center justify-between py-2 border-b border-gray-100">
<span className="text-xs text-gray-400 uppercase tracking-wider">Obtenu le</span> <span className="text-xs text-gray-500 uppercase tracking-wider">Obtenu le</span>
<span className="text-sm text-gray-700">{formatDateTime(wonAt)}</span> <span className="text-sm text-gray-700">{formatDateTime(wonAt)}</span>
</div> </div>
)} )}
{/* Statut */} {/* Statut */}
<div className="flex items-center justify-between py-2"> <div className="flex items-center justify-between py-2">
<span className="text-xs text-gray-400 uppercase tracking-wider">Statut</span> <span className="text-xs text-gray-500 uppercase tracking-wider">Statut</span>
<span className="text-xs font-semibold px-2.5 py-1 rounded-full bg-yellow-100 text-yellow-700"> <span className="text-xs font-semibold px-2.5 py-1 rounded-full bg-yellow-100 text-yellow-700">
En attente de remise En attente de remise
</span> </span>

View File

@@ -88,7 +88,7 @@ export default function Sitemap() {
<p className="text-sm font-medium text-gray-800 group-hover:text-[#006B6B] transition-colors"> <p className="text-sm font-medium text-gray-800 group-hover:text-[#006B6B] transition-colors">
{link.label} {link.label}
</p> </p>
<p className="text-xs text-gray-400 mt-0.5">{link.desc}</p> <p className="text-xs text-gray-500 mt-0.5">{link.desc}</p>
</div> </div>
</Link> </Link>
</li> </li>