Files
qaffee/frontend/src/routes/admin/company/entries/+page.svelte

148 lines
4.4 KiB
Svelte
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script lang="ts">
import { onMount } from 'svelte';
import { page } from '$app/stores';
import { api, type TallyEntry } from '$lib/api/client';
import Header from '$lib/components/Header.svelte';
import MonthPicker from '$lib/components/MonthPicker.svelte';
let token = '';
let entries: TallyEntry[] = [];
let loading = true;
let selectedMonth = new Date().toISOString().slice(0, 7);
let deletingId: number | null = null;
let confirmId: number | null = null;
$: token = $page.url.searchParams.get('token') ?? '';
onMount(async () => {
if (!token) return;
await loadEntries();
});
async function loadEntries() {
loading = true;
entries = await api.companyAdmin.getTallyEntries(token, selectedMonth);
loading = false;
}
async function changeMonth(e: CustomEvent<string>) {
selectedMonth = e.detail;
await loadEntries();
}
function askConfirm(id: number) {
confirmId = id;
}
async function confirmDelete() {
if (confirmId === null) return;
const idToDelete = confirmId;
deletingId = idToDelete;
confirmId = null;
await api.companyAdmin.deleteTallyEntry(token, idToDelete);
deletingId = null;
await loadEntries();
}
function formatPrice(cents: number): string {
return (cents / 100).toFixed(2).replace('.', ',') + ' €';
}
function formatDateTime(iso: string): string {
const d = new Date(iso);
return d.toLocaleDateString('de-DE') + ' ' + d.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' });
}
</script>
<svelte:head>
<title>Einträge löschen Qaffee</title>
</svelte:head>
<Header title="Einträge verwalten" backHref="/admin/company?token={token}" />
<div class="admin-container">
{#if !token}
<p>Kein Zugangstoken angegeben.</p>
{:else}
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 24px;">
<h2>Produkteinträge</h2>
<MonthPicker bind:value={selectedMonth} on:change={changeMonth} />
</div>
{#if loading}
<p>Laden...</p>
{:else if entries.length === 0}
<p style="color: var(--color-text-muted); text-align: center; margin-top: 40px;">
Keine Einträge in diesem Monat.
</p>
{:else}
<p style="color: var(--color-text-muted); margin-bottom: 12px; font-size: 0.9rem;">
{entries.length} Einträge · {formatPrice(entries.reduce((s, e) => s + e.priceCents, 0))} gesamt
</p>
<table class="admin-table">
<thead>
<tr>
<th>Zeitpunkt</th>
<th>Mitarbeiter</th>
<th>Produkt</th>
<th style="text-align: right;">Preis</th>
<th></th>
</tr>
</thead>
<tbody>
{#each entries as entry}
<tr>
<td style="color: var(--color-text-muted); font-size: 0.85rem; white-space: nowrap;">
{formatDateTime(entry.createdAt)}
</td>
<td>{entry.employeeFirstName} {entry.employeeLastName}</td>
<td>{entry.productName}</td>
<td style="text-align: right;" class="price">{formatPrice(entry.priceCents)}</td>
<td>
{#if deletingId === entry.id}
<span style="font-size: 0.85rem; color: var(--color-text-muted);">Löschen...</span>
{:else}
<button
class="btn btn-secondary"
style="padding: 5px 10px; font-size: 0.8rem; color: #e05555; border-color: #e05555;"
on:click={() => askConfirm(entry.id)}
>
Löschen
</button>
{/if}
</td>
</tr>
{/each}
</tbody>
</table>
{/if}
{/if}
</div>
{#if confirmId !== null}
{@const confirmEntry = entries.find(e => e.id === confirmId)}
<div class="modal-overlay" on:click|self={() => confirmId = null}>
<div class="modal">
<h2>Eintrag löschen?</h2>
{#if confirmEntry}
<p style="margin: 16px 0; color: var(--color-text-muted);">
<strong style="color: var(--color-text-muted);">{confirmEntry.employeeFirstName} {confirmEntry.employeeLastName}</strong>
{confirmEntry.productName} ({formatPrice(confirmEntry.priceCents)})
am {formatDateTime(confirmEntry.createdAt)}
</p>
{/if}
<p style="margin-bottom: 20px; font-size: 0.9rem;">Dieser Eintrag wird unwiderruflich gelöscht.</p>
<div class="modal-actions">
<button class="btn btn-secondary" on:click={() => confirmId = null}>Abbrechen</button>
<button
class="btn btn-primary"
style="background: #e05555; border-color: #e05555;"
on:click={confirmDelete}
>
Löschen
</button>
</div>
</div>
</div>
{/if}