TonSite.ca
Menu

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 (

{/* Header */}

🍔

tonsite.ca

Coupons Restaurant Québec


{/* Public View */}
{view === ‘public’ && (

{/* Search Bar */}

🔍
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 */}

{categories.map(cat => (

))}

{/* Stats Bar */}

⚡

{filteredCoupons.length}

Offres actives

👥

32K+

Abonnés

📈

850K$

Économies totales

{/* Coupon Grid */}

{filteredCoupons.map(coupon => (


{/* Coupon Header */}

{coupon.logo}

{coupon.restaurant}

📍

{calculateDistance(userLocation.lat, userLocation.lng, coupon.location.lat, coupon.location.lng)} km

{coupon.title}

{/* Discount Badge */}

-{coupon.discount}

{/* 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 */}

{coupons.map(coupon => (

))}

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 && (

{selectedCoupon.logo}

Ouverture de l’application…

{selectedCoupon.restaurant}

Redirection dans {countdown} secondes ⚡

)}

);
};

export default CouponManagementSystem

S’ouvre dans un nouvel onglet