/** * ========================================================================= * PLATEFORME ECO-PANNEAU.FR - VERSION 1.0.0 * Composant Vue Riverains (Interface publique scannée via QR Code) * Design Mobile-First, gère l'affichage légal et la messagerie publique. * ========================================================================= */ const { useState, useEffect, useRef } = React; const { MapPin, Building, Phone, FileDigit, Users, MessageSquare, AlertTriangle, ExternalLink, Clock, Info, Shield, Download, PublicContactForm, ChatBox, Leaf, CheckCircle, Mail, SiteLogo, ArrowLeft, ArrowRight, X } = window; /** * Vue principale encapsulée pour le riverain. * S'affiche en plein écran sur mobile, ou confinée dans un mock-up iPhone sur l'espace client. */ window.RiverainView = ({ panneau, showToast, interactions = [], settings = {}, refreshData, isPreview = false, initialTab = 'home' }) => { const [activeTab, setActiveTab] = useState(initialTab); const [viewingPdf, setViewingPdf] = useState(null); // Gère l'affichage plein écran d'un document const [showArretesList, setShowArretesList] = useState(false); // Gère la liste multi-arrêtés const [demoLinkWarning, setDemoLinkWarning] = useState(null); // Gère la modale anti-spam du mode démo const scrollRef = useRef(null); useEffect(() => { setActiveTab(initialTab); }, [initialTab]); // Réinitialise le scroll à chaque changement d'onglet useEffect(() => { if (scrollRef.current) { scrollRef.current.scrollTo({ top: 0, behavior: 'smooth' }); } }, [activeTab]); // ========================================================================= // GESTION DES STATUTS DU PANNEAU (Bloqué pour le public, ignoré en Preview) // ========================================================================= if (!isPreview) { if (!panneau || panneau.status === 'Supprimé') { return (

Panneau introuvable

Ce panneau n'existe pas ou a été supprimé par son propriétaire.

); } if (panneau.status === 'Brouillon') { return (

En attente de publication

Ce panneau n'a pas encore été publié.

); } if (panneau.status === 'Hors ligne' || panneau.status === 'Désactivé' || panneau.status === 'Suspendu') { return (

Panneau inactif

Ce panneau a été désactivé par son propriétaire.

); } } else if (!panneau) { // Sécurité si on tente une preview d'un panneau totalement vide return (
Chargement de l'aperçu...
); } const isPublicContact = panneau.id === 'CONTACT_PUBLIC'; const isDemo = panneau.id === 'demo-panneau'; const themeColor = panneau.themeColor || '#059669'; const hasNoAds = panneau.hasNoAds; // Protection contre les fausses URL générées par l'éditeur (blob) const displayImageUrl = panneau.imageId ? `?api=file/download&type=image&id=${panneau.imageId}` : (panneau.imageUrl?.startsWith('blob:') ? null : panneau.imageUrl); const displayMoaLogoUrl = panneau.maitreOuvrageLogoId ? `?api=file/download&type=image&id=${panneau.maitreOuvrageLogoId}` : (panneau.maitreOuvrageLogoUrl?.startsWith('blob:') ? null : panneau.maitreOuvrageLogoUrl); const displayVue3dUrl = panneau.vue3dId ? `?api=file/download&type=image&id=${panneau.vue3dId}` : (panneau.vue3dUrl?.startsWith('blob:') ? null : panneau.vue3dUrl); // Fonction d'interception des liens sortants pour le mode démo const handleExternalLink = (e, url) => { if (isDemo) { e.preventDefault(); setDemoLinkWarning(url); } }; const handleChatSend = async (text) => { const threadEmail = interactions.find(m => m.author !== 'Admin' && m.author !== 'Client')?.author || localStorage.getItem('eco_riverain_email') || 'Visiteur anonyme'; if (threadEmail !== 'Visiteur anonyme') { localStorage.setItem('eco_riverain_email', threadEmail); } const data = { panneauId: panneau.id, detail: text, author: threadEmail, isAlert: 0 }; try { await fetch(window.ECO_CONFIG.apiBaseUrl + 'interactions', { method: 'POST', body: JSON.stringify(data) }); if (refreshData) { refreshData(); } } catch (e) { if (showToast) { showToast("Erreur lors de l'envoi", "error"); } } }; const chatMessages = interactions.map(m => ({ ...m, author: (m.author !== 'Admin' && m.author !== 'Client') ? 'Riverain' : m.author })); const unreadCount = interactions.filter(m => !m.resolved && (m.author === 'Admin' || m.author === 'Client')).length; const showPanelBanner = !isPublicContact && !isDemo && settings?.panel_banner_active === '1' && settings?.panel_banner_msg; const effectiveInteractions = (isPreview && !isDemo) ? [] : interactions; const isChatActive = activeTab === 'contact' && effectiveInteractions.length > 0; // Règle anti-scroll-imbriqué absolue const contentScrollClass = isChatActive ? 'min-h-0 overflow-hidden' : 'overflow-y-auto custom-scrollbar'; return (
{showPanelBanner && (
)} {/* --- EN-TÊTE DYNAMIQUE (HERO RÉDUIT) --- */}
{displayImageUrl && ( <> Panneau
)} {!displayImageUrl && (
)}

{panneau.name}

{/* --- CONTENU PRINCIPAL --- */}
{/* ONGLET 1 : INFORMATIONS (HOME) */} {activeTab === 'home' && (
{displayVue3dUrl && (

Vue 3D du projet

Vue 3D du projet
)} {(panneau.maitreOuvrage || displayMoaLogoUrl) && (
{displayMoaLogoUrl ? ( MOA ) : (
)}

Maître d'ouvrage

{panneau.maitreOuvrage &&

{panneau.maitreOuvrage}

}
)} {panneau.description && (

Description des travaux

{panneau.description}

)} {panneau.promoterLink && ( handleExternalLink(e, panneau.promoterLink)} className="bg-white p-3 rounded-xl shadow-sm border border-slate-100 flex items-center justify-between hover:bg-slate-50 transition group w-full" >

Acheter ou s'informer

)} {(panneau.pdfId || panneau.permitNumber || panneau.noiseSchedule) && (

Autorisation d'urbanisme

{panneau.permitNumber || 'Arrêté officiel'}

{panneau.pdfId && ( )} {panneau.noiseSchedule && (

Horaires de nuisances autorisées :
{panneau.noiseSchedule}

)}
)} {panneau.location && (

Localisation

{panneau.location}

)}
)} {/* ONGLET 2 : L'ÉQUIPE (TEAM) - VERSION COMPLÈTE RESTAURÉE */} {activeTab === 'team' && (
{(!panneau.intervenants?.length && !panneau.lots?.length) ? (
L'équipe du panneau n'a pas encore été renseignée.
) : ( <> {/* Intervenants principaux */} {panneau.intervenants?.length > 0 && (

Intervenants principaux

{panneau.intervenants.map((inter, idx) => (
{inter.logoId ? ( logo ) : (
)}

{inter.role || 'Rôle non défini'}

{inter.name}

{inter.description &&

{inter.description}

} {inter.address && (

{inter.address}

)} {(inter.phone || inter.email || inter.website) && ( )}
))}
)} {/* Sous-traitants par lots */} {panneau.lots?.length > 0 && (

Entreprises sous-traitantes

{panneau.lots.map((lot, idx) => (

{lot.name}

{lot.entreprises?.map((ent, eIdx) => (
{ent.logoId ? ( logo ) : (
)}

{ent.name}

{ent.role &&

{ent.role}

} {ent.description &&

{ent.description}

} {ent.address && (

{ent.address}

)} {(ent.phone || ent.email || ent.website) && ( )}
))} {(!lot.entreprises || lot.entreprises.length === 0) && (

En cours d'attribution

)}
))}
)} )}
)} {/* ONGLET 3 : CONTACT ET MESSAGERIE */} {activeTab === 'contact' && (
{panneau.emergencyPhone && (

Numéro d'urgence

{panneau.emergencyPhone}

handleExternalLink(e, `tel:${panneau.emergencyPhone}`)} className="w-10 h-10 bg-slate-800 text-white rounded-full flex items-center justify-center shadow-md hover:bg-slate-900 transition">
)}

Échanger avec le responsable

{effectiveInteractions.length === 0 ? ( { if (refreshData) refreshData(); }} /> ) : (
)}
)}
{/* --- NAVIGATION INFERIEURE --- */} {(!isPublicContact) && (
)} {!hasNoAds && ( )} {/* VISUALISATION PDF : Suppression de PDF.js au profit de l'image serveur WEBP ! */} {viewingPdf && (
setViewingPdf(null)}>
e.stopPropagation()}> Télécharger
Aperçu de l'arrêté e.stopPropagation()} />
)} {/* MODALE LISTE DES ARRÊTÉS (MULTI-PERMIS) */} {showArretesList && (
setShowArretesList(false)}>
e.stopPropagation()}>

Documents d'urbanisme

{/* Arrêté Initial */} {/* Arrêtés Modificatifs */} {panneau.modificatifs?.map((mod, idx) => ( ))}
)} {/* MODALE D'AVERTISSEMENT ANTI-SPAM (MODE DÉMO) */} {demoLinkWarning && ( setDemoLinkWarning(null)} zIndex="z-[999999]">

Liens de contact désactivés sur cet exemple.

)}
); }; /* EOF ===== [_riverains.jsx] =============== */