Aperçu de votre sanctuaire — retour au tunnel · cockpit Alexandre
Aller à la recherche
Site officiel · République Française

Votre Commune

Tapez trois lettres. Trouvez ce que vous cherchez.

Ajouter un événement
Ajouter une actualité

Mairie


Place de la Mairie
Code postal — Département

📞 Tél : 05 XX XX XX XX
✉ contact@mairie.fr

⏰ Lundi – Vendredi : 9h – 12h
Mardi : 14h – 17h

📅 Prendre rendez-vous

La mairie

Le maire et les élus

Conseil municipal

Délibérations & CGCT

Budget participatif

Consultations citoyennes

Marchés publics

Citoyens

Démarches en ligne

CCAS — Action sociale

Signaler un problème

Numéros d'urgence

Plan canicule

Plaintes & nuisances

Service-Public.fr ↗

Vie locale

Actualités & agenda

Événements

Hébergements

Restaurants

Visites & circuits

Réserver une salle

Cimetière

Éditeur du site

Mairie de
Place de la Mairie · Code postal · France
SIRET : ___________________________ · Code APE : 8411Z
Tél : 05 XX XX XX XX · contact@mairie.fr

Directeur de la publication

Le maire en exercice
Représentant légal de la commune au sens de l'article 6 III de la LCEN.

Hébergeur

Cloudflare Inc.
101 Townsend St · San Francisco
CA 94107 · USA
cloudflare.com ↗

Données personnelles & RGPD

Aucune donnée n'est collectée à des fins commerciales. Les formulaires sont chiffrés. Vous disposez d'un droit d'accès, de rectification, d'effacement et de portabilité (art. 15 à 22 du RGPD).

Délégué à la Protection des Données (DPO)
Service mutualisé du département
dpo@mairie.fr

Cookies & traceurs

Seuls des cookies fonctionnels essentiels au fonctionnement du site sont utilisés. Aucun tracking publicitaire, aucun partage avec des tiers, conformément à la recommandation CNIL.

Détail des cookies utilisés ↗

Accessibilité numérique

Conformité RGAA 4.1 niveau AA en cours d'audit. Décret n°2019-768 du 24 juillet 2019.

Si une page n'est pas accessible, vous pouvez nous le signaler :
accessibilite@mairie.fr
Vous pouvez saisir le Défenseur des droits ↗.

Médiation & litiges

Pour tout différend concernant le site ou les services en ligne :

Médiateur de la République
defenseurdesdroits.fr ↗

Tribunal Administratif territorialement compétent.

Signaler un contenu illicite

Conformément à la LCEN art. 6.I.5, tout citoyen peut signaler un contenu illicite hébergé sur ce site :

signalement@mairie.fr

Plateforme PHAROS pour les contenus internet :
internet-signalement.gouv.fr ↗

Crédits & propriété intellectuelle

Conception : Cimple — Studio de la Ville · cimple.fr ↗

Photographies historiques : Gallica BnF, Wikimedia Commons (licences libres). Cartes : IGN Géoportail, OpenStreetMap.

Textes & logo : © Mairie de . Reproduction soumise à autorisation.

Numérique responsable

Ce site est conçu pour minimiser sa consommation d'énergie : pas de tracking, images optimisées, hébergement à faible empreinte carbone.

Engagement éco-conception conforme au décret 2022-1539.

🇫🇷 République Française · Liberté · Égalité · Fraternité
Mentions légales · RGPD · Accessibilité RGAA · Cookies · Service-Public.fr ↗
🍪 Ce site utilise des cookies essentiels au fonctionnement. Aucun tracking publicitaire. En savoir plus
`; // Accusé citoyen const htmlCitoyen = `
ACCUSÉ DE RÉCEPTION

Merci, ${esc(data.nom)}.

Votre signalement « ${esc(data.categorie)} » concernant ${esc(data.lieu)} a été transmis aux services techniques de la mairie de ${esc(data.commune)}.

Vous recevrez une notification quand le problème sera traité. Délai moyen : 4,2 jours.

« La commune compte sur la vigilance de ses habitants. Merci. »
Mairie de ${esc(data.commune)} — Site officiel
`; try { // 1. Envoi à la mairie const r1 = await fetch(SIGNALEMENT_RELAY + '/api/send', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ to: getMairieEmail(), subject: `[Signalement ${data.categorie}] ${data.commune} — ${data.lieu}`, html: htmlMairie, replyTo: data.email, }), }); const d1 = await r1.json(); if (!d1.ok) throw new Error(d1.error || 'Échec envoi mairie'); // 2. Accusé citoyen await fetch(SIGNALEMENT_RELAY + '/api/send', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ to: data.email, subject: `Accusé de réception — votre signalement à ${data.commune}`, html: htmlCitoyen, }), }); status.className = 'sig-status ok show'; status.innerHTML = `✓ Signalement envoyé à la mairie. Un accusé de réception vient d'être envoyé à ${esc(data.email)}.`; submitBtn.textContent = '✓ Envoyé'; document.getElementById('sig-form').reset(); document.querySelectorAll('#sig-cats .sig-cat').forEach(x => x.classList.remove('on')); setTimeout(() => { submitBtn.disabled = false; submitBtn.textContent = '📨 Envoyer un autre signalement'; }, 4000); } catch (err) { status.className = 'sig-status err show'; status.textContent = '⚠️ Erreur lors de l\'envoi : ' + err.message + '. Vérifiez que le relais Resend tourne (port 8766).'; submitBtn.disabled = false; submitBtn.textContent = '📨 Réessayer'; } return false; } window.submitSignalement = submitSignalement; function esc(s){return (s||'').toString().replace(/[<>&"]/g,c=>({'<':'<','>':'>','&':'&','"':'"'}[c]))} // ════════════════════════════════════════════════════════════════ // MINI CMS — actualités éditables (mode admin via ?admin=1 ou bouton) // ════════════════════════════════════════════════════════════════ const DEFAULT_ACTUALITES = [ { id: 'a1', date: new Date().toLocaleDateString('fr-FR',{month:'long',year:'numeric'}), title: 'Conseil municipal : compte rendu', desc: 'Compte rendu de la dernière séance, délibérations adoptées, projets pour le prochain trimestre.', iconName: 'parchemin', emoji: '📰' }, { id: 'a2', date: 'À venir', title: 'Fête de la commune', desc: 'Animations, marché des producteurs, retraite aux flambeaux, feu d\'artifice — la fête de l\'année est de retour.', iconName: 'fete', emoji: '🎉' }, { id: 'a3', date: 'Travaux en cours', title: 'Réfection de la place', desc: 'Les travaux de la place du marché commencent. Voici les modifications de circulation et le calendrier.', iconName: 'travaux', emoji: '🏗️' }, ]; // Mode admin — activé par ?admin=1 ou bouton flottant const _adminParam = new URLSearchParams(location.search).get('admin'); window.cimpleAdminMode = (_adminParam === '1') || (localStorage.getItem('cimple_admin') === '1'); function toggleAdminMode() { window.cimpleAdminMode = !window.cimpleAdminMode; localStorage.setItem('cimple_admin', window.cimpleAdminMode ? '1' : '0'); const btn = document.getElementById('cimple-admin-toggle'); const publier = document.getElementById('cimple-publier-tout'); if (btn) { btn.classList.toggle('on', window.cimpleAdminMode); btn.textContent = window.cimpleAdminMode ? '✓ Mode admin (quitter)' : '✎ Mode admin'; } if (publier) publier.style.display = window.cimpleAdminMode ? '' : 'none'; rebuildSanctuaire(); } window.toggleAdminMode = toggleAdminMode; function rebuildSanctuaire() { document.getElementById('modules-zone').innerHTML = ''; buildSanctuaire(); } // Init bouton admin (état au chargement) setTimeout(() => { const btn = document.getElementById('cimple-admin-toggle'); const publier = document.getElementById('cimple-publier-tout'); if (btn && window.cimpleAdminMode) { btn.classList.add('on'); btn.textContent = '✓ Mode admin (quitter)'; } if (publier) publier.style.display = window.cimpleAdminMode ? '' : 'none'; }, 100); let _editingActuId = null; function addActualite() { _editingActuId = null; document.getElementById('modal-actu-title').textContent = 'Ajouter une actualité'; document.getElementById('modal-actu-date').value = ''; document.getElementById('modal-actu-text').value = ''; document.getElementById('modal-actu-desc').value = ''; document.getElementById('modal-actu-icon').value = 'actualite'; document.getElementById('cimple-modal-actu').classList.add('show'); } window.addActualite = addActualite; function editActualite(id) { const items = state.actualites && state.actualites.length ? state.actualites : DEFAULT_ACTUALITES; const it = items.find(x => x.id === id); if (!it) return; _editingActuId = id; document.getElementById('modal-actu-title').textContent = 'Modifier l\'actualité'; document.getElementById('modal-actu-date').value = it.date || ''; document.getElementById('modal-actu-text').value = it.title || ''; document.getElementById('modal-actu-desc').value = it.desc || ''; document.getElementById('modal-actu-icon').value = it.iconName || 'actualite'; document.getElementById('cimple-modal-actu').classList.add('show'); } window.editActualite = editActualite; function closeActuModal() { document.getElementById('cimple-modal-actu').classList.remove('show'); } window.closeActuModal = closeActuModal; function saveActuModal() { const date = document.getElementById('modal-actu-date').value.trim(); const title = document.getElementById('modal-actu-text').value.trim(); const desc = document.getElementById('modal-actu-desc').value.trim(); const iconName = document.getElementById('modal-actu-icon').value; if (!title) { alert('Le titre est obligatoire'); return; } // Initialise l'array si vide (copie des défauts) if (!state.actualites || !state.actualites.length) { state.actualites = DEFAULT_ACTUALITES.map(x => ({...x})); } if (_editingActuId) { const it = state.actualites.find(x => x.id === _editingActuId); if (it) Object.assign(it, { date, title, desc, iconName }); } else { state.actualites.push({ id: 'a' + Date.now(), date, title, desc, iconName }); } persist(); closeActuModal(); rebuildSanctuaire(); } window.saveActuModal = saveActuModal; function deleteActualite(id) { if (!confirm('Supprimer cette actualité ?')) return; if (!state.actualites || !state.actualites.length) { state.actualites = DEFAULT_ACTUALITES.map(x => ({...x})); } state.actualites = state.actualites.filter(x => x.id !== id); persist(); rebuildSanctuaire(); } window.deleteActualite = deleteActualite; // ── Mini CMS — événements ──────────────────────────────────── const DEFAULT_EVENEMENTS = [ { id: 'e1', when: 'Tous les samedis · 8h–13h', name: 'Marché des producteurs', desc: 'Maraîchers, fromagers, boulanger, vignerons. Place du village.', iconName: 'alimentation', emoji: '🎪' }, { id: 'e2', when: '14 juillet · 19h', name: 'Fête nationale', desc: 'Bal populaire, retraite aux flambeaux, feu d\'artifice depuis le pont.', iconName: 'france', emoji: '🎆' }, { id: 'e3', when: 'Septembre · weekend des vendanges', name: 'Fête des vendanges', desc: 'Défilé de chars, dégustation, repas républicain sous la halle.', iconName: 'fete', emoji: '🍇' }, ]; let _editingEventId = null; function addEvenement() { _editingEventId = null; document.getElementById('modal-event-title').textContent = 'Ajouter un événement'; document.getElementById('modal-event-when').value = ''; document.getElementById('modal-event-name').value = ''; document.getElementById('modal-event-desc').value = ''; document.getElementById('modal-event-icon').value = 'fete'; document.getElementById('cimple-modal-event').classList.add('show'); } window.addEvenement = addEvenement; function editEvenement(id) { const items = state.evenements && state.evenements.length ? state.evenements : DEFAULT_EVENEMENTS; const it = items.find(x => x.id === id); if (!it) return; _editingEventId = id; document.getElementById('modal-event-title').textContent = 'Modifier l\'événement'; document.getElementById('modal-event-when').value = it.when || ''; document.getElementById('modal-event-name').value = it.name || ''; document.getElementById('modal-event-desc').value = it.desc || ''; document.getElementById('modal-event-icon').value = it.iconName || 'fete'; document.getElementById('cimple-modal-event').classList.add('show'); } window.editEvenement = editEvenement; function closeEventModal() { document.getElementById('cimple-modal-event').classList.remove('show'); } window.closeEventModal = closeEventModal; function saveEventModal() { const when = document.getElementById('modal-event-when').value.trim(); const name = document.getElementById('modal-event-name').value.trim(); const desc = document.getElementById('modal-event-desc').value.trim(); const iconName = document.getElementById('modal-event-icon').value; if (!name) { alert('Le nom est obligatoire'); return; } if (!state.evenements || !state.evenements.length) { state.evenements = DEFAULT_EVENEMENTS.map(x => ({...x})); } if (_editingEventId) { const it = state.evenements.find(x => x.id === _editingEventId); if (it) Object.assign(it, { when, name, desc, iconName }); } else { state.evenements.push({ id: 'e' + Date.now(), when, name, desc, iconName }); } persist(); closeEventModal(); rebuildSanctuaire(); } window.saveEventModal = saveEventModal; function deleteEvenement(id) { if (!confirm('Supprimer cet événement ?')) return; if (!state.evenements || !state.evenements.length) { state.evenements = DEFAULT_EVENEMENTS.map(x => ({...x})); } state.evenements = state.evenements.filter(x => x.id !== id); persist(); rebuildSanctuaire(); } window.deleteEvenement = deleteEvenement; // ── 🪄 BAGUETTE MAGIQUE — cycle les 17 esthétiques d'icônes function wandClick() { const current = getCurrentIconSetId(); const idx = ICON_SETS.findIndex(s => s.id === current); const nextIdx = (idx + 1) % ICON_SETS.length; const next = ICON_SETS[nextIdx]; state.iconSet = next.id; persist(); // Animation : la baguette pulse, l'étiquette apparaît const btn = document.getElementById('cimple-wand-btn'); if (btn) { btn.style.transform = 'rotate(-25deg) scale(1.15)'; setTimeout(() => { btn.style.transform = ''; }, 250); } const lbl = document.getElementById('cimple-wand-label'); if (lbl) { lbl.innerHTML = `★ ${esc(next.name)}
${esc(next.mood)}
${nextIdx + 1} / ${ICON_SETS.length} — clic pour suivant`; lbl.style.display = 'block'; clearTimeout(window._wandLblTimer); window._wandLblTimer = setTimeout(() => { lbl.style.display = 'none'; }, 4500); } rebuildSanctuaire(); } window.wandClick = wandClick; // ── "Tout publier d'un coup" — active tous les modules citoyens essentiels function publierTout() { const ESSENTIELS = ['accueil-3-portes', 'actualites-agenda', 'alertes', 'elus', 'module-demarches', 'services-essentiels', 'signaler', 'evenements', 'mentions-legales']; if (!state.modules) state.modules = {}; ESSENTIELS.forEach(m => state.modules[m] = true); // Et les contenus défaut si vides if (!state.actualites || !state.actualites.length) state.actualites = DEFAULT_ACTUALITES.map(x => ({...x})); if (!state.evenements || !state.evenements.length) state.evenements = DEFAULT_EVENEMENTS.map(x => ({...x})); persist(); alert('✓ Tous les modules citoyens essentiels sont publiés (' + ESSENTIELS.length + ').\n\nVotre site est complet : actualités, alertes, élus, démarches, signalement, événements, mentions légales — tout est en ligne.'); rebuildSanctuaire(); } window.publierTout = publierTout; // ════════════════════════════════════════════════════════════════ // HELPER ICÔNES — set adaptable + baguette magique (16 esthétiques) // ════════════════════════════════════════════════════════════════ const SKIN_TO_ICONSET = { patrimoine: 'generated', villageois: 'generated_aquarelle', mediterraneen: 'generated_ligne', republicain: 'generated_republicain', contemporain: 'generated_moderne', }; window.SKIN_TO_ICONSET = SKIN_TO_ICONSET; // Cycle des esthétiques disponibles (baguette magique) const ICON_SETS = [ { id: 'generated', name: 'Vintage / Imagen', mood: 'Patine ancienne, parchemin' }, { id: 'generated_republicain', name: 'Républicain', mood: 'Gravure XIXᵉ, bleu marine & or' }, { id: 'generated_aquarelle', name: 'Aquarelle', mood: 'Pinceaux doux, pastoral' }, { id: 'generated_ligne', name: 'Ligne unique', mood: 'Terracotta, calligraphie continue' }, { id: 'generated_moderne', name: 'Flat moderne', mood: 'Vecteur 2 couleurs, app moderne' }, { id: 'generated_bauhaus', name: 'Bauhaus', mood: 'Géométrie pure, primaires' }, { id: 'generated_brutalist', name: 'Brutaliste', mood: 'Béton, contraste radical' }, { id: 'generated_isometric', name: 'Isométrique', mood: 'Vue 3D pixel-perfect' }, { id: 'generated_memphis', name: 'Memphis 80s', mood: 'Couleurs vives, motifs ludiques' }, { id: 'generated_muji', name: 'Muji', mood: 'Minimal japonais, neutre' }, { id: 'generated_newyorker', name: 'New Yorker', mood: 'Illustration éditoriale' }, { id: 'generated_rams', name: 'Dieter Rams', mood: 'Braun, fonctionnaliste' }, { id: 'generated_risograph', name: 'Risograph', mood: 'Sérigraphie, encre superposée' }, { id: 'generated_scandinave', name: 'Scandinave', mood: 'Design nordique épuré' }, { id: 'generated_scher', name: 'Paula Scher', mood: 'Typo expressive' }, { id: 'generated_swiss_grid', name: 'Grille suisse', mood: 'International style, Helvetica' }, { id: 'generated_y2k', name: 'Y2K', mood: 'Chrome, métal, années 2000' }, ]; function iconBase() { // Si l'utilisateur a choisi via la baguette magique → on respecte if (state && state.iconSet) return '../_icons_premium/' + state.iconSet + '/'; // Sinon mapping automatique selon skin const skin = (state && state.skin) || 'republicain'; const set = SKIN_TO_ICONSET[skin] || 'generated'; return '../_icons_premium/' + set + '/'; } function getCurrentIconSetId() { if (state && state.iconSet) return state.iconSet; const skin = (state && state.skin) || 'republicain'; return SKIN_TO_ICONSET[skin] || 'generated'; } function icon(name, fallback, opts) { const size = (opts && opts.size) || 'inline'; const cls = 'cimple-icon cimple-icon-' + size; // avec onerror double-fallback : // 1) si le PNG du skin manque → essai sur 'generated' (set par défaut) // 2) si le default manque aussi → fallback emoji const escFb = (fallback || '').replace(/'/g, "\\'").replace(/"/g, '"'); const fbDefault = '../_icons_premium/generated/icon-' + name + '.png'; return ``; } // (Fonction askCommune retirée — remplacée par window.CimpleSearch dans _lib/cimple-search.js)