checkflo/app/src/routes/admin/stations/+page.svelte

147 lines
3.5 KiB
Svelte

<script lang="ts">
import { pb } from '$lib/pb';
import { onMount } from 'svelte';
const TYPE_LABEL: Record<string, string> = {
kuehlschrank: 'Kühlschrank',
tiefkuehl: 'Tiefkühl',
warmhalte: 'Warmhalte',
hygiene: 'Hygiene',
sonstiges: 'Sonstiges'
};
let stations = $state<any[]>([]);
let loading = $state(true);
let copied = $state<string | null>(null);
onMount(async () => {
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) {
return `https://checkflo.de/s/${qrId}`;
}
async function copyUrl(qrId: string) {
await navigator.clipboard.writeText(qrUrl(qrId));
copied = qrId;
setTimeout(() => copied = null, 2000);
}
</script>
<svelte:head><title>Stationen — checkflo</title></svelte:head>
<div class="page">
<h1>Stationen</h1>
<p class="hint-text">Jeden QR-Code ausdrucken und an der Station befestigen. Der Link öffnet die Checkliste direkt im Browser.</p>
{#if loading}
<p class="hint">Lädt…</p>
{:else}
<div class="list">
{#each stations as s}
<div class="card">
<div class="card-head">
<div>
<div class="station-name">{s.name}</div>
<div class="station-type">{TYPE_LABEL[s.type] ?? s.type}
{#if s.target_temp_min || s.target_temp_max}
· {s.target_temp_min}° bis {s.target_temp_max}°C
{/if}
</div>
</div>
</div>
<div class="qr-row">
<code class="qr-url">{qrUrl(s.qr_id)}</code>
<button class="btn-copy" onclick={() => copyUrl(s.qr_id)}>
{copied === s.qr_id ? '✓ Kopiert' : 'Kopieren'}
</button>
<a
href="https://api.qrserver.com/v1/create-qr-code/?size=200x200&data={encodeURIComponent(qrUrl(s.qr_id))}"
target="_blank"
class="btn-qr"
>
QR öffnen
</a>
</div>
</div>
{/each}
</div>
{/if}
</div>
<style>
.page { max-width: 800px; }
h1 { font-size: 1.6rem; font-weight: 800; color: #0B1023; margin-bottom: 0.5rem; }
.hint-text { color: #666; font-size: 0.9rem; margin-bottom: 2rem; }
.hint { color: #aaa; }
.list { display: flex; flex-direction: column; gap: 1rem; }
.card {
background: #fff;
border-radius: 12px;
padding: 1.25rem 1.5rem;
box-shadow: 0 1px 4px rgba(0,0,0,0.06);
}
.card-head { margin-bottom: 1rem; }
.station-name { font-weight: 700; font-size: 1.05rem; color: #0B1023; }
.station-type { font-size: 0.85rem; color: #888; margin-top: 0.2rem; }
.qr-row {
display: flex;
align-items: center;
gap: 0.75rem;
flex-wrap: wrap;
}
.qr-url {
flex: 1;
font-size: 0.8rem;
background: #F5F7FA;
padding: 0.5rem 0.75rem;
border-radius: 6px;
color: #555;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.btn-copy, .btn-qr {
padding: 0.5rem 1rem;
border-radius: 6px;
font-size: 0.85rem;
font-weight: 600;
cursor: pointer;
white-space: nowrap;
transition: all 0.15s;
}
.btn-copy {
background: #F5F7FA;
border: 1.5px solid #ddd;
color: #555;
}
.btn-copy:hover { border-color: #F97316; color: #F97316; }
.btn-qr {
background: #F97316;
color: #fff;
border: none;
text-decoration: none;
display: inline-flex;
align-items: center;
}
.btn-qr:hover { background: #ea6c10; }
</style>