Fix market status card edit mode

This commit is contained in:
gitea_admin committed 2026-09-19 13:49:41 +02:00
1 parent f66c22027e
commit 9064d4eb42
1 file changed
+3 -3
+3 -3
View File
@@ -1044,11 +1044,11 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best
echo " const marketDate = (value) => { if (!value) { return 'Nicht hinterlegt'; } const parts = String(value).split('-'); return parts.length === 3 ? parts[2] + '.' + parts[1] + '.' + parts[0] : marketEscape(value); };";
echo " const marketStatusLabel = (value) => ({ open: 'Offen', waitlist: 'Warteliste', registered: 'Angemeldet', confirmation_pending: 'Bestätigung ausstehend', confirmed: 'Bestätigt', cancelled: 'Abgesagt', completed: 'Abgeschlossen' }[value] || value || 'Nicht hinterlegt');";
echo " const marketStatusSegment = (value) => ({ waitlist: 'sg-card-segment--signal-red', registered: 'sg-card-segment--signal-yellow', confirmation_pending: 'sg-card-segment--signal-yellow', confirmed: 'sg-card-segment--signal-green' }[value] || 'sg-card-segment--gray');";
echo " const marketStatusTextClass = (value) => ({ waitlist: 'sg-text-on-dark', registered: 'sg-text-on-dark', confirmation_pending: 'sg-text-on-dark', confirmed: 'sg-text-on-dark' }[value] || '');";
echo " const marketRow = (label, value, specific = false) => '<div class=\"market-detail-row\"><dt>' + marketEscape(label) + (specific ? ' <span class=\"sg-table-label market-day-specific\">(Tagesspezifisch)</span>' : '') + '</dt><dd>' + marketDisplay(value) + '</dd></div>';";
echo " const marketCard = (title, body, headerClass = 'sg-card-segment--darkgreen', actions = '', scope = '', id = '', values = null) => { const isStatus = title.indexOf('Status') === 0; const displayTitle = isStatus ? 'Status: ' + marketStatusLabel(values.status) : title; const headerTextClass = isStatus && headerClass === 'sg-card-segment--gray' ? '' : 'sg-text-on-dark'; 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 ' + headerTextClass + '\">' + displayTitle + '</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' : '') + '>' + (isStatus ? '<div data-shared-editable-card-read>' + header + '</div>' : 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 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><div data-shared-editable-card-read>' + header + '</div><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 = (scope, id) => '<button class=\"sg-interaction-element sg-button sg-button--active\" type=\"button\" data-market-edit=\"true\" data-shared-editable-card-edit data-market-edit-scope=\"' + scope + '\" data-market-edit-id=\"' + marketEscape(id) + '\">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-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) + marketRow('Standzeit Line truncated
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 fieldSets = { status: [['status', 'Status', 'select', statusOptions]], overview: [['place', 'Ort', 'text'], ['address', 'Adresse', 'textarea']], 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 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; };";