/* QUITOS — UI mockups */ const { useState, useEffect, useRef } = React; /* ---------- Relance list — QUITOS Quote ---------- */ const RELANCE_ROWS = [ { name: 'ACME SAS', ref: 'DEV-047', amount: '8 400 €', when: 'Envoyé il y a 3j' }, { name: 'Tech Pulse', ref: 'DEV-048', amount: '3 200 €', when: 'Envoyé il y a 6j' }, { name: 'Studio Kalon', ref: 'DEV-051', amount: '12 800 €', when: 'Envoyé il y a 1j' }, ]; const STATUS_CYCLE = [ { key: 'sent', label: 'Envoyée', color: '#A0A0A0' }, { key: 'opened', label: 'Ouverte', color: '#E8892A' }, { key: 'replied', label: 'Répondue', color: '#2D6A4F' }, ]; function RelanceMockup() { const [tick, setTick] = useState(0); const notifRef = useRef(null); /* Status cycling — each row has a different starting offset so they don't change simultaneously */ useEffect(() => { const id = setInterval(() => setTick((t) => t + 1), 2500); return () => clearInterval(id); }, []); /* Floating notification — GSAP pop-in with scale */ useEffect(() => { const el = notifRef.current; if (!el || !window.gsap) return; gsap.set(el, { opacity: 0, y: 16, scale: 0.96 }); const showNotif = () => { gsap.fromTo(el, { opacity: 0, y: 16, scale: 0.96 }, { opacity: 1, y: 0, scale: 1, duration: 0.5, ease: 'power3.out', onComplete: () => { gsap.to(el, { opacity: 0, y: -8, scale: 0.97, duration: 0.4, delay: 3, ease: 'power2.in' }); }, } ); }; const initial = setTimeout(showNotif, 800); const id = setInterval(showNotif, 5000); return () => { clearTimeout(initial); clearInterval(id); }; }, []); return (
Relances devis en cours
{RELANCE_ROWS.map((row, i) => { /* Each row starts at a different phase so they cycle independently */ const status = STATUS_CYCLE[(tick + i) % STATUS_CYCLE.length]; return (
{row.name}
{row.when}
{row.ref}
{row.amount}
{status.label}
); })}
{/* Floating notification — GSAP animated, always in DOM */}
↑ 2 devis relancés ce matin
); } /* ---------- Pay timeline — QUITOS Pay ---------- */ const PAY_STEPS = [ { day: 'J+5', label: 'Email compréhensif' }, { day: 'J+15', label: 'Rappel courtois' }, { day: 'J+30', label: 'Mise en demeure' }, { day: 'J+60', label: 'Recommandé électronique' }, ]; function PayTimelineMockup() { const [filled, setFilled] = useState(0); const ref = useRef(null); useEffect(() => { const el = ref.current; if (!el) return; if (window.gsap && window.ScrollTrigger) { /* GSAP ScrollTrigger approach */ const trigger = ScrollTrigger.create({ trigger: el, start: 'top 75%', onEnter: () => { PAY_STEPS.forEach((_, i) => { setTimeout(() => setFilled((f) => Math.max(f, i + 1)), i * 400); }); /* Animate connector lines appearing */ const connectors = el.querySelectorAll(".pay-connector"); connectors.forEach((line, i) => { gsap.fromTo(line, { opacity: 0 }, { opacity: 1, duration: 0.4, delay: (i * 0.4) + 0.3, ease: 'power2.out' } ); }); }, once: true, }); return () => trigger.kill(); } else { /* Fallback: IntersectionObserver */ const io = new IntersectionObserver(([entry]) => { if (entry.isIntersecting) { PAY_STEPS.forEach((_, i) => { setTimeout(() => setFilled((f) => Math.max(f, i + 1)), i * 350); }); io.disconnect(); } }, { threshold: 0.4 }); io.observe(el); return () => io.disconnect(); } }, []); const filledTarget = Math.min(filled, 2); return (
Séquence de relance — QUITOS Pay
{PAY_STEPS.map((step, i) => { const isFilled = i < filledTarget; return (
{i < PAY_STEPS.length - 1 && (
)}
{step.day}
{step.label}
); })}
); } /* ---------- Monthly report mockup ---------- */ function ReportMockup() { const rows = [ { lbl: 'CA récupéré ce mois', val: '14 200 €', accent: true }, { lbl: 'Devis relancés', val: '23' }, { lbl: 'Taux de réponse', val: '34 %' }, { lbl: 'DSO réduit de', val: '-8 jours' }, ]; const top3 = [ { name: 'Renault RH', amt: '12 800 €' }, { name: 'Geodis Comms', amt: '8 400 €' }, { name: 'Bouygues Tél.', amt: '6 200 €' }, ]; return (
QUITOS — Rapport Mai 2026
{rows.map((r) => (
{r.lbl} {r.val}
))}
Top 3 devis signés ce mois
{top3.map((t, i) => (
{t.name} {t.amt}
))}
); } /* ---------- Lifestyle photo — uses real image with overlay UI ---------- */ function LifestylePhoto() { const imgSrc = 'assets/images/quitos-ambiance.png'; return (
{ e.target.style.display = 'none'; }} />
{/* Overlay UI — rapport mini (bottom-left) */}
Rapport QUITOS · Mai 2026
CA récupéré 14 200 € ↑
Devis traités 23
{/* Overlay UI — pill (bottom-right) */}
3 relances envoyées
); } Object.assign(window, { RelanceMockup, PayTimelineMockup, ReportMockup, LifestylePhoto });