6 Commits

4 changed files with 65 additions and 46 deletions

View File

@@ -5,6 +5,24 @@ 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.6] - 2024-03-19
### Geändert
- Verbesserte Suchfunktion: Keine Ergebnisse mehr bei leeren Suchfeldern
- Optimiertes Highlighting der Suchergebnisse für alle Suchfelder
- Fachrichtung wird jetzt in den Suchergebnissen hervorgehoben
## [1.2.5] - 2024-03-19
### Hinzugefügt
- Neues Suchfeld für Fachrichtung
- Index für das Fachrichtung-Feld in der Datenbank
- Fachrichtung in der allgemeinen Suche integriert
## [1.2.4] - 2024-03-19
### Geändert
- Performance-Optimierung: Indizes für alle Suchfelder hinzugefügt
- Verbesserte Suchgeschwindigkeit durch optimierte Datenbankindizes
- Zusammengesetzter Index für die häufigste Suchkombination (Name + Ort) hinzugefügt
## [1.2.3] - 2024-03-19
### Geändert
- Performance-Optimierung: Entfernung aller console.log Anweisungen

View File

@@ -51,7 +51,7 @@ Die Anwendung unterstützt CIDR-Notation für IP-Bereiche. Beispiele:
## Version
Aktuelle Version: 1.2.1
Aktuelle Version: v1.2.6
## Lizenz
@@ -103,4 +103,4 @@ curl "http://localhost:5001/search?fachrichtung=Zahnarzt&ort=Berlin&name=Schmidt
## Version
Aktuelle Version: [v1.2.0](CHANGELOG.md#v120---2024-03-17)
Aktuelle Version: [v1.2.4](CHANGELOG.md#v124---2024-03-19)

21
app.py
View File

@@ -50,7 +50,8 @@ def init_db():
telefon TEXT,
mobil TEXT,
email TEXT,
bemerkung TEXT
bemerkung TEXT,
fachrichtung TEXT
)
''')
@@ -63,6 +64,7 @@ def init_db():
c.execute('CREATE INDEX IF NOT EXISTS idx_customers_telefon ON customers(telefon)')
c.execute('CREATE INDEX IF NOT EXISTS idx_customers_mobil ON customers(mobil)')
c.execute('CREATE INDEX IF NOT EXISTS idx_customers_email ON customers(email)')
c.execute('CREATE INDEX IF NOT EXISTS idx_customers_fachrichtung ON customers(fachrichtung)')
# Erstelle einen zusammengesetzten Index für die häufigste Suchkombination
c.execute('CREATE INDEX IF NOT EXISTS idx_customers_name_ort ON customers(name, ort)')
@@ -97,8 +99,8 @@ def import_csv():
# Importiere die Daten
for _, row in df.iterrows():
c.execute('''
INSERT INTO customers (nummer, name, strasse, plz, ort, telefon, mobil, email, bemerkung)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
INSERT INTO customers (nummer, name, strasse, plz, ort, telefon, mobil, email, bemerkung, fachrichtung)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
''', (
row['Nummer'],
row['name'],
@@ -108,7 +110,8 @@ def import_csv():
row['Tel'],
row['Handy'],
row['mail'],
f"Fachrichtung: {row['Fachrichtung']}"
f"Fachrichtung: {row['Fachrichtung']}",
row['Fachrichtung']
))
conn.commit()
@@ -132,8 +135,8 @@ def search_customers(search_params):
# Allgemeine Suche über alle Felder
if search_params.get('q'):
search_term = f"%{search_params['q']}%"
query += " AND (name LIKE ? OR ort LIKE ? OR nummer LIKE ? OR telefon LIKE ? OR mobil LIKE ? OR email LIKE ? OR bemerkung LIKE ?)"
params.extend([search_term] * 7)
query += " AND (name LIKE ? OR ort LIKE ? OR nummer LIKE ? OR telefon LIKE ? OR mobil LIKE ? OR email LIKE ? OR bemerkung LIKE ? OR fachrichtung LIKE ?)"
params.extend([search_term] * 8)
# Spezifische Suche für einzelne Felder
if search_params.get('name'):
@@ -169,7 +172,8 @@ def search_customers(search_params):
'telefon': row[6],
'mobil': row[7],
'email': row[8],
'bemerkung': row[9]
'bemerkung': row[9],
'fachrichtung': row[10]
}
customers.append(customer)
@@ -270,7 +274,8 @@ def search():
'plz': request.args.get('plz', ''),
'telefon': request.args.get('telefon', ''),
'email': request.args.get('email', ''),
'q': request.args.get('q', '')
'q': request.args.get('q', ''),
'fachrichtung': request.args.get('fachrichtung', '')
}
# Führe die Suche in der Datenbank durch

View File

@@ -58,6 +58,14 @@
<i class="fas fa-search search-icon"></i>
</div>
</div>
<div class="search-field">
<div class="input-group">
<input type="text" id="fachrichtungInput" class="form-control" placeholder="Fachrichtung" oninput="searchCustomers()">
<i class="fas fa-times reset-icon" onclick="clearInput('fachrichtungInput')"></i>
<i class="fas fa-search search-icon"></i>
</div>
</div>
</div>
<div class="result-counts">
@@ -82,7 +90,7 @@
<footer class="footer">
<div class="footer-content">
Proudly made with ❤️ and 🍺 by <a href="https://www.medisoftware.de" target="_blank" class="footer-link">medisoftware</a>
<div style="font-size: 0.8em;">Version: v1.2.2</div>
<div style="font-size: 0.8em;">Version: v1.2.6</div>
</div>
</footer>
@@ -225,20 +233,33 @@
return;
}
const searchTerm = document.getElementById('q').value;
// Hole alle Suchbegriffe
const searchTerms = {
general: document.getElementById('q').value,
name: document.getElementById('nameInput').value,
ort: document.getElementById('ortInput').value,
nummer: document.getElementById('nummerInput').value,
plz: document.getElementById('plzInput').value,
fachrichtung: document.getElementById('fachrichtungInput').value
};
results.forEach(customer => {
const card = document.createElement('div');
card.className = 'customer-card';
card.innerHTML = `
<div class="customer-info">
<h5 class="mb-1">${highlightText(customer.name, searchTerm)}</h5>
<h5 class="mb-1">${highlightText(customer.name, searchTerms.general || searchTerms.name)}</h5>
<p class="mb-1 customer-number">${createCustomerLink(customer.nummer)}</p>
<p class="mb-1">${createAddressLink(customer.strasse, customer.plz, customer.ort)}</p>
<p class="mb-1">${createAddressLink(
customer.strasse,
highlightText(customer.plz, searchTerms.general || searchTerms.plz),
highlightText(customer.ort, searchTerms.general || searchTerms.ort)
)}</p>
<p class="mb-1">Tel: ${createPhoneLink(customer.telefon)}</p>
${customer.mobil ? `<p class="mb-1">Mobil: ${createPhoneLink(customer.mobil)}</p>` : ''}
${customer.email ? `<p class="mb-1">E-Mail: ${createEmailLink(customer.email)}</p>` : ''}
${customer.bemerkung ? `<p class="mb-1">Bemerkung: ${customer.bemerkung}</p>` : ''}
${customer.fachrichtung ? `<p class="mb-1">Fachrichtung: ${highlightText(customer.fachrichtung, searchTerms.general || searchTerms.fachrichtung)}</p>` : ''}
</div>
<div class="card-actions">
<button class="share-button" onclick="copyCustomerLink('${customer.nummer}')">
@@ -256,6 +277,7 @@
const ort = document.getElementById('ortInput').value;
const nummer = document.getElementById('nummerInput').value;
const plz = document.getElementById('plzInput').value;
const fachrichtung = document.getElementById('fachrichtungInput').value;
// Zeige das Lade-Icon
document.getElementById('loading').style.display = 'block';
@@ -267,6 +289,7 @@
if (ort) params.append('ort', ort);
if (nummer) params.append('nummer', nummer);
if (plz) params.append('plz', plz);
if (fachrichtung) params.append('fachrichtung', fachrichtung);
// Führe die Suche durch
fetch('/search?' + params.toString())
@@ -281,36 +304,7 @@
lastResults = data;
updateResultCounts();
const resultsDiv = document.getElementById('results');
resultsDiv.innerHTML = '';
if (data.length === 0) {
resultsDiv.innerHTML = '<p class="text-center text-muted">Keine Ergebnisse gefunden</p>';
return;
}
data.forEach(customer => {
const card = document.createElement('div');
card.className = 'customer-card';
card.innerHTML = `
<div class="customer-info">
<h5 class="mb-1">${highlightText(customer.name, q || name)}</h5>
<p class="mb-1 customer-number">${createCustomerLink(customer.nummer)}</p>
<p class="mb-1">${createAddressLink(customer.strasse, customer.plz, customer.ort)}</p>
<p class="mb-1">Tel: ${createPhoneLink(customer.telefon)}</p>
${customer.mobil ? `<p class="mb-1">Mobil: ${createPhoneLink(customer.mobil)}</p>` : ''}
${customer.email ? `<p class="mb-1">E-Mail: ${createEmailLink(customer.email)}</p>` : ''}
${customer.bemerkung ? `<p class="mb-1">Bemerkung: ${customer.bemerkung}</p>` : ''}
</div>
<div class="card-actions">
<button class="share-button" onclick="copyCustomerLink('${customer.nummer}')">
<i class="fas fa-share-alt"></i> Teilen
</button>
</div>
`;
resultsDiv.appendChild(card);
});
displayResults(data);
})
.catch(error => {
document.getElementById('loading').style.display = 'none';
@@ -323,7 +317,8 @@
document.getElementById('nameInput'),
document.getElementById('ortInput'),
document.getElementById('nummerInput'),
document.getElementById('plzInput')
document.getElementById('plzInput'),
document.getElementById('fachrichtungInput')
];
const resetIcons = [
@@ -331,7 +326,8 @@
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\')"]')
document.querySelector('.reset-icon[onclick="clearInput(\'plzInput\')"]'),
document.querySelector('.reset-icon[onclick="clearInput(\'fachrichtungInput\')"]')
];
searchInputs.forEach((input, index) => {