import React, { useState, useEffect } from 'react'; import { PieChart, Pie, Cell, BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, Legend } from 'recharts'; import { Leaf, Recycle, TreeDeciduous, Users, Download, Share2, LogOut, LayoutDashboard, History, User, Building2, Database, Wand2, Copy, CheckCircle2, Award, Lock, Mail, ArrowRight, ShieldCheck, Calendar, FileSpreadsheet, ArrowUpRight, Filter, Clock } from 'lucide-react'; const clientDatabase = { "acme": { id: "acme", name: "Acme Corp", email: "contact@acme-logistique.fr", sector: "Industrie & Logistique", serviceData: [ { name: 'Recyclage papier', value: 60, color: '#56b954' }, { name: 'Recyclage carton', value: 30, color: '#004924' }, { name: 'Destruction confidentielle', value: 10, color: '#e8d3bd' } ], monthlyData: [ { name: 'Mars', volume: 1.2 }, { name: 'Avril', volume: 1.5 }, { name: 'Mai', volume: 2.1 }, { name: 'Juin', volume: 1.8 }, { name: 'Juillet', volume: 2.4 }, { name: 'Août', volume: 2.7 } ], historyLogs: [ { id: "LOG-9021", date: "24/08/2026", type: "Collecte Carton & Papier", volume: "2.7 Tonnes", rawVolume: 2.7, co2: "45 kg", insertionHours: "22h", agent: "Équipe Rennes Nord", status: "Validé" }, { id: "LOG-8843", date: "15/07/2026", type: "Destruction Confidentielle", volume: "0.8 Tonnes", rawVolume: 0.8, co2: "15 kg", insertionHours: "10h", agent: "Équipe Spécialisée LFE", status: "Validé" }, { id: "LOG-8612", date: "02/06/2026", type: "Collecte Papiers de Bureau", volume: "1.8 Tonnes", rawVolume: 1.8, co2: "30 kg", insertionHours: "15h", agent: "Équipe Centre", status: "Validé" }, { id: "LOG-8304", date: "19/05/2026", type: "Collecte Carton Global", volume: "2.1 Tonnes", rawVolume: 2.1, co2: "35 kg", insertionHours: "18h", agent: "Équipe Rennes Nord", status: "Validé" }, { id: "LOG-8109", date: "10/04/2026", type: "Collecte Papier & Carton", volume: "1.5 Tonnes", rawVolume: 1.5, co2: "25 kg", insertionHours: "12h", agent: "Équipe Ouest", status: "Validé" }, { id: "LOG-7920", date: "05/03/2026", type: "Destruction d'archives", volume: "1.2 Tonnes", rawVolume: 1.2, co2: "20 kg", insertionHours: "10h", agent: "Équipe Spécialisée LFE", status: "Validé" } ], metrics: { volume: "14,5", volumeUnit: "Tonnes", volumeSub: "Papiers et/ou cartons", co2: "250", co2Unit: "kg", co2Sub: "d'équivalent CO₂ évités", social: "120", socialUnit: "heures", socialSub: "de travail générées pour des salariés en parcours d'insertion" } }, "bretagne_tech": { id: "bretagne_tech", name: "Bretagne Tech & Co", email: "rse@bretagnetech.io", sector: "Services Numériques", serviceData: [ { name: 'Recyclage papier', value: 75, color: '#56b954' }, { name: 'Recyclage carton', value: 15, color: '#004924' }, { name: 'Destruction confidentielle', value: 10, color: '#e8d3bd' } ], monthlyData: [ { name: 'Mars', volume: 0.8 }, { name: 'Avril', volume: 1.0 }, { name: 'Mai', volume: 1.4 }, { name: 'Juin', volume: 1.3 }, { name: 'Juillet', volume: 1.9 }, { name: 'Août', volume: 2.2 } ], historyLogs: [ { id: "LOG-9012", date: "22/08/2026", type: "Collecte Papiers Administratifs", volume: "2.2 Tonnes", rawVolume: 2.2, co2: "40 kg", insertionHours: "18h", agent: "Équipe Rennes Centre", status: "Validé" }, { id: "LOG-8810", date: "12/07/2026", type: "Collecte Papiers & Cartons", volume: "1.9 Tonnes", rawVolume: 1.9, co2: "35 kg", insertionHours: "16h", agent: "Équipe Rennes Centre", status: "Validé" }, { id: "LOG-8555", date: "28/06/2026", type: "Destruction Sécurisée DSI", volume: "1.3 Tonnes", rawVolume: 1.3, co2: "25 kg", insertionHours: "12h", agent: "Équipe Spécialisée", status: "Validé" }, { id: "LOG-8240", date: "14/05/2026", type: "Collecte Papiers de Bureau", volume: "1.4 Tonnes", rawVolume: 1.4, co2: "25 kg", insertionHours: "12h", agent: "Équipe Rennes Centre", status: "Validé" }, { id: "LOG-8011", date: "03/04/2026", type: "Collecte Papiers Administratifs", volume: "1.0 Tonnes", rawVolume: 1.0, co2: "18 kg", insertionHours: "9h", agent: "Équipe Ouest", status: "Validé" }, { id: "LOG-7850", date: "10/03/2026", type: "Collecte Bureautique", volume: "0.8 Tonnes", rawVolume: 0.8, co2: "15 kg", insertionHours: "8h", agent: "Équipe Ouest", status: "Validé" } ], metrics: { volume: "8,6", volumeUnit: "Tonnes", volumeSub: "Papiers administratifs", co2: "160", co2Unit: "kg", co2Sub: "d'équivalent CO₂ évités", social: "75", socialUnit: "heures", socialSub: "de travail générées pour des salariés en parcours d'insertion" } }, "armor_logistique": { id: "armor_logistique", name: "Armor Logistique", email: "logistique@armor-trans.fr", sector: "Transport & Supply Chain", serviceData: [ { name: 'Recyclage papier', value: 20, color: '#56b954' }, { name: 'Recyclage carton', value: 70, color: '#004924' }, { name: 'Destruction confidentielle', value: 10, color: '#e8d3bd' } ], monthlyData: [ { name: 'Mars', volume: 3.5 }, { name: 'Avril', volume: 4.1 }, { name: 'Mai', volume: 3.9 }, { name: 'Juin', volume: 4.5 }, { name: 'Juillet', volume: 5.2 }, { name: 'Août', volume: 6.0 } ], historyLogs: [ { id: "LOG-9050", date: "25/08/2026", type: "Collecte Massive Cartons", volume: "6.0 Tonnes", rawVolume: 6.0, co2: "100 kg", insertionHours: "45h", agent: "Équipe Logistique Sud", status: "Validé" }, { id: "LOG-8890", date: "18/07/2026", type: "Collecte Cartons Entrepôt", volume: "5.2 Tonnes", rawVolume: 5.2, co2: "90 kg", insertionHours: "40h", agent: "Équipe Logistique Sud", status: "Validé" }, { id: "LOG-8600", date: "30/06/2026", type: "Tri et Conditionnement", volume: "4.5 Tonnes", rawVolume: 4.5, co2: "80 kg", insertionHours: "35h", agent: "Équipe Centre", status: "Validé" }, { id: "LOG-8310", date: "12/05/2026", type: "Collecte Emballages", volume: "3.9 Tonnes", rawVolume: 3.9, co2: "70 kg", insertionHours: "30h", agent: "Équipe Logistique Sud", status: "Validé" }, { id: "LOG-8050", date: "20/04/2026", type: "Collecte Cartons Standard", volume: "4.1 Tonnes", rawVolume: 4.1, co2: "75 kg", insertionHours: "32h", agent: "Équipe Logistique Sud", status: "Validé" }, { id: "LOG-7800", date: "05/03/2026", type: "Collecte Entrepôt", volume: "3.5 Tonnes", rawVolume: 3.5, co2: "65 kg", insertionHours: "28h", agent: "Équipe Logistique Sud", status: "Validé" } ], metrics: { volume: "27,2", volumeUnit: "Tonnes", volumeSub: "Cartons d'emballage", co2: "480", co2Unit: "kg", co2Sub: "d'équivalent CO₂ évités", social: "210", socialUnit: "heures", socialSub: "de travail générées pour des salariés en parcours d'insertion" } } }; export default function App() { const [isAuthenticated, setIsAuthenticated] = useState(false); const [selectedClientId, setSelectedClientId] = useState("acme"); const [clientData, setClientData] = useState(clientDatabase["acme"]); const [activeTab, setActiveTab] = useState("dashboard"); const [timeRange, setTimeRange] = useState("1y"); const [loginEmail, setLoginEmail] = useState("contact@acme-logistique.fr"); const [loginPassword, setLoginPassword] = useState("********"); const [loginError, setLoginError] = useState(""); const [isLoggingIn, setIsLoggingIn] = useState(false); const [isLoaded, setIsLoaded] = useState(false); const [isGeneratingPost, setIsGeneratingPost] = useState(false); const [postContent, setPostContent] = useState(''); const [postCopied, setPostCopied] = useState(false); const [isGeneratingInsight, setIsGeneratingInsight] = useState(false); const [insightContent, setInsightContent] = useState(''); const getFilteredData = () => { if (!clientData) return clientData; let multiplier = 1; let filteredMonths = [...clientData.monthlyData]; let filteredLogs = [...clientData.historyLogs]; if (timeRange === "1w") { multiplier = 0.08; filteredMonths = filteredMonths.slice(-1); filteredLogs = filteredLogs.slice(0, 1); } else if (timeRange === "1m") { multiplier = 0.25; filteredMonths = filteredMonths.slice(-1); filteredLogs = filteredLogs.slice(0, 2); } else if (timeRange === "1q") { multiplier = 0.5; filteredMonths = filteredMonths.slice(-3); filteredLogs = filteredLogs.slice(0, 3); } else { multiplier = 1; } const baseVol = parseFloat(clientData.metrics.volume.replace(',', '.')); const filteredVol = (baseVol * multiplier).toFixed(1).replace('.', ','); const filteredCo2 = Math.round(parseInt(clientData.metrics.co2) * multiplier); const filteredSocial = Math.round(parseInt(clientData.metrics.social) * multiplier); return { ...clientData, monthlyData: filteredMonths, historyLogs: filteredLogs, metrics: { ...clientData.metrics, volume: filteredVol, co2: filteredCo2.toString(), social: filteredSocial.toString() } }; }; const currentFilteredData = getFilteredData(); const handleLogin = (e) => { e.preventDefault(); setLoginError(""); setIsLoggingIn(true); setTimeout(() => { const foundEntry = Object.entries(clientDatabase).find( ([_, data]) => data.email.toLowerCase() === loginEmail.toLowerCase().trim() ); if (foundEntry) { const [clientId, data] = foundEntry; setSelectedClientId(clientId); setClientData(data); setIsAuthenticated(true); setIsLoaded(true); setActiveTab("dashboard"); } else { setLoginError("Identifiants non reconnus. Essayez avec un email de démonstration (ex: contact@acme-logistique.fr)"); } setIsLoggingIn(false); }, 800); }; const handleDemoLogin = (clientId) => { const data = clientDatabase[clientId]; setLoginEmail(data.email); setSelectedClientId(clientId); setClientData(data); setIsAuthenticated(true); setIsLoaded(true); setActiveTab("dashboard"); }; const handleLogout = () => { setIsAuthenticated(false); setIsLoaded(false); setPostContent(''); setActiveTab("dashboard"); }; useEffect(() => { if (isAuthenticated && isLoaded && activeTab === "dashboard") { generateInsights(currentFilteredData); } }, [isAuthenticated, clientData, activeTab]); const generateInsights = async (currentClient) => { setIsGeneratingInsight(true); try { const summaryMonths = currentClient.monthlyData.map(m => `${m.name}: ${m.volume}T`).join(', '); const prompt = `Tu es un expert data spécialisé en environnement. Voici les données de recyclage de l'entreprise ${currentClient.name} (${currentClient.sector}) : ${summaryMonths}. Analyse brièvement cette tendance en 2 phrases maximum, de manière très encourageante et professionnelle, pour un tableau de bord B2B de 'La Feuille d'Érable'.`; const payload = { contents: [{ parts: [{ text: prompt }] }] }; const apiKey = ""; const apiUrl = `https://generativelanguage.googleapis.com/v1beta/models/gemini-3-flash-preview:generateContent?key=${apiKey}`; const response = await fetch(apiUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); const result = await response.json(); if (result.candidates?.[0]?.content?.parts?.[0]?.text) { setInsightContent(result.candidates[0].content.parts[0].text); } } catch (e) { console.error(e); setInsightContent(`Félicitations à ${currentClient.name} pour votre engagement continu !`); } finally { setIsGeneratingInsight(false); } }; const generateLinkedInPost = async () => { setIsGeneratingPost(true); setPostContent(''); try { const prompt = `Agis comme un Community Manager expert en communication RSE. Rédige un post LinkedIn engageant et professionnel pour l'entreprise '${currentFilteredData.name}' qui est fière d'être partenaire de 'La Feuille d'Érable'. Utilise ces données d'impact : ${currentFilteredData.metrics.volume} tonnes de matières recyclées, ${currentFilteredData.metrics.co2} kg d'équivalent CO2 évités, et ${currentFilteredData.metrics.social} heures de travail d'insertion générées. Ton enthousiaste avec émojis et hashtags pertinents.`; const payload = { contents: [{ parts: [{ text: prompt }] }] }; const apiKey = ""; const apiUrl = `https://generativelanguage.googleapis.com/v1beta/models/gemini-3-flash-preview:generateContent?key=${apiKey}`; const response = await fetch(apiUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); const result = await response.json(); if (result.candidates?.[0]?.content?.parts?.[0]?.text) { setPostContent(result.candidates[0].content.parts[0].text); } } catch (e) { console.error(e); setPostContent("Erreur de connexion à l'assistant IA."); } finally { setIsGeneratingPost(false); } }; const copyToClipboard = () => { navigator.clipboard.writeText(postContent); setPostCopied(true); setTimeout(() => setPostCopied(false), 2000); }; const getAnimationClass = (delay) => { return `transition-all duration-700 ease-out transform ${ isLoaded ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-8' } ${delay}`; }; if (!isAuthenticated) { return (
Club LFE Logo

Espace Client Club LFE

Connectez-vous pour accéder à vos indicateurs d'impact RSE personnalisés

{loginError && (
{loginError}
)}
setLoginEmail(e.target.value)} className="block w-full pl-10 pr-3 py-3 border border-slate-200 rounded-xl text-slate-900 placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-[#56b954] focus:border-transparent text-sm font-medium" placeholder="vous@entreprise.fr" />
setLoginPassword(e.target.value)} className="block w-full pl-10 pr-3 py-3 border border-slate-200 rounded-xl text-slate-900 placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-[#56b954] focus:border-transparent text-sm font-medium" />

Comptes de démonstration disponibles :

Chiffrement des flux cloud sécurisé (PostgreSQL / Airtable)
); } return (
Logo Club LFE
Connecté en tant que {clientData.name}
{clientData.name}
{} {activeTab === "dashboard" && (

Bonjour {clientData.name},

Voici votre impact global grâce à votre partenariat avec La Feuille d'Érable. {clientData.sector}

Période active {timeRange === '1w' ? '1 Semaine' : timeRange === '1m' ? '1 Mois' : timeRange === '1q' ? '1 Trimestre' : '1 Année'} (Modifiable dans l'Historique)

Volume valorisé

{currentFilteredData.metrics.volume} {currentFilteredData.metrics.volumeUnit}

{currentFilteredData.metrics.volumeSub}

Impact Environnemental

{currentFilteredData.metrics.co2} {currentFilteredData.metrics.co2Unit}

{currentFilteredData.metrics.co2Sub}

Impact Social

{currentFilteredData.metrics.social} {currentFilteredData.metrics.socialUnit}

{currentFilteredData.metrics.socialSub}

Analyse IA de vos performances ({timeRange === '1w' ? 'Semaine' : timeRange === '1m' ? 'Mois' : timeRange === '1q' ? 'Trimestre' : 'Année'})

{isGeneratingInsight ? (
) : (

{insightContent}

)}

Répartition des services utilisés ({clientData.name})

{clientData.serviceData.map((entry, index) => ( ))} [`${value}%`, 'Utilisation']} contentStyle={{ borderRadius: '12px', border: 'none', boxShadow: '0 4px 6px -1px rgb(0 0 0 / 0.1)' }} />

Évolution des volumes collectés

[`${value} Tonnes`, 'Volume']} contentStyle={{ borderRadius: '12px', border: 'none', boxShadow: '0 4px 6px -1px rgb(0 0 0 / 0.1)' }} />
Studio RSE - {clientData.name}

Valorisez votre engagement !

La communication RSE est essentielle. Exportez vos résultats personnalisés en un clic pour les partager avec vos équipes, vos clients ou sur vos réseaux sociaux professionnels.

{postContent && (
Brouillon généré pour {clientData.name}

{postContent}

)}
Sceau Club LFE

Partenaire Engagé

{clientData.name} x LFE

Matières sauvées {currentFilteredData.metrics.volume} {currentFilteredData.metrics.volumeUnit.charAt(0)}
CO2 évité {currentFilteredData.metrics.co2} {currentFilteredData.metrics.co2Unit}
Heures d'insertion {currentFilteredData.metrics.social} h
Certifié La Feuille d'Érable
)} {} {activeTab === "history" && (

Historique et Périodes d'Analyse

Sélectionnez ci-dessous une période pour filtrer instantanément vos données d'impact et consulter le journal détaillé des interventions pour {clientData.name}.

{/* Time Range Selector Cards */}
setTimeRange("1w")} className={`cursor-pointer rounded-2xl p-6 border transition-all duration-300 shadow-sm relative overflow-hidden ${ timeRange === '1w' ? 'bg-[#004924] text-white border-[#004924] shadow-md ring-2 ring-[#56b954]' : 'bg-white text-slate-800 border-[#e8d3bd] hover:border-[#56b954] hover:shadow-md' }`} >
Court terme

1 Semaine

Dernière intervention & flux récents

{timeRange === '1w' &&
}
setTimeRange("1m")} className={`cursor-pointer rounded-2xl p-6 border transition-all duration-300 shadow-sm relative overflow-hidden ${ timeRange === '1m' ? 'bg-[#004924] text-white border-[#004924] shadow-md ring-2 ring-[#56b954]' : 'bg-white text-slate-800 border-[#e8d3bd] hover:border-[#56b954] hover:shadow-md' }`} >
Mensuel

1 Mois

Bilan des 30 derniers jours

{timeRange === '1m' &&
}
setTimeRange("1q")} className={`cursor-pointer rounded-2xl p-6 border transition-all duration-300 shadow-sm relative overflow-hidden ${ timeRange === '1q' ? 'bg-[#004924] text-white border-[#004924] shadow-md ring-2 ring-[#56b954]' : 'bg-white text-slate-800 border-[#e8d3bd] hover:border-[#56b954] hover:shadow-md' }`} >
Trimestriel

1 Trimestre

3 derniers mois d'activité

{timeRange === '1q' &&
}
setTimeRange("1y")} className={`cursor-pointer rounded-2xl p-6 border transition-all duration-300 shadow-sm relative overflow-hidden ${ timeRange === '1y' ? 'bg-[#004924] text-white border-[#004924] shadow-md ring-2 ring-[#56b954]' : 'bg-white text-slate-800 border-[#e8d3bd] hover:border-[#56b954] hover:shadow-md' }`} >
Annuel

1 An

Bilan complet des 12 derniers mois

{timeRange === '1y' &&
}
Interventions pour la période

{currentFilteredData.historyLogs.length} collectes

Filtre actif : {timeRange === '1w' ? '1 Semaine' : timeRange === '1m' ? '1 Mois' : timeRange === '1q' ? '1 Trimestre' : '1 An'}
Volume filtré

{currentFilteredData.metrics.volume} {currentFilteredData.metrics.volumeUnit}

Conforme aux objectifs RSE
Insertion active

{currentFilteredData.metrics.social} heures

Validation sociale certifiée

Journaux d'intervention détaillés ({timeRange.toUpperCase()})

Synchronisé cloud
{currentFilteredData.historyLogs.map((log, idx) => ( ))}
ID Opération Date Type de service / Flux Volume CO2 Évité Insertion Équipe LFE Statut
{log.id} {log.date} {log.type} {log.volume} {log.co2} {log.insertionHours} {log.agent} {log.status}
)} {} {activeTab === "profile" && (

Mon Profil Partenaire

Informations relatives à votre structure et paramètres de connexion au Club LFE.

{clientData.name.charAt(0)}

{clientData.name}

{clientData.sector} • Partenaire certifié La Feuille d'Érable

)}
); }

Auclair propreté

Nettoyage écoresponsable d’entretien courant des locaux professionnels à Rennes.

Un nettoyage efficace et responsable

Entreprise d’insertion spécialisée dans le nettoyage écologique. Nous accompagnons les entreprises, collectivités, syndics et structures éducatives dans l’entretien durable de leurs locaux à Rennes et dans le département d’Ille-et-Vilaine.

C.ablain 3626 2

Ils nous font confiance

Nos prestations

Nos prestations couvrent toutes les étapes du nettoyage professionnel, du diagnostic propreté aux services sur-mesure qui en découlent.

C.ablain 3593

Diagnostic propreté

Le diagnostic propreté permet de comprendre votre organisation quotidienne et d'adapter nos interventions à la vie de votre structure. Il détaille nos préconisations et les scénarios envisageables.
C.ablain 3919

Travaux spéciaux

La rénovation, la remise en état après chantier, sont des techniques qui consistent à nettoyer un local en profondeur pour lui redonner son aspect d’origine.
C.ablain 3596

Service qualité

Auclair garantit la qualité du nettoyage courant de vos locaux avec des produits naturels et/ou écolabellisés.
C.ablain 3696

Nettoyage des vitres

Le nettoyage des vitres nécessite un véritable savoir-faire. Nos laveurs de vitres interviennent rapidement et en toute discrétion.

Nos interventions

Spécialiste du nettoyage écologique, Auclair intervient dans différents secteurs professionnels sur Rennes et le département d’Ille-et-Vilaine.

Bureaux et locaux professionnels

Copropriétés et espaces communs

Administration et collectivité

Établissements scolaires et publics

Fin de chantier et évenementiel

Nos engagements sociaux et environnementaux

Auclair a mis en place une démarche RSE plaçant l’humain et l’environnement au centre de son action :

  • Insertion de publics en situation d’exclusion professionnelle (agréée entreprise d’insertion par l’État).
  • Horaires d’intervention en journée et sans morcellement permettant de mieux concilier vie professionnelle et privée.
  • Utilisation de produits respectueux de l’environnement et de la santé des salariés et des clients.
  • Utilisation de matériels réutilisables et lavables.
C.ablain 3919

Nous contacter

Une question ? Besoin d’un renseignement ?

Nous contacter