import React, { useState, useEffect } from ‘react’;
const CouponManagementSystem = () => {
const [view, setView] = useState(‘public’);
const [selectedCategory, setSelectedCategory] = useState(‘all’);
const [searchTerm, setSearchTerm] = useState( »);
const [userLocation, setUserLocation] = useState({ lat: 45.5017, lng: -73.5673 });
const [favorites, setFavorites] = useState([]);
const [showAddModal, setShowAddModal] = useState(false);
const [selectedCoupon, setSelectedCoupon] = useState(null);
const [countdown, setCountdown] = useState(3);
const [coupons, setCoupons] = useState([
{
id: 1,
restaurant: « McDonald’s »,
logo: « 🍔 »,
title: « 2 Big Mac pour 10$ »,
discount: « 50% »,
savings: « 12$ »,
expires: new Date(Date.now() + 2 * 24 * 60 * 60 * 1000),
category: « rapide »,
location: { lat: 45.5088, lng: -73.5878, address: « 1250 Rue Sainte-Catherine O » },
usedBy: 8432,
deepLink: « mcdonalds://offers/bigmac2026 »,
webLink: « https://www.mcdonalds.com/ca/fr-ca/offers.html »,
conditions: « Valide avec l’app McDonald’s seulement »
},
{
id: 2,
restaurant: « PFK »,
logo: « 🍗 »,
title: « Bucket 10 morceaux à 19.99$ »,
discount: « 40% »,
savings: « 13$ »,
expires: new Date(Date.now() + 5 * 24 * 60 * 60 * 1000),
category: « rapide »,
location: { lat: 45.5276, lng: -73.5981, address: « 3575 Boulevard Saint-Laurent » },
usedBy: 6234,
deepLink: « kfc://offers/bucket2026 »,
webLink: « https://www.kfc.ca/fr/menu/offers »,
conditions: « Non cumulable avec autres offres »
},
{
id: 3,
restaurant: « Salvatoré »,
logo: « 🍕 »,
title: « Pizza Large + Ailes gratuites »,
discount: « 35% »,
savings: « 18$ »,
expires: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
category: « assis »,
location: { lat: 45.5456, lng: -73.6329, address: « 5555 Avenue du Parc » },
usedBy: 3821,
deepLink: « salvatore://offers/pizza2026 »,
webLink: « https://www.salvatore.ca/promotions »,
conditions: « Dine-in ou livraison »
},
{
id: 4,
restaurant: « Benny & Co »,
logo: « 🍗 »,
title: « Repas Famille 25.99$ »,
discount: « 30% »,
savings: « 11$ »,
expires: new Date(Date.now() + 3 * 24 * 60 * 60 * 1000),
category: « rapide »,
location: { lat: 45.5617, lng: -73.7128, address: « 8500 Boulevard Henri-Bourassa » },
usedBy: 4567,
deepLink: « bennyco://offers/family2026 »,
webLink: « https://www.bennyco.com/promotions »,
conditions: « Valide tous les jours »
},
{
id: 5,
restaurant: « Burger King »,
logo: « 👑 »,
title: « 2 Whoppers pour 12$ »,
discount: « 45% »,
savings: « 10$ »,
expires: new Date(Date.now() + 4 * 24 * 60 * 60 * 1000),
category: « rapide »,
location: { lat: 45.5017, lng: -73.5673, address: « Montreal, QC » },
usedBy: 5621,
deepLink: « burgerking://offers/whopper2026 »,
webLink: « https://www.burgerking.ca/offers »,
conditions: « Avec application mobile »
},
{
id: 6,
restaurant: « A&W »,
logo: « 🍔 »,
title: « Teen Burger + Frites + Boisson 9.99$ »,
discount: « 35% »,
savings: « 8$ »,
expires: new Date(Date.now() + 6 * 24 * 60 * 60 * 1000),
category: « rapide »,
location: { lat: 45.5088, lng: -73.5878, address: « Montreal, QC » },
usedBy: 4234,
deepLink: « aw://offers/teen2026 »,
webLink: « https://www.aw.ca/fr/promotions »,
conditions: « Offre limitée »
}
]);
const calculateDistance = (lat1, lon1, lat2, lon2) => {
const R = 6371;
const dLat = (lat2 – lat1) * Math.PI / 180;
const dLon = (lon2 – lon1) * Math.PI / 180;
const a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
Math.sin(dLon/2) * Math.sin(dLon/2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
return (R * c).toFixed(1);
};
const getTimeRemaining = (expireDate) => {
const now = new Date();
const diff = expireDate – now;
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
if (days > 0) return `${days}j ${hours}h`;
if (hours > 0) return `${hours}h`;
return « Expire bientôt! »;
};
const filteredCoupons = coupons
.filter(c => selectedCategory === ‘all’ || c.category === selectedCategory)
.filter(c => c.restaurant.toLowerCase().includes(searchTerm.toLowerCase()) ||
c.title.toLowerCase().includes(searchTerm.toLowerCase()))
.sort((a, b) => {
const distA = calculateDistance(userLocation.lat, userLocation.lng, a.location.lat, a.location.lng);
const distB = calculateDistance(userLocation.lat, userLocation.lng, b.location.lat, b.location.lng);
return distA – distB;
});
const toggleFavorite = (id) => {
setFavorites(prev =>
prev.includes(id) ? prev.filter(fid => fid !== id) : […prev, id]
);
};
const handleDeepLink = (coupon) => {
setSelectedCoupon(coupon);
setCountdown(3);
};
useEffect(() => {
if (selectedCoupon && countdown > 0) {
const timer = setTimeout(() => setCountdown(countdown – 1), 1000);
return () => clearTimeout(timer);
} else if (selectedCoupon && countdown === 0) {
window.open(selectedCoupon.deepLink, ‘_blank’);
setTimeout(() => {
window.open(selectedCoupon.webLink, ‘_blank’);
setSelectedCoupon(null);
setCountdown(3);
}, 2000);
}
}, [selectedCoupon, countdown]);
const categories = [
{ id: ‘all’, label: ‘Tous’, icon: ‘🎯’ },
{ id: ‘rapide’, label: ‘Rapide’, icon: ‘🍔’ },
{ id: ‘assis’, label: ‘Restaurant’, icon: ‘🍝’ },
{ id: ‘ethnique’, label: ‘Ethnique’, icon: ‘🌮’ }
];
const [newCoupon, setNewCoupon] = useState({
restaurant: »,
title: »,
discount: »,
savings: »,
category: ‘rapide’,
expires: »,
deepLink: »,
webLink: »
});
const handleAddCoupon = () => {
if (!newCoupon.restaurant || !newCoupon.title || !newCoupon.expires) {
alert(‘Veuillez remplir tous les champs obligatoires’);
return;
}
const coupon = {
id: coupons.length + 1,
logo: newCoupon.category === ‘rapide’ ? ‘🍔’ : newCoupon.category === ‘assis’ ? ‘🍝’ : ‘🌮’,
restaurant: newCoupon.restaurant,
title: newCoupon.title,
discount: newCoupon.discount,
savings: newCoupon.savings,
expires: new Date(newCoupon.expires),
category: newCoupon.category,
location: { lat: 45.5017, lng: -73.5673, address: « Montreal, QC » },
usedBy: 0,
deepLink: newCoupon.deepLink,
webLink: newCoupon.webLink,
conditions: « Nouvellement ajouté »
};
setCoupons([…coupons, coupon]);
setShowAddModal(false);
setNewCoupon({
restaurant: »,
title: »,
discount: »,
savings: »,
category: ‘rapide’,
expires: »,
deepLink: »,
webLink: »
});
};
const deleteCoupon = (id) => {
if (window.confirm(‘Voulez-vous vraiment supprimer ce coupon ?’)) {
setCoupons(coupons.filter(c => c.id !== id));
}
};
return (
tonsite.ca
Coupons Restaurant Québec
{/* Public View */}
{view === ‘public’ && (
setSearchTerm(e.target.value)}
className= »w-full pl-14 pr-4 py-4 rounded-2xl border-2 border-gray-200 focus:border-red-500 focus:outline-none text-lg shadow-lg »
/>
{/* Category Pills */}
))}
{/* Stats Bar */}
{filteredCoupons.length}
Offres actives
32K+
Abonnés
850K$
Économies totales
{/* Coupon Grid */}
{/* Coupon Header */}
{coupon.restaurant}
{calculateDistance(userLocation.lat, userLocation.lng, coupon.location.lat, coupon.location.lng)} km
{coupon.title}
{/* Discount Badge */}
{/* Coupon Body */}
Économise {coupon.savings}
{getTimeRemaining(coupon.expires)}
{coupon.usedBy.toLocaleString()} utilisations
{coupon.conditions}
))}
{filteredCoupons.length === 0 && (
Aucun coupon trouvé
Essayez une autre recherche ou catégorie
)}
)}
{/* Admin View */}
{view === ‘admin’ && (
⚙️ Tableau de Bord Admin
Gérez vos coupons en 30 secondes ⚡
{/* Admin Stats */}
📊 Total Coupons
{coupons.length}
✅ Actifs
{coupons.length}
👥 Utilisations
{coupons.reduce((sum, c) => sum + c.usedBy, 0).toLocaleString()}
❤️ Favoris
{favorites.length}
{/* Coupon Table */}
| Restaurant | Titre | Rabais | Expire | Utilisations | Actions |
|---|---|---|---|---|---|
|
{coupon.logo}
{coupon.restaurant} |
{coupon.title} |
-{coupon.discount} |
{getTimeRemaining(coupon.expires)} | {coupon.usedBy.toLocaleString()} |
|
)}
{/* Add Coupon Modal */}
{showAddModal && (
➕ Ajouter un Coupon
setNewCoupon({…newCoupon, restaurant: e.target.value})}
placeholder= »Ex: McDonald’s »
className= »w-full px-4 py-3 rounded-xl border-2 border-gray-200 focus:border-red-500 focus:outline-none »
/>
setNewCoupon({…newCoupon, title: e.target.value})}
placeholder= »Ex: 2 Big Mac pour 10$ »
className= »w-full px-4 py-3 rounded-xl border-2 border-gray-200 focus:border-red-500 focus:outline-none »
/>
setNewCoupon({…newCoupon, discount: e.target.value})}
placeholder= »Ex: 50% »
className= »w-full px-4 py-3 rounded-xl border-2 border-gray-200 focus:border-red-500 focus:outline-none »
/>
setNewCoupon({…newCoupon, savings: e.target.value})}
placeholder= »Ex: 12$ »
className= »w-full px-4 py-3 rounded-xl border-2 border-gray-200 focus:border-red-500 focus:outline-none »
/>
setNewCoupon({…newCoupon, expires: e.target.value})}
className= »w-full px-4 py-3 rounded-xl border-2 border-gray-200 focus:border-red-500 focus:outline-none »
/>
setNewCoupon({…newCoupon, deepLink: e.target.value})}
placeholder= »Ex: mcdonalds://offers/promo2026″
className= »w-full px-4 py-3 rounded-xl border-2 border-gray-200 focus:border-red-500 focus:outline-none »
/>
setNewCoupon({…newCoupon, webLink: e.target.value})}
placeholder= »Ex: https://www.mcdonalds.com/ca/fr-ca/offers.html »
className= »w-full px-4 py-3 rounded-xl border-2 border-gray-200 focus:border-red-500 focus:outline-none »
/>
)}
{/* Redirect Modal */}
{selectedCoupon && (
Ouverture de l’application…
{selectedCoupon.restaurant}
)}
);
};
export default CouponManagementSystem