import { useCallback, useEffect, useState } from 'react'; import styled from 'styled-components'; import DashboardPage from './components/DashboardPage'; import ChatInterface from './components/ChatInterface'; import BusinessShowcasePage from './components/PublicBusinessPage'; import LoginPage from './components/LoginPage'; import OnboardingFlow from './components/OnboardingFlow'; import SuccessPage from './components/SuccessPage'; import AboutPage from './components/AboutPage'; import FaqPage from './components/FaqPage'; import BlogPage from './components/BlogPage'; import SahelLogo from './components/SahelLogo'; import MarketingFooter from './components/layout/MarketingFooter'; import MarketingHeader from './components/layout/MarketingHeader'; import { ROUTES, loginUrl } from './lib/routes'; import { getSession } from './lib/session'; import { API_URL } from './config'; const AppContainer = styled.div` min-height: 100vh; background: #ffffff; color: #1c1b1b; font-family: 'Inter', system-ui, sans-serif; `; const Header = styled.header` position: sticky; top: 0; z-index: 20; display: flex; align-items: center; justify-content: space-between; min-height: 76px; padding: 0 clamp(18px, 5vw, 64px); background: rgba(255, 255, 255, 0.96); border-bottom: 0.5px solid #d9d6cc; backdrop-filter: blur(12px); `; const HeaderActions = styled.div` display: flex; align-items: center; gap: 12px; `; const Brand = styled.div` color: #185fa5; font-size: clamp(18px, 3vw, 22px); font-weight: 500; `; const HeaderNav = styled.nav` display: flex; align-items: center; gap: 18px; a { color: #414751; font-size: 14px; font-weight: 600; text-decoration: none; } @media (max-width: 720px) { a:not(.primary-link) { display: none; } } `; const PageTransition = styled.div` animation: page-in 420ms ease both; @keyframes page-in { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } } `; const Shell = styled.main` display: grid; grid-template-columns: minmax(280px, 380px) minmax(0, 1fr); gap: 24px; padding: 24px 32px; @media (max-width: 900px) { grid-template-columns: 1fr; padding: 16px; } `; const DashboardIntro = styled.section` display: grid; gap: 18px; padding: 24px 32px 0; @media (max-width: 900px) { padding: 18px 16px 0; } `; const DashboardHero = styled.div` display: grid; gap: 16px; padding: clamp(20px, 4vw, 34px); border: 0.5px solid #d9d6cc; border-radius: 8px; background: #f6f3f2; @media (min-width: 860px) { grid-template-columns: minmax(0, 1fr) auto; align-items: end; } `; const DashboardTitle = styled.h1` margin: 0; font-size: clamp(32px, 5vw, 54px); font-weight: 500; line-height: 1; `; const DashboardSubnav = styled.nav` display: flex; flex-wrap: wrap; gap: 8px; a { display: inline-flex; align-items: center; min-height: 36px; padding: 0 12px; border: 0.5px solid #c8c5bc; border-radius: 6px; background: #ffffff; color: #2f3540; font-size: 13px; font-weight: 700; text-decoration: none; } a:hover { border-color: #378add; color: #185fa5; } `; const WorkspaceHeader = styled.div` display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 18px; `; const WorkspaceActions = styled.div` display: flex; flex-wrap: wrap; gap: 8px; `; const Panel = styled.section` background: #ffffff; border: 0.5px solid #d9d6cc; border-radius: 8px; padding: clamp(18px, 3vw, 28px); `; const PanelTitle = styled.h2` margin: 0 0 14px; font-size: clamp(24px, 4vw, 34px); font-weight: 500; `; const Form = styled.form` display: grid; gap: 12px; `; const Label = styled.label` display: grid; gap: 9px; color: #2f3540; font-size: 13px; font-weight: 600; text-transform: uppercase; `; const Input = styled.input` border: 0.5px solid #c8c5bc; border-radius: 6px; min-height: 58px; padding: 0 16px; background: #ffffff; color: #1c1b1b; font-size: 15px; &:focus { border-color: #378add; outline: none; } `; const TextArea = styled.textarea` min-height: 78px; border: 0.5px solid #c8c5bc; border-radius: 6px; padding: 14px 16px; font-size: 14px; resize: vertical; &:focus { border-color: #378add; outline: none; } `; const Button = styled.button` border: 0; border-radius: 6px; min-height: 46px; padding: 0 18px; background: #378add; color: white; font-weight: 700; cursor: pointer; transition: background 150ms ease, border-color 150ms ease; &:hover { background: #185fa5; } &:disabled { background: #9db6cc; cursor: not-allowed; } `; const SecondaryButton = styled(Button)` background: #ffffff; color: #1c1b1b; border: 0.5px solid #c8c5bc; &:hover { background: #f6f3f2; } `; const GhostButton = styled.button` border: 0.5px solid #c8c5bc; border-radius: 6px; min-height: 40px; padding: 0 12px; background: #ffffff; color: #17201b; font-weight: 700; cursor: pointer; `; const BusinessList = styled.div` display: grid; gap: 8px; margin-top: 18px; `; const BusinessButton = styled.button` border: 1px solid ${({ $active }) => ($active ? '#207a4c' : '#dfe7df')}; border-radius: 6px; padding: 10px; background: ${({ $active }) => ($active ? '#eef8f1' : '#ffffff')}; text-align: left; cursor: pointer; `; const LinkBox = styled.div` display: grid; gap: 8px; margin-bottom: 16px; padding: 12px; border-radius: 6px; background: #f8faf8; font-size: 14px; `; const EmbedCode = styled.pre` margin: 8px 0 0; padding: 12px; overflow-x: auto; border: 1px solid #dfe7df; border-radius: 6px; background: #17201b; color: #eef8f1; font-size: 12px; line-height: 1.5; `; const QrBox = styled.div` display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 14px; align-items: center; margin-bottom: 16px; padding: 12px; border-radius: 6px; background: #ffffff; border: 1px solid #dfe7df; @media (max-width: 560px) { grid-template-columns: 1fr; } `; const SmallButton = styled.button` border: 1px solid #c6ddce; border-radius: 6px; min-height: 36px; padding: 0 12px; background: #eef8f1; color: #207a4c; font-weight: 700; cursor: pointer; `; const Muted = styled.span` color: #617065; `; const StatsGrid = styled.div` display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin-bottom: 16px; @media (max-width: 560px) { grid-template-columns: 1fr; } `; const StatBox = styled.div` padding: 12px; border: 1px solid #dfe7df; border-radius: 6px; background: #f8faf8; `; const StatValue = styled.div` font-size: 28px; font-weight: 800; `; const RecentList = styled.div` display: grid; gap: 8px; margin-bottom: 16px; `; const RecentItem = styled.div` padding: 10px; border-radius: 6px; background: #f8faf8; border: 1px solid #e5ece5; font-size: 14px; `; const ItemMeta = styled.div` display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 6px; color: #617065; font-size: 12px; `; const StatusText = styled.div` min-height: 18px; color: ${({ $error }) => ($error ? '#a13a2b' : '#207a4c')}; font-size: 13px; `; const ActionRow = styled.div` display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; `; const StatusBadge = styled.span` display: inline-flex; align-items: center; min-height: 22px; padding: 0 8px; border-radius: 999px; background: ${({ $status }) => $status === 'closed' ? '#eef0f2' : $status === 'contacted' ? '#eef8f1' : '#fff4df'}; color: ${({ $status }) => $status === 'closed' ? '#596168' : $status === 'contacted' ? '#207a4c' : '#8a5a00'}; font-size: 12px; font-weight: 700; `; const LanguageBadge = styled(StatusBadge)` background: ${({ $language }) => $language === 'ar' ? '#eef3ff' : $language === 'fr' ? '#fff4df' : '#eef8f1'}; color: ${({ $language }) => $language === 'ar' ? '#2f5faa' : $language === 'fr' ? '#8a5a00' : '#207a4c'}; `; const PublicShell = styled.main` max-width: 1180px; margin: 0 auto; padding: clamp(28px, 6vw, 72px) 18px; `; const PublicHero = styled.section` display: grid; gap: 18px; margin-bottom: 28px; padding: clamp(32px, 6vw, 72px) clamp(20px, 5vw, 48px); background: #185fa5; color: #e6f1fb; border-radius: 8px; overflow: hidden; `; const PublicTitle = styled.h1` margin: 0; max-width: 780px; font-size: clamp(48px, 9vw, 92px); font-weight: 500; line-height: 0.96; `; const PublicActions = styled.div` display: flex; flex-wrap: wrap; gap: 10px; margin-top: 8px; `; const LinkButton = styled.a` display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-height: 46px; padding: 0 18px; border-radius: 6px; background: #378add; color: white; font-weight: 700; text-decoration: none; transition: background 150ms ease, border-color 150ms ease; &:hover { background: #185fa5; } `; const SecondaryLink = styled(LinkButton)` background: #ffffff; color: #1c1b1b; border: 0.5px solid #c8c5bc; &:hover { background: #f6f3f2; } `; const LandingHero = styled.section` position: relative; display: grid; gap: 40px; min-height: calc(100svh - 76px); padding: clamp(44px, 7vw, 88px) clamp(18px, 5vw, 64px) 28px; overflow: hidden; @media (min-width: 980px) { grid-template-columns: minmax(0, 1.08fr) minmax(360px, 0.92fr); align-items: center; } `; const Eyebrow = styled.div` display: inline-flex; width: fit-content; align-items: center; gap: 8px; margin-bottom: 18px; padding: 7px 11px; border: 1px solid rgba(0, 0, 0, 0.08); border-radius: 999px; background: #ffffff; color: #414751; font-size: 12px; font-weight: 700; `; const HeroTitle = styled.h1` max-width: 780px; margin: 0; font-size: clamp(48px, 10vw, 92px); font-weight: 500; line-height: 0.98; em { font-style: italic; } `; const HeroCopy = styled.p` max-width: 620px; margin: 20px 0 0; color: #414751; font-size: clamp(16px, 2.2vw, 20px); line-height: 1.65; `; const HeroActions = styled.div` display: flex; flex-wrap: wrap; gap: 12px; margin-top: 30px; a { min-width: min(100%, 228px); } `; const ProductVisual = styled.div` display: grid; gap: 14px; `; const BrowserMock = styled.div` border: 0.5px solid #d9d6cc; border-radius: 8px; background: #ffffff; overflow: hidden; `; const BrowserBar = styled.div` display: flex; align-items: center; gap: 6px; height: 36px; padding: 0 12px; border-bottom: 0.5px solid #d9d6cc; background: #f6f3f2; span { width: 8px; height: 8px; border-radius: 50%; background: #b8c2cc; } `; const DashboardPreview = styled.div` display: grid; gap: 16px; padding: 18px; `; const ChartImage = styled.div` min-height: 210px; border-radius: 6px; border: 0.5px solid #d9d6cc; background: #f1efe8; position: relative; &::before { content: ''; position: absolute; inset: 36px 28px; border-left: 0.5px solid #b5d4f4; border-bottom: 0.5px solid #b5d4f4; } &::after { content: ''; position: absolute; left: 54px; right: 34px; bottom: 54px; height: 72px; background: #378add; clip-path: polygon(0 78%, 18% 58%, 38% 68%, 58% 30%, 78% 42%, 100% 8%, 100% 100%, 0 100%); opacity: 0.9; } `; const PreviewGrid = styled.div` display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; div { min-height: 76px; padding: 12px; border-radius: 6px; background: #f6f3f2; color: #185fa5; font-size: 26px; } span { display: block; margin-top: 6px; color: #717783; font-family: 'Inter', sans-serif; font-size: 11px; font-weight: 700; } `; const SectionBand = styled.section` padding: clamp(48px, 8vw, 92px) clamp(18px, 5vw, 64px); background: ${({ $tone }) => ($tone === 'warm' ? '#f1efe8' : '#ffffff')}; border-top: 0.5px solid #d9d6cc; `; const SectionInner = styled.div` max-width: 1180px; margin: 0 auto; `; const SectionTitle = styled.h2` max-width: 720px; margin: 0 0 16px; font-size: clamp(34px, 6vw, 58px); font-weight: 500; line-height: 1.05; `; const SectionLead = styled.p` max-width: 640px; margin: 0 0 32px; color: #414751; line-height: 1.7; `; const FeatureGrid = styled.div` display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 16px; `; const FeatureCard = styled.div` min-height: 190px; padding: 22px; border: 0.5px solid #d9d6cc; border-radius: 8px; background: #ffffff; transition: background 150ms ease, border-color 150ms ease; &:hover { border-color: #85b7eb; background: #f8fbff; } `; const IconBox = styled.div` display: grid; place-items: center; width: 44px; height: 44px; margin-bottom: 18px; border-radius: 6px; background: #e6f1fb; color: #185fa5; font-size: 22px; `; const StepsGrid = styled.div` display: grid; gap: 28px; @media (min-width: 900px) { grid-template-columns: minmax(0, 1fr) 420px; align-items: center; } `; const StepList = styled.div` display: grid; gap: 18px; `; const StepItem = styled.div` display: grid; grid-template-columns: 42px minmax(0, 1fr); gap: 16px; strong { display: block; margin-bottom: 5px; } p { margin: 0; color: #414751; line-height: 1.6; } `; const StepNumber = styled.div` display: grid; place-items: center; width: 36px; height: 36px; border: 0.5px solid #378add; border-radius: 6px; color: #185fa5; font-weight: 800; `; const QrPhoto = styled.div` aspect-ratio: 4 / 5; border-radius: 8px; border: 0.5px solid #d9d6cc; background: #ffffff; position: relative; &::before { content: ''; position: absolute; width: 46%; aspect-ratio: 1; left: 27%; top: 24%; background: #185fa5; border: 14px solid #f1efe8; outline: 0.5px solid #d9d6cc; } &::after { content: 'QR code partageable'; position: absolute; left: 0; right: 0; bottom: 24%; text-align: center; color: #414751; font-size: 13px; font-weight: 500; } `; const PricingGrid = styled.div` display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 16px; `; const PriceCard = styled.div` position: relative; padding: 24px; border: ${({ $featured }) => ($featured ? '2px solid #378add' : '0.5px solid #d9d6cc')}; border-radius: 8px; background: #ffffff; h3 { margin: 0 0 16px; color: ${({ $featured }) => ($featured ? '#185fa5' : '#414751')}; font-size: 12px; letter-spacing: 0.08em; text-transform: uppercase; } strong { display: block; margin-bottom: 18px; font-size: 34px; font-weight: 500; } p { color: #414751; line-height: 1.7; } `; const PopularBadge = styled.div` position: absolute; top: 0; right: 0; padding: 5px 9px; background: #378add; color: #ffffff; font-size: 10px; font-weight: 800; text-transform: uppercase; `; const Footer = styled.footer` padding: 44px clamp(18px, 5vw, 64px); border-top: 0.5px solid #d9d6cc; background: #ffffff; `; const FooterInner = styled.div` display: grid; max-width: 1180px; margin: 0 auto; gap: 24px; @media (min-width: 760px) { grid-template-columns: 1fr auto auto; } a { color: #414751; text-decoration: none; } `; const MiniSiteGrid = styled.div` display: grid; gap: 28px; @media (min-width: 980px) { grid-template-columns: minmax(0, 0.85fr) minmax(360px, 0.65fr); align-items: start; } `; const InfoPills = styled.div` display: flex; flex-wrap: wrap; gap: 10px; `; const InfoPill = styled.span` display: inline-flex; align-items: center; gap: 7px; min-height: 38px; padding: 0 12px; border-radius: 6px; background: rgba(255, 255, 255, 0.82); color: #2f3540; font-weight: 700; `; const ConciergeCard = styled(Panel)` padding: 0; overflow: hidden; `; const ConciergeHeader = styled.div` display: flex; align-items: center; gap: 16px; padding: 24px; border-bottom: 0.5px solid #d9d6cc; `; const BotAvatar = styled.div` display: grid; place-items: center; width: 58px; height: 58px; border-radius: 8px; background: #378add; color: #ffffff; font-size: 26px; `; const PublicFooterLinks = styled.div` display: flex; flex-wrap: wrap; justify-content: center; gap: 28px; margin-top: 44px; color: #414751; `; function landingCta() { const session = getSession(); return session?.owner ? ROUTES.dashboard : loginUrl(ROUTES.onboarding); } function LandingPage() { useEffect(() => { const observer = new IntersectionObserver( (entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { entry.target.classList.add('opacity-100', 'translate-y-0'); entry.target.classList.remove('opacity-0', 'translate-y-8'); } }); }, { threshold: 0.05 } ); const sections = document.querySelectorAll('.reveal-section'); sections.forEach((section) => { section.classList.add('transition-all', 'duration-700', 'opacity-0', 'translate-y-8'); observer.observe(section); }); return () => { sections.forEach((section) => observer.unobserve(section)); }; }, []); return (
{/* Hero Section */}

Votre commerce en ligne en moins de 5 minutes

Transformez votre boutique locale en une puissance digitale. Gérez vos ventes avec l'IA, des mini-sites rapides et des QR codes intelligents.

Commencer maintenant Demander une démo
{/* Key Stats */}
5 min Mise en ligne
3 langues Ar, Fr, Eng
0 DH Frais d'inscription
{/* Background Decorative Elements */}
{/* Product Preview — Live Chat Demo */}
{/* Chat Mockup */}
{/* Window chrome */}
smart_toy chat.sahel.ai — Assistant IA • En ligne
{/* Conversation */}
{/* Context label */}
store Épicerie Atlas — Tinghir
{/* User message 1 */}
السلام عليكم، شنو كاين عندكم فالحلويات؟
15:32
{/* AI typing indicator */}
S
{/* AI response 1 */}
S
وعليكم السلام! 😊 عندنا فهاد الأسبوع:
• الجبن البلدي — 35 درهم للكيلو
• الكوك بطريقة تقليدية — 25 درهم
• الشباكية بالعسل — 40 درهم
شنو تحب تأمر؟
15:32
{/* User message 2 */}
بغيت 2 كيلو جبن وجريدة دالشباكية. واش عندكم توصيل؟
15:34
{/* AI response 2 */}
S
Bien sûr ! ✅ Voici votre commande :
• 2 kg Jben — 70 DH
• 1 lot Chebakia — 40 DH
Total : 110 DH

Oui, on livre à Tinghir sans frais supplémentaires 🚚
Vous passez la commande ?
15:34
{/* Input bar mockup */}
Écrivez votre message...
send
{/* Value Props */}
Démo en direct

Votre assistant IA parle la langue de vos clients.

Le chatbot RAG de Sahel.ai répond en Darija, Arabe, Français ou Anglais — avec une connaissance précise de votre inventaire et de vos prix.

database

RAG sur vos documents

Importez vos catalogues, menus ou fiches produits — l'IA apprend et répond avec vos vraies données.

translate

Multilingue naturel

Darija, Arabe, Français — le client parle sa langue, l'IA comprend et répond.

qr_code_2

QR Code → Chat → Vente

Un scan, une question, une commande. Le parcours client le plus court du Maroc.

Essayer gratuitement arrow_forward
{/* Features Bento Grid */}
Fonctionnalités

Une technologie de pointe pour
les PME marocaines.

{/* RAG AI Card */}
smart_toy

Chatbot IA RAG

L'IA qui connaît votre inventaire. Elle répond aux clients sur WhatsApp et sur votre site 24/7 avec une précision humaine.

{/* Chat Mockup */}
C
Avez-vous des tables dispo ce soir ?
S
Oui ! Nous avons 3 tables libres en terrasse pour ce soir. Vous souhaitez que je réserve au nom de qui ? 😊
{/* Mini-sites Card */}
language

Mini-sites Ultra-rapides

Votre catalogue digital optimisé pour le mobile et le SEO local.

{/* Visual Store Catalogue Mockup */}
{/* QR Codes */}
qr_code_2

QR Codes Dynamiques

Lien direct entre votre boutique physique et votre inventaire digital.

qr_code_2
{/* Analytics */}
insights

Analyses en temps réel

Comprenez ce que vos clients achètent et pourquoi.

Live data
{/* How it Works Timeline */}

Prêt en 3 étapes simples

{/* Vertical Line */}
{/* Step 1 */}

Connectez votre stock

Importez vos produits via Excel ou simplement en prenant des photos.

1

Connectez votre stock

Importez vos produits via Excel ou simplement en prenant des photos.

{/* Step 2 */}
2

Activez l'IA Sahel

L'IA apprend vos prix et vos stocks pour répondre aux clients instantanément.

{/* Step 3 */}

Vendez partout

Partagez votre lien sur WhatsApp, Instagram ou affichez vos QR codes en magasin.

3

Vendez partout

Partagez votre lien sur WhatsApp, Instagram ou affichez vos QR codes en magasin.

{/* Pricing Section */}

Tarification transparente

Pas de frais cachés. Annulez à tout moment.

{/* Free Tier */}
Essentiel
0 DH / mois

Parfait pour démarrer votre digitalisation.

  • check_circle Mini-site catalogue
  • check_circle Jusqu'à 50 produits
  • check_circle QR Codes basiques
Commencer gratuitement
{/* Pro Tier */}
RECOMMANDÉ
Croissance Pro
290 DH / mois

La solution complète pour les PME ambitieuses.

  • check_circle Chatbot IA RAG (WhatsApp + Web)
  • check_circle Produits illimités
  • check_circle Analyses avancées & CRM
  • check_circle Support prioritaire 24/7
Essai gratuit de 14 jours
{/* CTA Section */}

Rejoignez la révolution de l'e-commerce local.

Plus de 500 commerces marocains utilisent déjà Sahel.ai pour booster leurs ventes.

Lancer mon commerce
); } function ContactPage() { const [name, setName] = useState(''); const [email, setEmail] = useState(''); const [message, setMessage] = useState(''); const [submitted, setSubmitted] = useState(false); const handleSubmit = (e) => { e.preventDefault(); if (!name.trim() || !email.trim() || !message.trim()) { alert("Veuillez remplir tous les champs."); return; } setSubmitted(true); }; return (
arrow_back Retour à l'accueil {submitted ? (
check_circle

Merci pour votre intérêt !

Votre demande de démonstration pour Sahel.ai a bien été reçue. Notre équipe vous contactera par email à {email} dans les plus brefs délais.

) : ( <>

Parlons de votre commerce

Pour une mise en place, une question commerciale ou un accompagnement personnalisé, n'hésitez pas à contacter l'équipe Sahel.ai.

)}
); } function Section({ number, title, children }) { return (

{number}.{title}

{children}
); } function LegalPage({ title }) { const isPrivacy = title === "Politique de confidentialité"; const isTerms = title === "Conditions d'utilisation"; const isCookies = title === "Politique cookies"; return (
arrow_back Retour à l'accueil Sahel.ai

{title}

{isPrivacy ? ( <>

Dernière mise à jour : avril 2026 — Sahel.ai, développé dans le cadre d'un stage PFE à Minnova Consulting, Tinghir, Maroc.

Sahel.ai collecte uniquement les données nécessaires au fonctionnement de la plateforme :

  • Nom complet et adresse email lors de l'inscription
  • Informations du commerce (nom, type, description, horaires) saisies dans le formulaire
  • Documents uploadés (PDF, Word) contenant les informations du commerce
  • Logs de conversations du chatbot (questions posées par les visiteurs — anonymisées)
  • Adresse IP et navigateur à des fins de sécurité uniquement

Vos données sont utilisées exclusivement pour faire fonctionner votre chatbot, vous envoyer des notifications de service, améliorer les réponses de l'IA, et vous contacter en cas de problème technique. Sahel.ai ne vend jamais vos données à des tiers et n'utilise pas vos documents pour entraîner des modèles globaux.

Toutes les données sont stockées sur Supabase (serveurs en Europe) avec chiffrement en transit (HTTPS) et au repos. Les documents uploadés sont traités localement dans notre pipeline RAG et ne sont jamais transmis à des services tiers sans votre consentement. Votre clé API Groq n'est jamais exposée côté client.

Vos données de commerce sont conservées tant que votre compte est actif. Les logs de conversations sont conservés 90 jours glissants. Après suppression de votre compte, toutes vos données sont définitivement effacées sous 30 jours.

Conformément au RGPD et à la loi marocaine 09-08 sur la protection des données, vous avez le droit d'accéder à vos données, de les corriger, de les exporter ou de les supprimer à tout moment depuis votre dashboard ou en nous contactant à : contact@sahel.ai

) : isTerms ? ( <>

Dernière mise à jour : avril 2026 — Sahel.ai, Minnova Consulting, Tinghir.

Les présentes Conditions Générales d'Utilisation (CGU) régissent l'accès et l'utilisation de la plateforme Sahel.ai, développée par MOUHAMED dans le cadre d'un stage PFE à Minnova Consulting, Tinghir. En utilisant Sahel.ai, vous acceptez sans réserve les présentes conditions.

Sahel.ai est une plateforme SaaS permettant aux commerces marocains de créer un chatbot IA personnalisé et un mini-site web à partir de leurs documents. Le service comprend : la création et l'hébergement d'un chatbot, la génération d'un mini-site public, un QR code téléchargeable et un tableau de bord analytique.

En utilisant Sahel.ai, vous vous engagez à :

  • Fournir des informations exactes et légales sur votre commerce
  • Ne pas uploader de contenu illégal, diffamatoire ou trompeur
  • Ne pas tenter de contourner les limites du plan gratuit
  • Ne pas utiliser Sahel.ai à des fins frauduleuses ou commercialement abusives
  • Être responsable du contenu de votre chatbot vis-à-vis de vos clients

Sahel.ai est fourni « en l'état » dans le cadre d'un projet étudiant. Nous ne garantissons pas une disponibilité 24h/24 ni l'exactitude absolue des réponses du chatbot. L'utilisateur est seul responsable des informations fournies dans ses documents et des réponses générées par son chatbot.

Le code source, le design et la marque Sahel.ai sont la propriété de leur auteur. Le contenu uploadé par les utilisateurs (documents, descriptions) reste leur propriété exclusive. Sahel.ai n'acquiert aucun droit sur vos données métier.

Vous pouvez supprimer votre compte et tous vos commerces à tout moment depuis votre dashboard. Sahel.ai se réserve le droit de suspendre un compte en cas de violation des présentes conditions, sans préavis.

Les présentes CGU sont soumises au droit marocain. En cas de litige, les tribunaux compétents sont ceux de Tinghir, Maroc.

) : isCookies ? ( <>

Dernière mise à jour : avril 2026 — Sahel.ai.

Un cookie est un petit fichier texte stocké sur votre navigateur lors de votre visite. Sahel.ai utilise un nombre minimal de cookies, listés ci-dessous avec leur fonction exacte.

  • Session d'authentificationObligatoire
    Géré par Supabase Auth. Permet de vous maintenir connecté à votre dashboard sans ressaisir votre mot de passe à chaque visite. Expire après 7 jours d'inactivité. Impossible à désactiver sans perdre l'accès au dashboard.
  • Préférences RGPDObligatoire
    Mémorise votre choix de consentement aux cookies (accepté / refusé) afin de ne pas vous redemander à chaque visite. Stocké dans localStorage. Expire après 1 an.
  • Analytics internesFonctionnel
    Compte le nombre de conversations sur votre chatbot, les langues utilisées, les questions les plus fréquentes. Données 100% anonymes, stockées dans Supabase, jamais partagées. Nécessaire pour alimenter votre dashboard analytique.
  • Aucun cookie publicitaireNon utilisé
    Sahel.ai ne contient aucun tracker publicitaire (Google Ads, Facebook Pixel, etc.). Aucune de vos données de navigation n'est vendue ou transmise à des régies publicitaires. Jamais.
) : ( <>

Cette page est en cours de finalisation. Pour toute question officielle, contactez l'équipe Sahel.ai et nous vous répondrons avec les informations adaptées à votre commerce.

)}
); } function formatDate(value) { if (!value) return ''; return new Intl.DateTimeFormat(undefined, { dateStyle: 'medium', timeStyle: 'short', }).format(new Date(value)); } function cleanPhone(value) { return (value || '').replace(/[^\d+]/g, '').replace(/^\+/, ''); } function whatsappUrl(phone, message) { const cleanedPhone = cleanPhone(phone); if (!cleanedPhone) return ''; return `https://wa.me/${cleanedPhone}?text=${encodeURIComponent(message)}`; } function emailFromContact(value) { return (value || '').match(/[^\s@]+@[^\s@]+\.[^\s@]+/)?.[0] || ''; } function phoneFromContact(value) { const cleanedPhone = cleanPhone(value); return cleanedPhone.replace(/\D/g, '').length >= 8 ? cleanedPhone : ''; } function mailtoUrl(email, subject, body) { if (!email) return ''; return `mailto:${email}?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`; } function embedSnippet(origin, businessSlug) { return ``; } function languageLabel(language) { return { ar: 'Arabic', fr: 'French', en: 'English', unknown: 'Unknown', }[language] || 'Unknown'; } function InquiryForm({ business, conversationId }) { const [form, setForm] = useState({ name: '', contact: '', message: '' }); const [status, setStatus] = useState(''); const [sentMessage, setSentMessage] = useState(''); const [isSending, setIsSending] = useState(false); const submitInquiry = async (event) => { event.preventDefault(); setIsSending(true); setStatus(''); setSentMessage(form.message.trim()); try { const response = await fetch(`${API_URL}/businesses/${business.id}/inquiries`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ ...form, conversation_id: conversationId || null }), }); if (!response.ok) { throw new Error('Could not send inquiry'); } setForm({ name: '', contact: '', message: '' }); setStatus('Request sent.'); } catch { setSentMessage(''); setStatus('Could not send your request. Please try again.'); } finally { setIsSending(false); } }; return (