let searchTimeout; let lastResults = []; let fachrichtungTimeout; let ortTimeout; function createPhoneLink(phone) { if (!phone) return ''; const clientIP = document.querySelector('meta[name="client-ip"]').content; const allowedIPRanges = document.querySelector('meta[name="allowed-ip-ranges"]').content.split(','); // Überprüfen, ob die Client-IP in einem der erlaubten Bereiche liegt const isAllowed = allowedIPRanges.some(range => isIPInSubnet(clientIP, range.trim())); // Entferne alle nicht-numerischen Zeichen let cleanNumber = phone.replace(/\D/g, ''); // Formatiere die Nummer let formattedNumber = cleanNumber; if (cleanNumber.length === 11) { formattedNumber = cleanNumber.replace(/(\d{4})(\d{7})/, '$1-$2'); } else if (cleanNumber.length === 10) { formattedNumber = cleanNumber.replace(/(\d{3})(\d{7})/, '$1-$2'); } // Erstelle den Link return `${formattedNumber}`; } function createEmailLink(email) { if (!email) return ''; return `${email}`; } function highlightText(text, searchTerm) { if (!searchTerm || !text) return text; // Escapen von Sonderzeichen im Suchbegriff const escapedSearchTerm = searchTerm.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // Erstelle einen regulären Ausdruck ohne Wortgrenzen const regex = new RegExp(escapedSearchTerm, 'gi'); return text.replace(regex, '$&'); } function createAddressLink(street, plz, city) { if (!street || !plz || !city) return ''; const address = `${street}, ${plz} ${city}`; const searchQuery = encodeURIComponent(address); const routeQuery = encodeURIComponent(address); return `${address} `; } function adjustCustomerNumber(number) { return number - 12000; } function isIPInSubnet(ip, subnet) { // Teile die IP und das Subnetz in ihre Komponenten const [subnetIP, bits] = subnet.split('/'); const ipParts = ip.split('.').map(Number); const subnetParts = subnetIP.split('.').map(Number); // Konvertiere IPs in 32-bit Zahlen const ipNum = (ipParts[0] << 24) | (ipParts[1] << 16) | (ipParts[2] << 8) | ipParts[3]; const subnetNum = (subnetParts[0] << 24) | (subnetParts[1] << 16) | (subnetParts[2] << 8) | subnetParts[3]; // Erstelle die Subnetzmaske const mask = ~((1 << (32 - bits)) - 1); // Prüfe, ob die IP im Subnetz liegt return (ipNum & mask) === (subnetNum & mask); } function createCustomerLink(nummer) { const clientIP = document.querySelector('meta[name="client-ip"]').content; const allowedIPRanges = document.querySelector('meta[name="allowed-ip-ranges"]').content.split(','); // Überprüfe, ob die Client-IP in einem der erlaubten Bereiche liegt const isAllowed = allowedIPRanges.some(range => { const trimmedRange = range.trim(); return isIPInSubnet(clientIP, trimmedRange); }); if (isAllowed) { const adjustedNumber = adjustCustomerNumber(nummer); return `${nummer}`; } else { return nummer; } } function showCopyFeedback() { const feedback = document.getElementById('shareFeedback'); feedback.style.display = 'block'; feedback.style.opacity = '1'; feedback.addEventListener('animationend', () => { feedback.style.display = 'none'; }, { once: true }); } async function copyCustomerLink(customerNumber) { const url = new URL(window.location.href); url.searchParams.set('kundennummer', customerNumber); try { await navigator.clipboard.writeText(url.toString()); showCopyFeedback(); } catch (err) { // Fehlerbehandlung ohne console.log } } function updateResultCounts() { // Nur Gesamtzahl anzeigen const generalCount = lastResults.length; document.getElementById('resultCount').textContent = generalCount > 0 ? `${generalCount} Treffer gefunden` : ''; document.getElementById('resultCount').classList.toggle('visible', generalCount > 0); // Export-Button anzeigen/verstecken document.getElementById('exportButton').style.display = generalCount > 0 ? 'inline-block' : 'none'; } function exportToCSV() { if (!lastResults || lastResults.length === 0) return; // CSV-Header definieren const headers = [ 'Nummer', 'Name', 'Fachrichtung', 'Straße', 'PLZ', 'Ort', 'Telefon', 'Mobil', 'Handy', 'Telefon Firma', 'E-Mail', 'Kontakt 1', 'Kontakt 2', 'Kontakt 3', 'Tags' ]; // CSV-Daten erstellen const csvRows = [headers]; lastResults.forEach(customer => { const row = [ customer.nummer, customer.name, customer.fachrichtung, customer.strasse, customer.plz, customer.ort, customer.telefon, customer.mobil, customer.handy, customer.tele_firma, customer.email, customer.kontakt1, customer.kontakt2, customer.kontakt3, (customer.tags || []).join(';') ].map(value => { // Werte mit Kommas oder Anführungszeichen in Anführungszeichen setzen if (value && (value.includes(',') || value.includes('"') || value.includes('\n'))) { return `"${value.replace(/"/g, '""')}"`; } return value || ''; }); csvRows.push(row); }); // CSV-String erstellen const csvContent = csvRows.map(row => row.join(',')).join('\n'); // Blob erstellen und Download starten const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' }); const link = document.createElement('a'); const url = URL.createObjectURL(blob); link.setAttribute('href', url); link.setAttribute('download', `kundensuche_${new Date().toISOString().split('T')[0]}.csv`); link.style.visibility = 'hidden'; document.body.appendChild(link); link.click(); document.body.removeChild(link); } function displayResults(results) { const resultsDiv = document.getElementById('results'); const resultCount = document.getElementById('resultCount'); const generalSearchTerm = document.getElementById('q').value; const nameSearchTerm = document.getElementById('nameInput').value; const fachrichtungSearchTerm = document.getElementById('fachrichtungInput').value; if (!results || results.length === 0) { resultsDiv.innerHTML = '
Keine Ergebnisse gefunden.
'; resultCount.textContent = '0 Ergebnisse'; return; } resultCount.textContent = `${results.length} Ergebnisse`; lastResults = results; const resultsHTML = results.map(customer => { const highlightedName = highlightText(customer.name, nameSearchTerm); const highlightedFachrichtung = highlightText(customer.fachrichtung, fachrichtungSearchTerm); const highlightedGeneral = highlightText(customer.name, generalSearchTerm) || highlightText(customer.fachrichtung, generalSearchTerm) || highlightText(customer.ort, generalSearchTerm); // Hilfsfunktion zum Erstellen von Feldern nur wenn sie Werte haben const createFieldIfValue = (label, value, formatter = (v) => v) => { if (!value || value === 'N/A' || value === 'n/a' || value === 'N/a' || (typeof value === 'string' && value.trim() === '')) return ''; const formattedValue = formatter(value); return `${label}: ${formattedValue}
`; }; return `Tags: ${customer.tags.map(tag => `${tag}`).join('')}
` : ''}Ein Fehler ist aufgetreten. Bitte versuchen Sie es später erneut.
'; } finally { loading.style.display = 'none'; } }, 300); } function setupFachrichtungAutocomplete() { const fachrichtungInput = document.getElementById('fachrichtungInput'); const autocompleteList = document.createElement('div'); autocompleteList.className = 'autocomplete-items'; fachrichtungInput.parentNode.appendChild(autocompleteList); fachrichtungInput.addEventListener('input', function() { clearTimeout(fachrichtungTimeout); const searchTerm = this.value; if (searchTerm.length < 2) { autocompleteList.style.display = 'none'; return; } fachrichtungTimeout = setTimeout(() => { fetch(`/api/fachrichtungen?q=${encodeURIComponent(searchTerm)}`) .then(response => response.json()) .then(data => { autocompleteList.innerHTML = ''; if (data.length > 0) { data.forEach(item => { const div = document.createElement('div'); div.textContent = item; div.addEventListener('click', () => { fachrichtungInput.value = item; autocompleteList.style.display = 'none'; searchCustomers(); }); autocompleteList.appendChild(div); }); autocompleteList.style.display = 'block'; } else { autocompleteList.style.display = 'none'; } }); }, 300); }); document.addEventListener('click', function(e) { if (!fachrichtungInput.contains(e.target) && !autocompleteList.contains(e.target)) { autocompleteList.style.display = 'none'; } }); } function setupOrtAutocomplete() { const ortInput = document.getElementById('ortInput'); const autocompleteList = document.createElement('div'); autocompleteList.className = 'autocomplete-items'; ortInput.parentNode.appendChild(autocompleteList); ortInput.addEventListener('input', function() { clearTimeout(ortTimeout); const searchTerm = this.value; if (searchTerm.length < 2) { autocompleteList.style.display = 'none'; return; } ortTimeout = setTimeout(() => { fetch(`/api/orte?q=${encodeURIComponent(searchTerm)}`) .then(response => response.json()) .then(data => { autocompleteList.innerHTML = ''; if (data.length > 0) { data.forEach(item => { const div = document.createElement('div'); div.textContent = item; div.addEventListener('click', () => { ortInput.value = item; autocompleteList.style.display = 'none'; searchCustomers(); }); autocompleteList.appendChild(div); }); autocompleteList.style.display = 'block'; } else { autocompleteList.style.display = 'none'; } }); }, 300); }); document.addEventListener('click', function(e) { if (!ortInput.contains(e.target) && !autocompleteList.contains(e.target)) { autocompleteList.style.display = 'none'; } }); } // Event-Listener für die URL-Parameter und Autocomplete-Setup document.addEventListener('DOMContentLoaded', function() { const urlParams = new URLSearchParams(window.location.search); const kundennummer = urlParams.get('kundennummer'); const name = urlParams.get('name'); const ort = urlParams.get('ort'); const plz = urlParams.get('plz'); if (kundennummer) { document.getElementById('nummerInput').value = kundennummer; searchCustomers(); } if (name) { document.getElementById('nameInput').value = name; searchCustomers(); } if (ort) { document.getElementById('ortInput').value = ort; searchCustomers(); } if (plz) { document.getElementById('plzInput').value = plz; searchCustomers(); } // Setup Autocomplete setupFachrichtungAutocomplete(); setupOrtAutocomplete(); });