Complete market overview card editing

This commit is contained in:
gitea_admin committed 2026-09-19 14:22:07 +02:00
1 parent 94d336f090
commit 6a12a43114
4 files changed
+62 -4

No files matched your search

+32
View File
@@ -188,6 +188,38 @@ function get_contact_options(PDO $pdo): array
);
}
function update_contact_details(PDO $pdo, int $contactId, array $input): array
{
if ($contactId <= 0) {
throw new InvalidArgumentException('contact_person_id muss positiv sein.');
}
$sets = [];
$params = [':id' => $contactId];
foreach (['email', 'phone'] as $field) {
if (array_key_exists($field, $input)) {
$sets[] = $field . ' = :' . $field;
$value = trim((string) ($input[$field] ?? ''));
$params[':' . $field] = $value !== '' ? $value : null;
}
}
if ($sets === []) {
throw new InvalidArgumentException('Keine änderbaren Kontaktdaten übergeben.');
}
$sets[] = 'updated_at = NOW()';
$stmt = $pdo->prepare(
'UPDATE contact SET ' . implode(', ', $sets) . ' WHERE id = :id
RETURNING id, party_id, first_name, last_name, email, phone, position_title'
);
$stmt->execute($params);
$contact = $stmt->fetch();
if (!is_array($contact)) {
throw new RuntimeException('Kontaktperson nicht gefunden.');
}
return $contact;
}
function create_manufacturer(PDO $pdo, string $name, ?string $email = null, ?string $phone = null): array
{
$name = trim($name);
+1
View File
@@ -535,6 +535,7 @@ function market_management_get_occurrence(PDO $pdo, int $occurrenceId, bool $inc
$occurrence['contact_person_id'] = is_array($organizer) ? (int) $organizer['contact_person_id'] : null;
$referenceData = market_management_list_reference_data($pdo, []);
$occurrence['reference_options'] = [
'categories' => market_management_list_categories($pdo),
'municipalities' => $referenceData['municipalities'] ?? [],
'parties' => get_party_options($pdo),
'contacts' => get_contact_options($pdo),
+3 -3
View File
@@ -1048,9 +1048,9 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best
echo " const marketCard = (title, body, headerClass = 'sg-card-segment--darkgreen', actions = '', scope = '', id = '', values = null) => { const header = '<header class=\"sg-card-segment sg-card-segment--header ' + headerClass + ' sg-object-card__header\" data-component-part=\"card-header\"><div class=\"sg-strong sg-text-on-dark\">' + title + '</div>' + (actions ? '<div class=\"sg-component-row\">' + actions + '</div>' : '') + '</header>'; return '<article class=\"sg-card sg-card--content-card market-detail-card\" data-component=\"content-card\"' + (scope ? ' data-shared-editable-action-card' : '') + '>' + header + '<div class=\"sg-card-segment sg-card-segment--body\" data-component-part=\"card-body\"' + (scope ? ' data-shared-editable-card-read' : '') + '>' + body + '</div>' + (scope ? '<div class=\"sg-card-segment sg-card-segment--body sg-card-segment--gray\" data-shared-editable-card-form hidden>' + marketEditForm(scope, id, values) + '</div>' : '') + '</article>'; };";
echo " const marketStatusCard = (id, values) => { const headerClass = marketStatusSegment(values.status); const textClass = headerClass === 'sg-card-segment--gray' || headerClass === 'sg-card-segment--signal-yellow' ? '' : 'sg-text-on-dark'; const actions = marketEditButton('status', id); const header = '<header class=\"sg-card-segment sg-card-segment--header ' + headerClass + ' sg-object-card__header\" data-component-part=\"card-header\"><div class=\"sg-strong ' + textClass + '\">Status: ' + marketEscape(marketStatusLabel(values.status)) + '</div><div class=\"sg-component-row\">' + actions + '</div></header>'; return '<article class=\"sg-card sg-card--content-card market-detail-card\" data-component=\"content-card\" data-shared-editable-action-card>' + header + '<div class=\"sg-card-segment sg-card-segment--body sg-card-segment--gray\" data-shared-editable-card-form hidden>' + marketEditForm('status', id, values) + '</div></article>'; };";
echo " const marketEditButton = () => '<button class=\"sg-interaction-element sg-button sg-button--active\" type=\"button\" data-shared-editable-card-edit>Bearbeiten</button>';";
echo " const renderMarketDetail = (payload) => { const market = payload.market || {}; const occurrence = payload.occurrence || {}; const days = Array.isArray(occurrence.days) ? occurrence.days : []; const organizer = occurrence.organizer || {}; const organization = organizer.organization || {}; const contactPerson = organizer.contact_person || {}; const website = market.website_url ? '<a class=\"sg-hyperlink\" href=\"' + marketEscape(market.website_url) + '\" target=\"_blank\" rel=\"noopener\">' + marketEscape(market.website_url) + '</a>' : 'Nicht hinterlegt'; const contract = occurrence.contract_folder_url ? '<a class=\"sg-hyperlink\" href=\"' + marketEscape(occurrence.contract_folder_url) + '\" target=\"_blank\" rel=\"noopener\">Vertragsordner öffnen</a>' : 'Nicht hinterlegt'; const overview = marketRow('Veranstaltung', market.name) + marketRow('Kategorie', market.category_name || market.category_code) + '<div class=\"market-detail-row\"><dt>Website</dt><dd>' + website + '</dd></div>' + marketRow('Ort', occurrence.place) + marketRow('Adresse', occurrence.address) + marketRow('Gemeinde', occurrence.municipality_reference_id) + marketRow('Veranstalter', organization.name) + marketRow('Kontaktperson', marketContactName(contactPerson)) + marketRow('Kontakt E-Mail', contactPerson.email) + marketRow('Kontakt Telefon', contactPerson.phone); const dates = days.map((day) => marketDate(day.date)).join(' – '); const costSummary = occurrence.cost_summary || {}; const participation = marketRow('Anmeldung / Anfrage', occurrence.request_or_registration_date) + marketRow('Anmeldefrist', occurrence.registration_deadline) + marketRow('Bestätigung', occurrence.confirmation_date) + marketRow('Zahlungsfrist', occurrence.payment_deadline) + marketRow('Zahlungsstatus', occurrence.payment_status) + marketRow('Zahlungsdatum', occurrence.payment_date) + marketRow('Bezahlter Betrag', marketMoney(occurrence.paid_amount)) + marketRow('Zahlungsart', occurrence.payment_method_code) + marketRow('Gesamtkosten brutto', marketMoney(costSummary.gross_amount)) + marketRow('Gesamtkosten netto', marketMoney(costSummary.net_amount)) + marketRow('Steuern', marketMoney(costSummary.tax_amount)) + marketRow('Offener Betrag', marketMoney(costSummary.open_amount)) + '<div class=\"market-detail-row\"><dt>Kostenpositionen</dt><dd>' + marketCostItems(occurrence.cost_items) + '</dd></div>'; const infrastructure = marketRow('Standgrösse', occurrence.stand_size) + marketRow('Tisch vorhanden', marketBoolean(occurrence.table_available)) + marketRow('Tisch mietbar', marketBoolean(occurrence.table_rentable)) + marketRow('Eigener Tisch erforderlich', marketBoolean(occurrence.own_table_required)) + marketRow('Überdachung', marketBoolean(occurrence.shelter_available)) + marketRow('Strom', marketBoolean(occurrence.power_available)) + marketRow('Wasser', marketBoolean(occurrence.water_available)) + marketRow('Beleuchtung', marketBoolean(occurrence.lighting_available)) + marketRow('Weitere Infrastruktur', occurrence.other_infrastructure) + marketRow('Anforderungen an den eigenen Stand', occurrence.own_stand_requirements); const travel = marketRow('Reiseadresse', occurrence.travel_address) + marketRow('Distanz (km)', occurrence.travel_distance_km) + marketRow('Reisedauer (Minuten)', occurrence.travel_duration_minutes) + marketRow('Parkmöglichkeiten', occurrence.parking_options) + marketRow('Anlieferung', occurrence.delivery_access) + marketRow('Direktes Entladen', marketBoolean(occurrence.direct_unload_possible)) + marketRow('Lagerung', occurrence.storage_options) + marketRow('Besondere Anreisehinweise', occurrence.travel_notes); const notes = marketRow('Teilnahmebedingungen', occurrence.other_participation_conditions) + marketRow('Rücktrittsbedingungen', occurrence.cancellation_terms) + marketRow('Umsatzbeteiligung', occurrence.revenue_share_terms) + marketRow('Notizen', occurrence.notes) + '<div class=\"market-detail-row\"><dt>Vertragsordner</dt><dd>' + contract + '</dd></div>'; const salesSummary = occurrence.sales_summary || {}; const dayTabs = days.map((day, index) => '<button class=\"sg-interaction-element sg-button sg-button--active sg-tab-button\" type=\"button\" role=\"tab\" aria-selected=\"' + (index === 0 ? 'true' : 'false') + '\" aria-controls=\"market-day-panel-' + day.id + '\" id=\"market-day-tab-' + day.id + '\" data-market-day-tab=\"true\">' + marketDate(day.date) + '</button>').join(''); const dayPanels = days.map((day, index) => '<div class=\"sg-content-block-card-group__panel\" id=\"market-day-panel-' + day.id + '\" role=\"tabpanel\" aria-labelledby=\"market-day-tab-' + day.id + '\"' + (index === 0 ? '' : ' hidden') + '><div class=\"sg-content-cards-group\" data-pattern=\"content-cards-group\" aria-label=\"Durchführungstag ' + marketDate(day.date) + '\">' + marketCard(marketDate(day.date), '<dl class=\"market-detail-grid\">' + marketRow('Datum', marketDate(day.date), true) + marketRow('Standzeit von', day.stand_start_time, true) + ma Line truncated
echo " const marketEditField = (key, label, type, value, options = []) => { const current = value === null || value === undefined ? '' : String(value); const control = type === 'textarea' ? '<textarea class=\"sg-interaction-element sg-input-multi-line\" name=\"' + key + '\" rows=\"4\">' + marketEscape(current) + '</textarea>' : type === 'select' ? '<select class=\"sg-interaction-element sg-input-single-line\" name=\"' + key + '\">' + options.map(([optionValue, optionLabel]) => '<option value=\"' + marketEscape(optionValue) + '\"' + (String(optionValue) === current ? ' selected' : '') + '>' + marketEscape(optionLabel) + '</option>').join('') + '</select>' : '<input class=\"sg-interaction-element sg-input-single-line\" type=\"' + type + '\" name=\"' + key + '\" value=\"' + marketEscape(current) + '\">'; return '<label class=\"sg-labeled-input-row\"><span class=\"sg-label\">' + marketEscape(label) + '</span>' + control + '</label>'; };";
echo " const marketEditForm = (scope, id, values) => { const boolOptions = [['', 'Nicht hinterlegt'], ['1', 'Ja'], ['0', 'Nein']]; const statusOptions = [['open', 'Offen'], ['waitlist', 'Warteliste'], ['registered', 'Angemeldet'], ['confirmation_pending', 'Bestätigung ausstehend'], ['confirmed', 'Bestätigt'], ['cancelled', 'Abgesagt'], ['completed', 'Abgeschlossen']]; const referenceOptions = values.reference_options || {}; const municipalityOptions = [['', 'Nicht hinterlegt'], ...(Array.isArray(referenceOptions.municipalities) ? referenceOptions.municipalities.map((option) => [option.id, option.name]) : [])]; const partyOptions = [['', 'Nicht hinterlegt'], ...(Array.isArray(referenceOptions.parties) ? referenceOptions.parties.map((option) => [option.id, option.name]) : [])]; const contactOptions = [['', 'Nicht hinterlegt'], ...(Array.isArray(referenceOptions.contacts) ? referenceOptions.contacts.map((option) => [option.id, [[option.first_name, option.last_name].filter(Boolean).join(' ') || 'Nicht hinterlegt', option.party_name].filter(Boolean).join(' – ')]) : [])]; const fieldSets = { status: [['status', 'Status', 'select', statusOptions]], overview: [['place', 'Ort', 'text'], ['address', 'Adresse', 'textarea'], ['municipality_reference_id', 'Gemeinde', 'select', municipalityOptions], ['organization_contact_id', 'Veranstalter', 'select', partyOptions], ['contact_person_id', 'Kontaktperson', 'select', contactOptions]], participation: [['registration_deadline', 'Anmeldefrist', 'date'], ['request_or_registration_date', 'Anmeldung / Anfrage', 'date'], ['confirmation_date', 'Bestätigung', 'date'], ['payment_deadline', 'Zahlungsfrist', 'date'], ['payment_status', 'Zahlungsstatus', 'select', [['', 'Nicht hinterlegt'], ['paid', 'Bezahlt'], ['unpaid', 'Unbezahlt']]], ['payment_date', 'Zahlungsdatum', 'date'], ['paid_amount', 'Bezahlter Betrag', 'number'], ['payment_method_code', 'Zahlungsart', 'text']], infrastructure: [['stand_size', 'Standgrösse', 'text'], ['table_available', 'Tisch vorhanden', 'select', boolOptions], ['table_rentable', 'Tisch mietbar', 'select', boolOptions], ['own_table_required', 'Eigener Tisch erforderlich', 'select', boolOptions], ['shelter_available', 'Überdachung', 'select', boolOptions], ['power_available', 'Strom', 'select', boolOptions], ['water_available', 'Wasser', 'select', boolOptions], ['lighting_available', 'Beleuchtung', 'select', boolOptions], ['other_infrastructure', 'Weitere Infrastruktur', 'textarea'], ['own_stand_requirements', 'Anforderungen an den eigenen Stand', 'textarea']], travel: [['travel_address', 'Reiseadresse', 'textarea'], ['travel_distance_km', 'Distanz (km)', 'number'], ['travel_duration_minutes', 'Reisedauer (Minuten)', 'number'], ['parking_options', 'Parkmöglichkeiten', 'textarea'], ['delivery_access', 'Anlieferung', 'textarea'], ['direct_unload_possible', 'Direktes Entladen', 'select', boolOptions], ['storage_options', 'Lagerung', 'textarea'], ['travel_notes', 'Besondere Anreisehinweise', 'textarea']], notes: [['cancellation_terms', 'Rücktrittsbedingungen', 'textarea'], ['revenue_share_terms', 'Umsatzbeteiligung', 'textarea'], ['other_participation_conditions', 'Teilnahmebedingungen', 'textarea'], ['notes', 'Notizen', 'textarea'], ['contract_folder_url', 'Vertragsordner', 'url']], day: [['date', 'Datum', 'date'], ['stand_start_time', 'Standzeit von', 'time'], ['stand_end_time', 'Standzeit bis', 'time'], ['setup_start_time', 'Aufbau von', 'time'], ['setup_end_time', 'Aufbau bis', 'time'], ['delivery_start_time', 'Anlieferung von', 'time'], ['delivery_end_time', 'Anlieferung bis', 'time'], ['observations', 'Beobachtungen', 'textarea']] }; const fields = fieldSets[scope] || []; const formFields = fields.map(([key, label, type, options]) => marketEditField(key, label, type, values[key], options)).join(''); return '<div class=\"sg-form-sections-card-wrapper\" data-pattern=\"form-sections\"><form class=\"sg-form-sections-card market-edit-form\" data-market-edit-form=\"true\" data-market-edit-scope=\"' + scope + '\" data-market-edit-id=\"' + id + '\"><div class=\"sg-form-sections-card__body\" data-pattern-part=\"form-body\"><h2 class=\"sg-strong sg-form-sections-card__title\">' + marketEscape(marketStatusLabel(values.status || scope)) + ' bearbeiten</h2><div class=\"sg-form-sections-card__section\">' + formFields + '</div></div><footer class=\"sg-form-sections-card__actions-segment\" data-pattern-part=\"form-actions-segment\"><div class=\"sg-form-sections-card__actions\" data-pattern-part=\"form-actions\"><button class=\"sg-interaction-element sg-button sg-button--active sg-form-sections-card__action\" type=\"button\" data-market-edit-cancel data-shared-editable-card-cancel>Abbrechen</button><button class=\"sg-interaction-element sg-button sg-button--process sg-form-sections-card__action\" type=\"submit\">Speichern</button></div></footer><p class=\"sg-body\" data-market-edit-status aria-live=\"polite\"></p></form></div>'; };";
echo " const renderMarketDetail = (payload) => { const market = payload.market || {}; const occurrence = payload.occurrence || {}; const days = Array.isArray(occurrence.days) ? occurrence.days : []; const organizer = occurrence.organizer || {}; const organization = organizer.organization || {}; const contactPerson = organizer.contact_person || {}; const website = market.website_url ? '<a class=\"sg-hyperlink\" href=\"' + marketEscape(market.website_url) + '\" target=\"_blank\" rel=\"noopener\">' + marketEscape(market.website_url) + '</a>' : 'Nicht hinterlegt'; const contract = occurrence.contract_folder_url ? '<a class=\"sg-hyperlink\" href=\"' + marketEscape(occurrence.contract_folder_url) + '\" target=\"_blank\" rel=\"noopener\">Vertragsordner öffnen</a>' : 'Nicht hinterlegt'; const overview = marketRow('Veranstaltung', market.name) + marketRow('Kategorie', market.category_name || market.category_code) + '<div class=\"market-detail-row\"><dt>Website</dt><dd>' + website + '</dd></div>' + marketRow('Ort', occurrence.place) + marketRow('Adresse', occurrence.address) + marketRow('Gemeinde', occurrence.municipality_reference_id) + marketRow('Veranstalter', organization.name) + marketRow('Kontaktperson', marketContactName(contactPerson)) + marketRow('Kontakt E-Mail', contactPerson.email) + marketRow('Kontakt Telefon', contactPerson.phone); const dates = days.map((day) => marketDate(day.date)).join(' – '); const costSummary = occurrence.cost_summary || {}; const participation = marketRow('Anmeldung / Anfrage', occurrence.request_or_registration_date) + marketRow('Anmeldefrist', occurrence.registration_deadline) + marketRow('Bestätigung', occurrence.confirmation_date) + marketRow('Zahlungsfrist', occurrence.payment_deadline) + marketRow('Zahlungsstatus', occurrence.payment_status) + marketRow('Zahlungsdatum', occurrence.payment_date) + marketRow('Bezahlter Betrag', marketMoney(occurrence.paid_amount)) + marketRow('Zahlungsart', occurrence.payment_method_code) + marketRow('Gesamtkosten brutto', marketMoney(costSummary.gross_amount)) + marketRow('Gesamtkosten netto', marketMoney(costSummary.net_amount)) + marketRow('Steuern', marketMoney(costSummary.tax_amount)) + marketRow('Offener Betrag', marketMoney(costSummary.open_amount)) + '<div class=\"market-detail-row\"><dt>Kostenpositionen</dt><dd>' + marketCostItems(occurrence.cost_items) + '</dd></div>'; const infrastructure = marketRow('Standgrösse', occurrence.stand_size) + marketRow('Tisch vorhanden', marketBoolean(occurrence.table_available)) + marketRow('Tisch mietbar', marketBoolean(occurrence.table_rentable)) + marketRow('Eigener Tisch erforderlich', marketBoolean(occurrence.own_table_required)) + marketRow('Überdachung', marketBoolean(occurrence.shelter_available)) + marketRow('Strom', marketBoolean(occurrence.power_available)) + marketRow('Wasser', marketBoolean(occurrence.water_available)) + marketRow('Beleuchtung', marketBoolean(occurrence.lighting_available)) + marketRow('Weitere Infrastruktur', occurrence.other_infrastructure) + marketRow('Anforderungen an den eigenen Stand', occurrence.own_stand_requirements); const travel = marketRow('Reiseadresse', occurrence.travel_address) + marketRow('Distanz (km)', occurrence.travel_distance_km) + marketRow('Reisedauer (Minuten)', occurrence.travel_duration_minutes) + marketRow('Parkmöglichkeiten', occurrence.parking_options) + marketRow('Anlieferung', occurrence.delivery_access) + marketRow('Direktes Entladen', marketBoolean(occurrence.direct_unload_possible)) + marketRow('Lagerung', occurrence.storage_options) + marketRow('Besondere Anreisehinweise', occurrence.travel_notes); const notes = marketRow('Teilnahmebedingungen', occurrence.other_participation_conditions) + marketRow('Rücktrittsbedingungen', occurrence.cancellation_terms) + marketRow('Umsatzbeteiligung', occurrence.revenue_share_terms) + marketRow('Notizen', occurrence.notes) + '<div class=\"market-detail-row\"><dt>Vertragsordner</dt><dd>' + contract + '</dd></div>'; const salesSummary = occurrence.sales_summary || {}; const dayTabs = days.map((day, index) => '<button class=\"sg-interaction-element sg-button sg-button--active sg-tab-button\" type=\"button\" role=\"tab\" aria-selected=\"' + (index === 0 ? 'true' : 'false') + '\" aria-controls=\"market-day-panel-' + day.id + '\" id=\"market-day-tab-' + day.id + '\" data-market-day-tab=\"true\">' + marketDate(day.date) + '</button>').join(''); const dayPanels = days.map((day, index) => '<div class=\"sg-content-block-card-group__panel\" id=\"market-day-panel-' + day.id + '\" role=\"tabpanel\" aria-labelledby=\"market-day-tab-' + day.id + '\"' + (index === 0 ? '' : ' hidden') + '><div class=\"sg-content-cards-group\" data-pattern=\"content-cards-group\" aria-label=\"Durchführungstag ' + marketDate(day.date) + '\">' + marketCard(marketDate(day.date), '<dl class=\"market-detail-grid\">' + marketRow('Datum', marketDate(day.date), true) + marketRow('Standzeit von', day.stand_start_time, true) + ma Line truncated
echo " const marketEditField = (key, label, type, value, options = []) => { const current = value === null || value === undefined ? '' : String(value); const control = type === 'textarea' ? '<textarea class=\"sg-interaction-element sg-input-multi-line\" name=\"' + key + '\" rows=\"4\">' + marketEscape(current) + '</textarea>' : type === 'select' ? '<select class=\"sg-interaction-element sg-input-single-line\" name=\"' + key + '\">' + options.map(([optionValue, optionLabel, contactEmail = '', contactPhone = '']) => '<option value=\"' + marketEscape(optionValue) + '\" data-contact-email=\"' + marketEscape(contactEmail) + '\" data-contact-phone=\"' + marketEscape(contactPhone) + '\"' + (String(optionValue) === current ? ' selected' : '') + '>' + marketEscape(optionLabel) + '</option>').join('') + '</select>' : '<input class=\"sg-interaction-element sg-input-single-line\" type=\"' + type + '\" name=\"' + key + '\" value=\"' + marketEscape(current) + '\">'; return '<label class=\"sg-labeled-input-row\"><span class=\"sg-label\">' + marketEscape(label) + '</span>' + control + '</label>'; };";
echo " const marketEditForm = (scope, id, values) => { const boolOptions = [['', 'Nicht hinterlegt'], ['1', 'Ja'], ['0', 'Nein']]; const statusOptions = [['open', 'Offen'], ['waitlist', 'Warteliste'], ['registered', 'Angemeldet'], ['confirmation_pending', 'Bestätigung ausstehend'], ['confirmed', 'Bestätigt'], ['cancelled', 'Abgesagt'], ['completed', 'Abgeschlossen']]; const referenceOptions = values.reference_options || {}; const categoryOptions = [['', 'Nicht hinterlegt'], ...(Array.isArray(referenceOptions.categories) ? referenceOptions.categories.map((option) => [option.id, option.name]) : [])]; const municipalityOptions = [['', 'Nicht hinterlegt'], ...(Array.isArray(referenceOptions.municipalities) ? referenceOptions.municipalities.map((option) => [option.id, option.name]) : [])]; const partyOptions = [['', 'Nicht hinterlegt'], ...(Array.isArray(referenceOptions.parties) ? referenceOptions.parties.map((option) => [option.id, option.name]) : [])]; const contactOptions = [['', 'Nicht hinterlegt'], ...(Array.isArray(referenceOptions.contacts) ? referenceOptions.contacts.map((option) => [option.id, [[option.first_name, option.last_name].filter(Boolean).join(' ') || 'Nicht hinterlegt', option.party_name].filter(Boolean).join(' – '), option.email || '', option.phone || '']) : [])]; const fieldSets = { status: [['status', 'Status', 'select', statusOptions]], overview: [['market_name', 'Veranstaltung', 'text'], ['category_id', 'Kategorie', 'select', categoryOptions], ['website_url', 'Website', 'url'], ['place', 'Ort', 'text'], ['address', 'Adresse', 'textarea'], ['municipality_reference_id', 'Gemeinde', 'select', municipalityOptions], ['organization_contact_id', 'Veranstalter', 'select', partyOptions], ['contact_person_id', 'Kontaktperson', 'select', contactOptions], ['contact_email', 'Kontakt E-Mail', 'email'], ['contact_phone', 'Kontakt Telefon', 'tel']], participation: [['registration_deadline', 'Anmeldefrist', 'date'], ['request_or_registration_date', 'Anmeldung / Anfrage', 'date'], ['confirmation_date', 'Bestätigung', 'date'], ['payment_deadline', 'Zahlungsfrist', 'date'], ['payment_status', 'Zahlungsstatus', 'select', [['', 'Nicht hinterlegt'], ['paid', 'Bezahlt'], ['unpaid', 'Unbezahlt']]], ['payment_date', 'Zahlungsdatum', 'date'], ['paid_amount', 'Bezahlter Betrag', 'number'], ['payment_method_code', 'Zahlungsart', 'text']], infrastructure: [['stand_size', 'Standgrösse', 'text'], ['table_available', 'Tisch vorhanden', 'select', boolOptions], ['table_rentable', 'Tisch mietbar', 'select', boolOptions], ['own_table_required', 'Eigener Tisch erforderlich', 'select', boolOptions], ['shelter_available', 'Überdachung', 'select', boolOptions], ['power_available', 'Strom', 'select', boolOptions], ['water_available', 'Wasser', 'select', boolOptions], ['lighting_available', 'Beleuchtung', 'select', boolOptions], ['other_infrastructure', 'Weitere Infrastruktur', 'textarea'], ['own_stand_requirements', 'Anforderungen an den eigenen Stand', 'textarea']], travel: [['travel_address', 'Reiseadresse', 'textarea'], ['travel_distance_km', 'Distanz (km)', 'number'], ['travel_duration_minutes', 'Reisedauer (Minuten)', 'number'], ['parking_options', 'Parkmöglichkeiten', 'textarea'], ['delivery_access', 'Anlieferung', 'textarea'], ['direct_unload_possible', 'Direktes Entladen', 'select', boolOptions], ['storage_options', 'Lagerung', 'textarea'], ['travel_notes', 'Besondere Anreisehinweise', 'textarea']], notes: [['cancellation_terms', 'Rücktrittsbedingungen', 'textarea'], ['revenue_share_terms', 'Umsatzbeteiligung', 'textarea'], ['other_participation_conditions', 'Teilnahmebedingungen', 'textarea'], ['notes', 'Notizen', 'textarea'], ['contract_folder_url', 'Vertragsordner', 'url']], day: [['date', 'Datum', 'date'], ['stand_start_time', 'Standzeit von', 'time'], ['stand_end_time', 'Standzeit bis', 'time'], ['setup_start_time', 'Aufbau von', 'time'], ['setup_end_time', 'Aufbau bis', 'time'], ['delivery_start_time', 'Anlieferung von', 'time'], ['delivery_end_time', 'Anlieferung bis', 'time'], ['observations', 'Beobachtungen', 'textarea']] }; const fields = fieldSets[scope] || []; const formFields = fields.map(([key, label, type, options]) => '<div class=\"sg-form-sections-card__field-group\">' + marketEditField(key, label, type, values[key], options) + '</div>').join(''); return '<div class=\"sg-form-sections-card-wrapper\" data-pattern=\"form-sections\"><form class=\"sg-form-sections-card market-edit-form\" data-market-edit-form=\"true\" data-market-edit-scope=\"' + scope + '\" data-market-edit-id=\"' + id + '\"><div class=\"sg-form-sections-card__body\" data-pattern-part=\"form-body\"><h2 class=\"sg-strong sg-form-sections-card__title\">' + marketEscape(marketStatusLabel(values.status || scope)) + ' bearbeiten</h2><div class=\"sg-form-sections-card__section\">' + formFields + '</div></div><footer class=\"sg-form-sections-card__actions-segment\" data-pattern-part=\"form-actions-segment\"><div class=\"sg-form-sect Line truncated
echo " const buildUrl = (params) => { const url = new URL(window.location.href); Object.entries(params).forEach(([key, value]) => { if (value === null || value === undefined || value === '') { url.searchParams.delete(key); } else { url.searchParams.set(key, String(value)); } }); return url; };";
echo " const replaceFragment = (html) => { const doc = new DOMParser().parseFromString(html, 'text/html'); const fragment = doc.querySelector('[data-markets-content]'); if (!fragment) { return false; } contentRoot.innerHTML = fragment.innerHTML; return Boolean(getTable()); };";
echo " const loadFragment = async (params) => { if (searchTimer) { window.clearTimeout(searchTimer); searchTimer = null; } const input = getSearchInput(); const wasFocused = input ? document.activeElement === input : false; const response = await fetch(buildUrl({ ...params, market_fragment: '1' }).toString(), { credentials: 'same-origin', headers: { 'X-Requested-With': 'XMLHttpRequest' } }); if (!response.ok) { return; } const replaced = replaceFragment(await response.text()); if (!replaced) { return; } window.history.replaceState({}, '', buildUrl(params)); bindTable(); if (wasFocused) { const nextInput = getSearchInput(); nextInput?.focus({ preventScroll: true }); if (nextInput) { nextInput.setSelectionRange(nextInput.value.length, nextInput.value.length); } } };";
+26 -1
View File
@@ -39,6 +39,31 @@ if ($requestMethod === 'POST') {
if ($scope === 'day') {
market_management_update_day($pdo, $id, $fields);
} elseif (in_array($scope, ['occurrence', 'status', 'overview', 'participation', 'infrastructure', 'travel', 'notes'], true)) {
$marketFields = [];
foreach (['market_name', 'category_id', 'website_url'] as $marketField) {
if (array_key_exists($marketField, $fields)) {
$marketFields[$marketField === 'market_name' ? 'name' : $marketField] = $fields[$marketField];
unset($fields[$marketField]);
}
}
$contactFields = [];
foreach (['contact_email', 'contact_phone'] as $contactField) {
if (array_key_exists($contactField, $fields)) {
$contactFields[substr($contactField, 8)] = $fields[$contactField];
unset($fields[$contactField]);
}
}
$existingOccurrence = null;
if ($marketFields !== [] || $contactFields !== [] || array_key_exists('organization_contact_id', $fields) || array_key_exists('contact_person_id', $fields)) {
$existingOccurrence = market_management_get_occurrence($pdo, $id, true);
}
if ($marketFields !== []) {
market_management_update_market($pdo, (int) ($existingOccurrence['market_definition_id'] ?? 0), $marketFields);
}
if ($contactFields !== []) {
$contactId = (int) ($fields['contact_person_id'] ?? $existingOccurrence['contact_person_id'] ?? 0);
update_contact_details($pdo, $contactId, $contactFields);
}
$organizerFields = [];
foreach (['organization_contact_id', 'contact_person_id'] as $organizerField) {
if (array_key_exists($organizerField, $fields)) {
@@ -47,7 +72,7 @@ if ($requestMethod === 'POST') {
}
}
if ($organizerFields !== []) {
$existingOccurrence = market_management_get_occurrence($pdo, $id, true);
$existingOccurrence ??= market_management_get_occurrence($pdo, $id, true);
$existingOrganizer = $existingOccurrence['organizer'] ?? null;
$organizerFields['occurrence_id'] = $id;
$organizerFields['organization_contact_id'] ??= $existingOrganizer['organization_contact_id'] ?? null;