Compare commits
22 commits
18570a42f0
...
37364c54e4
| Author | SHA1 | Date | |
|---|---|---|---|
| 37364c54e4 | |||
| 708744b724 | |||
| 808523a890 | |||
| 2c5a6dcfb7 | |||
| 5219a8822f | |||
| b5cac0e12c | |||
| a3281261ab | |||
| f8b82a3cff | |||
| ea7a48a995 | |||
| c7d4d5ae81 | |||
| cf50ab12df | |||
| 34c33864a4 | |||
| 67e801a018 | |||
| ecba1da140 | |||
| ca499dd4e5 | |||
| cd82a75774 | |||
| 0f88032293 | |||
| 7dae2cb1de | |||
| 6899e92191 | |||
| 562972c740 | |||
| 5bffae2fa7 | |||
| eacd1bf167 |
|
|
@ -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">
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 2 MiB After Width: | Height: | Size: 213 KiB |
|
|
@ -17,6 +17,10 @@
|
|||
padding: 0;
|
||||
}
|
||||
|
||||
:global(html) {
|
||||
color-scheme: light;
|
||||
}
|
||||
|
||||
:global(body) {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
||||
color: #1a1a2e;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
After Width: | Height: | Size: 1.1 KiB |
BIN
app/static/favicon-32.png
Normal file
|
After Width: | Height: | Size: 2 KiB |
BIN
app/static/favicon.ico
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
15
app/static/favicon.svg
Normal 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
app/static/icons/app-icon-512.png
Normal file
|
After Width: | Height: | Size: 102 KiB |
BIN
app/static/icons/apple-touch-icon.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
app/static/icons/icon-192.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
app/static/icons/icon-512.png
Normal file
|
After Width: | Height: | Size: 102 KiB |
|
|
@ -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: {
|
||||
|
|
|
|||
9
logo/checkflo-app-icon.svg
Normal 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 |
15
logo/checkflo-favicon-fixed.svg
Normal 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
|
After Width: | Height: | Size: 2 MiB |