Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
f626cd52fd |
@@ -5,6 +5,12 @@ 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.15] - 2024-03-20
|
||||
### Hinzugefügt
|
||||
- Autovervollständigung für das Ort-Feld
|
||||
- Neue API-Route für Ortsvorschläge
|
||||
- Optimierte SQL-Abfragen für die Ortssuche
|
||||
|
||||
## [1.2.14] - 2024-03-20
|
||||
### Hinzugefügt
|
||||
- Autovervollständigung für das Fachrichtungsfeld
|
||||
|
@@ -14,7 +14,7 @@ Eine moderne Webanwendung zur Suche und Verwaltung von Kundendaten, die MEDISOFT
|
||||
|
||||
## Version
|
||||
|
||||
Aktuelle Version: 1.2.14
|
||||
Aktuelle Version: 1.2.15
|
||||
|
||||
## Installation
|
||||
|
||||
|
28
app.py
28
app.py
@@ -18,7 +18,7 @@ logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Version der Anwendung
|
||||
VERSION = "1.2.14"
|
||||
VERSION = "1.2.15"
|
||||
|
||||
# Pfad zur Datenbank
|
||||
DB_FILE = 'data/customers.db'
|
||||
@@ -374,6 +374,32 @@ def get_fachrichtungen():
|
||||
logger.error(f"Fehler beim Abrufen der Fachrichtungen: {str(e)}")
|
||||
return jsonify([])
|
||||
|
||||
@app.route('/api/orte')
|
||||
def get_orte():
|
||||
try:
|
||||
search_term = request.args.get('q', '').lower()
|
||||
conn = get_db_connection()
|
||||
c = conn.cursor()
|
||||
|
||||
# Hole alle eindeutigen Orte, die mit dem Suchbegriff übereinstimmen
|
||||
c.execute('''
|
||||
SELECT DISTINCT ort
|
||||
FROM customers
|
||||
WHERE ort IS NOT NULL
|
||||
AND ort != ''
|
||||
AND LOWER(ort) LIKE ?
|
||||
ORDER BY ort
|
||||
LIMIT 10
|
||||
''', (f'%{search_term}%',))
|
||||
|
||||
orte = [row[0] for row in c.fetchall()]
|
||||
conn.close()
|
||||
|
||||
return jsonify(orte)
|
||||
except Exception as e:
|
||||
logger.error(f"Fehler beim Abrufen der Orte: {str(e)}")
|
||||
return jsonify([])
|
||||
|
||||
def init_app(app):
|
||||
"""Initialisiert die Anwendung mit allen notwendigen Einstellungen."""
|
||||
with app.app_context():
|
||||
|
@@ -107,6 +107,8 @@
|
||||
<script>
|
||||
let searchTimeout;
|
||||
let lastResults = [];
|
||||
let fachrichtungTimeout;
|
||||
let ortTimeout;
|
||||
|
||||
function createPhoneLink(phone) {
|
||||
if (!phone) return '';
|
||||
@@ -407,6 +409,103 @@
|
||||
searchCustomers();
|
||||
}
|
||||
});
|
||||
|
||||
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';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
setupFachrichtungAutocomplete();
|
||||
setupOrtAutocomplete();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Reference in New Issue
Block a user