the-tip-top-frontend/app/contact/page.tsx
soufiane dce1559a32 feat: improve user management and profile features
- 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>
2025-11-28 13:59:52 +01:00

344 lines
16 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'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>
);
}