Feat: Offline-Funktionalität mit IndexedDB implementiert
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" rel="stylesheet">
|
||||
<link href="{{ url_for('static', filename='css/styles.css') }}" rel="stylesheet">
|
||||
<script src="{{ url_for('static', filename='js/db.js') }}"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="main-content">
|
||||
@@ -110,28 +111,49 @@
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<div id="syncStatus" class="sync-status" style="display: none;">
|
||||
<span class="sync-icon">🔄</span>
|
||||
<span class="sync-text">Synchronisiere Daten...</span>
|
||||
</div>
|
||||
|
||||
<div id="offlineIndicator" class="offline-indicator" style="display: none;">
|
||||
<span class="offline-icon">📡</span>
|
||||
<span class="offline-text">Offline-Modus</span>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Service Worker Registrierung
|
||||
// Service Worker und IndexedDB initialisieren
|
||||
if ('serviceWorker' in navigator) {
|
||||
window.addEventListener('load', () => {
|
||||
navigator.serviceWorker.register('/sw.js')
|
||||
.then(registration => {
|
||||
console.log('ServiceWorker registration successful');
|
||||
})
|
||||
.catch(err => {
|
||||
console.log('ServiceWorker registration failed: ', err);
|
||||
});
|
||||
window.addEventListener('load', async () => {
|
||||
try {
|
||||
const registration = await navigator.serviceWorker.register('/sw.js');
|
||||
console.log('ServiceWorker registration successful');
|
||||
|
||||
// IndexedDB initialisieren und erste Synchronisation starten
|
||||
await window.dbHelper.initDB();
|
||||
await window.dbHelper.synchronizeData();
|
||||
} catch (err) {
|
||||
console.log('ServiceWorker registration failed: ', err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Offline-Status-Überwachung
|
||||
window.addEventListener('online', function() {
|
||||
document.body.classList.remove('offline');
|
||||
});
|
||||
// Offline-Status-Anzeige aktualisieren
|
||||
const updateOfflineStatus = () => {
|
||||
const offlineIndicator = document.getElementById('offlineIndicator');
|
||||
const syncStatus = document.getElementById('syncStatus');
|
||||
|
||||
if (!navigator.onLine) {
|
||||
offlineIndicator.style.display = 'block';
|
||||
syncStatus.style.display = 'none';
|
||||
} else {
|
||||
offlineIndicator.style.display = 'none';
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('offline', function() {
|
||||
document.body.classList.add('offline');
|
||||
});
|
||||
window.addEventListener('online', updateOfflineStatus);
|
||||
window.addEventListener('offline', updateOfflineStatus);
|
||||
updateOfflineStatus();
|
||||
|
||||
let searchTimeout;
|
||||
let lastResults = [];
|
||||
@@ -309,46 +331,48 @@
|
||||
});
|
||||
}
|
||||
|
||||
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;
|
||||
const fachrichtung = document.getElementById('fachrichtungInput').value;
|
||||
const searchOperator = document.querySelector('input[name="searchOperator"]:checked').value;
|
||||
async function searchCustomers() {
|
||||
const searchParams = {
|
||||
q: 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,
|
||||
operator: document.querySelector('input[name="searchOperator"]:checked').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);
|
||||
if (fachrichtung) params.append('fachrichtung', fachrichtung);
|
||||
if (searchOperator) params.append('operator', searchOperator);
|
||||
try {
|
||||
let results;
|
||||
if (navigator.onLine) {
|
||||
// Online: Server-Suche
|
||||
const response = await fetch('/api/search', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(searchParams)
|
||||
});
|
||||
results = await response.json();
|
||||
|
||||
// Speichere die Ergebnisse in IndexedDB
|
||||
await window.dbHelper.saveCustomers(results);
|
||||
} else {
|
||||
// Offline: Lokale Suche
|
||||
results = await window.dbHelper.searchCustomersOffline(searchParams);
|
||||
}
|
||||
|
||||
// Führe die Suche durch
|
||||
fetch('/search?' + params.toString())
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
// Verstecke das Lade-Icon
|
||||
document.getElementById('loading').style.display = 'none';
|
||||
|
||||
if (data.error) {
|
||||
return;
|
||||
}
|
||||
|
||||
lastResults = data;
|
||||
updateResultCounts();
|
||||
displayResults(data);
|
||||
})
|
||||
.catch(error => {
|
||||
document.getElementById('loading').style.display = 'none';
|
||||
});
|
||||
lastResults = results;
|
||||
displayResults(results);
|
||||
updateResultCounts();
|
||||
} catch (error) {
|
||||
console.error('Fehler bei der Suche:', error);
|
||||
document.getElementById('results').innerHTML = '<p>Ein Fehler ist aufgetreten. Bitte versuchen Sie es später erneut.</p>';
|
||||
} finally {
|
||||
document.getElementById('loading').style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
// Event-Listener für die Live-Suche
|
||||
|
Reference in New Issue
Block a user