diff --git a/CHANGELOG.md b/CHANGELOG.md index 34ec32d..297a5e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ Alle wichtigen Änderungen an diesem Projekt werden in dieser Datei dokumentiert Das Format basiert auf [Keep a Changelog](https://keepachangelog.com/de/1.0.0/), und dieses Projekt adhäriert zu [Semantic Versioning](https://semver.org/lang/de/). +## [1.2.2] - 2024-03-19 +### Geändert +- Verbesserte Telefonnummern-Formatierung: Führende "0" wird immer hinzugefügt, wenn der Benutzer von einer erlaubten IP-Adresse zugreift + ## [1.2.1] - 2024-03-18 ### Geändert - Verbesserte CSV-Import-Funktionalität mit pandas diff --git a/templates/index.html b/templates/index.html index 4d282fb..9382cb2 100644 --- a/templates/index.html +++ b/templates/index.html @@ -16,45 +16,52 @@ medisoftware Logo
-

medisoftware Kundensuche

+

Kundensuche

-
- - - 🔍 +
- - +
+ + + +
+
- - +
+ + + +
+
- - +
+ + + +
+
- - -
-
- - +
+ + + +
- +
@@ -63,21 +70,19 @@
-
- -
+
- Link kopiert! + Link in die Zwischenablage kopiert!
@@ -87,15 +92,45 @@ function createPhoneLink(phone) { if (!phone) return 'N/A'; - const cleaned = phone.replace(/[^\d+\s]/g, ''); + const clientIP = '{{ request.headers.get("X-Forwarded-For", request.remote_addr) }}'; const allowedIPRanges = '{{ allowed_ip_ranges }}'.split(','); - + // Überprüfen, ob die Client-IP in einem der erlaubten Bereiche liegt - const isAllowed = allowedIPRanges.some(range => clientIP.startsWith(range.trim())); - - const telLink = cleaned.startsWith('+') ? cleaned : (isAllowed ? '0' + cleaned.replace(/\s/g, '') : cleaned.replace(/\s/g, '')); - return `${phone}`; + const isAllowed = allowedIPRanges.some(range => isIPInSubnet(clientIP, range.trim())); + + // Debug-Ausgabe für die IP-Bereiche + console.log('Client IP in createPhoneLink:', clientIP); + console.log('Allowed IP Ranges:', allowedIPRanges); + console.log('isAllowed in createPhoneLink:', isAllowed); + console.log('Original phone:', phone); + + // Entferne alle nicht-numerischen Zeichen + let cleanNumber = phone.replace(/\D/g, ''); + console.log('Cleaned number:', cleanNumber); + + // Füge eine führende 0 hinzu, wenn isAllowed true ist + if (isAllowed) { + console.log('Adding leading 0 to:', cleanNumber); + cleanNumber = '0' + cleanNumber; + console.log('Number after adding 0:', cleanNumber); + } + + // 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'); + } + + console.log('Final formatted number:', formattedNumber); + console.log('Final clean number for tel link:', cleanNumber); + + // Erstelle den Link + const link = `${formattedNumber}`; + console.log('Final link:', link); + return link; } function createEmailLink(email) { @@ -103,48 +138,10 @@ return `${email}`; } - function highlightText(text, searchTerms) { - // Konvertiere text zu String und prüfe auf null/undefined - const textStr = String(text || ''); - if (!textStr || !searchTerms || searchTerms.length === 0) return textStr; - - // Escapen der Suchbegriffe für reguläre Ausdrücke - const escapedTerms = searchTerms.map(term => - String(term || '').replace(/[.*+?^${}()|[\]\\]/g, '\\$&') - ).filter(term => term.length > 0); - - if (escapedTerms.length === 0) return textStr; - - // Erstelle einen temporären div-Element - const tempDiv = document.createElement('div'); - tempDiv.innerHTML = textStr; - - // Funktion zum Hervorheben von Text - function highlightNode(node) { - if (node.nodeType === 3) { // Text node - const text = node.textContent; - let newText = text; - - escapedTerms.forEach(term => { - const regex = new RegExp(`(${term})`, 'gi'); - newText = newText.replace(regex, '$1'); - }); - - if (newText !== text) { - const span = document.createElement('span'); - span.innerHTML = newText; - node.parentNode.replaceChild(span, node); - } - } else if (node.nodeType === 1) { // Element node - // Überspringe mark-Tags und Links - if (node.tagName !== 'MARK' && node.tagName !== 'A') { - Array.from(node.childNodes).forEach(highlightNode); - } - } - } - - highlightNode(tempDiv); - return tempDiv.innerHTML; + function highlightText(text, searchTerm) { + if (!searchTerm) return text; + const regex = new RegExp(`(${searchTerm})`, 'gi'); + return text.replace(regex, '$1'); } function createAddressLink(street, plz, city) { @@ -236,154 +233,129 @@ function updateResultCounts() { // Nur Gesamtzahl anzeigen const generalCount = lastResults.length; - document.getElementById('generalCount').textContent = + document.getElementById('resultCount').textContent = generalCount > 0 ? `${generalCount} Treffer gefunden` : ''; - document.getElementById('generalCount').classList.toggle('visible', generalCount > 0); + document.getElementById('resultCount').classList.toggle('visible', generalCount > 0); } - function searchCustomers() { - const query = document.getElementById('searchInput').value.trim(); - const fachrichtung = document.getElementById('fachrichtungInput').value.trim(); - const ort = document.getElementById('ortInput').value.trim(); - const name = document.getElementById('nameInput').value.trim(); - const telefon = document.getElementById('telefonInput').value.trim(); - const kundennummer = document.getElementById('kundennummerInput')?.value.trim() || ''; + function displayResults(results) { + const resultsDiv = document.getElementById('results'); + resultsDiv.innerHTML = ''; - // Sammle alle nicht-leeren Suchbegriffe - const searchTerms = [query, fachrichtung, ort, name, telefon, kundennummer] - .filter(term => term && term.length > 0); - - // Prüfe, ob alle Suchfelder leer sind - if (searchTerms.length === 0) { - const resultsDiv = document.getElementById('results'); - const generalCount = document.getElementById('generalCount'); - resultsDiv.innerHTML = ''; - generalCount.textContent = ''; - generalCount.classList.remove('visible'); + if (results.length === 0) { + resultsDiv.innerHTML = '

Keine Ergebnisse gefunden.

'; return; } - const resultsDiv = document.getElementById('results'); - const loadingDiv = document.getElementById('loading'); - loadingDiv.style.display = 'block'; - resultsDiv.innerHTML = ''; + const searchTerm = document.getElementById('q').value; - const searchParams = new URLSearchParams(); - if (query) searchParams.append('q', query); - if (fachrichtung) searchParams.append('fachrichtung', fachrichtung); - if (ort) searchParams.append('ort', ort); - if (name) searchParams.append('name', name); - if (telefon) searchParams.append('telefon', telefon); - if (kundennummer) searchParams.append('kundennummer', kundennummer); - - fetch(`/search?${searchParams.toString()}`) + results.forEach(customer => { + const card = document.createElement('div'); + card.className = 'customer-card'; + card.innerHTML = ` +
+
${highlightText(customer.name, searchTerm)}
+

${createCustomerLink(customer.nummer)}

+

${createAddressLink(customer.strasse, customer.plz, customer.ort)}

+

Tel: ${createPhoneLink(customer.telefon)}

+ ${customer.mobil ? `

Mobil: ${createPhoneLink(customer.mobil)}

` : ''} + ${customer.email ? `

E-Mail: ${createEmailLink(customer.email)}

` : ''} + ${customer.bemerkung ? `

Bemerkung: ${customer.bemerkung}

` : ''} +
+
+ +
+ `; + resultsDiv.appendChild(card); + }); + } + + function searchCustomers() { + const q = document.getElementById('q').value; + const name = document.getElementById('nameInput').value; + const ort = document.getElementById('ortInput').value; + const nummer = document.getElementById('nummerInput').value; + const plz = document.getElementById('plzInput').value; + + // Zeige das Lade-Icon + document.getElementById('loading').style.display = 'block'; + + // Baue die Suchanfrage + const params = new URLSearchParams(); + if (q) params.append('q', q); + if (name) params.append('name', name); + if (ort) params.append('ort', ort); + if (nummer) params.append('nummer', nummer); + if (plz) params.append('plz', plz); + + // Führe die Suche durch + fetch('/search?' + params.toString()) .then(response => response.json()) .then(data => { - resultsDiv.innerHTML = ''; + // Verstecke das Lade-Icon + document.getElementById('loading').style.display = 'none'; - // Prüfe, ob data ein Objekt mit results-Array ist - if (!data || !data.results || !Array.isArray(data.results)) { - console.error('Unerwartetes Datenformat:', data); - resultsDiv.innerHTML = '
Unerwartetes Datenformat vom Server
'; + if (data.error) { + console.error('Fehler bei der Suche:', data.error); return; } - - const results = data.results; - if (results.length === 0) { - resultsDiv.innerHTML = '
Keine Ergebnisse gefunden
'; - } else { - results.forEach(customer => { - const card = document.createElement('div'); - card.className = 'customer-card'; - - // Debug-Ausgabe für die Kundendaten - console.log('Kundendaten:', customer); - console.log('Alle verfügbaren Felder:', Object.keys(customer)); - console.log('Telefon-bezogene Felder:', { - Telefon: customer.Telefon, - Telefonnummer: customer.Telefonnummer, - telefon: customer.telefon, - telefonnummer: customer.telefonnummer, - phone: customer.phone, - 'phone.number': customer.phone?.number - }); - - // Erstelle die Adresse mit Hervorhebung - const address = `${customer.Strasse || ''}, ${customer.PLZ || ''} ${customer.Ort || ''}`; - const addressLink = createAddressLink(customer.Strasse, customer.PLZ, customer.Ort); - const highlightedAddress = highlightText(addressLink, searchTerms); - - // Erstelle die Kundennummer mit Hervorhebung - const highlightedNumber = highlightText(customer.Nummer, searchTerms); - const customerLink = createCustomerLink(customer.Nummer); - - // Erstelle die Telefonnummern mit Hervorhebung - let phoneNumber = ''; - let companyPhone = ''; - let mobilePhone = ''; - - if (typeof customer === 'object') { - phoneNumber = customer.Tel || ''; - companyPhone = customer['Tele Firma'] || ''; - mobilePhone = customer.Handy || ''; - } - - const phoneLink = createPhoneLink(phoneNumber); - const companyPhoneLink = createPhoneLink(companyPhone); - const mobilePhoneLink = createPhoneLink(mobilePhone); - - const highlightedPhone = highlightText(phoneLink, searchTerms); - const highlightedCompanyPhone = highlightText(companyPhoneLink, searchTerms); - const highlightedMobilePhone = highlightText(mobilePhoneLink, searchTerms); - - card.innerHTML = ` -
- Kundennummer: ${customerLink}
- Name: ${highlightText(`${customer.Vorname || ''} ${customer.Nachname || ''}`, searchTerms)}
- Fachrichtung: ${highlightText(customer.Fachrichtung || '', searchTerms)}
- Adresse: ${highlightedAddress}
- Telefon: ${highlightedPhone}
- Firma: ${highlightedCompanyPhone}
- Mobil: ${highlightedMobilePhone} -
- - `; - resultsDiv.appendChild(card); - }); - } - // Aktualisiere die Anzahl der Treffer - const generalCount = document.getElementById('generalCount'); - generalCount.textContent = results.length > 0 ? `${results.length} Treffer gefunden` : ''; - generalCount.classList.toggle('visible', results.length > 0); + + `; + resultsDiv.appendChild(card); + }); }) .catch(error => { console.error('Fehler bei der Suche:', error); - resultsDiv.innerHTML = '
Ein Fehler ist aufgetreten
'; - }) - .finally(() => { - loadingDiv.style.display = 'none'; + document.getElementById('loading').style.display = 'none'; }); } // Event-Listener für die Live-Suche const searchInputs = [ + document.getElementById('q'), document.getElementById('nameInput'), document.getElementById('ortInput'), - document.getElementById('kundennummerInput'), - document.getElementById('fachrichtungInput'), - document.getElementById('telefonInput'), - document.getElementById('searchInput') + document.getElementById('nummerInput'), + document.getElementById('plzInput') ]; const resetIcons = [ - document.getElementById('nameReset'), - document.getElementById('ortReset'), - document.getElementById('kundennummerReset'), - document.getElementById('fachrichtungReset'), - document.getElementById('telefonReset'), - document.getElementById('searchReset') + document.querySelector('.reset-icon[onclick="clearInput(\'q\')"]'), + document.querySelector('.reset-icon[onclick="clearInput(\'nameInput\')"]'), + document.querySelector('.reset-icon[onclick="clearInput(\'ortInput\')"]'), + document.querySelector('.reset-icon[onclick="clearInput(\'nummerInput\')"]'), + document.querySelector('.reset-icon[onclick="clearInput(\'plzInput\')"]') ]; searchInputs.forEach((input, index) => { @@ -408,18 +380,14 @@ const name = urlParams.get('name'); const ort = urlParams.get('ort'); const kundennummer = urlParams.get('kundennummer'); - const fachrichtung = urlParams.get('fachrichtung'); - const telefon = urlParams.get('telefon'); - const query = urlParams.get('q'); + const plz = urlParams.get('plz'); if (name) document.getElementById('nameInput').value = name; if (ort) document.getElementById('ortInput').value = ort; - if (kundennummer) document.getElementById('kundennummerInput').value = kundennummer; - if (fachrichtung) document.getElementById('fachrichtungInput').value = fachrichtung; - if (telefon) document.getElementById('telefonInput').value = telefon; - if (query) document.getElementById('searchInput').value = query; + if (kundennummer) document.getElementById('nummerInput').value = kundennummer; + if (plz) document.getElementById('plzInput').value = plz; - if (name || ort || kundennummer || fachrichtung || telefon || query) { + if (name || ort || kundennummer || plz) { searchCustomers(); } });