Newwebshop/public/offline.html

373 lines
13 KiB
HTML

<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Offline - Webshop System</title>
<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.0.0/css/all.min.css" rel="stylesheet">
<style>
body {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.offline-container {
background: white;
border-radius: 1rem;
padding: 3rem;
text-align: center;
box-shadow: 0 1rem 3rem rgba(0,0,0,0.1);
max-width: 500px;
width: 90%;
}
.offline-icon {
font-size: 4rem;
color: #6c757d;
margin-bottom: 1rem;
}
.btn-retry {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border: none;
color: white;
padding: 0.75rem 2rem;
border-radius: 0.5rem;
font-weight: 600;
transition: transform 0.2s;
}
.btn-retry:hover {
transform: translateY(-2px);
color: white;
}
.offline-features {
margin-top: 2rem;
text-align: left;
}
.feature-item {
display: flex;
align-items: center;
margin-bottom: 1rem;
padding: 0.5rem;
border-radius: 0.5rem;
background: #f8f9fa;
}
.feature-icon {
margin-right: 1rem;
color: #28a745;
font-size: 1.2rem;
}
.cached-content {
margin-top: 2rem;
padding: 1rem;
background: #e9ecef;
border-radius: 0.5rem;
}
.cached-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.5rem 0;
border-bottom: 1px solid #dee2e6;
}
.cached-item:last-child {
border-bottom: none;
}
.btn-cached {
background: #6c757d;
border: none;
color: white;
padding: 0.25rem 0.75rem;
border-radius: 0.25rem;
font-size: 0.875rem;
}
.btn-cached:hover {
background: #5a6268;
color: white;
}
.connection-status {
position: fixed;
top: 1rem;
right: 1rem;
padding: 0.5rem 1rem;
border-radius: 0.5rem;
color: white;
font-weight: 600;
z-index: 1000;
transition: opacity 0.3s;
}
.status-online {
background: #28a745;
}
.status-offline {
background: #dc3545;
}
</style>
</head>
<body>
<!-- Connection Status -->
<div id="connectionStatus" class="connection-status status-offline">
<i class="fas fa-wifi-slash"></i> Offline
</div>
<div class="offline-container">
<div class="offline-icon">
<i class="fas fa-wifi-slash"></i>
</div>
<h1 class="h3 mb-3">Keine Internetverbindung</h1>
<p class="text-muted mb-4">
Es scheint, als hätten Sie keine Internetverbindung.
Einige Funktionen sind möglicherweise nicht verfügbar.
</p>
<button id="retryBtn" class="btn btn-retry mb-4">
<i class="fas fa-redo me-2"></i>Verbindung testen
</button>
<div class="offline-features">
<h5 class="mb-3">
<i class="fas fa-check-circle text-success me-2"></i>
Verfügbare Offline-Funktionen:
</h5>
<div class="feature-item">
<i class="fas fa-shopping-cart feature-icon"></i>
<div>
<strong>Warenkorb verwalten</strong><br>
<small class="text-muted">Produkte hinzufügen und entfernen</small>
</div>
</div>
<div class="feature-item">
<i class="fas fa-eye feature-icon"></i>
<div>
<strong>Gecachte Produkte anzeigen</strong><br>
<small class="text-muted">Zuletzt besuchte Produkte</small>
</div>
</div>
<div class="feature-item">
<i class="fas fa-user feature-icon"></i>
<div>
<strong>Profil verwalten</strong><br>
<small class="text-muted">Persönliche Daten bearbeiten</small>
</div>
</div>
<div class="feature-item">
<i class="fas fa-heart feature-icon"></i>
<div>
<strong>Wunschliste</strong><br>
<small class="text-muted">Gespeicherte Produkte anzeigen</small>
</div>
</div>
</div>
<div class="cached-content">
<h6 class="mb-3">
<i class="fas fa-download me-2"></i>
Gecachte Inhalte:
</h6>
<div id="cachedItems">
<!-- Wird dynamisch gefüllt -->
</div>
</div>
<div class="mt-4">
<small class="text-muted">
<i class="fas fa-info-circle me-1"></i>
Diese Seite wird automatisch aktualisiert, sobald eine Internetverbindung verfügbar ist.
</small>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
// Connection Status Management
function updateConnectionStatus() {
const statusElement = document.getElementById('connectionStatus');
const retryBtn = document.getElementById('retryBtn');
if (navigator.onLine) {
statusElement.className = 'connection-status status-online';
statusElement.innerHTML = '<i class="fas fa-wifi"></i> Online';
statusElement.style.opacity = '0.8';
// Automatische Weiterleitung nach 3 Sekunden
setTimeout(() => {
window.location.href = '/';
}, 3000);
retryBtn.innerHTML = '<i class="fas fa-check me-2"></i>Verbunden!';
retryBtn.disabled = true;
} else {
statusElement.className = 'connection-status status-offline';
statusElement.innerHTML = '<i class="fas fa-wifi-slash"></i> Offline';
statusElement.style.opacity = '1';
retryBtn.innerHTML = '<i class="fas fa-redo me-2"></i>Verbindung testen';
retryBtn.disabled = false;
}
}
// Retry Button Handler
document.getElementById('retryBtn').addEventListener('click', function() {
this.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>Teste...';
this.disabled = true;
// Teste Internetverbindung
fetch('/api/stats', { method: 'HEAD' })
.then(response => {
if (response.ok) {
updateConnectionStatus();
window.location.reload();
} else {
throw new Error('Server nicht erreichbar');
}
})
.catch(error => {
console.log('Verbindungstest fehlgeschlagen:', error);
this.innerHTML = '<i class="fas fa-redo me-2"></i>Verbindung testen';
this.disabled = false;
});
});
// Cached Items laden
async function loadCachedItems() {
const cachedItemsContainer = document.getElementById('cachedItems');
try {
// Prüfe Cache für verschiedene Inhalte
const cacheNames = ['webshop-static-v1', 'webshop-dynamic-v1'];
const cachedItems = [];
for (const cacheName of cacheNames) {
const cache = await caches.open(cacheName);
const requests = await cache.keys();
for (const request of requests) {
const url = new URL(request.url);
// Nur relevante Inhalte anzeigen
if (url.pathname.startsWith('/product/') ||
url.pathname.startsWith('/category/') ||
url.pathname === '/products') {
const response = await cache.match(request);
const contentType = response.headers.get('content-type');
if (contentType && contentType.includes('text/html')) {
cachedItems.push({
url: url.pathname,
title: getPageTitle(url.pathname),
type: getContentType(url.pathname)
});
}
}
}
}
// Cached Items anzeigen
if (cachedItems.length > 0) {
cachedItems.forEach(item => {
const itemElement = document.createElement('div');
itemElement.className = 'cached-item';
itemElement.innerHTML = `
<div>
<strong>${item.title}</strong><br>
<small class="text-muted">${item.type}</small>
</div>
<button class="btn btn-cached" onclick="openCachedPage('${item.url}')">
<i class="fas fa-external-link-alt"></i>
</button>
`;
cachedItemsContainer.appendChild(itemElement);
});
} else {
cachedItemsContainer.innerHTML = `
<div class="text-muted">
<i class="fas fa-info-circle me-1"></i>
Keine gecachten Inhalte verfügbar
</div>
`;
}
} catch (error) {
console.error('Fehler beim Laden der gecachten Inhalte:', error);
cachedItemsContainer.innerHTML = `
<div class="text-muted">
<i class="fas fa-exclamation-triangle me-1"></i>
Fehler beim Laden der gecachten Inhalte
</div>
`;
}
}
// Hilfsfunktionen
function getPageTitle(pathname) {
const titles = {
'/products': 'Produktkatalog',
'/cart': 'Warenkorb',
'/account': 'Mein Konto'
};
if (pathname.startsWith('/product/')) {
return 'Produktdetails';
}
if (pathname.startsWith('/category/')) {
return 'Kategorie';
}
return titles[pathname] || 'Seite';
}
function getContentType(pathname) {
if (pathname.startsWith('/product/')) {
return 'Produktseite';
}
if (pathname.startsWith('/category/')) {
return 'Kategorieseite';
}
return 'Seite';
}
function openCachedPage(url) {
window.location.href = url;
}
// Event Listeners
window.addEventListener('online', updateConnectionStatus);
window.addEventListener('offline', updateConnectionStatus);
// Initialisierung
document.addEventListener('DOMContentLoaded', function() {
updateConnectionStatus();
loadCachedItems();
// Service Worker registrieren
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js')
.then(registration => {
console.log('Service Worker registriert:', registration);
})
.catch(error => {
console.error('Service Worker Registrierung fehlgeschlagen:', error);
});
}
});
// Periodische Verbindungsprüfung
setInterval(() => {
if (navigator.onLine) {
updateConnectionStatus();
}
}, 5000);
</script>
</body>
</html>