function colorHeadingTable() { const headers = document.querySelectorAll('th'); headers.forEach(header => { const text = header.textContent; const match = text.match(/\((\d+)\s*\/\s*(\d+)\)/); if (match) { const [_, completed, total] = match; const ratio = completed / total; const alpha = ratio.toFixed(2); header.style.backgroundColor = `rgba(154, 205, 50, ${alpha})`; } }); } function check_validity(e) { list_inputs_good_to_fill = [ 'input[name="commerce_tag_value__contact:email"]', 'input[name="commerce_tag_value__contact:phone"]', 'input[name="commerce_tag_value__contact:website"]', 'input[name="commerce_tag_value__contact:mastodon"]', 'input[name="commerce_tag_value__address"]', 'input[name="custom_opening_hours"]', 'input[name="commerce_tag_value__contact:street"]', 'input[name="commerce_tag_value__contact:housenumber"]', 'input[name="custom__cuisine"]', ] list_inputs_good_to_fill.forEach(selector => { const input = document.querySelector(selector); if (input) { if (input.value.trim() !== '') { input.classList.add('good_filled'); } else { input.classList.remove('good_filled'); } } }); let errors = []; document.querySelectorAll('.is-invalid').forEach(input => { input.classList.remove('is-invalid'); }); const nameInput = document.querySelector('input[name="commerce_tag_value__name"]'); if (!nameInput.value.trim()) { errors.push("Le nom de l'établissement est obligatoire"); nameInput.classList.add('is-invalid'); } const emailInput = document.querySelector('input[name="commerce_tag_value__contact:email"]'); if (emailInput && emailInput.value) { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!emailRegex.test(emailInput.value)) { errors.push("L'adresse email n'est pas valide"); emailInput.classList.add('is-invalid'); } } const phoneInput = document.querySelector('input[name="commerce_tag_value__contact:phone"]'); if (phoneInput && phoneInput.value) { const phoneRegex = /^(\+33|0)[1-9](\d{2}){4}$/; if (!phoneRegex.test(phoneInput.value.replace(/\s/g, ''))) { errors.push("Le numéro de téléphone n'est pas valide"); phoneInput.classList.add('is-invalid'); } } if (errors.length > 0) { e.preventDefault(); document.querySelector('#validation_messages').innerHTML = errors.join('
'); document.querySelector('#validation_messages').classList.add('is-invalid'); } } // Générer une couleur pastel aléatoire const genererCouleurPastel = () => { // Utiliser des valeurs plus claires (180-255) pour obtenir des tons pastel const r = Math.floor(Math.random() * 75 + 180); const g = Math.floor(Math.random() * 75 + 180); const b = Math.floor(Math.random() * 75 + 180); return `rgb(${r}, ${g}, ${b})`; }; async function searchInseeCode(query) { try { // Afficher l'indicateur de chargement document.querySelector('#loading_search_insee').classList.remove('d-none'); const response = await fetch(`https://geo.api.gouv.fr/communes?nom=${query}&fields=nom,code,codesPostaux&limit=10`); const data = await response.json(); document.querySelector('#loading_search_insee').classList.add('d-none'); return data.map(commune => ({ label: `${commune.nom} (${commune.codesPostaux.join(', ')}, code insee ${commune.code})`, insee: commune.code, postcodes: commune.codesPostaux })); } catch (error) { console.error('Erreur lors de la recherche du code INSEE:', error); return []; } } function updateMapHeightForLargeScreens() { const mapFound = document.querySelector('#map'); if (mapFound && window.innerHeight > 800 && window.innerWidth > 800) { mapFound.style.height = window.innerWidth * 0.8 + 'px'; } else { console.log('window.innerHeight', window.innerHeight); } } // lister les changesets de l'utilisateur osm-commerces async function listChangesets() { // Ajouter le header Accept pour demander du JSON const options = { headers: { 'Accept': 'application/json' } }; const changesets = await fetch('https://api.openstreetmap.org/api/0.6/changesets?display_name=osm-commerce-fr', options); const data = await changesets.json(); console.log(data.changesets.length); // Grouper les changesets par période const now = new Date(); const last24h = new Date(now - 24 * 60 * 60 * 1000); const last7days = new Date(now - 7 * 24 * 60 * 60 * 1000); const last30days = new Date(now - 30 * 24 * 60 * 60 * 1000); const stats = { last24h: 0, last7days: 0, last30days: 0 }; data.changesets.forEach(changeset => { const changesetDate = new Date(changeset.closed_at); if (changesetDate >= last24h) { stats.last24h++; } if (changesetDate >= last7days) { stats.last7days++; } if (changesetDate >= last30days) { stats.last30days++; } }); // Afficher les statistiques const historyDiv = document.getElementById('userChangesHistory'); if (historyDiv) { historyDiv.innerHTML = `

Changesets créés :

Dernières 24h :
${stats.last24h}
7 derniers jours :
${stats.last7days}
30 derniers jours :
${stats.last30days}
`; } } function openInPanoramax() { const center = map.getCenter(); const zoom = map.getZoom(); const panoramaxUrl = `https://api.panoramax.xyz/?focus=map&map=${zoom}/${center.lat}/${center.lng}`; window.open(panoramaxUrl); } function enableLabourageForm() { // Récupérer les éléments du formulaire const citySearchInput = document.getElementById('citySearch'); const citySuggestionsList = document.getElementById('citySuggestions'); if (citySearchInput && citySuggestionsList) { // Configurer la recherche de ville avec la fonction existante setupCitySearch('citySearch', 'citySuggestions', function (result_search) { console.log('code_insee', result_search.insee); // Activer le spinner dans le bouton de labourage const labourageBtn = document.querySelector('.btn-labourer'); if (labourageBtn) { labourageBtn.innerHTML = ' Chargement...'; labourageBtn.disabled = true; } console.log('result_search', result_search, getLabourerUrl(result_search)); window.location.href = getLabourerUrl(result_search); }); } } // Fonction pour gérer la recherche de villes /** * Configure la recherche de ville avec autocomplétion * @param {string} inputId - ID de l'input de recherche * @param {string} suggestionListId - ID de la liste des suggestions * @param {Function} onSelect - Callback appelé lors de la sélection d'une ville */ function setupCitySearch(inputId, suggestionListId, onSelect) { const searchInput = document.getElementById(inputId); const suggestionList = document.getElementById(suggestionListId); window.searchInput = searchInput; window.suggestionList = suggestionList; window.onSelect = onSelect; if (!searchInput || !suggestionList) return; let timeoutId = null; let searchOngoing = false; searchInput.addEventListener('input', function () { console.log('input', this.value); clearTimeout(timeoutId); const query = this.value.trim(); timeoutId = setTimeout(() => { if (!searchOngoing) { searchOngoing = true; performSearch(query); searchOngoing = false; } }, 300); }); } function performSearch(query) { console.log('performSearch', query); fetch(`https://geo.api.gouv.fr/communes?nom=${encodeURIComponent(query)}&fields=nom,code,codesPostaux&limit=5`) .then(response => response.json()) .then(data => { const citySuggestions = data.map(city => ({ name: city.nom, postcode: city.codesPostaux[0], insee: city.code })); displaySuggestions(citySuggestions); }) .catch(error => { console.error('Erreur lors de la recherche:', error); clearSuggestions(); }); } function displaySuggestions(suggestions) { console.log('displaySuggestions', suggestions); clearSuggestions(); suggestions.forEach(suggestion => { const li = document.createElement('li'); li.className = 'list-group-item p-2'; li.textContent = `${suggestion.name} (${suggestion.postcode})`; li.addEventListener('click', () => { searchInput.value = suggestion.name; clearSuggestions(); if (onSelect) onSelect(suggestion); }); window.suggestionList.appendChild(li); }); window.suggestionList.classList.remove('d-none'); console.log('window.suggestionList', window.suggestionList); } function clearSuggestions() { window.suggestionList.innerHTML = ''; } // Fermer les suggestions en cliquant en dehors document.addEventListener('click', function (e) { if (window.searchInput && !window.searchInput?.contains(e.target) && !window.suggestionList?.contains(e.target)) { clearSuggestions(); } }); // Fonction pour formater l'URL de labourage /** * Génère l'URL de labourage pour un code postal donné * @param {string} zipCode - Le code postal * @returns {string} L'URL de labourage */ function getLabourerUrl(obj) { return `/admin/labourer/${obj.insee}`; } // Fonction pour gérer la soumission du formulaire d'ajout de ville function handleAddCityFormSubmit(event) { event.preventDefault(); const form = event.target; const submitButton = form.querySelector('button[type="submit"]'); const zipCodeInput = form.querySelector('input[name="zip_code"]'); if (!zipCodeInput.value) { return; } // Afficher le spinner submitButton.disabled = true; const originalContent = submitButton.innerHTML; submitButton.innerHTML = ' Labourer...'; // Rediriger window.location.href = getLabourerUrl(zipCodeInput.value); } /** * Colore les cellules d'un tableau en fonction des pourcentages * @param {string} selector - Le sélecteur CSS pour cibler les cellules à colorer * @param {string} color - La couleur de base en format RGB (ex: '154, 205, 50') */ function colorizePercentageCells(selector, color = '154, 205, 50') { document.querySelectorAll(selector).forEach(cell => { const percentage = parseInt(cell.textContent); if (!isNaN(percentage)) { const alpha = percentage / 100; cell.style.backgroundColor = `rgba(${color}, ${alpha})`; } }); } /** * Colore les cellules d'un tableau avec un gradient relatif à la valeur maximale * @param {string} selector - Le sélecteur CSS pour cibler les cellules à colorer * @param {string} color - La couleur de base en format RGB (ex: '154, 205, 50') */ function colorizePercentageCellsRelative(selector, color = '154, 205, 50') { // Récupérer toutes les cellules const cells = document.querySelectorAll(selector); // Trouver la valeur maximale let maxValue = 0; cells.forEach(cell => { const value = parseInt(cell.textContent); if (!isNaN(value) && value > maxValue) { maxValue = value; } }); // Appliquer le gradient relatif à la valeur max cells.forEach(cell => { const value = parseInt(cell.textContent); if (!isNaN(value)) { const alpha = value / maxValue; // Ratio relatif au maximum cell.style.backgroundColor = `rgba(${color}, ${alpha})`; } }); } /** * Ajuste dynamiquement la taille du texte des éléments list-group-item selon leur nombre * @param {string} selector - Le sélecteur CSS des éléments à ajuster * @param {number} [minFont=0.8] - Taille de police minimale en rem * @param {number} [maxFont=1.2] - Taille de police maximale en rem */ function adjustListGroupFontSize(selector, minFont = 0.8, maxFont = 1.2) { const items = document.querySelectorAll(selector); const count = items.length; let fontSize = maxFont; if (count > 0) { // Plus il y a d'items, plus la taille diminue, mais jamais en dessous de minFont fontSize = Math.max(minFont, maxFont - (count - 5) * 0.05); } items.forEach(item => { item.style.fontSize = fontSize + 'rem'; }); } function check_validity() { if (!document.getElementById('editLand')) { return; } const form = document.getElementById('editLand'); const fields = { 'name': { required: true, message: 'Le nom est requis' }, 'contact:street': { required: true, message: 'La rue est requise' }, 'contact:housenumber': { required: true, message: 'Le numéro est requis' }, 'contact:phone': { pattern: /^(?:(?:\+|00)33|0)\s*[1-9](?:[\s.-]*\d{2}){4}$/, message: 'Le numéro de téléphone n\'est pas valide' }, 'contact:email': { pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, message: 'L\'adresse email n\'est pas valide' }, 'contact:website': { pattern: /^(https?:\/\/)?([\da-z.-]+)\.([a-z.]{2,6})([/\w .-]*)*\/?$/, message: 'L\'URL du site web n\'est pas valide' } }; let isValid = true; const errorMessages = {}; // Supprimer les messages d'erreur précédents document.querySelectorAll('.error-message').forEach(el => el.remove()); // Vérifier chaque champ for (const [fieldName, rules] of Object.entries(fields)) { const input = form.querySelector(`[name="${fieldName}"]`); if (!input) continue; const value = input.value.trim(); let fieldError = null; // Ne valider que si le champ n'est pas vide if (value) { if (rules.pattern && !rules.pattern.test(value)) { fieldError = rules.message; } } else if (rules.required) { // Si le champ est vide et requis fieldError = rules.message; } if (fieldError) { isValid = false; errorMessages[fieldName] = fieldError; // Créer et afficher le message d'erreur const errorDiv = document.createElement('div'); errorDiv.className = 'error-message text-danger small mt-1'; errorDiv.textContent = fieldError; input.parentNode.appendChild(errorDiv); // Ajouter une classe d'erreur au champ input.classList.add('is-invalid'); } else { input.classList.remove('is-invalid'); } } return isValid; } // Exporter les fonctions dans window window.setupCitySearch = setupCitySearch; window.getLabourerUrl = getLabourerUrl; window.handleAddCityFormSubmit = handleAddCityFormSubmit; window.colorizePercentageCells = colorizePercentageCells; window.colorizePercentageCellsRelative = colorizePercentageCellsRelative; window.adjustListGroupFontSize = adjustListGroupFontSize; window.check_validity = check_validity; window.enableLabourageForm = enableLabourageForm; window.performSearch = performSearch; window.openInPanoramax = openInPanoramax; window.listChangesets = listChangesets; window.updateMapHeightForLargeScreens = updateMapHeightForLargeScreens; window.searchInseeCode = searchInseeCode; window.genererCouleurPastel = genererCouleurPastel; window.check_validity = check_validity;