bump
This commit is contained in:
@@ -18,6 +18,7 @@ export interface Company {
|
||||
id: number;
|
||||
name: string;
|
||||
active: boolean;
|
||||
hasLogo: boolean;
|
||||
}
|
||||
|
||||
export interface Employee {
|
||||
@@ -90,6 +91,17 @@ export const api = {
|
||||
|
||||
// --- Company Admin ---
|
||||
companyAdmin: {
|
||||
uploadLogo: async (token: string, file: File): Promise<void> => {
|
||||
const form = new FormData();
|
||||
form.append('file', file);
|
||||
const res = await fetch(`${API_BASE}/admin/company/logo?token=${token}`, {
|
||||
method: 'POST',
|
||||
body: form
|
||||
});
|
||||
if (!res.ok) throw new Error(`API error: ${res.status}`);
|
||||
},
|
||||
deleteLogo: (token: string) =>
|
||||
request<void>(`/admin/company/logo?token=${token}`, { method: 'DELETE' }),
|
||||
getEmployees: (token: string) =>
|
||||
request<Employee[]>(`/admin/company/employees?token=${token}`),
|
||||
createEmployee: (token: string, firstName: string, lastName: string) =>
|
||||
|
||||
@@ -28,7 +28,15 @@
|
||||
<div class="card-grid" style="padding: 24px;">
|
||||
{#each companies as company}
|
||||
<a href="/company/{company.id}" class="card">
|
||||
<div style="font-size: 2.5rem;">🏢</div>
|
||||
{#if company.hasLogo}
|
||||
<img
|
||||
src="/api/companies/{company.id}/logo"
|
||||
alt={company.name}
|
||||
style="width: 2.5rem; height: 2.5rem; object-fit: contain;"
|
||||
/>
|
||||
{:else}
|
||||
<div style="font-size: 2.5rem;">🏢</div>
|
||||
{/if}
|
||||
<h3>{company.name}</h3>
|
||||
</a>
|
||||
{/each}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { page } from '$app/stores';
|
||||
import { api, type Employee, type MonthlyReport, type EmployeeReportLine } from '$lib/api/client';
|
||||
import { api, type Employee, type MonthlyReport, type EmployeeReportLine, type Company } from '$lib/api/client';
|
||||
|
||||
let token = '';
|
||||
let employees: Employee[] = [];
|
||||
@@ -10,6 +10,11 @@
|
||||
let loading = true;
|
||||
let selectedMonth = new Date().toISOString().slice(0, 7);
|
||||
|
||||
// Logo state
|
||||
let company: Company | null = null;
|
||||
let logoTimestamp = Date.now();
|
||||
let logoUploading = false;
|
||||
|
||||
// Modal state
|
||||
let showModal = false;
|
||||
let editId: number | null = null;
|
||||
@@ -25,13 +30,37 @@
|
||||
|
||||
async function loadData() {
|
||||
loading = true;
|
||||
[employees, report] = await Promise.all([
|
||||
const [emps, rep, companies] = await Promise.all([
|
||||
api.companyAdmin.getEmployees(token),
|
||||
api.companyAdmin.getReport(token, selectedMonth)
|
||||
api.companyAdmin.getReport(token, selectedMonth),
|
||||
api.getCompanies()
|
||||
]);
|
||||
employees = emps;
|
||||
report = rep;
|
||||
// Identifiziere die eigene Firma über den ersten Mitarbeiter oder via Report
|
||||
if (rep.companyId) {
|
||||
company = companies.find(c => c.id === rep.companyId) ?? null;
|
||||
}
|
||||
loading = false;
|
||||
}
|
||||
|
||||
async function handleLogoUpload(event: Event) {
|
||||
const input = event.target as HTMLInputElement;
|
||||
const file = input.files?.[0];
|
||||
if (!file) return;
|
||||
logoUploading = true;
|
||||
await api.companyAdmin.uploadLogo(token, file);
|
||||
logoTimestamp = Date.now();
|
||||
if (company) company = { ...company, hasLogo: true };
|
||||
logoUploading = false;
|
||||
}
|
||||
|
||||
async function handleLogoDelete() {
|
||||
await api.companyAdmin.deleteLogo(token);
|
||||
logoTimestamp = Date.now();
|
||||
if (company) company = { ...company, hasLogo: false };
|
||||
}
|
||||
|
||||
async function changeMonth() {
|
||||
report = await api.companyAdmin.getReport(token, selectedMonth);
|
||||
selectedEmployee = null;
|
||||
@@ -89,6 +118,29 @@
|
||||
{:else if loading}
|
||||
<p>Laden...</p>
|
||||
{:else}
|
||||
<!-- Firmenlogo -->
|
||||
<section style="margin-bottom: 32px;">
|
||||
<h2 style="margin-bottom: 12px;">Firmenlogo</h2>
|
||||
<div style="display: flex; align-items: center; gap: 20px;">
|
||||
{#if company?.hasLogo}
|
||||
<img
|
||||
src="/api/companies/{company.id}/logo?t={logoTimestamp}"
|
||||
alt="Firmenlogo"
|
||||
style="width: 2.5rem; height: 2.5rem; object-fit: contain; border-radius: 4px;"
|
||||
/>
|
||||
{:else}
|
||||
<div style="font-size: 2.5rem;">🏢</div>
|
||||
{/if}
|
||||
<label class="btn btn-secondary" style="cursor: pointer;">
|
||||
{logoUploading ? 'Hochladen...' : 'Bild hochladen'}
|
||||
<input type="file" accept="image/*" style="display: none;" on:change={handleLogoUpload} disabled={logoUploading} />
|
||||
</label>
|
||||
{#if company?.hasLogo}
|
||||
<button class="btn btn-secondary" on:click={handleLogoDelete}>Logo entfernen</button>
|
||||
{/if}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Mitarbeiterverwaltung -->
|
||||
<section style="margin-bottom: 40px;">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;">
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { goto } from '$app/navigation';
|
||||
import { page } from '$app/stores';
|
||||
import { api, type Product, type MonthlyTally, type Employee } from '$lib/api/client';
|
||||
|
||||
@@ -38,8 +39,10 @@
|
||||
await api.createTally(employeeId, productId);
|
||||
toastMessage = `${productName} hinzugefügt!`;
|
||||
showToast = true;
|
||||
setTimeout(() => { showToast = false; }, 2000);
|
||||
await loadTallies();
|
||||
setTimeout(() => {
|
||||
showToast = false;
|
||||
goto('/');
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
function formatPrice(cents: number): string {
|
||||
|
||||
Reference in New Issue
Block a user