dolibarr.stundenzettel/pwa.php
data ba94de5c72 PWA: Service Worker v1.1 + No-Cache-Header für pwa.php
- Service Worker Version auf v1.1 erhöht (erzwingt Cache-Invalidierung)
- pwa.php: Cache-Control no-store Header damit Browser immer die
  aktuelle HTML-Seite mit neuen JS/CSS-Versionen lädt

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-21 21:57:33 +01:00

179 lines
6.4 KiB
PHP

<?php
/* Copyright (C) 2026 Eduard Wisch <data@data-it-solution.de>
*
* Stundenzettel PWA - Standalone Mobile App
*/
// Kein Dolibarr-Login erforderlich - eigenes Token-System
if (!defined('NOLOGIN')) {
define('NOLOGIN', '1');
}
if (!defined('NOREQUIREMENU')) {
define('NOREQUIREMENU', '1');
}
if (!defined('NOREQUIREHTML')) {
define('NOREQUIREHTML', '1');
}
// Dolibarr-Umgebung laden (fuer Theme-Color und Config)
$res = 0;
if (!$res && file_exists("../main.inc.php")) $res = @include "../main.inc.php";
if (!$res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php";
if (!$res && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php";
if (!$res) die("Dolibarr konnte nicht geladen werden");
// Theme-Farbe aus Dolibarr
$themeColor = getDolGlobalString('THEME_ELDY_TOPMENU_BACK1', '#4390dc');
// Kein Caching fuer PWA-Einstiegsseite (damit neue JS/CSS-Versionen sofort geladen werden)
header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
header('Expires: 0');
?><!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
<meta name="theme-color" content="#1d1e20">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="STZ">
<title>Stundenzettel</title>
<link rel="manifest" href="manifest.json">
<link rel="icon" type="image/png" sizes="192x192" href="img/icon-192.png">
<link rel="apple-touch-icon" href="img/icon-192.png">
<link rel="stylesheet" href="css/pwa.css?v=2.9">
<style>:root { --primary: <?php echo htmlspecialchars($themeColor); ?>; }</style>
</head>
<body>
<div id="app" class="app">
<!-- Toast-Container -->
<div id="toast-container" class="toast-container"></div>
<!-- Loading-Overlay -->
<div id="loading-overlay" class="loading-overlay">
<div class="loading-spinner"></div>
</div>
<!-- Confirm-Dialog -->
<div id="confirm-dialog" class="confirm-dialog">
<div class="confirm-box">
<div id="confirm-title" class="confirm-title"></div>
<div id="confirm-text" class="confirm-text"></div>
<div class="confirm-actions">
<button id="confirm-cancel" class="btn btn-ghost">Abbrechen</button>
<button id="confirm-ok" class="btn btn-danger">OK</button>
</div>
</div>
</div>
<!-- Bottom-Sheet (wiederverwendbar) -->
<div id="bottom-sheet-overlay" class="bottom-sheet-overlay"></div>
<div id="bottom-sheet" class="bottom-sheet">
<div class="bottom-sheet-handle"></div>
<div id="bottom-sheet-header" class="bottom-sheet-header"></div>
<div id="bottom-sheet-body" class="bottom-sheet-body"></div>
<div id="bottom-sheet-footer" class="bottom-sheet-footer"></div>
</div>
<!-- ===== LOGIN SCREEN ===== -->
<div id="screen-login" class="screen login-screen active">
<div class="login-container">
<div class="login-logo">
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z"/>
</svg>
</div>
<h1 class="login-title">Stundenzettel</h1>
<p class="login-subtitle">Mobile Zeiterfassung</p>
<form id="login-form" class="login-form">
<div class="form-group">
<label for="login-user">Benutzername</label>
<input type="text" id="login-user" autocomplete="username" required>
</div>
<div class="form-group">
<label for="login-pass">Passwort</label>
<input type="password" id="login-pass" autocomplete="current-password" required>
</div>
<button type="submit" class="btn btn-primary">Anmelden</button>
<p id="login-error" class="error-text"></p>
</form>
</div>
</div>
<!-- ===== SEARCH SCREEN ===== -->
<div id="screen-search" class="screen search-screen">
<div class="search-header">
<div class="search-input-wrap">
<span class="search-icon">&#128269;</span>
<input type="search" id="search-input" placeholder="Kunde suchen..." autocomplete="off">
</div>
<button id="btn-logout" class="btn btn-ghost btn-small">Abmelden</button>
</div>
<div id="search-results" class="search-results">
<div class="search-empty">
<p>Kundenname eingeben um Auftr&auml;ge zu finden</p>
</div>
</div>
</div>
<!-- ===== MAIN SCREEN (Swipe-Panels) ===== -->
<div id="screen-main" class="screen main-screen">
<!-- Tab-Bar -->
<div class="tab-bar">
<div id="btn-back" class="back-btn">&#8592;</div>
<div class="tab-items">
<div class="tab-item" data-panel="0">Alle STZ</div>
<div class="tab-item" data-panel="1">Stundenzettel</div>
<div class="tab-item active" data-panel="2">Produktliste</div>
<div class="tab-item" data-panel="3">Lieferauflistung</div>
</div>
</div>
<!-- Swipe-Viewport -->
<div class="swipe-viewport">
<div id="swipe-container" class="swipe-container">
<!-- Panel 0: Alle Stundenzettel -->
<div id="panel-stzlist" class="swipe-panel"></div>
<!-- Panel 1: Stundenzettel (Leistungen + Merkzettel) -->
<div id="panel-stundenzettel" class="swipe-panel"></div>
<!-- Panel 2: Produktliste (Standard) -->
<div id="panel-products" class="swipe-panel"></div>
<!-- Panel 3: Lieferauflistung -->
<div id="panel-tracking" class="swipe-panel"></div>
</div>
</div>
<!-- FAB -->
<button id="fab-add" class="fab hidden">+</button>
</div>
</div>
<!-- JavaScript -->
<script src="<?php echo DOL_URL_ROOT; ?>/includes/jquery/js/jquery.min.js"></script>
<script>
window.STZ_CONFIG = {
moduleUrl: '<?php echo dol_buildpath('/stundenzettel/', 1); ?>',
apiUrl: '<?php echo dol_buildpath('/stundenzettel/ajax/pwa_api.php', 1); ?>',
authUrl: '<?php echo dol_buildpath('/stundenzettel/ajax/pwa_auth.php', 1); ?>'
};
</script>
<script src="js/pwa.js?v=2.9"></script>
<!-- Service Worker Registration -->
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('sw.js')
.then(function(reg) { console.log('[STZ-PWA] Service Worker registriert'); })
.catch(function(err) { console.error('[STZ-PWA] SW Registrierung fehlgeschlagen:', err); });
}
</script>
</body>
</html>