|
|
|
@@ -171,22 +171,8 @@ function auth_render_bestellungen_large_table(array $bestellungenTable): string
|
|
|
|
|
$html[] = '<h2 class="sg-heading-h2 sg-card-list-page-drawer__title" data-order-drawer-title>Bestellung</h2>';
|
|
|
|
|
$html[] = '<button class="sg-interaction-element sg-hyperlink" type="button" data-order-drawer-close>schliessen</button>';
|
|
|
|
|
$html[] = '</div>';
|
|
|
|
|
$html[] = '<div class="sg-card-list-page-drawer__content">';
|
|
|
|
|
$html[] = '<article class="sg-card sg-vsf-drawer-card" data-component="card" data-pattern="card" aria-label="Bestell-Details">';
|
|
|
|
|
$html[] = '<header class="sg-card-segment sg-card-segment--header sg-card-segment--darkblue sg-vsf-drawer-card__header">';
|
|
|
|
|
$html[] = '<div class="sg-strong">Bestell-Details</div>';
|
|
|
|
|
$html[] = '</header>';
|
|
|
|
|
$html[] = '<div class="sg-card-segment sg-card-segment--body sg-vsf-drawer-card__content">';
|
|
|
|
|
$html[] = '<p class="sg-body"><strong>Bestellnummer:</strong> <span data-order-drawer-order-number></span></p>';
|
|
|
|
|
$html[] = '<p class="sg-body"><strong>Bestelldatum:</strong> <span data-order-drawer-order-date></span></p>';
|
|
|
|
|
$html[] = '<p class="sg-body"><strong>Lieferadresse:</strong></p>';
|
|
|
|
|
$html[] = '<p class="sg-body" data-order-drawer-address-line-1></p>';
|
|
|
|
|
$html[] = '<p class="sg-body" data-order-drawer-address-line-2></p>';
|
|
|
|
|
$html[] = '<p class="sg-body" data-order-drawer-address-line-3></p>';
|
|
|
|
|
$html[] = '<p class="sg-body"><strong>Gesamtsumme:</strong> <span data-order-drawer-total></span></p>';
|
|
|
|
|
$html[] = '<p class="sg-body">Detailinhalt wird noch definiert.</p>';
|
|
|
|
|
$html[] = '</div>';
|
|
|
|
|
$html[] = '</article>';
|
|
|
|
|
$html[] = '<div class="sg-card-list-page-drawer__content" data-order-drawer-cards>';
|
|
|
|
|
$html[] = '<p class="sg-body" data-order-drawer-loading>Bestelldetails werden geladen …</p>';
|
|
|
|
|
$html[] = '</div>';
|
|
|
|
|
$html[] = '</aside>';
|
|
|
|
|
|
|
|
|
@@ -256,9 +242,14 @@ function auth_render_lager_table(string $title, array $rows, array $columns, str
|
|
|
|
|
$detailData = ' data-lager-drawer-forecast="' . auth_escape_html($forecastText) . '"'
|
|
|
|
|
. ' data-lager-drawer-forecast-warning="' . ($forecastWarning ? 'true' : 'false') . '"'
|
|
|
|
|
. ' data-lager-drawer-forecast-mhd-warning="' . ($forecastMhdWarning ? 'true' : 'false') . '"'
|
|
|
|
|
. ' data-lager-drawer-lot-id="' . auth_escape_html((string) ($row['lot_id'] ?? '')) . '"'
|
|
|
|
|
. ' data-lager-drawer-lot-number="' . auth_escape_html((string) ($row['lot_number'] ?? '')) . '"'
|
|
|
|
|
. ' data-lager-drawer-supplier-lot-number="' . auth_escape_html((string) ($row['supplier_lot_number'] ?? '')) . '"'
|
|
|
|
|
. ' data-lager-drawer-manufacturer-party-id="' . auth_escape_html((string) ($row['manufacturer_party_id'] ?? '')) . '"'
|
|
|
|
|
. ' data-lager-drawer-manufacturer-name="' . auth_escape_html((string) ($row['manufacturer_name'] ?? '')) . '"'
|
|
|
|
|
. ' data-lager-drawer-manufacturer-lot-number="' . auth_escape_html((string) ($row['manufacturer_lot_number'] ?? '')) . '"'
|
|
|
|
|
. ' data-lager-drawer-mfg-date="' . auth_escape_html((string) ($row['mfg_date'] ?? '')) . '"'
|
|
|
|
|
. ' data-lager-drawer-expiry-date="' . auth_escape_html((string) ($row['expiry_date'] ?? '')) . '"'
|
|
|
|
|
. ' data-lager-drawer-purchase-date="' . auth_escape_html((string) ($row['purchase_date'] ?? '')) . '"'
|
|
|
|
|
. ' data-lager-drawer-virtual-lot-number="' . auth_escape_html((string) ($row['virtual_lot_number'] ?? '')) . '"';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -278,9 +269,14 @@ function auth_render_lager_table(string $title, array $rows, array $columns, str
|
|
|
|
|
return implode('', $html);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function auth_render_lager_content(array $lagerProducts, array $lagerArtikel): string
|
|
|
|
|
function auth_render_lager_content(array $lagerProducts, array $lagerArtikel, array $lagerManufacturers, string $csrfToken): string
|
|
|
|
|
{
|
|
|
|
|
return '<div data-lager-content="true">'
|
|
|
|
|
$manufacturerOptions = '<option value="">Hersteller auswählen</option>';
|
|
|
|
|
foreach ($lagerManufacturers as $manufacturer) {
|
|
|
|
|
$manufacturerOptions .= '<option value="' . (int) ($manufacturer['id'] ?? 0) . '">' . auth_escape_html((string) ($manufacturer['name'] ?? '')) . '</option>';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return '<div data-lager-content="true" data-lager-csrf-token="' . auth_escape_html($csrfToken) . '">'
|
|
|
|
|
. '<section class="sg-card-list-page" aria-label="Lager">'
|
|
|
|
|
. auth_render_lager_table('Produkte', $lagerProducts, ['Produktname', 'Anzahl im Lager', 'Verbraucht bis'], 'products')
|
|
|
|
|
. auth_render_lager_table('Artikel', $lagerArtikel, ['Artikel-Name', 'Artikelnummer'], 'articles')
|
|
|
|
@@ -299,7 +295,22 @@ function auth_render_lager_content(array $lagerProducts, array $lagerArtikel): s
|
|
|
|
|
. '</article>'
|
|
|
|
|
. '<article class="sg-card sg-card--content-card" data-component="content-card" data-lager-drawer-topic="lot" aria-label="Lagercharge">'
|
|
|
|
|
. '<div class="sg-card-segment sg-card-segment--header sg-card-segment--darkgreen" data-component-part="card-header"><div class="sg-strong sg-text-on-dark">Lagercharge</div></div>'
|
|
|
|
|
. '<div class="sg-card-segment sg-card-segment--body" data-component-part="card-body"><p class="sg-body"><strong>Naurua-Chargennummer:</strong> <span data-lager-drawer-lot-number></span><br><strong>Hersteller-Chargennummer:</strong> <span data-lager-drawer-supplier-lot-number></span><br><strong>MHD:</strong> <span data-lager-drawer-expiry-date></span></p></div>'
|
|
|
|
|
. '<div class="sg-card-segment sg-card-segment--body" data-component-part="card-body"><p class="sg-body"><strong>Naurua-Chargennummer:</strong> <span data-lager-drawer-lot-number></span><br><strong>Hersteller:</strong> <span data-lager-drawer-manufacturer-name></span><br><strong>Hersteller-Chargennummer:</strong> <span data-lager-drawer-manufacturer-lot-number></span><br><strong>Herstellungsdatum:</strong> <span data-lager-drawer-mfg-date></span><br><strong>MHD:</strong> <span data-lager-drawer-expiry-date></span><br><strong>Einkaufsdatum:</strong> <span data-lager-drawer-purchase-date></span></p><button class="sg-interaction-element sg-button sg-button--active" type="button" data-lager-edit-open>Charge bearbeiten</button></div>'
|
|
|
|
|
. '<div class="sg-card-segment sg-card-segment--body sg-card-segment--gray" data-lager-edit-form hidden>'
|
|
|
|
|
. '<form class="sg-form-sections-card" data-lager-edit-form-element><div class="sg-form-sections-card__body">'
|
|
|
|
|
. '<div class="sg-form-sections-card__field-group"><label class="sg-label" for="lager-manufacturer">Hersteller</label><select class="sg-interaction-element sg-input-single-line" id="lager-manufacturer" data-lager-manufacturer>' . $manufacturerOptions . '</select></div>'
|
|
|
|
|
. '<div class="sg-form-sections-card__field-group"><label class="sg-label" for="lager-manufacturer-lot">Hersteller-Chargennummer</label><input class="sg-interaction-element sg-input-single-line" type="text" id="lager-manufacturer-lot" data-lager-manufacturer-lot></div>'
|
|
|
|
|
. '<div class="sg-form-sections-card__field-group"><label class="sg-label" for="lager-mfg-date">Herstellungsdatum</label><input class="sg-interaction-element sg-input-single-line" type="date" id="lager-mfg-date" data-lager-mfg-date></div>'
|
|
|
|
|
. '<div class="sg-form-sections-card__field-group"><label class="sg-label" for="lager-expiry-date">MHD</label><input class="sg-interaction-element sg-input-single-line" type="date" id="lager-expiry-date" data-lager-expiry-date></div>'
|
|
|
|
|
. '<div class="sg-form-sections-card__field-group"><label class="sg-label" for="lager-purchase-date">Einkaufsdatum</label><input class="sg-interaction-element sg-input-single-line" type="date" id="lager-purchase-date" data-lager-purchase-date></div>'
|
|
|
|
|
. '<div class="sg-component-row sg-basic-card__actions"><button class="sg-interaction-element sg-button sg-button--active" type="submit">Speichern</button><button class="sg-interaction-element sg-button" type="button" data-lager-edit-close>Abbrechen</button></div>'
|
|
|
|
|
. '<p class="sg-body" data-lager-edit-status aria-live="polite"></p></div></form>'
|
|
|
|
|
. '<form class="sg-form-sections-card" data-lager-manufacturer-form><div class="sg-form-sections-card__body"><h3 class="sg-strong">Neuen Hersteller anlegen</h3>'
|
|
|
|
|
. '<div class="sg-form-sections-card__field-group"><label class="sg-label" for="lager-new-manufacturer-name">Name</label><input class="sg-interaction-element sg-input-single-line" type="text" id="lager-new-manufacturer-name" data-lager-new-manufacturer-name required></div>'
|
|
|
|
|
. '<div class="sg-form-sections-card__field-group"><label class="sg-label" for="lager-new-manufacturer-email">E-Mail</label><input class="sg-interaction-element sg-input-single-line" type="email" id="lager-new-manufacturer-email" data-lager-new-manufacturer-email></div>'
|
|
|
|
|
. '<div class="sg-form-sections-card__field-group"><label class="sg-label" for="lager-new-manufacturer-phone">Telefon</label><input class="sg-interaction-element sg-input-single-line" type="text" id="lager-new-manufacturer-phone" data-lager-new-manufacturer-phone></div>'
|
|
|
|
|
. '<div class="sg-component-row sg-basic-card__actions"><button class="sg-interaction-element sg-button sg-button--active" type="submit">Hersteller anlegen</button></div></div></form>'
|
|
|
|
|
. '</div></article>'
|
|
|
|
|
. '</article>'
|
|
|
|
|
. '<article class="sg-card sg-card--content-card" data-component="content-card" data-lager-drawer-topic="virtual-lot" aria-label="Virtuelle Charge">'
|
|
|
|
|
. '<div class="sg-card-segment sg-card-segment--header sg-card-segment--darkgreen" data-component-part="card-header"><div class="sg-strong sg-text-on-dark">Virtuelle Charge</div></div>'
|
|
|
|
@@ -310,7 +321,7 @@ function auth_render_lager_content(array $lagerProducts, array $lagerArtikel): s
|
|
|
|
|
. '</div>';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function render_auth_home_page(array $user, array $otcProducts = [], array $bestellungenTable = [], array $lagerProducts = [], array $lagerArtikel = []): void
|
|
|
|
|
function render_auth_home_page(array $user, array $otcProducts = [], array $bestellungenTable = [], array $lagerProducts = [], array $lagerArtikel = [], array $lagerManufacturers = []): void
|
|
|
|
|
{
|
|
|
|
|
$otcProductRows = '';
|
|
|
|
|
foreach ($otcProducts as $product) {
|
|
|
|
@@ -344,7 +355,7 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best
|
|
|
|
|
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES
|
|
|
|
|
);
|
|
|
|
|
$bestellungenContent = auth_render_bestellungen_content($bestellungenTable);
|
|
|
|
|
$lagerContent = auth_render_lager_content($lagerProducts, $lagerArtikel);
|
|
|
|
|
$lagerContent = auth_render_lager_content($lagerProducts, $lagerArtikel, $lagerManufacturers, auth_csrf_token());
|
|
|
|
|
$moduleContentCards = json_encode(
|
|
|
|
|
[
|
|
|
|
|
'Bestellungen' => $bestellungenContent,
|
|
|
|
@@ -655,10 +666,13 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best
|
|
|
|
|
echo " const warning = trigger.dataset.lagerDrawerForecastWarning === 'true' || trigger.dataset.lagerDrawerForecastMhdWarning === 'true';";
|
|
|
|
|
echo " const warningText = warning ? forecast : 'Keine akute Warnung.';";
|
|
|
|
|
echo " const lotNumber = trigger.dataset.lagerDrawerLotNumber || 'Nicht hinterlegt';";
|
|
|
|
|
echo " const supplierLotNumber = trigger.dataset.lagerDrawerSupplierLotNumber || 'Nicht hinterlegt';";
|
|
|
|
|
echo " const manufacturerName = trigger.dataset.lagerDrawerManufacturerName || 'Nicht hinterlegt';";
|
|
|
|
|
echo " const manufacturerLotNumber = trigger.dataset.lagerDrawerManufacturerLotNumber || 'Nicht hinterlegt';";
|
|
|
|
|
echo " const mfgDate = trigger.dataset.lagerDrawerMfgDate || 'Nicht hinterlegt';";
|
|
|
|
|
echo " const expiryDate = trigger.dataset.lagerDrawerExpiryDate || 'Nicht hinterlegt';";
|
|
|
|
|
echo " const purchaseDate = trigger.dataset.lagerDrawerPurchaseDate || 'Nicht hinterlegt';";
|
|
|
|
|
echo " const virtualLot = trigger.dataset.lagerDrawerVirtualLotNumber || '';";
|
|
|
|
|
echo " return ['<div class=\"sg-lager-mobile-detail-host\" data-lager-mobile-detail-host=\"true\">', '<div class=\"sg-navigation-card-layout sg-mobile-detail-back-card\">', '<div class=\"sg-navigation-card-block\">', '<article class=\"sg-card\" data-component=\"card\" data-pattern=\"navigation-card\" aria-label=\"Navigation Detailansicht zurück oben\">', '<div class=\"sg-card-segment sg-card-segment--body\" data-component-part=\"card-body\" data-pattern-part=\"navigation-card-segment\">', '<div class=\"sg-navigation-card-center\">', '<button class=\"sg-interaction-element sg-hyperlink\" type=\"button\" data-lager-detail-back>zurück</button>', '</div></div></article></div></div>', '<article class=\"sg-card sg-vsf-drawer-card\" data-component=\"card\" data-pattern=\"card\" aria-label=\"Lager-Details\">', '<header class=\"sg-card-segment sg-card-segment--header sg-card-segment--darkblue\"><div class=\"sg-strong\">' + escapeLagerHtml(type) + ': ' + escapeLagerHtml(name) + '</div></header>', '<div class=\"sg-card-segment sg-card-segment--body sg-vsf-drawer-card__content\"><p class=\"sg-body\"><strong>Name:</strong> ' + escapeLagerHtml(name) + '</p><p class=\"sg-body\"><strong>' + (isProduct ? 'Anzahl im Lager:' : 'Artikelnummer:') + '</strong> ' + escapeLagerHtml(value) + '</p>' + (isProduct ? '<p class=\"sg-body\"><strong>Warnungen:</strong> ' + escapeLagerHtml(warningText) + '</p><p class=\"sg-body\"><strong>Naurua-Chargennummer:</strong> ' + escapeLagerHtml(lotNumber) + '<br><strong>Hersteller-Chargennummer:</strong> ' + escapeLagerHtml(supplierLotNumber) + '<br><strong>MHD:</strong> ' + escapeLagerHtml(expiryDate) + '</p><p class=\"sg-body\"><strong>Virtuelle Charge:</strong> ' + escapeLagerHtml(virtualLot || 'Keine virtuelle Fehlbestandscharge vorhanden.') + '</p>' : '') + '</div></article></div>'].join('');";
|
|
|
|
|
echo " return ['<div class=\"sg-lager-mobile-detail-host\" data-lager-mobile-detail-host=\"true\">', '<div class=\"sg-navigation-card-layout sg-mobile-detail-back-card\">', '<div class=\"sg-navigation-card-block\">', '<article class=\"sg-card\" data-component=\"card\" data-pattern=\"navigation-card\" aria-label=\"Navigation Detailansicht zurück oben\">', '<div class=\"sg-card-segment sg-card-segment--body\" data-component-part=\"card-body\" data-pattern-part=\"navigation-card-segment\">', '<div class=\"sg-navigation-card-center\">', '<button class=\"sg-interaction-element sg-hyperlink\" type=\"button\" data-lager-detail-back>zurück</button>', '</div></div></article></div></div>', '<article class=\"sg-card sg-vsf-drawer-card\" data-component=\"card\" data-pattern=\"card\" aria-label=\"Lager-Details\">', '<header class=\"sg-card-segment sg-card-segment--header sg-card-segment--darkblue\"><div class=\"sg-strong\">' + escapeLagerHtml(type) + ': ' + escapeLagerHtml(name) + '</div></header>', '<div class=\"sg-card-segment sg-card-segment--body sg-vsf-drawer-card__content\"><p class=\"sg-body\"><strong>Name:</strong> ' + escapeLagerHtml(name) + '</p><p class=\"sg-body\"><strong>' + (isProduct ? 'Anzahl im Lager:' : 'Artikelnummer:') + '</strong> ' + escapeLagerHtml(value) + '</p>' + (isProduct ? '<p class=\"sg-body\"><strong>Warnungen:</strong> ' + escapeLagerHtml(warningText) + '</p><p class=\"sg-body\"><strong>Naurua-Chargennummer:</strong> ' + escapeLagerHtml(lotNumber) + '<br><strong>Hersteller:</strong> ' + escapeLagerHtml(manufacturerName) + '<br><strong>Hersteller-Chargennummer:</strong> ' + escapeLagerHtml(manufacturerLotNumber) + '<br><strong>Herstellungsdatum:</strong> ' + escapeLagerHtml(mfgDate) + '<br><strong>MHD:</strong> ' + escapeLagerHtml(expiryDate) + '<br><strong>Einkaufsdatum:</strong> ' + escapeLagerHtml(purchaseDate) + '</p><p class=\"sg-body\"><strong>Virtuelle Charge:</strong> ' + escapeLagerHtml(virtualLot || 'Keine virtuelle Fehlbestandscharge vorhanden.') + '</p>' : '') + '</div></article></div>'].join('');";
|
|
|
|
|
echo " };";
|
|
|
|
|
echo " const restoreLagerMobileDetail = () => {";
|
|
|
|
|
echo " if (lagerMobileDetailHost && lagerMobileDetailHost.parentNode) { lagerMobileDetailHost.parentNode.removeChild(lagerMobileDetailHost); }";
|
|
|
|
@@ -683,9 +697,12 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best
|
|
|
|
|
echo " const closeDrawer = () => { setDrawerState(false); contentRoot.querySelectorAll('[data-lager-drawer-open]').forEach((trigger) => trigger.setAttribute('aria-expanded', 'false')); };";
|
|
|
|
|
echo " contentRoot.addEventListener('click', (event) => {";
|
|
|
|
|
echo " const trigger = event.target.closest('[data-lager-drawer-open]');";
|
|
|
|
|
echo " if (trigger) { event.preventDefault(); if (window.matchMedia('(max-width: 767px)').matches) { openLagerMobileDetail(trigger); return; } const drawer = getDrawer(); if (!drawer) { return; } const type = trigger.dataset.lagerDrawerType || 'Lager'; const name = trigger.dataset.lagerDrawerName || ''; const value = trigger.dataset.lagerDrawerValue || ''; drawer.querySelector('[data-lager-drawer-title]').textContent = type + ': ' + name; drawer.querySelector('[data-lager-drawer-name-value]').textContent = name; const valueRow = drawer.querySelector('[data-lager-drawer-value-row]'); if (valueRow) { valueRow.hidden = false; } drawer.querySelector('[data-lager-drawer-value-label]').textContent = type === 'Produkt' ? 'Anzahl im Lager:' : 'Artikelnummer:'; drawer.querySelector('[data-lager-drawer-value-value]').textContent = value; drawer.querySelectorAll('[data-lager-drawer-topic]').forEach((card) => { card.hidden = type !== 'Produkt'; }); if (type === 'Produkt') { const forecast = trigger.dataset.lagerDrawerForecast || 'Keine Prognose'; const warning = trigger.dataset.lagerDrawerForecastWarning === 'true' || trigger.dataset.lagerDrawerForecastMhdWarning === 'true'; const warningValue = drawer.querySelector('[data-lager-drawer-warning-value]'); if (warningValue) { warningValue.textContent = warning ? forecast : 'Keine akute Warnung.'; warningValue.classList.toggle('sg-strong', warning); warningValue.classList.toggle('lager-forecast-warning', trigger.dataset.lagerDrawerForecastWarning === 'true'); warningValue.classList.toggle('lager-forecast-mhd-warning', trigger.dataset.lagerDrawerForecastMhdWarning === 'true'); } drawer.querySelector('[data-lager-drawer-lot-number]').textContent = trigger.dataset.lagerDrawerLotNumber || 'Nicht hinterlegt'; drawer.querySelector('[data-lager-drawer-supplier-lot-number]').textContent = trigger.dataset.lagerDrawerSupplierLotNumber || 'Nicht hinterlegt'; drawer.querySelector('[data-lager-drawer-expiry-date]').textContent = trigger.dataset.lagerDrawerExpiryDate || 'Nicht hinterlegt'; const virtualLot = trigger.dataset.lagerDrawerVirtualLotNumber || ''; drawer.querySelector('[data-lager-drawer-virtual-lot-value]').textContent = virtualLot ? 'Virtuelle Charge: ' + virtualLot : 'Keine virtuelle Fehlbestandscharge vorhanden.'; } setDrawerState(true); contentRoot.querySelectorAll('[data-lager-drawer-open]').forEach((button) => button.setAttribute('aria-expanded', String(button === trigger))); return; }";
|
|
|
|
|
echo " if (trigger) { event.preventDefault(); if (window.matchMedia('(max-width: 767px)').matches) { openLagerMobileDetail(trigger); return; } const drawer = getDrawer(); if (!drawer) { return; } const type = trigger.dataset.lagerDrawerType || 'Lager'; const name = trigger.dataset.lagerDrawerName || ''; const value = trigger.dataset.lagerDrawerValue || ''; drawer.querySelector('[data-lager-drawer-title]').textContent = type + ': ' + name; drawer.querySelector('[data-lager-drawer-name-value]').textContent = name; const valueRow = drawer.querySelector('[data-lager-drawer-value-row]'); if (valueRow) { valueRow.hidden = false; } drawer.querySelector('[data-lager-drawer-value-label]').textContent = type === 'Produkt' ? 'Anzahl im Lager:' : 'Artikelnummer:'; drawer.querySelector('[data-lager-drawer-value-value]').textContent = value; drawer.querySelectorAll('[data-lager-drawer-topic]').forEach((card) => { card.hidden = type !== 'Produkt'; }); if (type === 'Produkt') { const forecast = trigger.dataset.lagerDrawerForecast || 'Keine Prognose'; const warning = trigger.dataset.lagerDrawerForecastWarning === 'true' || trigger.dataset.lagerDrawerForecastMhdWarning === 'true'; const warningValue = drawer.querySelector('[data-lager-drawer-warning-value]'); if (warningValue) { warningValue.textContent = warning ? forecast : 'Keine akute Warnung.'; warningValue.classList.toggle('sg-strong', warning); warningValue.classList.toggle('lager-forecast-warning', trigger.dataset.lagerDrawerForecastWarning === 'true'); warningValue.classList.toggle('lager-forecast-mhd-warning', trigger.dataset.lagerDrawerForecastMhdWarning === 'true'); } drawer.querySelector('[data-lager-drawer-lot-number]').textContent = trigger.dataset.lagerDrawerLotNumber || 'Nicht hinterlegt'; drawer.querySelector('[data-lager-drawer-manufacturer-name]').textContent = trigger.dataset.lagerDrawerManufacturerName || 'Nicht hinterlegt'; drawer.querySelector('[data-lager-drawer-manufacturer-lot-number]').textContent = trigger.dataset.lagerDrawerManufacturerLotNumber || 'Nicht hinterlegt'; drawer.querySelector('[data-lager-drawer-mfg-date]').textContent = trigger.dataset.lagerDrawerMfgDate || 'Nicht hinterlegt'; drawer.querySelector('[data-lager-drawer-expiry-date]').textContent = trigger.dataset.lagerDrawerExpiryDate || 'Nicht hinterlegt'; drawer.querySelector('[data-lager-drawer-purchase-date]').textContent = trigger.dataset.lagerDrawerPurchaseDate || 'Nicht hinterlegt'; const virtualLot = trigger.dataset.lagerDrawerVirtualLotNumber || ''; drawer.querySelector('[data-lager-drawer-virtual-lot-value]').textContent = virtualLot ? 'Virtuelle Charge: ' + virtualLot : 'Keine virtuelle Fehlbestandscharge vorhanden.'; const manufacturer = drawer.querySelector('[data-lager-manufacturer]'); if (manufacturer) { manufacturer.value = trigger.dataset.lagerDrawerManufacturerPartyId || ''; } const manufacturerLot = drawer.querySelector('[data-lager-manufacturer-lot]'); if (manufacturerLot) { manufacturerLot.value = trigger.dataset.lagerDrawerManufacturerLotNumber || ''; } const mfgDate = drawer.querySelector('[data-lager-mfg-date]'); if (mfgDate) { mfgDate.value = trigger.dataset.lagerDrawerMfgDate || ''; } const expiryDate = drawer.querySelector('[data-lager-expiry-date]'); if (expiryDate) { expiryDate.value = trigger.dataset.lagerDrawerExpiryDate || ''; } const purchaseDate = drawer.querySelector('[data-lager-purchase-date]'); if (purchaseDate) { purchaseDate.value = trigger.dataset.lagerDrawerPurchaseDate || ''; } const editForm = drawer.querySelector('[data-lager-edit-form]'); if (editForm) { editForm.hidden = true; } drawer.dataset.lagerActiveLotId = trigger.dataset.lagerDrawerLotId || ''; } setDrawerState(true); contentRoot.querySelectorAll('[data-lager-drawer-open]').forEach((button) => button.setAttribute('aria-expanded', String(button === trigger))); return; }";
|
|
|
|
|
echo " if (event.target.closest('[data-lager-drawer-close]') || event.target.closest('[data-lager-drawer-backdrop]')) { closeDrawer(); }";
|
|
|
|
|
echo " });";
|
|
|
|
|
echo " const postLagerChange = async (payload) => { const response = await fetch('/api/lager-charge.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ ...payload, csrfToken: contentRoot.querySelector('[data-lager-csrf-token]')?.dataset.lagerCsrfToken || '' }) }); const result = await response.json(); if (!response.ok || result.ok !== true) { throw new Error(result.error || 'Speichern fehlgeschlagen'); } return result; };";
|
|
|
|
|
echo " contentRoot.addEventListener('click', (event) => { const editButton = event.target.closest('[data-lager-edit-open]'); if (editButton) { const drawer = getDrawer(); const editForm = drawer?.querySelector('[data-lager-edit-form]'); if (editForm) { editForm.hidden = false; } return; } const closeButton = event.target.closest('[data-lager-edit-close]'); if (closeButton) { const drawer = getDrawer(); const editForm = drawer?.querySelector('[data-lager-edit-form]'); if (editForm) { editForm.hidden = true; } } });";
|
|
|
|
|
echo " contentRoot.addEventListener('submit', async (event) => { const editForm = event.target.closest('[data-lager-edit-form-element]'); const manufacturerForm = event.target.closest('[data-lager-manufacturer-form]'); if (!editForm && !manufacturerForm) { return; } event.preventDefault(); const drawer = getDrawer(); const status = drawer?.querySelector('[data-lager-edit-status]'); if (status) { status.textContent = 'Speichern läuft …'; } try { if (manufacturerForm) { const result = await postLagerChange({ action: 'create_manufacturer', name: manufacturerForm.querySelector('[data-lager-new-manufacturer-name]')?.value || '', email: manufacturerForm.querySelector('[data-lager-new-manufacturer-email]')?.value || '', phone: manufacturerForm.querySelector('[data-lager-new-manufacturer-phone]')?.value || '' }); const select = drawer?.querySelector('[data-lager-manufacturer]'); if (select && result.manufacturer) { const option = document.createElement('option'); option.value = String(result.manufacturer.id); option.textContent = result.manufacturer.name; select.appendChild(option); select.value = String(result.manufacturer.id); } manufacturerForm.reset(); if (status) { status.textContent = 'Hersteller angelegt. Bitte Charge speichern.'; } return; } await postLagerChange({ action: 'update_lot', lotId: drawer?.dataset.lagerActiveLotId || '', manufacturerPartyId: drawer?.querySelector('[data-lager-manufacturer]')?.value || null, manufacturerLotNumber: drawer?.querySelector('[data-lager-manufacturer-lot]')?.value || '', mfgDate: drawer?.querySelector('[data-lager-mfg-date]')?.value || '', expiryDate: drawer?.querySelector('[data-lager-expiry-date]')?.value || '', purchaseDate: drawer?.querySelector('[data-lager-purchase-date]')?.value || '' }); window.location.reload(); } catch (error) { if (status) { status.textContent = error instanceof Error ? error.message : 'Speichern fehlgeschlagen'; } } });";
|
|
|
|
|
echo " document.addEventListener('click', (event) => { if (event.target.closest('[data-lager-detail-back]')) { event.preventDefault(); closeLagerMobileDetail(); } });";
|
|
|
|
|
echo " document.addEventListener('keydown', (event) => { if (event.key === 'Escape') { closeDrawer(); closeLagerMobileDetail(); } });";
|
|
|
|
|
echo " window.addEventListener('popstate', (event) => { if (lagerMobileDetailOpen && (!event.state || event.state.lagerView !== 'detail')) { restoreLagerMobileDetail(); } });";
|
|
|
|
@@ -746,6 +763,7 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best
|
|
|
|
|
echo " const zip = trigger.dataset.orderZip || '';";
|
|
|
|
|
echo " const city = trigger.dataset.orderCity || '';";
|
|
|
|
|
echo " const country = trigger.dataset.orderCountry || '';";
|
|
|
|
|
echo " const formatDate = (value) => value ? new Date(value).toLocaleString('de-CH', { dateStyle: 'short', timeStyle: 'short' }) : 'Nicht vorhanden';";
|
|
|
|
|
echo " const streetLine = [street, houseNumber].filter((part) => part && part.length > 0).join(' ').trim();";
|
|
|
|
|
echo " const cityLine = [zip, city].filter((part) => part && part.length > 0).join(' ').trim();";
|
|
|
|
|
echo " return [";
|
|
|
|
@@ -761,7 +779,7 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best
|
|
|
|
|
echo " '</article>',";
|
|
|
|
|
echo " '</div>',";
|
|
|
|
|
echo " '</div>',";
|
|
|
|
|
echo " '<article class=\"sg-card sg-vsf-drawer-card\" data-component=\"card\" data-pattern=\"card\" aria-label=\"Bestell-Details\">',";
|
|
|
|
|
echo " '<div data-bestellungen-mobile-cards><article class=\"sg-card sg-card--content-card\" data-component=\"content-card\" aria-label=\"Bestell-Details\">',";
|
|
|
|
|
echo " '<div class=\"sg-card-segment sg-card-segment--body sg-vsf-drawer-card__content\">',";
|
|
|
|
|
echo " '<p class=\"sg-body\"><strong>Bestellnummer:</strong> <span>' + escapeHtml(orderNumber) + '</span></p>',";
|
|
|
|
|
echo " '<p class=\"sg-body\"><strong>Bestelldatum:</strong> <span>' + escapeHtml(orderDate) + '</span></p>',";
|
|
|
|
@@ -772,7 +790,7 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best
|
|
|
|
|
echo " '<p class=\"sg-body\"><strong>Gesamtsumme:</strong> <span>' + escapeHtml(total) + '</span></p>',";
|
|
|
|
|
echo " '<p class=\"sg-body\">Detailinhalt wird noch definiert.</p>',";
|
|
|
|
|
echo " '</div>',";
|
|
|
|
|
echo " '</article>',";
|
|
|
|
|
echo " '</article></div>',";
|
|
|
|
|
echo " '</div>'";
|
|
|
|
|
echo " ].join('');";
|
|
|
|
|
echo " };";
|
|
|
|
@@ -802,30 +820,21 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best
|
|
|
|
|
echo " return;";
|
|
|
|
|
echo " }";
|
|
|
|
|
echo " const drawerTitle = drawer.querySelector('[data-order-drawer-title]');";
|
|
|
|
|
echo " const drawerOrderNumber = drawer.querySelector('[data-order-drawer-order-number]');";
|
|
|
|
|
echo " const drawerOrderDate = drawer.querySelector('[data-order-drawer-order-date]');";
|
|
|
|
|
echo " const drawerAddressLine1 = drawer.querySelector('[data-order-drawer-address-line-1]');";
|
|
|
|
|
echo " const drawerAddressLine2 = drawer.querySelector('[data-order-drawer-address-line-2]');";
|
|
|
|
|
echo " const drawerAddressLine3 = drawer.querySelector('[data-order-drawer-address-line-3]');";
|
|
|
|
|
echo " const drawerTotal = drawer.querySelector('[data-order-drawer-total]');";
|
|
|
|
|
echo " const orderNumber = trigger.dataset.orderNumber || '';";
|
|
|
|
|
echo " const orderDate = trigger.dataset.orderDate || '';";
|
|
|
|
|
echo " const total = trigger.dataset.orderTotal || '';";
|
|
|
|
|
echo " const street = trigger.dataset.orderStreet || '';";
|
|
|
|
|
echo " const houseNumber = trigger.dataset.orderHouseNumber || '';";
|
|
|
|
|
echo " const zip = trigger.dataset.orderZip || '';";
|
|
|
|
|
echo " const city = trigger.dataset.orderCity || '';";
|
|
|
|
|
echo " const country = trigger.dataset.orderCountry || '';";
|
|
|
|
|
echo " const streetLine = [street, houseNumber].filter((part) => part && part.length > 0).join(' ').trim();";
|
|
|
|
|
echo " const cityLine = [zip, city].filter((part) => part && part.length > 0).join(' ').trim();";
|
|
|
|
|
echo " const cards = drawer.querySelector('[data-order-drawer-cards]');";
|
|
|
|
|
echo " const orderId = trigger.dataset.orderId || '';";
|
|
|
|
|
echo " const formatAmount = (value, currency) => value === null || value === undefined ? 'Nicht vorhanden' : currency + ' ' + Number(value).toFixed(2);";
|
|
|
|
|
echo " const formatDate = (value) => value ? new Date(value).toLocaleString('de-CH', { dateStyle: 'short', timeStyle: 'short' }) : 'Nicht vorhanden';";
|
|
|
|
|
echo " const value = (label, content) => '<p class=\"sg-body\"><strong>' + escapeHtml(label) + ':</strong> ' + escapeHtml(content || 'Nicht vorhanden') + '</p>';";
|
|
|
|
|
echo " const renderCards = (order) => {";
|
|
|
|
|
echo " const c = order.customer || {}; const a = order.amounts || {}; const address = [[c.street, c.house_number].filter(Boolean).join(' '), [c.zip, c.city].filter(Boolean).join(' '), c.country_name].filter(Boolean).join('<br>');";
|
|
|
|
|
echo " const lines = (order.lines || []).map((line) => '<div class=\"sg-card-segment sg-card-segment--body\"><p class=\"sg-body\"><strong>' + escapeHtml(line.item_name) + '</strong> · ' + escapeHtml(line.item_code) + ' · Menge: ' + escapeHtml(String(line.qty)) + '</p>' + value('Positionsstatus', line.line_status) + value('Einzelpreis', formatAmount(line.unit_price, a.currency || 'CHF')) + value('Positionssumme', formatAmount(line.line_total, a.currency || 'CHF')) + '</div>').join('');";
|
|
|
|
|
echo " const allocations = (order.lines || []).flatMap((line) => (line.product_allocations || []).map((item) => '<div class=\"sg-body\"><strong>' + escapeHtml(item.product_name) + ':</strong> ' + escapeHtml(item.lot_number || 'Nicht zugeordnet') + ' · ' + escapeHtml(item.allocated_qty === null ? 'Nicht zugeordnet' : String(item.allocated_qty)) + ' · ' + escapeHtml(item.allocation_status || 'Nicht vorhanden') + (item.lot_status === 'virtual_shortage' ? ' · Virtuelle Fehlbestandscharge' : '') + '</div>')).join('');";
|
|
|
|
|
echo " return '<article class=\"sg-card sg-card--content-card\" data-component=\"content-card\" aria-label=\"Bestellübersicht\"><header class=\"sg-card-segment sg-card-segment--header sg-card-segment--darkgreen\" data-component-part=\"card-header\"><div class=\"sg-strong sg-text-on-dark\">Bestellübersicht</div></header><div class=\"sg-card-segment sg-card-segment--body\" data-component-part=\"card-body\">' + value('Bestellnummer', order.external_ref) + value('Bestelldatum', formatDate(order.order_date)) + value('Verkaufskanal', order.order_source) + value('Bestellstatus', order.order_status) + value('Zahlungsstatus', order.payment_status) + value('Zahlungsart', order.payment_method) + value('Versandart', order.shipping_method) + '<p class=\"sg-body\"><strong>Kunde:</strong> ' + escapeHtml([c.first_name, c.last_name].filter(Boolean).join(' ') || 'Nicht vorhanden') + '</p><p class=\"sg-body\"><strong>Lieferadresse:</strong><br>' + address + '</p>' + value('Netto', formatAmount(a.net, a.currency || 'CHF')) + value('Versand', formatAmount(a.shipping, a.currency || 'CHF')) + value('Rabatt', formatAmount(a.discount, a.currency || 'CHF')) + value('Steuer', formatAmount(a.tax, a.currency || 'CHF')) + value('Gesamtsumme', formatAmount(a.total, a.currency || 'CHF')) + '</div></article><article class=\"sg-card sg-card--content-card\" data-component=\"content-card\" aria-label=\"Bestellte Artikel\"><header class=\"sg-card-segment sg-card-segment--header sg-card-segment--darkgreen\" data-component-part=\"card-header\"><div class=\"sg-strong sg-text-on-dark\">Bestellte Artikel</div></header>' + (lines || '<div class=\"sg-card-segment sg-card-segment--body\" data-component-part=\"card-body\"><p class=\"sg-body\">Keine Artikel vorhanden.</p></div>') + '</article><article class=\"sg-card sg-card--content-card\" data-component=\"content-card\" aria-label=\"Chargenzuordnung\"><header class=\"sg-card-segment sg-card-segment--header sg-card-segment--darkgreen\" data-component-part=\"card-header\"><div class=\"sg-strong sg-text-on-dark\">Chargenzuordnung</div></header><div class=\"sg-card-segment sg-card-segment--body\" data-component-part=\"card-body\">' + (allocations || '<p class=\"sg-body\">Keine Chargenzuordnung vorhanden.</p>') + '</div></article>';";
|
|
|
|
|
echo " };";
|
|
|
|
|
echo " setDrawerState(true);";
|
|
|
|
|
echo " if (drawerTitle) { drawerTitle.textContent = orderNumber !== '' ? 'Bestellung ' + orderNumber : 'Bestellung'; }";
|
|
|
|
|
echo " if (drawerOrderNumber) { drawerOrderNumber.textContent = orderNumber; }";
|
|
|
|
|
echo " if (drawerOrderDate) { drawerOrderDate.textContent = orderDate; }";
|
|
|
|
|
echo " if (drawerAddressLine1) { drawerAddressLine1.textContent = streetLine; }";
|
|
|
|
|
echo " if (drawerAddressLine2) { drawerAddressLine2.textContent = cityLine; }";
|
|
|
|
|
echo " if (drawerAddressLine3) { drawerAddressLine3.textContent = country; }";
|
|
|
|
|
echo " if (drawerTotal) { drawerTotal.textContent = total; }";
|
|
|
|
|
echo " if (drawerTitle) { drawerTitle.textContent = trigger.dataset.orderNumber ? 'Bestellung ' + trigger.dataset.orderNumber : 'Bestellung'; }";
|
|
|
|
|
echo " if (cards) { cards.innerHTML = '<p class=\"sg-body\">Bestelldetails werden geladen …</p>'; }";
|
|
|
|
|
echo " fetch('/api/bestellungen/detail.php?id=' + encodeURIComponent(orderId), { credentials: 'same-origin' }).then((response) => response.ok ? response.json() : Promise.reject(new Error('Bestelldetails konnten nicht geladen werden.'))).then((payload) => { if (!payload.ok) { throw new Error('Bestelldetails konnten nicht geladen werden.'); } if (cards) { cards.innerHTML = renderCards(payload.order); } }).catch((error) => { if (cards) { cards.innerHTML = '<p class=\"sg-body\">' + escapeHtml(error.message) + '</p>'; } });";
|
|
|
|
|
echo " contentRoot.querySelectorAll('[data-order-drawer-open]').forEach((button) => {";
|
|
|
|
|
echo " button.setAttribute('aria-expanded', String(button === trigger));";
|
|
|
|
|
echo " });";
|
|
|
|
@@ -848,6 +857,7 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best
|
|
|
|
|
echo " document.body.appendChild(bestellungenMobileDetailHost);";
|
|
|
|
|
echo " document.body.classList.add('sg-bestellungen-mobile-detail-open');";
|
|
|
|
|
echo " }";
|
|
|
|
|
echo " fetch('/api/bestellungen/detail.php?id=' + encodeURIComponent(trigger.dataset.orderId || ''), { credentials: 'same-origin' }).then((response) => response.ok ? response.json() : Promise.reject(new Error('Bestelldetails konnten nicht geladen werden.'))).then((payload) => { if (!payload.ok || !bestellungenMobileDetailHost) { throw new Error('Bestelldetails konnten nicht geladen werden.'); } const order = payload.order; const cards = bestellungenMobileDetailHost.querySelector('[data-bestellungen-mobile-cards]'); const lines = (order.lines || []).map((line) => '<p class=\"sg-body\"><strong>' + escapeHtml(line.item_name) + '</strong> · ' + escapeHtml(line.item_code) + ' · Menge: ' + escapeHtml(String(line.qty)) + ' · Status: ' + escapeHtml(line.line_status) + '</p>').join(''); const allocations = (order.lines || []).flatMap((line) => (line.product_allocations || []).map((item) => '<p class=\"sg-body\"><strong>' + escapeHtml(item.product_name) + ':</strong> ' + escapeHtml(item.lot_number || 'Nicht zugeordnet') + ' · ' + escapeHtml(item.allocation_status || 'Nicht vorhanden') + '</p>')).join(''); if (cards) { cards.innerHTML = '<article class=\"sg-card sg-card--content-card\"><header class=\"sg-card-segment sg-card-segment--header sg-card-segment--darkgreen\"><div class=\"sg-strong sg-text-on-dark\">Bestellübersicht</div></header><div class=\"sg-card-segment sg-card-segment--body\"><p class=\"sg-body\"><strong>Bestellnummer:</strong> ' + escapeHtml(order.external_ref) + '</p><p class=\"sg-body\"><strong>Bestelldatum:</strong> ' + escapeHtml(formatDate(order.order_date)) + '</p><p class=\"sg-body\"><strong>Verkaufskanal:</strong> ' + escapeHtml(order.order_source) + '</p><p class=\"sg-body\"><strong>Status:</strong> ' + escapeHtml(order.order_status) + '</p></div></article><article class=\"sg-card sg-card--content-card\"><header class=\"sg-card-segment sg-card-segment--header sg-card-segment--darkgreen\"><div class=\"sg-strong sg-text-on-dark\">Bestellte Artikel</div></header><div class=\"sg-card-segment sg-card-segment--body\">' + (lines || '<p class=\"sg-body\">Keine Artikel vorhanden.</p>') + '</div></article><article class=\"sg-card sg-card--content-card\"><header class=\"sg-card-segment sg-card-segment--header sg-card-segment--darkgreen\"><div class=\"sg-strong sg-text-on-dark\">Chargenzuordnung</div></header><div class=\"sg-card-segment sg-card-segment--body\">' + (allocations || '<p class=\"sg-body\">Keine Chargenzuordnung vorhanden.</p>') + '</div></article>'; } }).catch((error) => { const cards = bestellungenMobileDetailHost?.querySelector('[data-bestellungen-mobile-cards]'); if (cards) { cards.innerHTML = '<p class=\"sg-body\">' + escapeHtml(error.message) + '</p>'; } });";
|
|
|
|
|
echo " bestellungenDetailOpen = true;";
|
|
|
|
|
echo " window.history.pushState({ bestellungenView: 'detail', orderId: trigger.dataset.orderId || '' }, '', window.location.href);";
|
|
|
|
|
echo " };";
|
|
|
|
|