fix(research): move all form fields to reactive state, add setField dispatcher
All Input fields used market?.xxx as initial value, so a Svelte re-render triggered by researchResult=null would reset them back to the server-loaded value, wiping every applied research suggestion. Replace all research-applicable fields with $state variables and route all apply calls through setField() instead of querySelector+dispatch. Country name->code mapping added for LLM-returned values like "Deutschland" -> "DE". writeReverseResult also updated to use setField.
This commit is contained in:
@@ -42,9 +42,35 @@
|
||||
|
||||
let marktName = $state(untrack(() => market?.name ?? ''));
|
||||
let description = $state(untrack(() => market?.description ?? ''));
|
||||
let street = $state(untrack(() => market?.street ?? ''));
|
||||
let city = $state(untrack(() => market?.city ?? ''));
|
||||
let marketState = $state(untrack(() => market?.state ?? ''));
|
||||
let zip = $state(untrack(() => market?.zip ?? ''));
|
||||
let selectedCountry = $state(untrack(() => market?.country ?? 'DE'));
|
||||
let startDate = $state(untrack(() => market?.start_date ?? ''));
|
||||
let endDate = $state(untrack(() => market?.end_date ?? ''));
|
||||
let website = $state(untrack(() => market?.website ?? ''));
|
||||
let organizerName = $state(untrack(() => market?.organizer_name ?? ''));
|
||||
let imageUrl = $state(untrack(() => market?.image_url ?? ''));
|
||||
const currency = $derived(currencyByCountry[selectedCountry] ?? 'EUR');
|
||||
|
||||
const countryNameToCode: Record<string, string> = {
|
||||
Deutschland: 'DE',
|
||||
Oesterreich: 'AT',
|
||||
Österreich: 'AT',
|
||||
Schweiz: 'CH',
|
||||
Frankreich: 'FR',
|
||||
Italien: 'IT',
|
||||
Spanien: 'ES',
|
||||
Polen: 'PL',
|
||||
Tschechien: 'CZ',
|
||||
Niederlande: 'NL',
|
||||
Belgien: 'BE',
|
||||
Dänemark: 'DK',
|
||||
Schweden: 'SE',
|
||||
Norwegen: 'NO'
|
||||
};
|
||||
|
||||
let hours: OpeningHoursEntry[] = $state(
|
||||
untrack(() => (market?.opening_hours?.length ? [...market.opening_hours] : []))
|
||||
);
|
||||
@@ -173,14 +199,10 @@
|
||||
['zip', data.zip]
|
||||
];
|
||||
let count = 0;
|
||||
for (const [name, value] of writes) {
|
||||
for (const [field, value] of writes) {
|
||||
if (!value) continue;
|
||||
const el = document.querySelector<HTMLInputElement>(`[name="${name}"]`);
|
||||
if (el) {
|
||||
el.value = value;
|
||||
el.dispatchEvent(new Event('input', { bubbles: true }));
|
||||
count++;
|
||||
}
|
||||
setField(field, value);
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
@@ -200,6 +222,47 @@
|
||||
export function setName(val: string) {
|
||||
marktName = val;
|
||||
}
|
||||
|
||||
export function setField(field: string, value: string) {
|
||||
switch (field) {
|
||||
case 'name':
|
||||
marktName = value;
|
||||
break;
|
||||
case 'description':
|
||||
description = value;
|
||||
break;
|
||||
case 'street':
|
||||
street = value;
|
||||
break;
|
||||
case 'city':
|
||||
city = value;
|
||||
break;
|
||||
case 'state':
|
||||
marketState = value;
|
||||
break;
|
||||
case 'zip':
|
||||
zip = value;
|
||||
break;
|
||||
case 'country':
|
||||
selectedCountry = countryNameToCode[value] ?? value;
|
||||
break;
|
||||
case 'start_date':
|
||||
startDate = value;
|
||||
break;
|
||||
case 'end_date':
|
||||
endDate = value;
|
||||
break;
|
||||
case 'website':
|
||||
website = value;
|
||||
break;
|
||||
case 'organizer_name':
|
||||
organizerName = value;
|
||||
break;
|
||||
case 'image_url':
|
||||
imageUrl = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if error}
|
||||
@@ -249,7 +312,7 @@
|
||||
label="Straße"
|
||||
name="street"
|
||||
type="text"
|
||||
value={market?.street ?? ''}
|
||||
value={street}
|
||||
placeholder={mode === 'public' ? 'z.B. Marienplatz 1' : ''}
|
||||
/>
|
||||
|
||||
@@ -259,14 +322,14 @@
|
||||
name="city"
|
||||
type="text"
|
||||
required
|
||||
value={market?.city ?? ''}
|
||||
value={city}
|
||||
placeholder={mode === 'public' ? 'z.B. München' : ''}
|
||||
/>
|
||||
<Input
|
||||
label="Bundesland"
|
||||
name="state"
|
||||
type="text"
|
||||
value={market?.state ?? ''}
|
||||
value={marketState}
|
||||
placeholder={mode === 'public' ? 'z.B. Bayern' : ''}
|
||||
/>
|
||||
</div>
|
||||
@@ -276,7 +339,7 @@
|
||||
label="PLZ"
|
||||
name="zip"
|
||||
type="text"
|
||||
value={market?.zip ?? ''}
|
||||
value={zip}
|
||||
placeholder={mode === 'public' ? 'z.B. 80331' : ''}
|
||||
/>
|
||||
<div class="space-y-1">
|
||||
@@ -390,20 +453,8 @@
|
||||
<legend class="text-lg font-semibold text-stone-800 dark:text-stone-100">Zeitraum</legend>
|
||||
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<Input
|
||||
label="Startdatum *"
|
||||
name="start_date"
|
||||
type="date"
|
||||
required
|
||||
value={market?.start_date ?? ''}
|
||||
/>
|
||||
<Input
|
||||
label="Enddatum *"
|
||||
name="end_date"
|
||||
type="date"
|
||||
required
|
||||
value={market?.end_date ?? ''}
|
||||
/>
|
||||
<Input label="Startdatum *" name="start_date" type="date" required value={startDate} />
|
||||
<Input label="Enddatum *" name="end_date" type="date" required value={endDate} />
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
@@ -414,7 +465,7 @@
|
||||
label="Website"
|
||||
name="website"
|
||||
type="url"
|
||||
value={market?.website ?? ''}
|
||||
value={website}
|
||||
placeholder={mode === 'public' ? 'https://...' : ''}
|
||||
/>
|
||||
|
||||
@@ -422,11 +473,11 @@
|
||||
label="Veranstalter"
|
||||
name="organizer_name"
|
||||
type="text"
|
||||
value={market?.organizer_name ?? ''}
|
||||
value={organizerName}
|
||||
placeholder={mode === 'public' ? 'Name des Veranstalters' : ''}
|
||||
/>
|
||||
|
||||
<Input label="Bild-URL" name="image_url" type="url" value={market?.image_url ?? ''} />
|
||||
<Input label="Bild-URL" name="image_url" type="url" value={imageUrl} />
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="space-y-4">
|
||||
|
||||
@@ -84,23 +84,8 @@
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (s.field === 'description' && typeof s.suggested_value === 'string') {
|
||||
marketForm.setDescription(s.suggested_value);
|
||||
continue;
|
||||
}
|
||||
if (s.field === 'name' && typeof s.suggested_value === 'string') {
|
||||
marketForm.setName(s.suggested_value);
|
||||
continue;
|
||||
}
|
||||
const el = document.querySelector<HTMLInputElement | HTMLTextAreaElement>(
|
||||
`[name="${s.field}"]`
|
||||
);
|
||||
if (el) {
|
||||
el.value =
|
||||
typeof s.suggested_value === 'string'
|
||||
? s.suggested_value
|
||||
: JSON.stringify(s.suggested_value);
|
||||
el.dispatchEvent(new Event('input', { bubbles: true }));
|
||||
if (typeof s.suggested_value === 'string') {
|
||||
marketForm.setField(s.field, s.suggested_value);
|
||||
}
|
||||
}
|
||||
const notesEl = document.querySelector<HTMLTextAreaElement>('[name="admin_notes"]');
|
||||
|
||||
Reference in New Issue
Block a user