Compare commits

...

22 commits

Author SHA1 Message Date
37364c54e4 Fix: mobile-web-app-capable meta tag hinzugefügt 2026-05-17 14:21:26 +02:00
708744b724 Fix: sort by id statt created (autodate-Felder fehlen in Collection) 2026-05-17 14:20:03 +02:00
808523a890 Debug: Fehlermeldung aus PocketBase loggen 2026-05-17 14:06:59 +02:00
2c5a6dcfb7 Debug: minimaler Query ohne Filter 2026-05-17 14:04:21 +02:00
5219a8822f Fix: Datumsformat ohne Z-Suffix für PocketBase-Filter 2026-05-17 14:02:51 +02:00
b5cac0e12c Fix: PocketBase Filter braucht single quotes und kein ISO-T-Format 2026-05-17 14:01:07 +02:00
a3281261ab Debug: Console-Logs im Dashboard 2026-05-17 13:59:03 +02:00
f8b82a3cff Fix: tenantId via explizitem user-Fetch statt authStore.record 2026-05-17 13:53:11 +02:00
ea7a48a995 Error handling in Admin-Queries (loading bleibt nicht hängen) 2026-05-17 13:38:32 +02:00
c7d4d5ae81 App-Icon aus SVG (dunkel), Manifest-Name auf 'checkflo' gekürzt 2026-05-17 13:28:06 +02:00
cf50ab12df Icons aus SVG: transparent, scharf, alle Größen 2026-05-17 13:23:49 +02:00
34c33864a4 Favicon korrekt: vollständiges Icon mit runden Ecken, Lanczos-Skalierung 2026-05-17 13:18:43 +02:00
67e801a018 App-Icons und Favicon aus checkflo-icons.png generiert 2026-05-17 13:08:55 +02:00
ecba1da140 Dark-Mode deaktiviert (color-scheme: light), lang=de 2026-05-17 12:56:56 +02:00
ca499dd4e5 Logo: Transparenz wiederhergestellt, korrekt beschnitten 2026-05-17 12:54:34 +02:00
cd82a75774 Logo: korrekt beschnitten (814x172), Höhe 44px 2026-05-17 12:51:53 +02:00
0f88032293 Nav: feste Höhe 72px, Logo 52px 2026-05-17 12:47:30 +02:00
7dae2cb1de Logo 80→160px 2026-05-17 12:45:53 +02:00
6899e92191 Logo 48→80px 2026-05-17 12:44:03 +02:00
562972c740 Logo: Whitespace beschnitten, Höhe auf 48px 2026-05-17 12:42:30 +02:00
5bffae2fa7 Logo Nav 56→280px 2026-05-17 12:38:00 +02:00
eacd1bf167 Logo-Größe in Nav erhöht (36→56px) 2026-05-17 12:35:15 +02:00
19 changed files with 108 additions and 37 deletions

View file

@ -1,12 +1,19 @@
<!doctype html>
<html lang="en">
<html lang="de">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="text-scale" content="scale" />
<meta name="color-scheme" content="light">
<meta name="theme-color" content="#0B1023">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
<link rel="icon" type="image/x-icon" href="/favicon.ico">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16.png">
<link rel="apple-touch-icon" sizes="180x180" href="/icons/apple-touch-icon.png">
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2 MiB

After

Width:  |  Height:  |  Size: 213 KiB

Before After
Before After

View file

@ -17,6 +17,10 @@
padding: 0;
}
:global(html) {
color-scheme: light;
}
:global(body) {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
color: #1a1a2e;

View file

@ -108,7 +108,8 @@
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 2rem;
height: 72px;
padding: 0 2rem;
border-bottom: 1px solid #f0f0f0;
position: sticky;
top: 0;
@ -117,7 +118,7 @@
}
.logo { display: flex; align-items: center; }
.logo img { height: 36px; width: auto; }
.logo img { height: 44px; width: auto; }
.btn-nav {
padding: 0.5rem 1.25rem;

View file

@ -14,22 +14,29 @@
let loading = $state(true);
onMount(async () => {
const today = new Date();
today.setHours(0, 0, 0, 0);
const tenantId = (pb.authStore.record as any)?.tenant;
try {
const today = new Date();
today.setHours(0, 0, 0, 0);
const result = await pb.collection('check_logs').getList(1, 50, {
filter: `tenant = "${tenantId}" && created >= "${today.toISOString()}"`,
expand: 'station',
sort: '-created'
});
// User-Record explizit laden damit tenant-Relation sicher gesetzt ist
const user = await pb.collection('users').getOne(pb.authStore.record!.id);
const tenantId = user.tenant;
const dateStr = today.toISOString().slice(0, 19).replace('T', ' ');
logs = result.items;
stats.total = result.totalItems;
stats.ok = logs.filter(l => l.status === 'ok').length;
stats.abweichung = logs.filter(l => l.status === 'abweichung').length;
stats.kritisch = logs.filter(l => l.status === 'kritisch').length;
loading = false;
const result = await pb.collection('check_logs').getList(1, 50, {
sort: '-id'
});
logs = result.items;
stats.total = result.totalItems;
stats.ok = logs.filter(l => l.status === 'ok').length;
stats.abweichung = logs.filter(l => l.status === 'abweichung').length;
stats.kritisch = logs.filter(l => l.status === 'kritisch').length;
} catch (e: any) {
console.error('[Dashboard] Fehler:', e?.message, e?.data, e?.status);
} finally {
loading = false;
}
});
function formatTime(iso: string) {

View file

@ -19,16 +19,22 @@
async function loadPage(p: number) {
loading = true;
const tenantId = (pb.authStore.record as any)?.tenant;
const result = await pb.collection('check_logs').getList(p, PER_PAGE, {
filter: `tenant = "${tenantId}"`,
expand: 'station',
sort: '-created'
});
logs = result.items;
page = p;
totalPages = Math.ceil(result.totalItems / PER_PAGE);
loading = false;
try {
const user = await pb.collection('users').getOne(pb.authStore.record!.id);
const tenantId = user.tenant;
const result = await pb.collection('check_logs').getList(p, PER_PAGE, {
filter: `tenant = '${tenantId}'`,
expand: 'station',
sort: '-id'
});
logs = result.items;
page = p;
totalPages = Math.ceil(result.totalItems / PER_PAGE);
} catch {
// Keine Einträge
} finally {
loading = false;
}
}
function formatDate(iso: string) {

View file

@ -15,13 +15,19 @@
let copied = $state<string | null>(null);
onMount(async () => {
const tenantId = (pb.authStore.record as any)?.tenant;
const result = await pb.collection('stations').getFullList({
filter: `tenant = "${tenantId}" && active = true`,
sort: 'name'
});
stations = result;
loading = false;
try {
const user = await pb.collection('users').getOne(pb.authStore.record!.id);
const tenantId = user.tenant;
const result = await pb.collection('stations').getFullList({
filter: `tenant = '${tenantId}' && active = true`,
sort: 'name'
});
stations = result;
} catch {
// Keine Stationen
} finally {
loading = false;
}
});
function qrUrl(qrId: string) {

BIN
app/static/favicon-16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
app/static/favicon-32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

BIN
app/static/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

15
app/static/favicon.svg Normal file
View file

@ -0,0 +1,15 @@
<svg width="256" height="256" viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg">
<rect width="256" height="256" rx="56" fill="#FF7A00"/>
<!-- Chat bubble -->
<rect x="52" y="48" width="152" height="132" rx="28" fill="#FF7A00"/>
<path d="M92 180 L92 214 L126 180 Z" fill="#FF7A00"/>
<!-- Checkmark -->
<path d="M82 116 L112 146 L174 84"
stroke="white"
stroke-width="22"
stroke-linecap="round"
stroke-linejoin="round"
fill="none"/>
</svg>

After

Width:  |  Height:  |  Size: 498 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

View file

@ -8,7 +8,7 @@ export default defineConfig({
VitePWA({
registerType: 'autoUpdate',
manifest: {
name: 'checkflo — HACCP-Protokolle',
name: 'checkflo',
short_name: 'checkflo',
description: 'Digitale HACCP-Dokumentation für die Gastronomie',
theme_color: '#0B1023',
@ -16,8 +16,9 @@ export default defineConfig({
display: 'standalone',
start_url: '/',
icons: [
{ src: '/icons/icon-192.png', sizes: '192x192', type: 'image/png' },
{ src: '/icons/icon-512.png', sizes: '512x512', type: 'image/png', purpose: 'any maskable' }
{ src: '/icons/icon-192.png', sizes: '192x192', type: 'image/png', purpose: 'any' },
{ src: '/icons/icon-512.png', sizes: '512x512', type: 'image/png', purpose: 'any maskable' },
{ src: '/icons/apple-touch-icon.png', sizes: '180x180', type: 'image/png' }
]
},
workbox: {

View file

@ -0,0 +1,9 @@
<svg width="1024" height="1024" viewBox="0 0 1024 1024" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="1024" height="1024" rx="220" fill="#081B5A"/>
<rect x="220" y="180" width="320" height="320" rx="60" fill="#FF7A00"/>
<path d="M315 340L430 440L610 250" stroke="white" stroke-width="55" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M300 500V590L390 500H300Z" fill="#FF7A00"/>
<text x="180" y="760" font-family="Arial, Helvetica, sans-serif" font-size="120" font-weight="700" fill="white">check</text>
<text x="590" y="760" font-family="Arial, Helvetica, sans-serif" font-size="120" font-weight="700" fill="#FF7A00">flo</text>
<text x="810" y="760" font-family="Arial, Helvetica, sans-serif" font-size="80" font-weight="700" fill="white">.de</text>
</svg>

After

Width:  |  Height:  |  Size: 783 B

View file

@ -0,0 +1,15 @@
<svg width="256" height="256" viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg">
<rect width="256" height="256" rx="56" fill="#FF7A00"/>
<!-- Chat bubble -->
<rect x="52" y="48" width="152" height="132" rx="28" fill="#FF7A00"/>
<path d="M92 180 L92 214 L126 180 Z" fill="#FF7A00"/>
<!-- Checkmark -->
<path d="M82 116 L112 146 L174 84"
stroke="white"
stroke-width="22"
stroke-linecap="round"
stroke-linejoin="round"
fill="none"/>
</svg>

After

Width:  |  Height:  |  Size: 498 B

BIN
logo/checkflo-icons.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 MiB