- Replace email verification status with active/inactive status - Add user archiving (soft delete) instead of hard delete - Add search by name/email in user management - Add status filter (active/inactive) in user management - Simplify actions to show only "Détails" button - Add Google Maps with clickable marker on contact page - Update button labels from "Désactiver" to "Supprimer" 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
344 lines
16 KiB
TypeScript
344 lines
16 KiB
TypeScript
'use client';
|
||
|
||
import { useState } from "react";
|
||
import type { Metadata } from "next";
|
||
import Link from "next/link";
|
||
|
||
export default function ContactPage() {
|
||
const [formData, setFormData] = useState({
|
||
fullName: '',
|
||
email: '',
|
||
subject: '',
|
||
message: '',
|
||
acceptPolicy: false,
|
||
});
|
||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||
|
||
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {
|
||
const { name, value } = e.target;
|
||
setFormData(prev => ({ ...prev, [name]: value }));
|
||
};
|
||
|
||
const handleCheckboxChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||
setFormData(prev => ({ ...prev, acceptPolicy: e.target.checked }));
|
||
};
|
||
|
||
const handleSubmit = async (e: React.FormEvent) => {
|
||
e.preventDefault();
|
||
setIsSubmitting(true);
|
||
|
||
try {
|
||
// Appel à l'API backend
|
||
const response = await fetch('http://localhost:4000/api/contact', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
},
|
||
body: JSON.stringify({
|
||
fullName: formData.fullName,
|
||
email: formData.email,
|
||
subject: formData.subject,
|
||
message: formData.message,
|
||
}),
|
||
});
|
||
|
||
const data = await response.json();
|
||
|
||
if (response.ok && data.success) {
|
||
alert('✅ Votre message a été envoyé avec succès ! Nous vous répondrons dans les plus brefs délais.');
|
||
|
||
// Reset form
|
||
setFormData({
|
||
fullName: '',
|
||
email: '',
|
||
subject: '',
|
||
message: '',
|
||
acceptPolicy: false,
|
||
});
|
||
} else {
|
||
alert('❌ ' + (data.message || 'Une erreur est survenue. Veuillez réessayer.'));
|
||
}
|
||
} catch (error) {
|
||
console.error('Erreur lors de l\'envoi du message:', error);
|
||
alert('❌ Une erreur est survenue lors de l\'envoi de votre message. Veuillez réessayer.');
|
||
} finally {
|
||
setIsSubmitting(false);
|
||
}
|
||
};
|
||
|
||
return (
|
||
<div className="min-h-screen bg-gradient-to-br from-[#f5f5f0] via-[#faf9f5] to-[#f5f5f0]">
|
||
{/* Hero Section */}
|
||
<section className="bg-gradient-to-r from-white to-[#faf9f5] py-12 border-b-2 border-[#e5e4dc]">
|
||
<div className="container mx-auto px-4">
|
||
<div className="max-w-4xl mx-auto text-center">
|
||
<h1 className="text-4xl md:text-5xl font-bold text-[#5a5a4e] mb-4">
|
||
Contactez-nous
|
||
</h1>
|
||
<p className="text-lg text-[#8a8a7a]">
|
||
Une question sur le jeu-concours ? Besoin d'aide ? Notre équipe est là pour vous accompagner !
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
{/* Main Content */}
|
||
<section className="py-12">
|
||
<div className="container mx-auto px-4">
|
||
<div className="max-w-6xl mx-auto">
|
||
<div className="grid lg:grid-cols-2 gap-12">
|
||
|
||
{/* Contact Form */}
|
||
<div>
|
||
<div className="bg-white rounded-xl shadow-md p-8 border border-[#e5e4dc]">
|
||
<h2 className="text-2xl font-bold text-[#5a5a4e] mb-6">Envoyez-nous un message</h2>
|
||
|
||
<form onSubmit={handleSubmit} className="space-y-6">
|
||
{/* Nom complet */}
|
||
<div>
|
||
<label htmlFor="fullName" className="block text-sm font-semibold text-[#5a5a4e] mb-2">
|
||
Nom complet <span className="text-red-500">*</span>
|
||
</label>
|
||
<input
|
||
id="fullName"
|
||
name="fullName"
|
||
type="text"
|
||
required
|
||
value={formData.fullName}
|
||
onChange={handleChange}
|
||
placeholder="Votre nom et prénom"
|
||
className="w-full px-4 py-3 border-2 border-[#e5e4dc] rounded-lg focus:outline-none focus:ring-2 focus:ring-[#d4a574] focus:border-[#d4a574]"
|
||
/>
|
||
</div>
|
||
|
||
{/* Email */}
|
||
<div>
|
||
<label htmlFor="email" className="block text-sm font-semibold text-[#5a5a4e] mb-2">
|
||
Email <span className="text-red-500">*</span>
|
||
</label>
|
||
<input
|
||
id="email"
|
||
name="email"
|
||
type="email"
|
||
required
|
||
value={formData.email}
|
||
onChange={handleChange}
|
||
placeholder="votre@email.com"
|
||
className="w-full px-4 py-3 border-2 border-[#e5e4dc] rounded-lg focus:outline-none focus:ring-2 focus:ring-[#d4a574] focus:border-[#d4a574]"
|
||
/>
|
||
</div>
|
||
|
||
{/* Sujet */}
|
||
<div>
|
||
<label htmlFor="subject" className="block text-sm font-semibold text-[#5a5a4e] mb-2">
|
||
Sujet <span className="text-red-500">*</span>
|
||
</label>
|
||
<select
|
||
id="subject"
|
||
name="subject"
|
||
required
|
||
value={formData.subject}
|
||
onChange={handleChange}
|
||
className="w-full px-4 py-3 border-2 border-[#e5e4dc] rounded-lg focus:outline-none focus:ring-2 focus:ring-[#d4a574] focus:border-[#d4a574] bg-white"
|
||
>
|
||
<option value="">Sélectionnez un sujet</option>
|
||
<option value="jeu-concours">Question sur le jeu-concours</option>
|
||
<option value="code">Problème avec mon code</option>
|
||
<option value="lot">Réclamation de lot</option>
|
||
<option value="compte">Gestion de compte</option>
|
||
<option value="autre">Autre demande</option>
|
||
</select>
|
||
</div>
|
||
|
||
{/* Message */}
|
||
<div>
|
||
<label htmlFor="message" className="block text-sm font-semibold text-[#5a5a4e] mb-2">
|
||
Message <span className="text-red-500">*</span>
|
||
</label>
|
||
<textarea
|
||
id="message"
|
||
name="message"
|
||
required
|
||
value={formData.message}
|
||
onChange={handleChange}
|
||
placeholder="Décrivez votre demande en détail..."
|
||
rows={6}
|
||
className="w-full px-4 py-3 border-2 border-[#e5e4dc] rounded-lg focus:outline-none focus:ring-2 focus:ring-[#d4a574] focus:border-[#d4a574] resize-none"
|
||
/>
|
||
</div>
|
||
|
||
{/* Checkbox RGPD */}
|
||
<div className="flex items-start gap-3">
|
||
<input
|
||
id="acceptPolicy"
|
||
name="acceptPolicy"
|
||
type="checkbox"
|
||
required
|
||
checked={formData.acceptPolicy}
|
||
onChange={handleCheckboxChange}
|
||
className="mt-1 w-5 h-5 text-[#d4a574] border-[#e5e4dc] rounded focus:ring-2 focus:ring-[#d4a574]"
|
||
/>
|
||
<label htmlFor="acceptPolicy" className="text-sm text-[#5a5a4e] select-none cursor-pointer">
|
||
J'accepte que mes données soient collectées et traitées conformément à la{' '}
|
||
<Link href="/privacy" className="text-[#d4a574] underline hover:text-[#c4956a]">
|
||
politique de confidentialité
|
||
</Link>{' '}
|
||
<span className="text-red-500">*</span>
|
||
</label>
|
||
</div>
|
||
|
||
{/* Submit Button */}
|
||
<div>
|
||
<button
|
||
type="submit"
|
||
disabled={isSubmitting}
|
||
className="w-full bg-gradient-to-r from-[#d4a574] to-[#c4956a] hover:from-[#e5b685] hover:to-[#d4a574] disabled:from-gray-400 disabled:to-gray-500 text-white font-bold px-8 py-4 rounded-lg transition-all duration-300 shadow-lg hover:shadow-[0_0_20px_rgba(212,165,116,0.6)] hover:scale-105"
|
||
>
|
||
{isSubmitting ? "Envoi en cours..." : "Envoyer le message"}
|
||
</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Contact Info */}
|
||
<div className="space-y-6">
|
||
|
||
{/* Nos coordonnées */}
|
||
<div className="bg-white rounded-xl shadow-md p-8 border border-[#e5e4dc]">
|
||
<h2 className="text-2xl font-bold text-[#5a5a4e] mb-6">Nos coordonnées</h2>
|
||
|
||
<div className="space-y-6">
|
||
{/* Siège social */}
|
||
<div className="flex items-start gap-4">
|
||
<div className="w-12 h-12 bg-gradient-to-br from-[#d4a574] to-[#c4956a] rounded-full flex items-center justify-center text-xl shadow-md flex-shrink-0">📍</div>
|
||
<div>
|
||
<h3 className="font-semibold text-[#5a5a4e] mb-1">Siège social</h3>
|
||
<a
|
||
href="https://www.google.com/maps/search/?api=1&query=18+Avenue+Thiers+06000+Nice+France"
|
||
target="_blank"
|
||
rel="noopener noreferrer"
|
||
className="text-[#8a8a7a] text-sm hover:text-[#d4a574] transition-colors block"
|
||
>
|
||
Thé Tip Top<br />
|
||
18 Avenue Thiers<br />
|
||
06000 Nice, France
|
||
</a>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Téléphone */}
|
||
<div className="flex items-start gap-4">
|
||
<div className="w-12 h-12 bg-gradient-to-br from-[#d4a574] to-[#c4956a] rounded-full flex items-center justify-center text-xl shadow-md flex-shrink-0">📞</div>
|
||
<div>
|
||
<h3 className="font-semibold text-[#5a5a4e] mb-1">Téléphone</h3>
|
||
<p className="text-[#8a8a7a] text-sm">
|
||
<a href="tel:+33123456789" className="hover:text-[#d4a574] transition-colors">
|
||
+33 1 23 45 67 89
|
||
</a><br />
|
||
<span className="text-xs">Du lundi au vendredi<br />9h00 - 18h00</span>
|
||
</p>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Email */}
|
||
<div className="flex items-start gap-4">
|
||
<div className="w-12 h-12 bg-gradient-to-br from-[#d4a574] to-[#c4956a] rounded-full flex items-center justify-center text-xl shadow-md flex-shrink-0">✉️</div>
|
||
<div>
|
||
<h3 className="font-semibold text-[#5a5a4e] mb-1">Email</h3>
|
||
<div className="text-[#8a8a7a] text-sm space-y-1">
|
||
<p>
|
||
<a href="mailto:thetiptopgr3@gmail.com" className="hover:text-[#d4a574] transition-colors">
|
||
thetiptopgr3@gmail.com
|
||
</a>
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Service client */}
|
||
<div className="flex items-start gap-4">
|
||
<div className="w-12 h-12 bg-gradient-to-br from-[#d4a574] to-[#c4956a] rounded-full flex items-center justify-center text-xl shadow-md flex-shrink-0">🕐</div>
|
||
<div>
|
||
<h3 className="font-semibold text-[#5a5a4e] mb-1">Service client</h3>
|
||
<p className="text-[#8a8a7a] text-sm">
|
||
Réponse sous 24h<br />
|
||
Support multilingue<br />
|
||
Du lundi au samedi
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Google Maps */}
|
||
<div className="bg-white rounded-xl shadow-md p-4 border border-[#e5e4dc]">
|
||
<h2 className="text-xl font-bold text-[#5a5a4e] mb-4">Nous trouver</h2>
|
||
<div className="rounded-lg overflow-hidden relative">
|
||
<iframe
|
||
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d2884.5!2d7.2619!3d43.7102!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x12cdd0106a852d31%3A0x40819a5fd979a70!2s18%20Av.%20Thiers%2C%2006000%20Nice%2C%20France!5e0!3m2!1sfr!2sfr!4v1700000000000!5m2!1sfr!2sfr"
|
||
width="100%"
|
||
height="250"
|
||
style={{ border: 0 }}
|
||
allowFullScreen
|
||
loading="lazy"
|
||
referrerPolicy="no-referrer-when-downgrade"
|
||
title="Localisation Thé Tip Top - 18 Avenue Thiers, Nice"
|
||
></iframe>
|
||
{/* Point rouge cliquable */}
|
||
<a
|
||
href="https://www.google.com/maps/search/?api=1&query=18+Avenue+Thiers+06000+Nice+France"
|
||
target="_blank"
|
||
rel="noopener noreferrer"
|
||
className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 z-10 group"
|
||
>
|
||
<span className="block w-6 h-6 bg-red-600 rounded-full border-2 border-white shadow-lg cursor-pointer hover:scale-125 transition-transform animate-pulse"></span>
|
||
<span className="absolute -bottom-1 left-1/2 transform -translate-x-1/2 w-0 h-0 border-l-[6px] border-r-[6px] border-t-[8px] border-l-transparent border-r-transparent border-t-red-600"></span>
|
||
</a>
|
||
</div>
|
||
<a
|
||
href="https://www.google.com/maps/search/?api=1&query=18+Avenue+Thiers+06000+Nice+France"
|
||
target="_blank"
|
||
rel="noopener noreferrer"
|
||
className="mt-3 inline-flex items-center gap-2 text-sm text-[#d4a574] hover:text-[#c4956a] transition-colors"
|
||
>
|
||
Ouvrir dans Google Maps
|
||
<svg xmlns="http://www.w3.org/2000/svg" className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
|
||
</svg>
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
{/* CTA FAQ Section */}
|
||
<section className="py-12">
|
||
<div className="container mx-auto px-4">
|
||
<div className="max-w-4xl mx-auto">
|
||
<div className="bg-gradient-to-r from-[#d4a574]/10 to-[#c4956a]/10 rounded-xl p-8 border-l-4 border-[#d4a574] shadow-lg">
|
||
<div className="flex items-start gap-4">
|
||
<div className="w-16 h-16 bg-gradient-to-br from-[#d4a574] to-[#c4956a] rounded-full flex items-center justify-center text-3xl shadow-md flex-shrink-0">💡</div>
|
||
<div className="flex-1">
|
||
<h3 className="text-xl font-bold text-[#5a5a4e] mb-2">Avant de nous contacter</h3>
|
||
<p className="text-[#5a5a4e] mb-4">
|
||
Consultez notre FAQ, vous y trouverez peut-être la réponse à votre question !
|
||
</p>
|
||
<Link
|
||
href="/faq"
|
||
className="inline-flex items-center justify-center bg-gradient-to-r from-[#d4a574] to-[#c4956a] hover:from-[#e5b685] hover:to-[#d4a574] text-white font-bold px-6 py-3 rounded-lg transition-all duration-300 shadow-lg hover:scale-105"
|
||
>
|
||
Voir la FAQ
|
||
</Link>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
);
|
||
}
|