diff --git a/web/src/lib/components/admin/ResearchPanel.svelte b/web/src/lib/components/admin/ResearchPanel.svelte
index 9f45441..2ebbdd8 100644
--- a/web/src/lib/components/admin/ResearchPanel.svelte
+++ b/web/src/lib/components/admin/ResearchPanel.svelte
@@ -41,10 +41,21 @@
return JSON.stringify(val, null, 2);
}
+ type LLMOeffnungszeit = { datum_von: string; datum_bis: string; von: string; bis: string };
+ type LLMEintrittspreis = { name: string; betrag: number; waehrung: string };
+
+ function isLLMOeffnungszeiten(val: unknown): val is LLMOeffnungszeit[] {
+ return Array.isArray(val) && val.length > 0 && 'datum_von' in (val[0] as object);
+ }
+
+ function isLLMEintrittspreise(val: unknown): val is LLMEintrittspreis[] {
+ return Array.isArray(val) && val.length > 0 && 'betrag' in (val[0] as object);
+ }
+
function isOpeningHours(
val: unknown
): val is Array<{ day: string; open: string; close: string }> {
- return Array.isArray(val) && val.length > 0 && 'day' in val[0];
+ return Array.isArray(val) && val.length > 0 && 'day' in (val[0] as object);
}
function isAdmissionInfo(val: unknown): val is {
@@ -111,7 +122,26 @@
{/if}
- {#if suggestion.field === 'opening_hours' && isOpeningHours(suggestion.suggested_value)}
+ {#if suggestion.field === 'opening_hours' && isLLMOeffnungszeiten(suggestion.suggested_value)}
+
+
+
+ | Datum |
+ Von |
+ Bis |
+
+
+
+ {#each suggestion.suggested_value as entry}
+
+ | {entry.datum_von} |
+ {entry.von} |
+ {entry.bis} |
+
+ {/each}
+
+
+ {:else if suggestion.field === 'opening_hours' && isOpeningHours(suggestion.suggested_value)}
@@ -130,6 +160,12 @@
{/each}
+ {:else if suggestion.field === 'admission_info' && isLLMEintrittspreise(suggestion.suggested_value)}
+
+ {#each suggestion.suggested_value as ticket}
+ - {ticket.name}: {ticket.betrag} {ticket.waehrung}
+ {/each}
+
{:else if suggestion.field === 'admission_info' && isAdmissionInfo(suggestion.suggested_value)}
- Erwachsene
diff --git a/web/src/routes/admin/maerkte/[id]/bearbeiten/+page.svelte b/web/src/routes/admin/maerkte/[id]/bearbeiten/+page.svelte
index 080e714..890990f 100644
--- a/web/src/routes/admin/maerkte/[id]/bearbeiten/+page.svelte
+++ b/web/src/routes/admin/maerkte/[id]/bearbeiten/+page.svelte
@@ -33,7 +33,18 @@
'Samstag'
];
+ // LLM opening hours entry shape (researcher_schema_simple.json)
+ type LLMOeffnungszeit = { datum_von: string; datum_bis: string; von: string; bis: string };
+ // LLM admission entry shape
+ type LLMEintrittspreis = { name: string; betrag: number; waehrung: string };
+
function normalizeDayName(day: string): string {
+ // ISO date YYYY-MM-DD
+ if (/^\d{4}-\d{2}-\d{2}$/.test(day)) {
+ const [y, m, d] = day.split('-').map(Number);
+ return validDays[new Date(y, m - 1, d).getDay()];
+ }
+ // German date DD.MM.YYYY
const dateMatch = day.match(/(\d{2})\.(\d{2})\.(\d{4})/);
if (dateMatch) {
const d = new Date(+dateMatch[3], +dateMatch[2] - 1, +dateMatch[1]);
@@ -46,19 +57,31 @@
function applyResearch(suggestions: FieldSuggestion[]) {
for (const s of suggestions) {
if (s.field === 'opening_hours' && Array.isArray(s.suggested_value)) {
- const normalized = (s.suggested_value as OpeningHoursEntry[]).map((entry) => ({
- ...entry,
- day: normalizeDayName(entry.day)
- }));
+ const entries = s.suggested_value as Array;
+ const normalized: OpeningHoursEntry[] = entries.map((entry) => {
+ if ('datum_von' in entry) {
+ return { day: normalizeDayName(entry.datum_von), open: entry.von, close: entry.bis };
+ }
+ return { ...entry, day: normalizeDayName(entry.day) };
+ });
marketForm.setHours(normalized);
continue;
}
- if (
- s.field === 'admission_info' &&
- typeof s.suggested_value === 'object' &&
- s.suggested_value !== null
- ) {
- marketForm.setAdmission(s.suggested_value as AdmissionInfo);
+ if (s.field === 'admission_info') {
+ if (Array.isArray(s.suggested_value)) {
+ // LLM format: [{name, betrag, waehrung}] — put in notes, leave cents at 0
+ const tickets = s.suggested_value as LLMEintrittspreis[];
+ const notes = tickets.map((t) => `${t.name}: ${t.betrag} ${t.waehrung}`).join('\n');
+ marketForm.setAdmission({
+ adult_cents: 0,
+ child_cents: 0,
+ reduced_cents: 0,
+ free_under_age: 0,
+ notes
+ });
+ } else if (typeof s.suggested_value === 'object' && s.suggested_value !== null) {
+ marketForm.setAdmission(s.suggested_value as AdmissionInfo);
+ }
continue;
}
const el = document.querySelector(