diff --git a/.claude/settings.local.json b/.claude/settings.local.json
index df9c8c4..3960f49 100644
--- a/.claude/settings.local.json
+++ b/.claude/settings.local.json
@@ -16,7 +16,8 @@
"Bash(mkdir -p backend/src/main/java/de/strichliste/resource)",
"Bash(mkdir -p backend/src/main/java/de/strichliste/filter)",
"Bash(mkdir -p backend/src/main/java/de/strichliste/dto)",
- "Bash(mkdir -p backend/src/main/resources/db/migration)"
+ "Bash(mkdir -p backend/src/main/resources/db/migration)",
+ "Bash(npm install:*)"
]
}
}
diff --git a/frontend/package.json b/frontend/package.json
index 9de6421..464e97a 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -8,6 +8,9 @@
"preview": "vite preview",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json"
},
+ "dependencies": {
+ "emoji-picker-element": "^1.26.0"
+ },
"devDependencies": {
"@sveltejs/adapter-node": "^5.2.0",
"@sveltejs/kit": "^2.8.0",
diff --git a/frontend/src/lib/components/EmojiPicker.svelte b/frontend/src/lib/components/EmojiPicker.svelte
new file mode 100644
index 0000000..e3a0971
--- /dev/null
+++ b/frontend/src/lib/components/EmojiPicker.svelte
@@ -0,0 +1,71 @@
+
+
+
+
+ Ausgewählt: {value}
+
+
+
+
+
diff --git a/frontend/src/lib/components/MonthPicker.svelte b/frontend/src/lib/components/MonthPicker.svelte
new file mode 100644
index 0000000..56d1e82
--- /dev/null
+++ b/frontend/src/lib/components/MonthPicker.svelte
@@ -0,0 +1,76 @@
+
+
+
+
+ {label}
+
+
+
+
diff --git a/frontend/src/routes/admin/company/+page.svelte b/frontend/src/routes/admin/company/+page.svelte
index 9503a1a..c2dc5f4 100644
--- a/frontend/src/routes/admin/company/+page.svelte
+++ b/frontend/src/routes/admin/company/+page.svelte
@@ -3,6 +3,7 @@
import { page } from '$app/stores';
import { api, type Employee, type MonthlyReport, type EmployeeReportLine, type Company } from '$lib/api/client';
import Header from '$lib/components/Header.svelte';
+ import MonthPicker from '$lib/components/MonthPicker.svelte';
let token = '';
let employees: Employee[] = [];
@@ -62,7 +63,8 @@
if (company) company = { ...company, hasLogo: false };
}
- async function changeMonth() {
+ async function changeMonth(e?: CustomEvent) {
+ if (e) selectedMonth = e.detail;
report = await api.companyAdmin.getReport(token, selectedMonth);
selectedEmployee = null;
}
@@ -181,9 +183,7 @@
{#if report}
diff --git a/frontend/src/routes/admin/provider/+page.svelte b/frontend/src/routes/admin/provider/+page.svelte
index 2151522..4d967fc 100644
--- a/frontend/src/routes/admin/provider/+page.svelte
+++ b/frontend/src/routes/admin/provider/+page.svelte
@@ -3,6 +3,8 @@
import { page } from '$app/stores';
import { api, type Company, type Product, type ProviderReport, type AccessLink } from '$lib/api/client';
import Header from '$lib/components/Header.svelte';
+ import EmojiPicker from '$lib/components/EmojiPicker.svelte';
+ import MonthPicker from '$lib/components/MonthPicker.svelte';
let token = '';
let activeTab: 'companies' | 'products' | 'report' | 'links' = 'companies';
@@ -27,6 +29,15 @@
let formProductPrice = 0;
let formProductIcon = 'coffee';
+ // Copy feedback
+ let copiedLinkId: number | null = null;
+
+ async function copyLink(link: AccessLink) {
+ await navigator.clipboard.writeText(buildLink(link));
+ copiedLinkId = link.id;
+ setTimeout(() => { copiedLinkId = null; }, 2000);
+ }
+
// Link Modal
let showLinkModal = false;
let formLinkRole = 'COMPANY_ADMIN';
@@ -50,7 +61,8 @@
loading = false;
}
- async function loadReport() {
+ async function loadReport(e?: CustomEvent) {
+ if (e) selectedMonth = e.detail;
report = await api.providerAdmin.getReport(token, selectedMonth);
}
@@ -252,9 +264,7 @@
{#if activeTab === 'report'}
{#if report}
{#each report.companies as companyReport}
@@ -299,7 +309,7 @@
- | Beschreibung | Rolle | Link |
+ | Beschreibung | Rolle | Firma | Link |
{#each accessLinks as link}
@@ -311,7 +321,21 @@
- {buildLink(link)}
+ {#if link.companyId}
+ {companies.find(c => c.id === link.companyId)?.name ?? '-'}
+ {:else}
+ -
+ {/if}
+ |
+
+
|
{/each}
@@ -352,12 +376,8 @@
-
-
+
+ formProductIcon = e.detail} />
@@ -400,3 +420,37 @@
{/if}
+
+
diff --git a/frontend/src/routes/company/[id]/tally/+page.svelte b/frontend/src/routes/company/[id]/tally/+page.svelte
index 3f44017..a297307 100644
--- a/frontend/src/routes/company/[id]/tally/+page.svelte
+++ b/frontend/src/routes/company/[id]/tally/+page.svelte
@@ -15,12 +15,16 @@
$: companyId = Number($page.params.id);
$: employeeId = Number($page.url.searchParams.get('employee'));
- const ICON_MAP: Record = {
+ const LEGACY_ICON_MAP: Record = {
coffee: '☕',
chocolate: '🍫',
tea: '🍵'
};
+ function getIcon(placeholder: string): string {
+ return LEGACY_ICON_MAP[placeholder] ?? placeholder;
+ }
+
onMount(async () => {
const [prods, emps] = await Promise.all([
api.getProducts(),
@@ -68,7 +72,7 @@
{#each products as product}