import React, { useState, useEffect, useRef } from 'react'; import { Trophy, Settings, Users, CheckCircle, XCircle, LogOut, Star, Camera, QrCode, User, Lock, Download, Trash2, ChevronRight, Palette, Percent, Plus, Sparkles, History, ShieldCheck, Bell, LayoutDashboard, Gift, Smartphone } from 'lucide-react'; const App = () => { // --- ÉTATS GLOBAUX --- const [view, setView] = useState('landing'); const [user, setUser] = useState(null); const [shopConfig, setShopConfig] = useState({ name: "Lojy Demo Shop", primaryColor: "#f59e0b", rewards: [ { id: 1, label: "-10% REMISE", color: "#f59e0b", weight: 40, highlighted: false }, { id: 2, label: "CADEAU", color: "#1e293b", weight: 20, highlighted: false }, { id: 3, label: "PERDU", color: "#334155", weight: 20, highlighted: false }, { id: 4, label: "-50% ARTICLE", color: "#f59e0b", weight: 10, highlighted: true }, { id: 5, label: "SURPRISE", color: "#1e293b", weight: 5, highlighted: false }, { id: 6, label: "BOISSON", color: "#334155", weight: 5, highlighted: false }, ] }); // --- ÉTATS CLIENT --- const [wonReward, setWonReward] = useState(null); const [isSpinning, setIsSpinning] = useState(false); const [rotation, setRotation] = useState(0); const [proofSubmitted, setProofSubmitted] = useState(false); const [showQR, setShowQR] = useState(false); const [clientHistory, setClientHistory] = useState([ { id: 101, reward: "-10% REMISE", date: "2024-01-20", status: "utilisé" }, { id: 102, reward: "BOISSON OFFERTE", date: "2024-01-25", status: "validé" }, ]); // --- ÉTATS ADMIN --- const [submissions, setSubmissions] = useState([ { id: 1, userName: "Alice Martin", reward: "CADEAU", platform: "Google", status: "pending", date: "2024-01-27" }, { id: 2, userName: "Julien Roux", reward: "-10% REMISE", platform: "Instagram", status: "pending", date: "2024-01-27" }, ]); const canvasRef = useRef(null); // --- LOGIQUE ADMIN --- const handleAdminAction = (id, action) => { setSubmissions(prev => prev.filter(s => s.id !== id)); }; const addReward = () => { const newId = Date.now(); setShopConfig({ ...shopConfig, rewards: [...shopConfig.rewards, { id: newId, label: "NOUVEAU LOT", color: "#1e293b", weight: 10, highlighted: false }] }); }; const removeReward = (id) => { if (shopConfig.rewards.length <= 2) return; setShopConfig({ ...shopConfig, rewards: shopConfig.rewards.filter(r => r.id !== id) }); }; const toggleHighlight = (id) => { setShopConfig({ ...shopConfig, rewards: shopConfig.rewards.map(r => r.id === id ? { ...r, highlighted: !r.highlighted, color: !r.highlighted ? "#f59e0b" : "#1e293b" } : r ) }); }; // --- DESSIN DE LA ROUE --- useEffect(() => { if ((view === 'wheel' || view === 'admin') && canvasRef.current) { const canvas = canvasRef.current; const ctx = canvas.getContext('2d'); const centerX = canvas.width / 2; const centerY = canvas.height / 2; const radius = canvas.width / 2 - 10; const arcSize = (2 * Math.PI) / shopConfig.rewards.length; ctx.clearRect(0, 0, canvas.width, canvas.height); shopConfig.rewards.forEach((reward, i) => { const angle = i * arcSize; ctx.beginPath(); ctx.fillStyle = reward.highlighted ? "#f59e0b" : reward.color; ctx.moveTo(centerX, centerY); ctx.arc(centerX, centerY, radius, angle, angle + arcSize); ctx.fill(); if (reward.highlighted) { ctx.strokeStyle = "#fff"; ctx.lineWidth = 3; ctx.stroke(); } else { ctx.strokeStyle = "rgba(255,255,255,0.1)"; ctx.lineWidth = 1; ctx.stroke(); } ctx.save(); ctx.translate(centerX, centerY); ctx.rotate(angle + arcSize / 2); ctx.fillStyle = reward.highlighted ? "#000" : "white"; ctx.font = "bold 11px sans-serif"; ctx.textAlign = "right"; ctx.fillText(reward.label, radius - 25, 5); ctx.restore(); }); } }, [view, shopConfig]); // --- JEU --- const spinWheel = () => { if (isSpinning) return; setIsSpinning(true); const extraDegrees = Math.floor(Math.random() * 360) + 1800; const newRotation = rotation + extraDegrees; setRotation(newRotation); setTimeout(() => { setIsSpinning(false); const actualDegree = newRotation % 360; const index = Math.floor((360 - actualDegree) / (360 / shopConfig.rewards.length)) % shopConfig.rewards.length; const result = shopConfig.rewards[index]; if (result.label === "PERDU") { setWonReward(null); setView('client_dashboard'); } else { setWonReward(result); setView('claim_reward'); } }, 4000); }; // --- NAVBAR --- const Navbar = () => ( ); return (
{/* LANDING */} {view === 'landing' && (
Solutions de fidélité 2.0

BOOSTEZ VOTRE
VISIBILITÉ.

Offrez des cadeaux à vos clients en échange d'avis positifs sur Google et les réseaux sociaux.

)} {/* AUTH */} {view === 'auth' && (

Rejoindre Lojy

Inscrivez-vous pour gagner des récompenses

{ e.preventDefault(); setUser({name: 'Client Demo', role:'client', email: 'client@demo.com'}); setView('client_dashboard'); }} className="space-y-5">
)} {/* CLIENT DASHBOARD */} {view === 'client_dashboard' && user && (

Salut, {user.name.split(' ')[0]} !

Vous avez 1 tirage disponible

Historique des lots

{clientHistory.map(item => (

{item.reward}

{item.date}

{item.status}
))}
VIP Pass

PROMO
EXCLUSIVE

Valable sur tout le shop

VIP2026
)} {/* CLIENT PROFILE */} {view === 'client_profile' && (

Mon Profil

Sécurité

Données & Vie Privée

Zone de danger

La suppression de votre compte est irréversible. Toutes vos récompenses non utilisées seront perdues.

)} {/* WHEEL GAME */} {view === 'wheel' && (

Tentez votre chance !

Lots garantis par {shopConfig.name}

)} {/* CLAIM REWARD */} {view === 'claim_reward' && (

{wonReward?.label}

Débloquez votre lot maintenant !

{!proofSubmitted ? (
{['Google Maps', 'Instagram'].map(p => (