@@ -243,7 +243,7 @@ function auth_render_lager_table(string $title, array $rows, array $columns, str
. ' data-lager-drawer-forecast-status="' . auth_escape_html ( $forecastStatus ) . '"'
. ' data-lager-drawer-forecast-warning="' . ( $forecastWarning ? 'true' : 'false' ) . '"'
. ' data-lager-drawer-forecast-mhd-warning="' . ( $forecastMhdWarning ? 'true' : 'false' ) . '"'
. ' data-lager-drawer-current-qty="' . auth_escape_html ( auth_format_lager_quantity (( float ) ( $row [ 'current _qty' ] ? ? 0 ))) . '"'
. ' data-lager-drawer-current-qty="' . auth_escape_html ( auth_format_lager_quantity (( float ) ( $row [ 'available _qty' ] ? ? 0 ))) . '"'
. ' data-lager-drawer-qty-in="' . auth_escape_html ( auth_format_lager_quantity (( float ) ( $row [ 'qty_in' ] ? ? 0 ))) . '"'
. ' data-lager-drawer-virtual-shortage-qty="' . auth_escape_html ( auth_format_lager_quantity (( float ) ( $row [ 'virtual_shortage_qty' ] ? ? 0 ))) . '"'
. ' data-lager-drawer-lot-id="' . auth_escape_html (( string ) ( $row [ 'lot_id' ] ? ? '' )) . '"'
@@ -254,7 +254,6 @@ function auth_render_lager_table(string $title, array $rows, array $columns, str
. ' 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-documents="' . auth_escape_html (( string ) json_encode ( $row [ 'documents' ] ? ? [], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES )) . '"'
. ' data-lager-drawer-virtual-lot-number="' . auth_escape_html (( string ) ( $row [ 'virtual_lot_number' ] ? ? '' )) . '"' ;
$openLot = $row [ 'open_lots' ][ 0 ] ? ? [];
$detailData .= ' data-lager-open-lot-id="' . auth_escape_html (( string ) ( $openLot [ 'lot_id' ] ? ? '' )) . '"'
@@ -298,42 +297,6 @@ function auth_format_lager_quantity(float $value): string
: number_format ( $value , 2 , ',' , '.' );
}
function auth_render_lager_documents ( array $documents , bool $editable , string $scope ) : string
{
$segmentClass = $editable ? ' sg-card-segment--gray' : '' ;
$segmentState = $editable ? ' hidden data-lager-edit-documents="' . auth_escape_html ( $scope ) . '"' : '' ;
$html = '<div class="sg-card-segment sg-card-segment--body' . $segmentClass . '" data-lager-documents="' . auth_escape_html ( $scope ) . '"' . $segmentState . '>' ;
if ( $editable ) {
$html .= '<div class="sg-form-sections-card-wrapper" data-pattern="form-sections" aria-label="Dokumente"><section class="sg-form-sections-card"><div class="sg-form-sections-card__body"><section class="sg-form-sections-card__chapter"><h2 class="sg-strong sg-form-sections-card__chapter-title">Dokumente</h2>' ;
} else {
$html .= '<section class="sg-form-sections-card__chapter"><h2 class="sg-strong sg-form-sections-card__chapter-title">Dokumente</h2>' ;
}
if ( ! $editable ) {
$html .= '<div data-lager-documents-read="' . auth_escape_html ( $scope ) . '">' ;
if ( $documents === []) {
$html .= '<p class="sg-body">Keine Dokumente vorhanden.</p>' ;
} else {
foreach ( $documents as $document ) {
$documentId = ( int ) ( $document [ 'id' ] ? ? 0 );
$filename = ( string ) ( $document [ 'original_filename' ] ? ? 'Dokument' );
$html .= '<p class="sg-body" data-lager-document-row="' . $documentId . '"><a class="sg-hyperlink" href="/api/lager-document.php?id=' . $documentId . '" data-component="hyperlink">' . auth_escape_html ( $filename ) . '</a></p>' ;
}
}
$html .= '</div>' ;
}
if ( $editable ) {
$html .= '<div data-lager-documents-edit="' . auth_escape_html ( $scope ) . '">' ;
foreach ( $documents as $document ) {
$documentId = ( int ) ( $document [ 'id' ] ? ? 0 );
$filename = ( string ) ( $document [ 'original_filename' ] ? ? 'Dokument' );
$html .= '<div class="sg-form-sections-card__field-group" data-lager-document-edit-row="' . $documentId . '"><span class="sg-body">' . auth_escape_html ( $filename ) . ' <span class="sg-tab-button-group" role="tablist" aria-label="Dokument entfernen" data-component="tab-navigation" data-component-size="compact"><button class="sg-interaction-element sg-button sg-tab-button sg-tab-button--compact" type="button" role="tab" aria-selected="false" data-component-part="tab-button" aria-label="Dokument entfernen: ' . auth_escape_html ( $filename ) . '" data-lager-document-delete="' . $documentId . '">× </button></span></span></div>' ;
}
$html .= '<div class="sg-file-upload" data-pattern="file-upload" data-lager-document-upload-form="' . auth_escape_html ( $scope ) . '"><div class="sg-file-input" data-component="file-input"><div class="sg-file-upload__dropzone sg-labeled-input-row"><label class="sg-label" for="lager-document-file-' . auth_escape_html ( $scope ) . '">Dateien auswählen</label><input class="sg-file-input__control" id="lager-document-file-' . auth_escape_html ( $scope ) . '" type="file" multiple aria-describedby="lager-document-file-status-' . auth_escape_html ( $scope ) . '" data-lager-document-file><button class="sg-interaction-element sg-button sg-button--active sg-file-input__trigger" type="button" data-lager-document-file-trigger>Dateien auswählen</button></div></div><ul class="sg-file-upload__files" data-lager-document-selected-files hidden></ul><p class="sg-body sg-file-upload__status" id="lager-document-file-status-' . auth_escape_html ( $scope ) . '" data-lager-document-status aria-live="polite">Noch keine Dateien ausgewählt.</p></div>' ;
$html .= '</div>' ;
}
return $html . ( $editable ? '</section></div></section></div></div>' : '</section></div>' );
}
function auth_render_lager_historical_lots ( array $lagerProducts ) : string
{
$html = [];
@@ -355,9 +318,7 @@ function auth_render_lager_historical_lots(array $lagerProducts): string
. '<strong>MHD:</strong> ' . auth_format_lager_date ( $lot [ 'expiry_date' ] ? ? null ) . '<br>'
. '<strong>Hersteller:</strong> ' . auth_escape_html (( string ) ( $lot [ 'manufacturer_name' ] ? ? 'Nicht hinterlegt' )) . '<br>'
. '<strong>Hersteller-Chargennummer:</strong> ' . auth_escape_html (( string ) ( $lot [ 'manufacturer_lot_number' ] ? ? 'Nicht hinterlegt' )) . '</p>'
. '</div>'
. auth_render_lager_documents ( $lot [ 'documents' ] ? ? [], false , 'historical-' . ( int ) ( $lot [ 'lot_id' ] ? ? 0 ))
. '</article>' ;
. '</div></article>' ;
}
$html [] = '</div>' ;
}
@@ -373,8 +334,8 @@ function auth_render_lager_open_lots(array $lagerProducts, string $manufacturerO
$html [] = '<div data-lager-open-product="' . $productId . '" hidden>' ;
foreach (( $product [ 'open_lots' ] ? ? []) as $lot ) {
$lotId = ( int ) ( $lot [ 'lot_id' ] ? ? 0 );
$html [] = '<div class="sg-delete-confirmation-pattern__stage sg-delete-confirmation-pattern__host" data-pattern="overlay-card" data-dialog-open="false" data-lager-open-card-wrapper="' . $lotId . '"><article class="sg-card sg-card--content-card sg-delete-confirmation-pattern__target" data-component="content-card" data-pattern="overlay-card " aria-label="Offene Charge">'
. '<div class="sg-card-segment sg-card-segment--header sg-card-segment--darkgreen sg-object-card__header" data-component-part="card-header"><div class="sg-strong sg-text-on-dark">Offene Charge</div><div class="sg-component-row"><button class="sg-interaction-element sg-button sg-button--warning" type="button" data-component="button" data-component-variant="warning" data-lager-open-delete>Löschen</button>< button class="sg-interaction-element sg-button sg-button--active" type="button" data-lager-open-edit-open>Bearbeiten</button></div></div> '
$html [] = '<article class="sg-card sg-card--content-card" data-component="content-card" data-lager-open-card-wrapper="' . $lotId . ' " aria-label="Offene Charge">'
. '<div class="sg-card-segment sg-card-segment--header sg-card-segment--darkgreen sg-object-card__header" data-component-part="card-header"><div class="sg-strong sg-text-on-dark">Offene Charge</div><button class="sg-interaction-element sg-button sg-button--active" type="button" data-lager-open-edit-open>Bearbeiten</button></div>'
. '<div class="sg-card-segment sg-card-segment--body" data-component-part="card-body" data-lager-open-card="' . ( int ) ( $lot [ 'lot_id' ] ? ? 0 ) . '"><p class="sg-body"><strong>Naurua-Chargennummer:</strong> <span data-lager-open-card-lot-number>' . auth_escape_html (( string ) ( $lot [ 'lot_number' ] ? ? 'Nicht hinterlegt' )) . '</span><br>'
. '<strong>Status:</strong> Vorbereitet<br>'
. '<strong>Bestand:</strong> <span data-lager-open-card-qty-net>' . auth_format_lager_quantity (( float ) ( $lot [ 'qty_net' ] ? ? 0 )) . '</span><br>'
@@ -384,22 +345,16 @@ function auth_render_lager_open_lots(array $lagerProducts, string $manufacturerO
. '<strong>Herstellungsdatum:</strong> <span data-lager-open-card-mfg-date>' . auth_format_lager_date ( $lot [ 'mfg_date' ] ? ? null ) . '</span><br>'
. '<strong>MHD:</strong> <span data-lager-open-card-expiry-date>' . auth_format_lager_date ( $lot [ 'expiry_date' ] ? ? null ) . '</span><br>'
. '<strong>Einkaufsdatum:</strong> <span data-lager-open-card-purchase-date>' . auth_format_lager_date ( $lot [ 'purchase_date' ] ? ? null ) . '</span></p></div>'
. auth_render_lager_documents ( $lot [ 'documents' ] ? ? [], false , 'open-read-' . $lotId )
. '<div class="sg-card-segment sg-card-segment--body sg-card-segment--gray" data-lager-open-edit-form hidden><div class="sg-form-sections-card-wrapper" data-pattern="form-sections" aria-label="Offene Charge bearbeiten"><form class="sg-form-sections-card" id="lager-open-edit-form-' . $lotId . '" data-lager-open-edit-form-element><div class="sg-form-sections-card__body" data-pattern-part="form-body"><h2 class="sg-strong sg-form-sections-card__title">Offene Charge bearbeiten</h2>'
. '<div class="sg-card-segment sg-card-segment--body sg-card-segment--gray" data-lager-open-edit-form hidden><div class="sg-form-sections-card-wrapper" data-pattern="form-sections" aria-label="Offene Charge bearbeiten"><form class="sg-form-sections-card" data-lager-open-edit-form-element><div class="sg-form-sections-card__body" data-pattern-part="form-body"><h2 class="sg-strong sg-form-sections-card__title">Offene Charge bearbeiten</h2>'
. '<section class="sg-form-sections-card__chapter" aria-labelledby="lager-open-charge-data-' . $lotId . '"><h2 id="lager-open-charge-data-' . $lotId . '" class="sg-strong sg-form-sections-card__chapter-title">Chargendaten</h2>'
. '<div class="sg-form-sections-card__field-group"><label class="sg-labeled-input-row"><span class="sg-label">Naurua-Chargennummer</span><input class="sg-interaction-element sg-input-single-line" type="text" data-lager-open-lot-number value="' . auth_escape_html (( string ) ( $lot [ 'lot_number' ] ? ? '' )) . '"></label></div>'
. '<div class="sg-form-sections-card__field-group"><label class="sg-labeled-input-row"><span class="sg-label">Naurua-Chargennummer</span><input class="sg-interaction-element sg-input-single-line" type="text" data-lager-open-lot-number required value="' . auth_escape_html (( string ) ( $lot [ 'lot_number' ] ? ? '' )) . '"></label></div>'
. '<div class="sg-form-sections-card__field-group"><label class="sg-labeled-input-row"><span class="sg-label">Hersteller</span><select class="sg-interaction-element sg-input-single-line" data-lager-open-manufacturer>' . str_replace ( 'value="' . ( int ) ( $lot [ 'manufacturer_party_id' ] ? ? 0 ) . '"' , 'value="' . ( int ) ( $lot [ 'manufacturer_party_id' ] ? ? 0 ) . '" selected' , $manufacturerOptions ) . '</select></label></div>'
. '<div class="sg-form-sections-card__field-group"><label class="sg-labeled-input-row"><span class="sg-label">Hersteller-Chargennummer</span><input class="sg-interaction-element sg-input-single-line" type="text" data-lager-open-manufacturer-lot value="' . auth_escape_html (( string ) ( $lot [ 'manufacturer_lot_number' ] ? ? '' )) . '"></label></div>'
. '<div class="sg-form-sections-card__field-group"><label class="sg-labeled-input-row"><span class="sg-label">Herstellungsdatum</span><input class="sg-interaction-element sg-input-single-line" type="date" data-lager-open-mfg-date value="' . auth_escape_html (( string ) ( $lot [ 'mfg_date' ] ? ? '' )) . '"></label></div>'
. '<div class="sg-form-sections-card__field-group"><label class="sg-labeled-input-row"><span class="sg-label">MHD</span><input class="sg-interaction-element sg-input-single-line" type="date" data-lager-open-expiry-date value="' . auth_escape_html (( string ) ( $lot [ 'expiry_date' ] ? ? '' )) . '"></label></div>'
. '<div class="sg-form-sections-card__field-group"><label class="sg-labeled-input-row"><span class="sg-label">Einkaufsdatum</span><input class="sg-interaction-element sg-input-single-line" type="date" data-lager-open-purchase-date value="' . auth_escape_html (( string ) ( $lot [ 'purchase_date' ] ? ? '' )) . '"></label></div>'
. '<div class="sg-form-sections-card__field-group"><label class="sg-labeled-input-row"><span class="sg-label">Menge </span><input class="sg-interaction-element sg-input-single-line" type="number" min="0" step="1" inputmode="numeric" data-lager-open-target-qty value="' . auth_escape_html (( string ) ( $lot [ 'qty_net' ] ? ? 0 )) . ' "></label></div>'
. '</section></div></form></div></div>'
. auth_render_lager_documents ( $lot [ 'documents' ] ? ? [], true , 'open-edit-' . $lotId )
. '<footer class="sg-card-segment sg-card-segment--body sg-card-segment--gray" data-lager-open-edit-actions hidden><div class="sg-form-sections-card-wrapper" data-pattern="form-sections"><div class="sg-form-sections-card"><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-lager-open-edit-close>Abbrechen</button><button class="sg-interaction-element sg-button sg-button--process sg-form-sections-card__action" type="submit" form="lager-open-edit-form-' . $lotId . '">Speichern</button></div><p class="sg-body" data-lager-open-edit-status aria-live="polite"></p></div></div></footer>'
. '</article>'
. '<article class="sg-card sg-card--overlay-host sg-delete-confirmation-pattern__floating-card" aria-label="Leere Felder bestätigen" role="dialog" aria-modal="true" aria-labelledby="lager-open-confirmation-title-' . $lotId . '" data-lager-open-confirmation-card hidden><div class="sg-card-segment sg-card-segment--body sg-delete-confirmation-pattern__body"><p class="sg-body sg-delete-confirmation-pattern__text" id="lager-open-confirmation-title-' . $lotId . '"><strong>Leere Felder speichern?</strong></p><p class="sg-body sg-delete-confirmation-pattern__text">Die folgenden Felder werden leer gespeichert:</p><div class="sg-delete-confirmation-pattern__list" data-lager-open-confirmation-empty-fields aria-label="Leer zu speichernde Felder"></div><div class="sg-delete-confirmation-pattern__actions"><button class="sg-interaction-element sg-button sg-button--active" type="button" data-lager-open-confirmation-cancel>Abbrechen</button><button class="sg-interaction-element sg-button sg-button--process" type="button" data-lager-open-confirmation-submit>Speichern</button></div></div></article>'
. '<article class="sg-card sg-card--overlay-host sg-delete-confirmation-pattern__floating-card" aria-label="Löschbestätigung" role="dialog" aria-modal="true" aria-labelledby="lager-open-delete-title-' . $lotId . '" data-overlay-dialog="delete" data-lager-open-delete-confirmation hidden><div class="sg-card-segment sg-card-segment--body sg-delete-confirmation-pattern__body"><p class="sg-body sg-delete-confirmation-pattern__text" id="lager-open-delete-title-' . $lotId . '"><strong>Möchtest du diese offene Charge wirklich löschen?</strong></p><p class="sg-body sg-delete-confirmation-pattern__text">Du kannst das nicht rückgängig machen. Bestätige durch Eingabe von <span class="sg-delete-confirmation-pattern__code">DELETE</span>.</p><label class="sg-labeled-input-row sg-delete-confirmation-pattern__input-row"><span class="sg-label">Bestätigung</span><input class="sg-interaction-element sg-input-single-line sg-input-single-line--inactive-selectable sg-form-inactive-selectable" type="text" placeholder="DELETE" aria-label="Löschbestätigung durch DELETE" data-lager-open-delete-confirmation-input></label><p class="sg-body" data-lager-open-delete-status aria-live="polite"></p><div class="sg-delete-confirmation-pattern__actions"><button class="sg-interaction-element sg-button sg-button--active" type="button" data-lager-open-delete-confirmation-cancel>Abbrechen</button><button class="sg-interaction-element sg-button sg-button--process sg-button--process-inactive" type="button" disabled aria-disabled="true" data-lager-open-delete-confirmation-submit>Löschen</button></div></div></article></div>' ;
. '<div class="sg-form-sections-card__field-group"><label class="sg-labeled-input-row"><span class="sg-label">Zugang buchen </span><input class="sg-interaction-element sg-input-single-line" type="number" min="0" step="1" inputmode="numeric" data-lager-open-receipt-qty placeholder="Menge "></label></div>'
. '</section><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-lager-open-edit-close>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-lager-open-edit-status aria-live="polite"></p>< /div></form></div></div></article>' ;
}
$html [] = '</div>' ;
}
@@ -424,11 +379,11 @@ function auth_render_lager_content(array $lagerProducts, array $lagerArtikel, ar
. '</section>'
. '<div class="sg-card-list-page-drawer-backdrop" aria-hidden="true" data-lager-drawer-backdrop="true" data-open="false"></div>'
. '<aside class="sg-card-list-page-drawer" aria-label="Lager-Details" aria-hidden="true" data-lager-drawer="true" data-open="false">'
. '<div class="sg-card-list-page-drawer__header"><h2 class="sg-heading-h2 sg-card-list-page-drawer__title" data-lager-drawer-title>Lager-Details</h2></div>'
. '<div class="sg-card-list-page-drawer__header"><h2 class="sg-heading-h2 sg-card-list-page-drawer__title" data-lager-drawer-title>Lager-Details</h2><button class="sg-interaction-element sg-hyperlink" type="button" data-lager-drawer-close>schliessen</button>< /div>'
. '<div class="sg-card-list-page-drawer__content">'
. '<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 sg-vsf-drawer-card__header"><div class="sg-strong">Lager-Details</div></header>'
. '<div class="sg-card-segment sg-card-segment--body sg-vsf-drawer-card__content"><p class="sg-body"><strong>Name:</strong> <span data-lager-drawer-name-value></span></p><p class="sg-body" data-lager-drawer-value-row><strong data-lager-drawer-value-label>Wert:</strong> <span data-lager-drawer-value-value></span><br><strong>Voraussichtlich leer:</strong> <span data-lager-drawer-forecast-value>Keine Prognose</span>< /p></div>'
. '<div class="sg-card-segment sg-card-segment--body sg-vsf-drawer-card__content"><p class="sg-body"><strong>Name:</strong> <span data-lager-drawer-name-value></span></p><p class="sg-body" data-lager-drawer-value-row><strong data-lager-drawer-value-label>Wert:</strong> <span data-lager-drawer-value-value></span></p></div>'
. '</article>'
. '<article class="sg-card sg-card--content-card" data-component="content-card" data-lager-drawer-topic="warning" aria-label="Warnungen">'
. '<div class="sg-card-segment sg-card-segment--header sg-card-segment--darkgreen" data-component-part="card-header" data-lager-drawer-warning-header><div class="sg-strong sg-text-on-dark" data-lager-drawer-warning-title>Keine Warnung</div></div>'
@@ -451,9 +406,9 @@ function auth_render_lager_content(array $lagerProducts, array $lagerArtikel, ar
. '<div data-lager-drawer-topic="open-lots" aria-label="Offene Chargen">' . auth_render_lager_open_lots ( $lagerProducts , $manufacturerOptions ) . '</div>'
. '<article class="sg-card sg-card--content-card" data-component="content-card" data-lager-drawer-topic="lot" aria-label="Aktive Charge">'
. '<div class="sg-card-segment sg-card-segment--header sg-card-segment--darkgreen sg-object-card__header" data-component-part="card-header"><div class="sg-strong sg-text-on-dark">Aktive Charge</div><button class="sg-interaction-element sg-button sg-button--active" type="button" data-lager-edit-open>Bearbeiten</button></div>'
. '<div class="sg-card-segment sg-card-segment--body" data-component-part="card-body" data-lager-read-view><p class="sg-body"><strong>Naurua-Chargennummer:</strong> <span data-lager-drawer-lot-number></span><br><strong>Aktueller Bestand:</strong> <span data-lager-drawer-current-qty></span><br><strong>Eingangsmenge:</strong> <span data-lager-drawer-qty-in></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></div>' . auth_render_lager_documents ([], false , 'current-read' )
. '<div class="sg-card-segment sg-card-segment--body" data-component-part="card-body" data-lager-read-view><p class="sg-body"><strong>Naurua-Chargennummer:</strong> <span data-lager-drawer-lot-number></span><br><strong>Aktueller Bestand:</strong> <span data-lager-drawer-current-qty></span><br><strong>Eingangsmenge:</strong> <span data-lager-drawer-qty-in></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></div>'
. '<div class="sg-card-segment sg-card-segment--body sg-card-segment--gray" data-lager-edit-form hidden><div class="sg-form-sections-card-wrapper" data-pattern="form-sections" aria-label="Aktive Charge bearbeiten">'
. '<form class="sg-form-sections-card" id="lager-edit-form" data-lager-edit-form-element><div class="sg-form-sections-card__body" data-pattern-part="form-body"><h2 class="sg-strong sg-form-sections-card__title">Aktive Charge bearbeiten</h2>'
. '<form class="sg-form-sections-card" data-lager-edit-form-element><div class="sg-form-sections-card__body" data-pattern-part="form-body"><h2 class="sg-strong sg-form-sections-card__title">Aktive Charge bearbeiten</h2>'
. '<section class="sg-form-sections-card__chapter" aria-labelledby="lager-charge-traceability-title"><h2 id="lager-charge-traceability-title" class="sg-strong sg-form-sections-card__chapter-title">Rückverfolgbarkeit</h2>'
. '<div class="sg-form-sections-card__field-group"><label class="sg-labeled-input-row"><span class="sg-label">Naurua-Chargennummer</span><input class="sg-interaction-element sg-input-single-line sg-form-inactive-selectable" type="text" data-lager-lot-number readonly></label></div>'
. '<div class="sg-form-sections-card__field-group"><label class="sg-labeled-input-row"><span class="sg-label">Hersteller</span><select class="sg-interaction-element sg-input-single-line" id="lager-manufacturer" data-lager-manufacturer>' . $manufacturerOptions . '</select></label></div>'
@@ -466,9 +421,8 @@ function auth_render_lager_content(array $lagerProducts, array $lagerArtikel, ar
. '<div class="sg-form-sections-card__field-group"><label class="sg-labeled-input-row"><span class="sg-label">Zugang buchen</span><input class="sg-interaction-element sg-input-single-line" type="number" min="0" step="0.01" inputmode="decimal" data-lager-receipt-qty placeholder="Menge"></label></div>'
. '<div class="sg-form-sections-card__field-group"><label class="sg-labeled-input-row"><span class="sg-label">Bestandskorrektur (+ / − )</span><input class="sg-interaction-element sg-input-single-line" type="number" step="1" inputmode="numeric" data-lager-adjustment-qty placeholder="+ / − Menge"></label></div>'
. '<div class="sg-form-sections-card__field-group"><label class="sg-labeled-input-row"><span class="sg-label">Abgang buchen</span><input class="sg-interaction-element sg-input-single-line" type="number" min="0" step="0.01" inputmode="decimal" data-lager-out-qty placeholder="Menge"></label></div>'
. '</section></div></form></div></div >'
. auth_render_lager_documents ([], true , 'current-edit' )
. '<footer class="sg-card-segment sg-card-segment--body sg-card-segment--gray" data-lager-edit-actions hidden><div class="sg-form-sections-card-wrapper" data-pattern="form-sections"><div class="sg-form-sections-card"><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-lager-edit-close>Abbrechen</button><button class="sg-interaction-element sg-button sg-button--process sg-form-sections-card__action" type="submit" form="lager-edit-form">Speichern</button></div><p class="sg-body" data-lager-edit-status aria-live="polite"></p></div></div></footer>'
. '</section><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-lager-edit-close>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-lager-edit-status aria-live="polite"></p>< /div></form>'
. '</div></div>'
. '</article>'
. '<div data-lager-drawer-topic="historical-lots" aria-label="Vergangene Chargen">' . auth_render_lager_historical_lots ( $lagerProducts ) . '</div>'
. '<article class="sg-card sg-card--content-card" data-component="content-card" data-lager-drawer-topic="virtual-lot" aria-label="Virtuelle Charge">'
@@ -494,9 +448,9 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best
$disabledAttribute = $hasSellableMapping ? '' : ' disabled aria-disabled="true"' ;
$otcProductRows .= '<div class="sg-form-sections-card__field-group">' ;
$otcProductRows .= '<label class="sg-labeled-input-row sg-otc-order-product-row"><span class="sg-label ">' . $productName . ( $productSku !== '' ? ' (' . $productSku . ')' : '' ) . $mappingNote . '</span >' ;
$otcProductRows .= '<input class="sg-interaction-element sg-input-single-line sg-input-single-line--inactive-selectable sg-form-inactive-selectable " type="number" id="' . $inputId . '" min="0" step="1" data-otc-order-product data-product-id="' . $productId . '" data-title="' . $productName . '" data-available-qty="' . $availableQty . '"' . $disabledAttribute . '>' ;
$otcProductRows .= '</label >' ;
$otcProductRows .= '<label class="sg-label" for="' . $inputId . ' ">' . $productName . ( $productSku !== '' ? ' (' . $productSku . ')' : '' ) . $mappingNote . '</label >' ;
$otcProductRows .= '<input class="sg-interaction-element sg-input-single-line" type="number" id="' . $inputId . '" min="0" step="1" data-otc-order-product data-product-id="' . $productId . '" data-title="' . $productName . '" data-available-qty="' . $availableQty . '"' . $disabledAttribute . '>' ;
$otcProductRows .= '<p class="sg-body sg-form-sections-card__sentence">Physischer Bestand: ' . $availableQty . '</p >';
$otcProductRows .= '</div>' ;
}
@@ -601,14 +555,14 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best
echo '</section>' ;
echo '<section class="sg-otc-order-overlay" data-otc-order-overlay data-open="false" aria-hidden="true">' ;
echo '<div class="sg-delete-confirmation-pattern__stage sg-delete-confirmation-pattern__host sg-object-card" data-pattern="overlay-card" data-dialog-open="false" data-otc-confirmation-stage>' ;
echo '<article class="sg-card sg-scrollable-card sg-delete-confirmation-pattern__target sg-otc-order-overlay__panel " data-pattern="scrollable -card" aria-labelledby="otc-order-modal-title" role="dialog" aria-modal="true">' ;
echo '<header class="sg-card-segment sg-card-segment--header sg-card-segment--darkblue sg-scrollable-card__header sg-object-card__header" data-pattern-part="scrollable-card- header">' ;
echo '<article class="sg-card sg-object-card sg-object-card--variable-height sg-otc-order-overlay__panel sg-delete-confirmation-pattern__target " data-pattern="object -card" aria-labelledby="otc-order-modal-title" role="dialog" aria-modal="true">' ;
echo '<header class="sg-card-segment sg-card-segment--header sg-card-segment--darkblue sg-object-card__ header">' ;
echo '<h2 id="otc-order-modal-title" class="sg-strong sg-otc-order-overlay__title">Neuen OTC-Verkauf erfassen</h2>' ;
echo '<button class="sg-interaction-element sg-button sg-button--active sg-otc-order-overlay__close" type="button" data-otc-order-close>Schliessen</button>' ;
echo '</header>' ;
echo '<div class="sg-card-segment sg-card-segment--gray sg-scrollable-card__content sg-object-card__content" data-pattern-part="scrollable-card-content" tabindex="0" aria-label="Scrollbarer Formularinhal t">' ;
echo '<div class="sg-card-segment sg-card-segment--gray sg-object-card__conten t">' ;
echo '<div class="sg-form-sections-card-wrapper" data-pattern="form-sections" aria-label="Formular mit Abschnitten">' ;
echo '<form id="otc-order-form" class="sg-form-sections-card" action="#" method="post" data-otc-order-form aria-label="Neuen OTC-Verkauf erfassen">' ;
echo '<form class="sg-form-sections-card" action="#" method="post" data-otc-order-form aria-label="Neuen OTC-Verkauf erfassen">' ;
echo '<div class="sg-form-sections-card__body" data-pattern-part="form-body">' ;
echo '<section class="sg-form-sections-card__chapter" aria-labelledby="otc-products-title">' ;
echo '<h2 id="otc-products-title" class="sg-strong sg-form-sections-card__chapter-title">PRODUKTE</h2>' ;
@@ -617,23 +571,20 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best
echo '<section class="sg-form-sections-card__chapter" aria-labelledby="otc-order-date-title">' ;
echo '<h2 id="otc-order-date-title" class="sg-strong sg-form-sections-card__chapter-title">Datum</h2>' ;
echo '<div class="sg-form-sections-card__field-group">' ;
echo '<label class="sg-labeled-input-row"><span class="sg-label ">Bestelldatum</span >' ;
echo '<input class="sg-interaction-element sg-input-single-line sg-input-single-line--inactive-selectable sg-form-inactive-selectable " type="date" id="otc-order-date" value="' . htmlspecialchars ( date ( 'Y-m-d' ), ENT_QUOTES , 'UTF-8' ) . '" data-otc-order-date>' ;
echo '</label>' ;
echo '<label class="sg-label" for="otc-order-date ">Bestelldatum</label >' ;
echo '<input class="sg-interaction-element sg-input-single-line" type="date" id="otc-order-date" value="' . htmlspecialchars ( date ( 'Y-m-d' ), ENT_QUOTES , 'UTF-8' ) . '" data-otc-order-date>' ;
echo '</div>' ;
echo '</section>' ;
echo '<section class="sg-form-sections-card__chapter" aria-labelledby="otc-payment-title">' ;
echo '<h2 id="otc-payment-title" class="sg-strong sg-form-sections-card__chapter-title">Bezahlung</h2>' ;
echo '<div data-otc-payment-rows>' ;
echo '<div class="sg-form-sections-card__field-group" data-otc-payment-row>' ;
echo '<label class="sg-labeled-input-row"><span class="sg-label ">Bezahlart</span >' ;
echo '<select class="sg-interaction-element sg-input-single-line sg-input-single-line--inactive-selectable sg-form-inactive-selectable sg-pulldown " id="otc-payment-method-1" data-otc-payment-method>' ;
echo '<label class="sg-label" for="otc-payment-method-1 ">Bezahlart</label >' ;
echo '<select class="sg-interaction-element sg-input-single-line" id="otc-payment-method-1" data-otc-payment-method>' ;
echo '<option value="twint">Twint</option><option value="card">Kreditkarte</option><option value="cash">Barzahlung</option><option value="paypal">PayPal</option><option value="bank_transfer">Überweisung</option>' ;
echo '</select>' ;
echo '</label>' ;
echo '<label class="sg-labeled-input-row"><span class="sg-label">Betrag (CHF)</span >' ;
echo '<input class="sg-interaction-element sg-input-single-line sg-input-single-line--inactive-selectable sg-form-inactive-selectable" type="number" id="otc-payment-amount-1" min="0.01" step="0.01" value="0.00" data-otc-payment-amount>' ;
echo '</label>' ;
echo '<label class="sg-label" for="otc-payment-amount-1">Betrag (CHF)< /label>' ;
echo '<input class="sg-interaction-element sg-input-single-line" type="number" id="otc-payment-amount-1" min="0.01" step="0.01" value="0.00" data-otc-payment-amount >' ;
echo '</div>' ;
echo '</div>' ;
echo '<div class="sg-form-sections-card__actions-segment">' ;
@@ -643,49 +594,43 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best
echo '<section class="sg-form-sections-card__chapter" aria-labelledby="otc-billing-title">' ;
echo '<h2 id="otc-billing-title" class="sg-strong sg-form-sections-card__chapter-title">Rechnungsadresse</h2>' ;
echo '<div class="sg-form-sections-card__field-group">' ;
echo '<label class="sg-labeled-input-row"><span class="sg-label ">Vorname</span >' ;
echo '<input class="sg-interaction-element sg-input-single-line sg-input-single-line--inactive-selectable sg-form-inactive-selectable " type="text" id="otc-first-name" value="Fabienne" data-otc-order-first-name>' ;
echo '</label>' ;
echo '<label class="sg-label" for="otc-first-name ">Vorname</label >' ;
echo '<input class="sg-interaction-element sg-input-single-line" type="text" id="otc-first-name" value="Fabienne" data-otc-order-first-name>' ;
echo '</div>' ;
echo '<div class="sg-form-sections-card__field-group">' ;
echo '<label class="sg-labeled-input-row"><span class="sg-label ">Nachname</span >' ;
echo '<input class="sg-interaction-element sg-input-single-line sg-input-single-line--inactive-selectable sg-form-inactive-selectable " type="text" id="otc-last-name" value="Föhn" data-otc-order-last-name>' ;
echo '</label>' ;
echo '<label class="sg-label" for="otc-last-name ">Nachname</label >' ;
echo '<input class="sg-interaction-element sg-input-single-line" type="text" id="otc-last-name" value="Föhn" data-otc-order-last-name>' ;
echo '</div>' ;
echo '<div class="sg-form-sections-card__field-group">' ;
echo '<label class="sg-labeled-input-row"><span class="sg-label ">Strasse</span >' ;
echo '<input class="sg-interaction-element sg-input-single-line sg-input-single-line--inactive-selectable sg-form-inactive-selectable " type="text" id="otc-street" value="Im Hochrain" data-otc-order-street>' ;
echo '</label>' ;
echo '<label class="sg-label" for="otc-street ">Strasse</label >' ;
echo '<input class="sg-interaction-element sg-input-single-line" type="text" id="otc-street" value="Im Hochrain" data-otc-order-street>' ;
echo '</div>' ;
echo '<div class="sg-form-sections-card__field-group">' ;
echo '<label class="sg-labeled-input-row"><span class="sg-la bel ">Hausnummer</span >' ;
echo '<input class="sg-interaction-element sg-input-single-line sg-input-single-line--inactive-selectable sg-form-inactive-selectable " type="text" id="otc-house-number" value="2" data-otc-order-house-number>' ;
echo '</label>' ;
echo '<label class="sg-label" for="otc-house-num ber ">Hausnummer</label >' ;
echo '<input class="sg-interaction-element sg-input-single-line" type="text" id="otc-house-number" value="2" data-otc-order-house-number>' ;
echo '</div>' ;
echo '<div class="sg-form-sections-card__field-group">' ;
echo '<label class="sg-labeled-input-row"><span class="sg-label ">PLZ</span >' ;
echo '<input class="sg-interaction-element sg-input-single-line sg-input-single-line--inactive-selectable sg-form-inactive-selectable " type="text" id="otc-zip" value="8102" data-otc-order-zip>' ;
echo '</label>' ;
echo '<label class="sg-label" for="otc-zip ">PLZ</label >' ;
echo '<input class="sg-interaction-element sg-input-single-line" type="text" id="otc-zip" value="8102" data-otc-order-zip>' ;
echo '</div>' ;
echo '<div class="sg-form-sections-card__field-group">' ;
echo '<label class="sg-labeled-input-row"><span class="sg-label ">Ort</span >' ;
echo '<input class="sg-interaction-element sg-input-single-line sg-input-single-line--inactive-selectable sg-form-inactive-selectable " type="text" id="otc-city" value="Oberengstringen" data-otc-order-city>' ;
echo '</label>' ;
echo '<label class="sg-label" for="otc-city ">Ort</label >' ;
echo '<input class="sg-interaction-element sg-input-single-line" type="text" id="otc-city" value="Oberengstringen" data-otc-order-city>' ;
echo '</div>' ;
echo '<div class="sg-form-sections-card__field-group">' ;
echo '<div class="sg-body sg-otc-order-form__status hidden" data-otc-order-success>Bestellung erfolgreich erfasst! Die Bestellnummer wird automatisch generiert.</div>' ;
echo '<div class="sg-body sg-otc-order-form__status sg-otc-order-form__status--error hidden" data-otc-order-error></div>' ;
echo '</div>' ;
echo '</div>' ;
echo '<footer class="sg-form-sections-card__actions-segment" data-pattern-part="form-actions-segment">' ;
echo '<div class="sg-form-sections-card__actions" data-pattern-part="form-actions">' ;
echo '<button class="sg-interaction-element sg-button sg-button--active sg-form-sections-card__action" type="button" data-otc-order-close>Abbrechen</button>' ;
echo '<button class="sg-interaction-element sg-button sg-button--process sg-button--process-inactive sg-form-sections-card__action" type="submit" disabled aria-disabled="true" data-otc-order-submit>Weiter</button>' ;
echo '</div>' ;
echo '</footer>' ;
echo '</form>' ;
echo '</div>' ;
echo '</div>' ;
echo '<footer class="sg-card-segment sg-card-segment--body sg-scrollable-card__actions-segment" data-pattern-part="scrollable-card-actions">' ;
echo '<div class="sg-scrollable-card__actions">' ;
echo '<button class="sg-interaction-element sg-button sg-button--active" type="button" form="otc-order-form" data-otc-order-close>Abbrechen</button>' ;
echo '<button class="sg-interaction-element sg-button sg-button--process sg-button--process-inactive" type="submit" form="otc-order-form" disabled aria-disabled="true" data-otc-order-submit>Weiter</button>' ;
echo '</div>' ;
echo '</footer>' ;
echo '</article>' ;
echo '<article class="sg-card sg-card--overlay-host sg-delete-confirmation-pattern__floating-card" aria-label="Verkaufsbestätigung" role="dialog" aria-modal="true" aria-labelledby="otc-confirmation-title" data-otc-confirmation-card hidden>' ;
echo '<div class="sg-card-segment sg-card-segment--body sg-delete-confirmation-pattern__body">' ;
@@ -830,13 +775,30 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best
echo " lagerBindingsInstalled = true; " ;
echo " let lagerMobileDetailHost = null; " ;
echo " let lagerMobileDetailOpen = false; " ;
echo " const renderLagerMobileDetail = (sourceDrawer, trigger) => { const type = trigger.dataset.lagerDrawerType || 'Lager'; const name = trigger.dataset.lagerDrawerName || ''; const value = trigger.dataset.lagerDrawerValue || ''; sourceDrawer.querySelector('[data-lager-drawer-title]').textContent = type + ': ' + name; sourceDrawer.querySelector('[data-lager-drawer-name-value]').textContent = name; sourceDrawer.querySelector('[data-lager-drawer-value-label]').textContent = type === 'Produkt' ? 'Anzahl im Lager:' : 'Artikelnummer:'; sourceDrawer.querySelector('[data-lager-drawer-value-value]').textContent = value; sourceDrawer.querySelectorAll('[data-lager-drawer-topic]').forEach((card) => { card.hidden = type !== 'Produkt'; }); const newLotForm = sourceDrawer.querySelector('[data-lager-drawer-topic= \" new-lot-form \" ]'); if (newLotForm) { newLotForm.hidden = true; } const newLotAction = sourceDrawer.querySelector('[data-lager-drawer-topic= \" new-lot-action \" ]'); if (newLotAction) { newLotAction.hidden = false; } if (type === 'Produkt') { const warning = trigger.dataset.lagerDrawerForecastWarning === 'true' || trigger.dataset.lagerDrawerForecastMhdWarning === 'true'; const warningValue = sourceDrawer.querySelector('[data-lager-drawer-warning-value]'); if (warningValue) { warningValue.textContent = warning ? (trigger.dataset.lagerDrawerForecast || 'Keine Prognose') : 'Keine akute Warnung.'; } const warningTitle = sourceDrawer.querySelector('[data-lager-drawer-warning-title]'); if (warningTitle) { warningTitle.textContent = getLagerWarningTitle(trigger); } sourceDrawer.querySelector('[data-lager-drawer-lot-number]').textContent = trigger.dataset.lagerDrawerLotNumber || 'Nicht hinterlegt'; sourceDrawer.querySelector('[data-lager-drawer-current-qty]').textContent = trigger.dataset.lagerDrawerCurrentQty || '0'; sourceDrawer.querySelector('[data-lager-drawer-qty-in]').textContent = trigger.dataset.lagerDrawerQtyIn || '0'; sourceDrawer.querySelector('[data-lager-drawer-manufacturer-name]').textContent = trigger.dataset.lagerDrawerManufacturerName || 'Nicht hinterlegt'; sourceDrawer.querySelector('[data-lager-drawer-manufacturer-lot-number]').textContent = trigger.dataset.lagerDrawerManufacturerLotNumber || 'Nicht hinterlegt'; sourceDrawer.querySelector('[data-lager-drawer-mfg-date]').textContent = trigger.dataset.lagerDrawerMfgDate || 'Nicht hinterlegt'; sourceDrawer.querySelector('[data-lager-drawer-expiry-date]').textContent = trigger.dataset.lagerDrawerExpiryDate || 'Nicht hinterlegt'; sourceDrawer.querySelector('[data-lager-drawer-purchase-date]').textContent = trigger.dataset.lagerDrawerPurchaseDate || 'Nicht hinterlegt'; const productId = trigger.closest('[data-lager-row]')?.dataset.lagerId || ''; sourceDrawer.querySelectorAll('[data-lager-historical-product]').forEach((product) => { product.hidden = product.dataset.lagerHistoricalProduct !== productId; }); } const host = document.createElement('div'); host.className = 'sg-lager-mobile-detail-host'; host.dataset.lagerMobileDetailHost = 'true'; host.innerHTML = '<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>'; const mobileDrawer = sourceDrawer; mobileDrawer.dataset.lagerMobileDrawer = 'true'; mobileDrawer.dataset.open = 'true'; mobileDrawer.setAttribute('aria-hidden', 'false'); host.appendChild(sourceDrawer); return host; } ;" ;
echo " const escapeLagerHtml = (value) => String(value ?? '').replace(/[&<> \" ']/g, (character) => ( { '&': '&', '<': '<', '>': '>', ' \" ': '"', \" ' \" : ''' }[character] || character)) ;" ;
echo " const renderLagerMobileDetail = (trigger) => { " ;
echo " const type = trigger.dataset.lagerDrawerType || 'Lager'; " ;
echo " const name = trigger.dataset.lagerDrawerName || ''; " ;
echo " const value = trigger.dataset.lagerDrawerValue || ''; " ;
echo " const isProduct = type === 'Produkt'; " ;
echo " const forecast = trigger.dataset.lagerDrawerForecast || 'Keine Prognose'; " ;
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 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:</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) { const mobileDrawer = lagerMobileDetailHost.querySelector('[data-lager-mobile-drawer]'); if (mobileDrawer) { contentRoot.appendChild(mobileDrawer); mobileDrawer.removeAttribute('data-lager-mobile-drawer'); mobileDrawer.dataset.open = 'false'; mobileDrawer.setAttribute('aria-hidden', 'true'); } lagerMobileDetailHost.parentNode.removeChild(lagerMobileDetailHost); }" ;
echo " if (lagerMobileDetailHost && lagerMobileDetailHost.parentNode) { lagerMobileDetailHost.parentNode.removeChild(lagerMobileDetailHost); } " ;
echo " lagerMobileDetailHost = null; lagerMobileDetailOpen = false; document.body.classList.remove('sg-lager-mobile-detail-open'); " ;
echo " }; " ;
echo " const openLagerMobileDetail = (trigger) => { " ;
echo " restoreLagerMobileDetail(); const sourceDrawer = contentRoot.querySelector('[data-lager-drawer]'); lagerMobileDetailHost = sourceDrawer ? renderLagerMobileDetail(sourceDrawer, trigger) : null; const mobileDrawer = lagerMobileDetailHost?.querySelector('[data-lager-mobile-drawer]'); if (mobileDrawer) { const virtualLot = trigger.dataset.lagerDrawerVirtualLotNumber || ''; const virtualLotValue = mobileDrawer.querySelector('[data-lager-drawer-virtual-lot-value]'); if (virtualLotValue) { virtualLotValue.textContent = virtualLot ? 'Virtuelle Charge: ' + virtualLot : 'Keine virtuelle Fehlbestandscharge vorhanden.'; } } " ;
echo " restoreLagerMobileDetail(); const host = document.createElement('div'); host.innerHTML = renderLagerMobileDetail(trigger); lagerMobileDetailHost = host.firstElementChild; " ;
echo " if (lagerMobileDetailHost) { document.body.appendChild(lagerMobileDetailHost); document.body.classList.add('sg-lager-mobile-detail-open'); } " ;
echo " lagerMobileDetailOpen = true; window.history.pushState( { ...(window.history.state || { }), lagerView: 'detail' }, '', window.location.href); " ;
echo " }; " ;
@@ -845,62 +807,38 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best
echo " if (window.history.state && window.history.state.lagerView === 'detail') { window.history.back(); return; } " ;
echo " restoreLagerMobileDetail(); " ;
echo " }; " ;
echo " const getDrawer = () => document.querySelector('[data-lager-mobile-drawer]') || contentRoot.querySelector('[data-lager-drawer]'); " ;
echo " const getDrawer = () => contentRoot.querySelector('[data-lager-drawer]'); " ;
echo " const setDrawerState = (open) => { " ;
echo " const drawer = getDrawer(); const backdrop = contentRoot.querySelector('[data-lager-drawer-backdrop]'); " ;
echo " if (!drawer || !backdrop) { return; } " ;
echo " drawer.dataset.open = String(open); drawer.setAttribute('aria-hidden', String(!open)); backdrop.dataset.open = String(open); backdrop.setAttribute('aria-hidden', String(!open)); document.body.classList.toggle('sg-card-list-page-drawer-open', open); " ;
echo " }; " ;
echo " const getLagerWarningTitle = (trigger) => trigger.dataset.lagerDrawerForecastStatus === 'depleted' ? 'Warnung: Charge ist aufgebraucht' : (trigger.dataset.lagerDrawerForecastMhdWarning === 'true' ? 'Warnung: MHD wird vor Chargenende erreicht' : (trigger.dataset.lagerDrawerForecastWarning === 'true' ? 'Warnung: Charge wird innerhalb von drei Monaten aufgebraucht sein' : 'Keine Warnung')); " ;
echo " const escapeLagerHtml = (value) => String(value ?? '').replace(/[&<> \" ']/g, (character) => ( { '&': '&', '<': '<', '>': '>', ' \" ': '"', \" ' \" : ''' }[character] || character)); " ;
echo " const renderLagerDocumentRows = (documents, editable) => { if (!documents.length) { return '<p class= \" sg-body \" >Keine Dokumente vorhanden.</p>'; } return documents.map((document) => { const id = Number(document.id || 0); const filename = escapeLagerHtml(document.original_filename || 'Dokument'); if (!editable) { return '<p class= \" sg-body \" data-lager-document-row= \" ' + id + ' \" ><a class= \" sg-hyperlink \" href= \" /api/lager-document.php?id=' + id + ' \" data-component= \" hyperlink \" >' + filename + '</a></p>'; } return '<div class= \" sg-form-sections-card__field-group \" data-lager-document-edit-row= \" ' + id + ' \" ><span class= \" sg-body \" >' + filename + ' <span class= \" sg-tab-button-group \" role= \" tablist \" aria-label= \" Dokument entfernen \" data-component= \" tab-navigation \" data-component-size= \" compact \" ><button class= \" sg-interaction-element sg-button sg-tab-button sg-tab-button--compact \" type= \" button \" role= \" tab \" aria-selected= \" false \" data-component-part= \" tab-button \" aria-label= \" Dokument entfernen: ' + filename + ' \" data-lager-document-delete= \" ' + id + ' \" >× </button></span></span></div>'; }).join(''); }; " ;
echo " const syncLagerDocumentViews = (root, documents) => { const read = root?.querySelector('[data-lager-documents-read]'); const edit = root?.querySelector('[data-lager-documents-edit]'); const upload = root?.querySelector('[data-lager-document-upload-form]'); if (read) { read.innerHTML = renderLagerDocumentRows(documents, false); } if (edit) { edit.innerHTML = renderLagerDocumentRows(documents, true); if (upload) { edit.appendChild(upload); } } }; " ;
echo " const syncLagerCurrentDocuments = (trigger) => { const drawer = getDrawer(); if (!drawer) { return; } let documents = []; try { documents = JSON.parse(trigger.dataset.lagerDrawerDocuments || '[]'); } catch (error) { documents = []; } syncLagerDocumentViews(drawer.querySelector('[data-lager-documents= \" current-read \" ]'), documents); syncLagerDocumentViews(drawer.querySelector('[data-lager-documents= \" current-edit \" ]'), documents); }; " ;
echo " const renderLagerSelectedFiles = (scope) => { const input = scope?.querySelector('[data-lager-document-file]'); const list = scope?.querySelector('[data-lager-document-selected-files]'); const status = scope?.querySelector('[data-lager-document-status]'); if (!input || !list) { return; } const files = Array.from(input.files || []); list.replaceChildren(...files.map((file, index) => { const item = document.createElement('li'); item.className = 'sg-file-upload__file'; const name = document.createElement('span'); name.className = 'sg-file-upload__file-name sg-body'; name.append(document.createTextNode(file.name + ' ')); const navigation = document.createElement('span'); navigation.className = 'sg-tab-button-group'; navigation.setAttribute('role', 'tablist'); navigation.setAttribute('aria-label', 'Datei entfernen'); navigation.dataset.component = 'tab-navigation'; navigation.dataset.componentSize = 'compact'; const remove = document.createElement('button'); remove.className = 'sg-interaction-element sg-button sg-tab-button sg-tab-button--compact sg-file-upload__remove'; remove.type = 'button'; remove.setAttribute('role', 'tab'); remove.setAttribute('aria-selected', 'false'); remove.setAttribute('data-component-part', 'tab-button'); remove.setAttribute('aria-label', 'Datei entfernen: ' + file.name); remove.dataset.lagerDocumentRemoveIndex = String(index); remove.textContent = '× '; navigation.append(remove); name.append(navigation); item.append(name); return item; })); list.hidden = files.length === 0; if (status && !status.textContent.includes('Upload') && !status.textContent.includes('hochgeladen')) { status.textContent = files.length ? files.length + ' Datei(en) ausgewählt.' : 'Noch keine Dateien ausgewählt.'; } }; " ;
echo " const closeDrawer = () => { setDrawerState(false); contentRoot.querySelectorAll('[data-lager-drawer-open]').forEach((trigger) => trigger.setAttribute('aria-expanded', 'false')); }; " ;
echo " documen t.addEventListener('click', (event) => { const trigger = event.target.closest('[data-lager-drawer-open]'); if (!trigger || trigger.dataset.lagerDrawerType !== 'Produkt') { return; } const drawer = getDrawer(); const forecast = drawer?.querySelector('[data-lager-drawer-forecast-value]'); if (forecast) { forecast.textContent = trigger.dataset.lagerDrawerForecast || 'Keine Prognose'; } syncLagerCurrentDocuments(trigger); }); " ;
echo " const getLagerForecastWarningText = (forecast, trigger, text) => { if (forecast?.status === 'depleted' || trigger?.dataset.lagerDrawerForecastStatus === 'depleted') { return 'Die Charge ist aufgebraucht. Voraussichtlich leer: ' + text + '.'; } if (trigger?.dataset.lagerDrawerForecastMhdWarning === 'true') { const expiry = trigger.dataset.lagerDrawerExpiryDate ? new Date(trigger.dataset.lagerDrawerExpiryDate + 'T00:00:00').toLocaleDateString('de-CH') : 'dem MHD'; return 'Das MHD wird am ' + expiry + ' erreicht, bevor das Lager leer ist. Voraussichtlich leer: ' + text + '.'; } if (trigger?.dataset.lagerDrawerForecastWarning === 'true') { return 'Voraussichtlich leer: ' + text + '.'; } return 'Keine akute Warnung.'; }; " ;
echo " document.addEventListener('click', (event) => { const trigger = event.target.closest('[data-lager-drawer-open]'); if (!trigger || trigger.dataset.lagerDrawerType !== 'Produkt') { return; } const drawer = getDrawer(); const warningValue = drawer?.querySelector('[data-lager-drawer-warning-value]'); if (warningValue) { warningValue.textContent = getLagerForecastWarningText(null, trigger, trigger.dataset.lagerDrawerForecast || 'Keine Prognose'); } }); " ;
echo " const syncLagerForecast = (forecast, productId) => { const drawer = getDrawer(); const trigger = contentRoot.querySelector('[data-lager-drawer-open][aria-expanded= \" true \" ]') || contentRoot.querySelector('[data-lager-row][data-lager-id= \" ' + (productId || '') + ' \" ] [data-lager-drawer-open]'); if (!forecast || !drawer) { return; } const forecastDate = forecast.date ? new Date(forecast.date + 'T00:00:00') : null; const expiryDate = forecast.expiryDate ? new Date(forecast.expiryDate + 'T00:00:00') : null; const mhdWarning = Boolean(forecastDate && expiryDate && forecastDate > expiryDate); const nearExpiryWarning = Boolean(forecastDate && expiryDate && forecastDate >= new Date(new Date(expiryDate).setMonth(expiryDate.getMonth() - 3)) && forecastDate <= expiryDate); const depleted = forecast.status === 'depleted'; const forecastWarning = depleted || nearExpiryWarning; const date = forecastDate ? forecastDate.toLocaleDateString('de-CH') : 'Keine Prognose'; const text = depleted ? date + ' (CHARGE ENDE)' : (nearExpiryWarning || mhdWarning ? date + ' (MHD: ' + expiryDate.toLocaleDateString('de-CH') + ')' : date); const value = drawer.querySelector('[data-lager-drawer-forecast-value]'); if (value) { value.textContent = text; } const header = drawer.querySelector('[data-lager-drawer-warning-header]'); const title = drawer.querySelector('[data-lager-drawer-warning-title]'); const warningValue = drawer.querySelector('[data-lager-drawer-warning-value]'); if (trigger) { trigger.dataset.lagerDrawerForecast = text; trigger.dataset.lagerDrawerForecastStatus = forecast.status || 'no_demand'; trigger.dataset.lagerDrawerForecastWarning = forecastWarning ? 'true' : 'false'; trigger.dataset.lagerDrawerForecastMhdWarning = mhdWarning ? 'true' : 'false'; if (header) { header.classList.toggle('sg-card-segment--darkgreen', !forecastWarning && !mhdWarning); header.classList.toggle('sg-card-segment--signal-red', forecastWarning); header.classList.toggle('sg-card-segment--signal-yellow', mhdWarning); } if (title) { title.textContent = getLagerWarningTitle(trigger); } if (warningValue) { warningValue.textContent = forecastWarning || mhdWarning ? text : 'Keine akute Warnung.'; warningValue.classList.toggle('sg-strong', forecastWarning || mhdWarning); warningValue.classList.toggle('lager-forecast-warning', forecastWarning); warningValue.classList.toggle('lager-forecast-mhd-warning', mhdWarning); } const row = trigger.closest('[data-lager-row]'); const cells = row?.querySelectorAll('[role= \" cell \" ]'); const forecastCell = cells?.[cells.length - 1]; if (forecastCell && cells.length === 3) { forecastCell.textContent = text; } } }; " ;
echo " document.addEventListener('lager-save-complete', (event) => { const forecast = event.detail?.forecast; const productId = event.detail?.productId || ''; const trigger = contentRoot.querySelector('[data-lager-drawer-open][aria-expanded= \" true \" ]') || contentRoot.querySelector('[data-lager-row][data-lager-id= \" ' + productId + ' \" ] [data-lager-drawer-open]'); const drawer = getDrawer(); if (!forecast || !drawer) { return; } const date = forecast.date ? new Date(forecast.date + 'T00:00:00').toLocaleDateString('de-CH') : 'Keine Prognose'; const text = forecast.status === 'depleted' ? date + ' (CHARGE ENDE)' : date; const value = drawer.querySelector('[data-lager-drawer-forecast-value]'); if (value) { value.textContent = text; } if (trigger) { trigger.dataset.lagerDrawerForecast = text; const row = trigger.closest('[data-lager-row]'); const cells = row?.querySelectorAll('[role= \" cell \" ]'); const forecastCell = cells?.[cells.length - 1]; if (forecastCell && cells.length === 3) { forecastCell.textContent = text; } } }); " ;
echo " document.addEventListener('click', (event) => { " ;
echo " contentRoo t.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-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 " document.addEventListener('click', (event) => { const trigger = event.target.closest('[data-lager-drawer-open]'); if (trigger?.dataset.lagerDrawerType === 'Produkt') { syncLagerCurrentDocuments(trigger); } }); " ;
echo " if (event.target.closest('[data-lager-drawer-close]') || event.target.closest('[data-lager-drawer-backdrop]')) { closeDrawer(); } " ;
echo " }); " ;
echo " documen t.addEventListener('click', (event) => { const trigger = event.target.closest('[data-lager-drawer-open]'); if (!trigger || trigger.dataset.lagerDrawerType !== 'Produkt' || window.matchMedia('(max-width: 767px)').matches) { return; } const header = contentRoot.querySelector('[data-lager-drawer-warning-header]'); const title = contentRoot.querySelector('[data-lager-drawer-warning-title]'); if (!header || !title) { return; } const forecastWarning = trigger.dataset.lagerDrawerForecastWarning === 'true'; const mhdWarning = trigger.dataset.lagerDrawerForecastMhdWarning === 'true'; title.textContent = getLagerWarningTitle(trigger); header.classList.toggle('sg-card-segment--darkgreen', !forecastWarning && !mhdWarning); header.classList.toggle('sg-card-segment--signal-red', forecastWarning); header.classList.toggle('sg-card-segment--signal-yellow', mhdWarning); }); " ;
echo " documen t.addEventListener('click', (event) => { const trigger = event.target.closest('[data-lager-drawer-open]'); if (!trigger || trigger.dataset.lagerDrawerType !== 'Produkt' || window.matchMedia('(max-width: 767px)').matches) { return; } setLagerEditMode(false); const drawer = getDrawer(); const currentQty = drawer?.querySelector('[data-lager-drawer-current-qty]'); const qtyIn = drawer?.querySelector('[data-lager-drawer-qty-in]'); const lotNumber = drawer?.querySelector('[data-lager-lot-number]'); if (currentQty) { currentQty.textContent = trigger.dataset.lagerDrawerCurrentQty || '0'; } if (qtyIn) { qtyIn.textContent = trigger.dataset.lagerDrawerQtyIn || '0'; } if (lotNumber) { lotNumber.value = trigger.dataset.lagerDrawerLotNumber || ''; } const productId = trigger.closest('[data-lager-row]')?.dataset.lagerId || ''; contentRoot.querySelectorAll('[data-lager-historical-product]').forEach((product) => { product.hidden = product.dataset.lagerHistoricalProduct !== productId; }); }); " ;
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'); } syncLagerForecast(result.forecast, result.productId); const trigger = contentRoot.querySelector('[data-lager-drawer-open][aria-expanded= \" true \" ]') || contentRoot.querySelector('[data-lager-row][data-lager-id= \" ' + (result.productId || '') + ' \" ] [data-lager-drawer-open]'); const drawer = getDrawer(); const warningValue = drawer?.querySelector('[data-lager-drawer-warning-value]'); if (warningValue) { warningValue.textContent = getLagerForecastWarningText(result.forecast, trigger, trigger?.dataset.lagerDrawerForecast || 'Keine Prognose'); } return result; };" ;
echo " documen t.addEventListener('click', (event) => { const remove = event.target.closest('[data-lager-document-remove-index]'); if (remove) { const scope = remove.closest('[data-lager-document-upload-form]'); const input = scope?.querySelector('[data-lager-document-file]'); const index = Number(remove.dataset.lagerDocumentRemoveIndex); if (input && Number.isInteger(index)) { const data = new DataTransfer(); Array.from(input.files || []).forEach((file, fileIndex) => { if (fileIndex !== index) { data.items.add(file); } }); input.files = data.files; input.dispatchEvent(new Event('change', { bubbles: true })) ; } return; } const trigger = event.target.closest('[data-lager-document-file-trigger]'); const input = trigger?.closest('[data-lager-document-upload-form]')?.querySelector('[data-lager-document-file]'); if (!input) { return; } event.preventDefault(); input.click(); });" ;
echo " document.addEventListener('dragover', (event) => { const dropzone = event.target.closest('[data-lager-document-upload-form] .sg-file-upload__dropzone'); if (!dropzone) { return; } event.preventDefault(); dropzone.dataset.dragOver = 'true' ; }) ;" ;
echo " documen t.addEventListener('dragleave ', (event) => { const dropzone = event.target.closest('[data-lager-document-upload-form] .sg-file-upload__dropzone'); if (dropzone && !dropzone.contains(event.relatedTarget)) { delete dropzone.dataset.dragOver ; } });" ;
echo " document.addEventListener('drop', (event) => { const dropzone = event.target.closest('[data-lager-document-upload-form] .sg-file-upload__dropzone'); if (!dropzone) { return; } event.preventDefault(); delete dropzone.dataset.dragOver; const input = dropzone.closest('[data-lager-document-upload-form]')?.querySelector('[data-lager-document-file]'); if (input && event.dataTransfer?.files) { input.files = event.dataTransfer.files; input.dispatchEvent(new Event('change', { bubbles: true })); } }); " ;
echo " document.addEventListener('change', (event) => { const input = event.target.closest('[data-lager-document-file]'); if (!input) { return; } const form = input.closest('[data-lager-document-upload-form]'); renderLagerSelectedFiles(form); }); " ;
echo " const uploadLagerDocuments = async (scope, lotId) => { const files = Array.from(scope?.querySelectorAll('[data-lager-document-file]') || []).flatMap((input) => Array.from(input.files || [])); if (!files.length) { return []; } const status = scope.querySelector('[data-lager-document-status]'); const uploaded = []; const errorMessage = (error) => error instanceof Error ? error.message : 'Upload fehlgeschlagen'; if (files.some((file) => file.size > 52428800)) { const error = new Error('Dokument darf maximal 50 MB groß sein.'); if (status) { status.textContent = error.message; } throw error; } if (status) { status.textContent = 'Upload läuft …'; } try { for (const file of files) { const data = new FormData(); data.append('action', 'upload_document'); data.append('csrfToken', contentRoot.querySelector('[data-lager-csrf-token]')?.dataset.lagerCsrfToken || ''); data.append('lotId', lotId || ''); data.append('document', file); const response = await fetch('/api/lager-charge.php', { method: 'POST', body: data }); const result = await response.json(); if (!response.ok || result.ok !== true) { throw new Error(result.error || 'Upload fehlgeschlagen'); } uploaded.push(result.document); } } catch (error) { if (status) { status.textContent = errorMessage(error); } throw error; } if (status) { status.textContent = files.length + ' Datei(en) hochgeladen.'; } return uploaded; }; " ;
echo " document.addEventListener('click', async (event) => { const remove = event.target.closest('[data-lager-document-delete]'); if (!remove) { return; } remove.disabled = true; try { await postLagerChange( { action: 'delete_document', documentId: remove.dataset.lagerDocumentDelete }); window.location.reload(); } catch (error) { remove.disabled = false; remove.setCustomValidity(error instanceof Error ? error.message : 'Dokument konnte nicht entfernt werden'); remove.reportValidity(); } }); " ;
echo " document.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 " const setLagerEditMode = (editing) => { const drawer = getDrawer(); const readView = drawer?.querySelector('[data-lager-read-view]'); const readDocuments = drawer?.querySelector('[data-lager-documents= \" current-read \" ]'); const editForm = drawer?.querySelector('[data-lager-edit-form]'); const documents = drawer?.querySelector('[data-lager-edit-documents= \" current-edit \" ]'); const actions = drawer?.querySelector('[data-lager-edit-actions]'); if (readView) { readView.hidden = editing; } if (readDocuments) { readDocuments.hidden = editing; } if (editForm) { editForm.hidden = !editing; } if (documents) { documents.hidden = !editing; } if (actions) { actions.hidden = !editing; } }; " ;
echo " document.addEventListener('click', (event) => { if (event.target.closest('[data-lager-edit-open]')) { setLagerEditMode(true); } if (event.target.closest('[data-lager-edit-close]')) { clearLagerMovementInputs(); setLagerEditMode(false); } }); " ;
echo " contentRoo t.addEventListener('click', (event) => { const trigger = event.target.closest('[data-lager-drawer-open]'); if (!trigger || trigger.dataset.lagerDrawerType !== 'Produkt' || window.matchMedia('(max-width: 767px)').matches) { return; } const header = contentRoot.querySelector('[data-lager-drawer-warning-header]'); const title = contentRoot.querySelector('[data-lager-drawer-warning-title]'); if (!header || !title) { return; } const forecastWarning = trigger.dataset.lagerDrawerForecastWarning === 'true'; const mhdWarning = trigger.dataset.lagerDrawerForecastMhdWarning === 'true'; title.textContent = getLagerWarningTitle(trigger); header.classList.toggle('sg-card-segment--darkgreen', !forecastWarning && !mhdWarning); header.classList.toggle('sg-card-segment--signal-red', forecastWarning); header.classList.toggle('sg-card-segment--signal-yellow', mhdWarning); }); " ;
echo " contentRoo t.addEventListener('click', (event) => { const trigger = event.target.closest('[data-lager-drawer-open]'); if (!trigger || trigger.dataset.lagerDrawerType !== 'Produkt' || window.matchMedia('(max-width: 767px)').matches) { return; } setLagerEditMode(false); const drawer = getDrawer(); const currentQty = drawer?.querySelector('[data-lager-drawer-current-qty]'); const qtyIn = drawer?.querySelector('[data-lager-drawer-qty-in]'); const lotNumber = drawer?.querySelector('[data-lager-lot-number]'); if (currentQty) { currentQty.textContent = trigger.dataset.lagerDrawerCurrentQty || '0'; } if (qtyIn) { qtyIn.textContent = trigger.dataset.lagerDrawerQtyIn || '0'; } if (lotNumber) { lotNumber.value = trigger.dataset.lagerDrawerLotNumber || ''; } const productId = trigger.closest('[data-lager-row]')?.dataset.lagerId || ''; contentRoot.querySelectorAll('[data-lager-historical-product]').forEach((product) => { product.hidden = product.dataset.lagerHistoricalProduct !== productId; }); }); " ;
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 " contentRoo t.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 " const setLagerEditMode = (editing) => { const drawer = getDrawer(); const readView = drawer?.querySelector('[data-lager-read-view]'); const editForm = drawer?.querySelector('[data-lager-edit-form]'); if (readView) { readView.hidden = editing; } if (editForm) { editForm.hidden = !editing ; } } ;" ;
echo " contentRoo t.addEventListener('click ', (event) => { if ( event.target.closest('[data-lager-edit-open]')) { setLagerEditMode(true); } if (event.target.closest('[data-lager-edit-close]')) { clearLagerMovementInputs(); setLagerEditMode(false) ; } });" ;
echo " const syncLagerReadView = () => { const drawer = getDrawer(); if (!drawer) { return; } const manufacturer = drawer.querySelector('[data-lager-manufacturer]'); const values = { '[data-lager-drawer-manufacturer-name]': manufacturer?.selectedOptions?.[0]?.textContent || 'Nicht hinterlegt', '[data-lager-drawer-manufacturer-lot-number]': drawer.querySelector('[data-lager-manufacturer-lot]')?.value || 'Nicht hinterlegt', '[data-lager-drawer-mfg-date]': drawer.querySelector('[data-lager-mfg-date]')?.value || 'Nicht hinterlegt', '[data-lager-drawer-expiry-date]': drawer.querySelector('[data-lager-expiry-date]')?.value || 'Nicht hinterlegt', '[data-lager-drawer-purchase-date]': drawer.querySelector('[data-lager-purchase-date]')?.value || 'Nicht hinterlegt' }; Object.entries(values).forEach(([selector, value]) => { const target = drawer.querySelector(selector); if (target) { target.textContent = value; } }); const trigger = contentRoot.querySelector('[data-lager-drawer-open][aria-expanded= \" true \" ]'); if (trigger) { trigger.dataset.lagerDrawerManufacturerName = values['[data-lager-drawer-manufacturer-name]']; trigger.dataset.lagerDrawerManufacturerLotNumber = values['[data-lager-drawer-manufacturer-lot-number]']; trigger.dataset.lagerDrawerMfgDate = values['[data-lager-drawer-mfg-date]']; trigger.dataset.lagerDrawerExpiryDate = values['[data-lager-drawer-expiry-date]']; trigger.dataset.lagerDrawerPurchaseDate = values['[data-lager-drawer-purchase-date]']; } }; " ;
echo " const syncLagerBalanceView = (balance) => { const drawer = getDrawer(); if (!drawer || !balance) { return; } const currentQty = drawer.querySelector('[data-lager-drawer-current-qty]'); const qtyIn = drawer.querySelector('[data-lager-drawer-qty-in]'); if (currentQty) { currentQty.textContent = String(balance.qty_net ?? 0); } if (qtyIn) { qtyIn.textContent = String(balance.qty_in ?? 0); } const trigger = contentRoot.querySelector('[data-lager-drawer-open][aria-expanded= \" true \" ]'); if (trigger) { trigger.dataset.lagerDrawerCurrentQty = String(balance.qty_net ?? 0); trigger.dataset.lagerDrawerQtyIn = String(balance.qty_in ?? 0); } }; " ;
echo " const clearLagerMovementInputs = () => { const drawer = getDrawer(); if (!drawer) { return; } drawer.querySelectorAll('[data-lager-receipt-qty], [data-lager-adjustment-qty], [data-lager-out-qty]').forEach((input) => { input.value = ''; }); }; " ;
echo " const syncLagerOpenLotCard = (lot, balance) => { const drawer = getDrawer(); const card = drawer?.querySelector('[data-lager-open-card= \" ' + (lot?.id || '') + ' \" ]'); if (!card) { return; } const values = { '[data-lager-open-card-lot-number]': lot?.lot_number || 'Nicht hinterlegt', '[data-lager-open-card-qty-net]': String(balance?.qty_net ?? 0), '[data-lager-open-card-qty-in]': String(balance?.qty_net ?? 0), '[data-lager-open-card-manufacturer]': drawer.querySelector('[data-lager-new-manufacturer]')?.selectedOptions?.[0]?.textContent || 'Nicht hinterlegt', '[data-lager-open-card-manufacturer-lot]': lot?.manufacturer_lot_number || 'Nicht hinterlegt', '[data-lager-open-card-mfg-date]': lot?.mfg_date || 'Nicht hinterlegt', '[data-lager-open-card-expiry-date]': lot?.expiry_date || 'Nicht hinterlegt', '[data-lager-open-card-purchase-date]': lot?.purchase_date || 'Nicht hinterlegt' }; Object.entries(values).forEach(([selector, value]) => { const target = card.querySelector(selector); if (target) { target.textContent = value; } }); const wrapper = card.closest('[data-lager-open-card-wrapper]'); wrapper?.querySelector('[data-lager-edit-documents]')?.setAttribute('hidden', ''); wrapper?.querySelector('[data-lager-open-edit-actions]')?.setAttribute('hidden', ''); wrapper?.querySelector('[data-lager-documents^= \" open-read- \" ]')?.removeAttribute('hidden'); };" ;
echo " documen t.addEventListener('click', (event) => { const trigger = event.target.closest('[data-lager-drawer-open]'); if (!trigger || trigger.dataset.lagerDrawerType !== 'Produkt' || window.matchMedia('(max-width: 767px)').matches) { return; } const drawer = getDrawer(); const productId = trigger.closest('[data-lager-row]')?.dataset.lagerId || ''; const openProduct = drawer?.querySelector('[data-lager-open-product= \" ' + productId + ' \" ]'); drawer?.querySelectorAll('[data-lager-open-product]').forEach((product) => { product.hidden = product !== openProduct; product.querySelectorAll('[data-lager-open-edit-form]').forEach((form) => { form.hidden = true; }); product.querySelectorAll('[data-lager-open-edit-actions]').forEach((actions) => { actions.hidden = true; }); product.querySelectorAll('[data-lager-open-card]').forEach((readView) => { readView.hidden = false; }); product.querySelectorAll('[data-lager-documents^= \" open-read- \" ]').forEach((readDocuments) => { readDocuments.hidden = false; }); product.querySelectorAll('[data-lager-edit-documents]').forEach((documents) => { documents.hidden = tru e; }); }); const newForm = drawer?.querySelector('[data-lager-drawer-topic=\" new-lot-form \" ]'); const newAction = drawer?.querySelector('[data-lager-drawer-topic= \" new-lot-action \" ]'); if (newForm) { newForm.hidden = true; } if (newAction) { newAction.hidden = false; } const notificationWrapper = drawer?.querySelector('[data-lager-new-lot-notification-wrapper]'); const notification = drawer?.querySelector('[data-lager-new-lot-notification]'); const shortageQty = trigger.dataset.lagerDrawerVirtualShortageQty || '0'; const hasShortage = shortageQty !== '0' && shortageQty !== '0,00'; if (notificationWrapper) { notificationWrapper.hidden = !hasShortage; } if (notification && hasShortage) { notification.textContent = 'Für dieses Produkt bestehen virtuelle Fehlbestände in Höhe von ' + shortageQty + '. Die Eingangsmenge wird nach Aktivierung der Charge zur Nachallokation verwendet.'; } const setValue = (selector, value) => { const field = drawer?.querySelector(selector); if (field) { field.value = value || ''; } }; setValue('[data-lager-new-lot-number]', trigger.dataset.lagerOpenLotNumber); setValue('[data-lager-new-manufacturer]', trigger.dataset.lagerOpenManufacturerPartyId); setValue('[data-lager-new-manufacturer-lot]', trigger.dataset.lagerOpenManufacturerLotNumber); setValue('[data-lager-new-mfg-date]', trigger.dataset.lagerOpenMfgDate); setValue('[data-lager-new-expiry-date]', trigger.dataset.lagerOpenExpiryDate); setValue('[data-lager-new-purchase-date]', trigger.dataset.lagerOpenPurchaseDate); if (drawer) { drawer.dataset.lagerOpenLotId = trigger.dataset.lagerOpenLotId || ''; drawer.dataset.lagerProductId = productId; } }); " ;
echo " documen t.addEventListener('click', (event) => { const openButton = event.target.closest('[data-lager-new-lot-open]'); if (openButton) { const drawer = getDrawer(); const form = drawer?.querySelector('[data-lager-drawer-topic= \" new-lot-form \" ]'); const action = drawer?.querySelector('[data-lager-drawer-topic= \" new-lot-action \" ]'); if (form) { form.hidden = false; } if (action) { action.hidden = true; } return; } if (event.target.closest('[data-lager-new-lot-close]')) { const drawer = getDrawer(); const form = drawer?.querySelector('[data-lager-drawer-topic= \" new-lot-form \" ]'); const action = drawer?.querySelector('[data-lager-drawer-topic= \" new-lot-action \" ]'); if (form) { form.hidden = true; } if (action) { action.hidden = false; } } }); " ;
echo " documen t.addEventListener('click', (event) => { const editButton = event.target.closest('[data-lager-open-edit-open]'); if (editButton) { const card = editButton.closest('[data-lager-open-card-wrapper]'); const form = card?.querySelector('[data-lager-open-edit-form]'); const readView = card?.querySelector('[data-lager-open-card]'); const readDocuments = card?.querySelector('[data-lager-documents^= \" open-read- \" ]'); const documents = card?.querySelector('[data-lager-edit-documents]'); const actions = card?.querySelector('[data-lager-open-edit-actions]'); if (form) { form.hidden = false; } if (readView) { readView.hidden = true; } if (readDocuments) { readDocuments.hidden = true; } if (documents) { documents.hidden = false; } if (actions) { actions.hidden = false; } return; } const closeButton = event.target.closest('[data-lager-open-edit-close]'); if (closeButton) { const card = closeButton.closest('[data-lager-open-card-wrapper]'); const form = card?.querySelector('[data-lager-open-edit-form]'); const readView = card?.querySelector('[data-lager-open-card]'); const readDocuments = card?.querySelector('[data-lager-documents^= \" open-read- \" ]'); const documents = card?.querySelector('[data-lager-edit-documents]'); const actions = card?.querySelector('[data-lager-open-edit-actions]'); if (form) { form.hidden = true; } if (readView) { readView.hidden = false; } if (readDocuments) { readDocuments.hidden = false; } if (documents) { documents.hidden = true; } if (actions) { actions.hidden = tru e; } } });" ;
echo " documen t.addEventListener('input', (event) => { const input = event.target.closest('[data-lager-open-delete-confirmation-input]'); if (!input) { return; } const card = input .closest('[data-lager-open-card-wrapper]'); const submit = card?.querySelector('[data-lager-open-delete-confirmation-submit]'); const valid = input.value === 'DELETE'; if (submit) { submit.disabled = !valid; submit.setAttribute('aria-disabled', String(!valid)); submit.classList.toggle('sg-button--process-inactive', !valid); } });" ;
echo " documen t.addEventListener('click ', async (event) => { const deleteButton = event.target.closest('[data-lager-open-delete]'); if (deleteButton) { const card = deleteButton.closest('[data-lager-open-card-wrapper]'); const confirmation = card?.querySelector('[data-lager-open-delete-confirmation]'); const input = card?.querySelector('[data-lager-open-delete-confirmation-input]'); const submit = card?.querySelector('[data-lager-open-delete-confirmation-submit]'); if (input) { input .value = ''; } if (submit) { submit.disabled = true; submit.setAttribute('aria-disabled', 'true'); submit.classList.add('sg-button--process-inactive'); } if (confirmation) { confirmation.hidden = false; } if (card) { card.dataset.dialogOpen = 'true'; } return; } const cancel = event.target.closest('[data-lager-open-delete-confirmation-cancel]'); if (cancel) { const card = cancel.closest('[data-lager-open-card-wrapper]'); const confirmation = card?.querySelector('[data-lager-open-delete-confirmation]'); if (confirmation) { confirmation.hidden = true; } if (card) { card.dataset.dialogOpen = 'false'; } return; } const submit = event.target.closest('[data-lager-open-delete-confirmation-submit]'); if (!submit || submit.disabled) { return; } const card = submi t.c losest('[data-lager-open-card-wrapper]'); const confirmation = card?.querySelector('[data-lager-open-delete-confirmation]'); const status = card ?.querySelector('[data-lager-open-delete-status ]'); if (status ) { status.textContent = 'Löschen läuft …'; } submit.disabled = true; try { await postLagerChange( { action: 'delete_open_lot', lotId: card?.dataset.lagerOpenCardWrapper || '' }); card?.remove(); } catch (error) { if (status) { status.textContent = error instanceof Error ? error.message : 'Lös chen fehlgeschlagen'; } submit.disabled = false; } }); " ;
echo " documen t.addEventListener('click', (event) => { const cancel = event.target.closest('[data-lager-open-confirmation-cancel]'); if (cancel) { const card = cancel.closest('[data-lager-open-card-wrapper]'); const confirmation = card?.querySelector('[data-lager-open-confirmation-card]'); if (confirmation) { confirmation.hidd en = true; } if (card) { card.dataset.dialogOpen = 'false'; } const form = card?.querySelector('[data-lager-open-edit-form-element]'); if (form) { form.dataset.confirmationAccepted = 'false'; } return; } const confirm = event.target.closest('[data-lager-open-confirmation-submit]'); if (confirm) { const card = confirm.closest('[data-lager-open-card-wrapper]'); const confirmation = card?.querySelector('[data-lager-open-confirmation-card]'); const form = card?.querySelector('[data-lager-open-edit-form-element]'); if (confirmation) { confirmation.hidden = true; } if (card) { card.dataset.dialogOp en = 'false'; } if (f orm ) { form.dataset.confirmationAccepted = 'true'; form.requestSubmit() ; } } }); " ;
echo " document.addEventListener('submit', async (event) => { const openLotForm = event.target.closest('[data-lager-open-edit-form-element]'); if (!openLotForm) { return; } event.preventDefault(); const drawer = getDrawer(); const card = openLotForm.closest('[data-lager-open-card-wrapper]'); const editSection = card?.querySelector('[data-lager-open-edit-form]'); const fields = [ { label: 'Naurua-Chargennummer', input: openLotForm.querySelector('[data-lager-open-lot-number]') }, { label: 'Hersteller', input: openLotForm.querySelector('[data-lager-open-manufacturer]') }, { label: 'Hersteller-Chargennummer', input: openLotForm.querySelector('[data-lager-open-manufacturer-lot]') }, { label: 'Herstellungsdatum', input: openLotForm.querySelector('[data-lager-open-mfg-date]') }, { label: 'MHD', input: openLotForm.querySelector('[data-lager-open-expiry-date]') }, { label: 'Einkaufsdatum', input: openLotForm.querySelector('[data-lager-open-purchase-date]') }, { label: 'Menge', input: openLotForm.querySelector('[data-lager-open-target-qty]') }]; const emptyFields = fields.filter((field) => (field.input?.value || '').trim() === ''); if (emptyFields.length > 0 && openLotForm.dataset.confirmationAccepted !== 'true') { const confirmation = card?.querySelector('[data-lager-open-confirmation-card]'); const emptyFieldsList = card?.querySelector('[data-lager-open-confirmation-empty-fields]'); if (emptyFieldsList) { emptyFieldsList.replaceChildren(...emptyFields.map((field) => { const item = document.createElement('div'); item.className = 'sg-body'; item.textContent = field.label; return item; })); } if (confirmation) { confirmation.hidden = false; } if (card) { card.dataset.dialogOpen = 'true'; } return; } openLotForm.dataset.confirmationAccepted = 'false'; const status = openLotForm.closest('[data-lager-open-edit-form]')?.querySelector('[data-lager-open-edit-status]'); if (status) { status.textContent = 'Speichern läuft …'; } try { const lotId = card?.dataset.lagerOpenCardWrapper || ''; const uploadedDocuments = await uploadLagerDocuments(card?.querySelector('[data-lager-documents=open-edit-' + lotId + ']'), lotId); const existingDocuments = Array.from(card?.querySelectorAll('[data-lager-documents^= \" open-read- \" ] [data-lager-document-row]') || []).map((row) => ( { id: Number(row.dataset.lagerDocumentRow || 0), original_filename: row.querySelector('a')?.textContent || 'Dokument' })); const targetQtyInput = openLotForm.querySelector('[data-lager-open-target-qty]'); const result = await postLagerChange( { action: 'prepare_lot', productId: drawer?.dataset.lagerProductId || '', lotId, lotNumber: openLotForm.querySelector('[data-lager-open-lot-number]')?.value || '', manufacturerPartyId: openLotForm.querySelector('[data-lager-open-manufacturer]')?.value || null, manufacturerLotNumber: openLotForm.querySelector('[data-lager-open-manufacturer-lot]')?.value || '', mfgDate: openLotForm.querySelector('[data-lager-open-mfg-date]')?.value || '', expiryDate: openLotForm.querySelector('[data-lager-open-expiry-date]')?.value || '', purchaseDate: openLotForm.querySelector('[data-lager-open-purchase-date]')?.value || '', targetQty: targetQtyInput?.value.trim() === '' ? '0' : targetQtyInput?.value || '' }); syncLagerDocumentViews(card, [...existingDocuments, ...uploadedDocuments]); syncLagerOpenLotCard(result.lot, result.balance); if (editSection) { editSection.hidden = true; } card?.querySelector('[data-lager-open-card]')?.removeAttribute('hidden'); if (status) { status.textContent = ''; } } catch (error) { if (status) { status.textContent = error instanceof Error ? error.message : 'Speichern fehlgeschlagen'; } } }); " ;
echo " document.addEventListener('submit', async (event) => { const newLotForm = event.target.closest('[data-lager-new-lot-form-element]'); if (!newLotForm) { return; } event.preventDefault(); const drawer = getDrawer(); const status = drawer?.querySelector('[data-lager-new-lot-status]'); if (status) { status.textContent = 'Speichern läuft …'; } try { const result = await postLagerChange( { action: 'prepare_lot', productId: drawer?.dataset.lagerProductId || '', lotId: drawer?.dataset.lagerOpenLotId || '', lotNumber: drawer?.querySelector('[data-lager-new-lot-number]')?.value || '', manufacturerPartyId: drawer?.querySelector('[data-lager-new-manufacturer]')?.value || null, manufacturerLotNumber: drawer?.querySelector('[data-lager-new-manufacturer-lot]')?.value || '', mfgDate: drawer?.querySelector('[data-lager-new-mfg-date]')?.value || '', expiryDate: drawer?.querySelector('[data-lager-new-expiry-date]')?.value || '', purchaseDate: drawer?.querySelector('[data-lager-new-purchase-date]')?.value || '', receiptQty: drawer?.querySelector('[data-lager-new-receipt-qty]')?.value || '' }); syncLagerOpenLotCard(result.lot, result.balance); const form = drawer?.querySelector('[data-lager-drawer-topic= \" new-lot-form \" ]'); const action = drawer?.querySelector('[data-lager-drawer-topic= \" new-lot-action \" ]'); if (form) { form.hidden = true; } if (action) { action.hidden = false; } if (status) { status.textContent = ''; } } catch (error) { if (status) { status.textContent = error instanceof Error ? error.message : 'Speichern fehlgeschlagen'; } } }); " ;
echo " document.addEventListener('submit', async (event) => { const editForm = event.target.closest('[data-lager-edit-form-element]'); if (!editForm) { return; } event.preventDefault(); const drawer = getDrawer(); const status = drawer?.querySelector('[data-lager-edit-status]'); if (status) { status.textContent = 'Speichern läuft …'; } try { const lotId = drawer?.dataset.lagerActiveLotId || ''; const uploadedDocuments = await uploadLagerDocuments(drawer?.querySelector('[data-lager-documents= \" current-edit \" ]'), lotId); const result = await postLagerChange( { action: 'update_lot', lotId, 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 || '', receiptQty: drawer?.querySelector('[data-lager-receipt-qty]')?.value || '', adjustmentQty: drawer?.querySelector('[data-lager-adjustment-qty]')?.value || '', outQty: drawer?.querySelector('[data-lager-out-qty]')?.value || '' }); const trigger = contentRoot.querySelector('[data-lager-drawer-open][aria-expanded= \" true \" ]'); if (trigger && uploadedDocuments.length) { let existingDocuments = []; try { existingDocuments = JSON.parse(trigger.dataset.lagerDrawerDocuments || '[]'); } catch (error) { existingDocuments = []; } trigger.dataset.lagerDrawerDocuments = JSON.stringify([...existingDocuments, ...uploadedDocuments]); syncLagerCurrentDocuments(trigger); } syncLagerReadView(); syncLagerBalanceView(result.balance); clearLagerMovementInputs(); setLagerEditMode(false); if (status) { status.textContent = ''; } } catch (error) { if (status) { status.textContent = error instanceof Error ? error.message : 'Speichern fehlgeschlagen'; } } }); " ;
echo " const syncLagerOpenLotCard = (lot, balance) => { const drawer = getDrawer(); const card = drawer?.querySelector('[data-lager-open-card= \" ' + (lot?.id || '') + ' \" ]'); if (!card) { return; } const values = { '[data-lager-open-card-lot-number]': lot?.lot_number || 'Nicht hinterlegt', '[data-lager-open-card-qty-net]': String(balance?.qty_net ?? 0), '[data-lager-open-card-qty-in]': String(balance?.qty_i n ?? 0), '[data-lager-open-card-manufacturer]': drawer.querySelector('[data-lager-new-manufacturer]')?.selectedOptions?.[0]?.textContent || 'Nicht hinterlegt', '[data-lager-open-card-manufacturer-lot]': lot?.manufacturer_lot_number || 'Nicht hinterlegt', '[data-lager-open-card-mfg-date]': lot?.mfg_date || 'Nicht hinterlegt', '[data-lager-open-card-expiry-date]': lot?.expiry_date || 'Nicht hinterlegt', '[data-lager-open-card-purchase-date]': lot?.purchase_date || 'Nicht hinterlegt' }; Object.entries(values).forEach(([selector, value]) => { const target = card.querySelector(selector); if (target) { target.textContent = value; } }); }; " ;
echo " contentRoo t.addEventListener('click', (event) => { const trigger = event.target.closest('[data-lager-drawer-open]'); if (!trigger || trigger.dataset.lagerDrawerType !== 'Produkt' || window.matchMedia('(max-width: 767px)').matches) { return; } const drawer = getDrawer(); const productId = trigger.closest('[data-lager-row]')?.dataset.lagerId || ''; const openProduct = drawer?.querySelector('[data-lager-open-product= \" ' + productId + ' \" ]'); drawer?.querySelectorAll('[data-lager-open-product]').forEach((product) => { product.hidden = product !== openProduct; product.querySelectorAll('[data-lager-open-edit-form]').forEach((form) => { form.hidden = true; }); product.querySelectorAll('[data-lager-open-card]').forEach((readView) => { readView.hidden = fals e; }); }); const newForm = drawer?.querySelector('[data-lager-drawer-topic=\" new-lot-form \" ]'); const newAction = drawer?.querySelector('[data-lager-drawer-topic= \" new-lot-action \" ]'); if (newForm) { newForm.hidden = true; } if (newAction) { newAction.hidden = false; } const notificationWrapper = drawer?.querySelector('[data-lager-new-lot-notification-wrapper]'); const notification = drawer?.querySelector('[data-lager-new-lot-notification]'); const shortageQty = trigger.dataset.lagerDrawerVirtualShortageQty || '0'; const hasShortage = shortageQty !== '0' && shortageQty !== '0,00'; if (notificationWrapper) { notificationWrapper.hidden = !hasShortage; } if (notification && hasShortage) { notification.textContent = 'Für dieses Produkt bestehen virtuelle Fehlbestände in Höhe von ' + shortageQty + '. Die Eingangsmenge wird nach Aktivierung der Charge zur Nachallokation verwendet.'; } const setValue = (selector, value) => { const field = drawer?.querySelector(selector); if (field) { field.value = value || ''; } }; setValue('[data-lager-new-lot-number]', trigger.dataset.lagerOpenLotNumber); setValue('[data-lager-new-manufacturer]', trigger.dataset.lagerOpenManufacturerPartyId); setValue('[data-lager-new-manufacturer-lot]', trigger.dataset.lagerOpenManufacturerLotNumber); setValue('[data-lager-new-mfg-date]', trigger.dataset.lagerOpenMfgDate); setValue('[data-lager-new-expiry-date]', trigger.dataset.lagerOpenExpiryDate); setValue('[data-lager-new-purchase-date]', trigger.dataset.lagerOpenPurchaseDate); if (drawer) { drawer.dataset.lagerOpenLotId = trigger.dataset.lagerOpenLotId || ''; drawer.dataset.lagerProductId = productId; } }); " ;
echo " contentRoo t.addEventListener('click', (event) => { const openButton = event.target.closest('[data-lager-new-lot-open]'); if (openButton) { const drawer = getDrawer(); const form = drawer?.querySelector('[data-lager-drawer-topic= \" new-lot-form \" ]'); const action = drawer?.querySelector('[data-lager-drawer-topic= \" new-lot-action \" ]'); if (form) { form.hidden = false; } if (action) { action.hidden = true; } return; } if (event.target.closest('[data-lager-new-lot-close]')) { const drawer = getDrawer(); const form = drawer?.querySelector('[data-lager-drawer-topic= \" new-lot-form \" ]'); const action = drawer?.querySelector('[data-lager-drawer-topic= \" new-lot-action \" ]'); if (form) { form.hidden = true; } if (action) { action.hidden = false; } } }); " ;
echo " contentRoo t.addEventListener('click', (event) => { const editButton = event.target.closest('[data-lager-open-edit-open]'); if (editButton) { const card = editButton.closest('[data-lager-open-card-wrapper]'); const form = card?.querySelector('[data-lager-open-edit-form]'); const readView = card?.querySelector('[data-lager-open-card]'); if (form) { form.hidden = false; } if (readView) { readView.hidden = true; } return; } const closeButton = event.target.closest('[data-lager-open-edit-close]'); if (closeButton) { const card = closeButton.closest('[data-lager-open-card-wrapper]'); const form = card?.querySelector('[data-lager-open-edit-form]'); const readView = card?.querySelector('[data-lager-open-card]'); if (form) { form.hidden = true; } if (readView) { readView.hidden = fals e; } } });" ;
echo " contentRoo t.addEventListener('submit', async (event) => { const openLotForm = event.target.closest('[data-lager-open-edit-form-element]'); if (!openLotForm) { return; } event.preventDefault(); const drawer = getDrawer(); const card = openLotForm .closest('[data-lager-open-card-wrapper]'); const status = openLotForm.querySelector('[data-lager-open-edit-status]'); if (status) { status.textContent = 'Speichern läuft …'; } try { const result = await postLagerChange( { action: 'prepare_lot', productId: drawer?.dataset.lagerProductId || '', lotId: card?.dataset.lagerOpenCardWrapper || '', lotNumber: openLotForm.querySelector('[data-lager-open-lot-number]')?.value || '', manufacturerPartyId: openLotForm.querySelector('[data-lager-open-manufacturer]')?.value || null, manufacturerLotNumber: openLotForm.querySelector('[data-lager-open-manufacturer-lot]')?.value || '', mfgDate: openLotForm.querySelector('[data-lager-open-mfg-date]')?.value || '', expiryDate: openLotForm.querySelector('[data-lager-open-expiry-date]')?.value || '', purchaseDate: openLotForm.querySelector('[data-lager-open-purchase-date]')?.value || '', receiptQty: openLotForm.querySelector('[data-lager-open-receipt-qty]')?.value || '' }); syncLagerOpenLotCard(result.lot, result.balance); openLotForm.querySelector('[data-lager-open-receipt-qty]').value = ''; openLotForm.setAttribute('hidden', 'hidden'); card?.querySelector('[data-lager-open-card]')?.removeAttribute('hidden'); if (status) { status.textContent = ''; } } catch (error) { if (status) { status.textContent = error instanceof Error ? error.message : 'Speichern fehlgeschlagen'; } } });" ;
echo " contentRoo t.addEventListener('submit ', async (event) => { const newLotForm = event.target.closest('[data-lager-new-lot-form-element]'); if (!newLotForm) { return; } event.preventDefault(); const drawer = getDrawer(); const status = drawer?.querySelector('[data-lager-new-lot-status]'); if (status) { status.textContent = 'Speichern läuft …'; } try { const result = await postLagerChange( { action: 'prepare_lot', productId: drawer?.dataset.lagerProductId || '', lotId: drawer?.dataset.lagerOpenLotId || '', lotNumber: drawer?.querySelector('[data-lager-new-lot-number]')? .value || '', manufacturerPartyId: drawer?.querySelector('[data-lager-new-manufacturer]')?.value || null, manufacturerLotNumber: drawer?.querySelector('[data-lager-new-manufacturer-lot]')?.value || '', mfgDate: drawer?.querySelector('[data-lager-new-mfg-date]')?.value || '', expiryDate: drawer?.querySelector('[data-lager-new-expiry-date]')?.value || '', purchaseDate: drawer?.querySelector('[data-lager-new-purchase-date]')?.value || '', receiptQty: drawer?.querySelector('[data-lager-new-receipt-qty]')?.value || '' }); syncLagerOpenLotCard(resul t.lot, result.balance); const form = drawer?.querySelector('[data-lager-drawer-topic= \" new-lot-form \" ]'); const action = drawer ?.querySelector('[data-lager-drawer-topic= \" new-lot-action \" ]'); if (form ) { form.hidden = true; } if (action) { action.hidden = false; } if (status) { status.textContent = ''; } } catch (error) { if (status) { status.textContent = error instanceof Error ? error.message : 'Spei cher n fehlgeschlagen'; } } }); " ;
echo " contentRoo t.addEventListener('submit', async (event) => { const editForm = event.target.closest('[data-lager-edit-form-element]'); if (!editForm) { return; } event.preventDefault(); const drawer = getDrawer(); const status = drawer?.querySelector('[data-lager-edit-status]'); if (status) { status.textCont ent = 'Speichern läuft …'; } try { const result = 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 || '', receiptQty: drawer?.querySelector('[data-lager-receipt-qty]')?.value || '', adjustmentQty: drawer?.querySelector('[data-lager-adjustment-qty]')?.value || '', outQty: drawer?.querySelector('[data-lager-out-qty]')?.value || '' }); syncLagerReadView(); syncLagerBalanceView(result.balance); clearLagerMovementInputs(); setLagerEditMode(false); if (status) { status.textCont ent = ''; } } catch (err or) { 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(); } }); " ;
echo " const syncLagerDisplayedTotal = () => { const drawer = getDrawer(); const trigger = contentRoot.querySelector('[data-lager-drawer-open][aria-expanded= \" true \" ]'); if (!drawer || !trigger || trigger.dataset.lagerDrawerType !== 'Produkt') { return; } const active = Number((drawer.querySelector('[data-lager-drawer-current-qty]')?.textContent || '0').replace(',', '.')) || 0; const productId = trigger.closest('[data-lager-row]')?.dataset.lagerId || ''; const openProduct = drawer.querySelector('[data-lager-open-product= \" ' + productId + ' \" ]'); const open = Array.from(openProduct?.querySelectorAll('[data-lager-open-card-qty-net]') || []).reduce((sum, node) => sum + (Number((node.textContent || '0').replace(',', '.')) || 0), 0); const total = active + open; const formatted = Number.isInteger(total) ? String(total) : total.toFixed(2).replace(/ \ .?0+ $ /, ''); const value = drawer.querySelector('[data-lager-drawer-value-value]'); if (value && value.textContent !== formatted) { value.textContent = formatted; } trigger.dataset.lagerDrawerValue = formatted; }; " ;
echo " const lagerTotalObserver = new MutationObserver(syncLagerDisplayedTotal); " ;
echo " lagerTotalObserver.observe(contentRoot, { childList: true, subtree: true, characterData: true }); " ;
echo " } " ;
echo " function initBestellungenBindings() { " ;
echo " const contentRoot = document.querySelector('[data-left-navigation-content-body]'); " ;
@@ -940,7 +878,7 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best
echo " const isMobileDetailMode = () => window.matchMedia('(max-width: 767px)').matches; " ;
echo " const escapeHtml = (value) => String(value ?? '').replace(/[&<> \" ']/g, (character) => ( { '&': '&', '<': '<', '>': '>', ' \" ': '"', \" ' \" : ''' }[character] || character)); " ;
echo " let bestellungenMobileDetailHost = null; " ;
echo " let bestellungenDetailOpen = false; let bestellungenOpeningMobileDetail = false; " ;
echo " let bestellungenDetailOpen = false; " ;
echo " const syncSearchState = () => { " ;
echo " const input = getSearchInput(); " ;
echo " const wrap = getSearchWrap(); " ;
@@ -949,10 +887,47 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best
echo " wrap.setAttribute('data-has-value', String(hasValue)); " ;
echo " wrap.dataset.componentState = hasValue ? 'active' : 'inactive-selectable'; " ;
echo " }; " ;
echo " const renderMobileDetail = () => { " ;
echo " return '<div class= \" sg-bestellungen-mobile-detail-host \" data-bestellungen-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-bestellungen-detail-back>zurück</button></div></div></article></div></div></div> ';" ;
echo " } ; " ;
echo " const getDrawer = () => document.querySelector('[data-bestellungen-mobile-drawer]') || contentRoot.querySelector('[data-bestellungen-drawer]') ; " ;
echo " const renderMobileDetail = (trigger ) => { " ;
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 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 [ " ;
echo " '<div class= \" sg-bestellungen-mobile-detail-host \" data-bestellungen-mobile-detail-host= \" true \" >', " ;
echo " '<div class= \" sg-navigation-card-layout sg-mobile-detail-back-card \" >', " ;
echo " '<div class= \" sg-navigation-card-block \" >', " ;
echo " '<article class= \" sg-card \" data-component= \" card \" data-pattern= \" navigation-card \" aria-label= \" Navigation Detailansicht zurück oben \" >', " ;
echo " '<div class= \" sg-card-segment sg-card-segment--body \" data-component-part= \" card-body \" data-pattern-part= \" navigation-card-segment \" >', " ;
echo " '<div class= \" sg-navigation-card-center \" >', " ;
echo " '<button class= \" sg-interaction-element sg-hyperlink \" type= \" button \" data-bestellungen-detail-back>zurück</button>', " ;
echo " '</div>', " ;
echo " '</div>', " ;
echo " '</article>', " ;
echo " '</div>', " ;
echo " '</div>', " ;
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>', " ;
echo " '<p class= \" sg-body \" ><strong>Lieferadresse:</strong></p>', " ;
echo " '<p class= \" sg-body \" >' + escapeHtml(streetLine) + '</p>', " ;
echo " '<p class= \" sg-body \" >' + escapeHtml(cityLine) + '</p>', " ;
echo " '<p class= \" sg-body \" >' + escapeHtml(country) + '</p>', " ;
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></div>', " ;
echo " '</div>' " ;
echo " ].join(''); " ;
echo " }; " ;
echo " const getDrawer = () => contentRoot.querySelector('[data-bestellungen-drawer]'); " ;
echo " const getDrawerBackdrop = () => contentRoot.querySelector('[data-bestellungen-drawer-backdrop]'); " ;
echo " const setDrawerState = (open) => { " ;
echo " const drawer = getDrawer(); " ;
@@ -973,7 +948,7 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best
echo " const openDrawer = (trigger) => { " ;
echo " const drawer = getDrawer(); " ;
echo " if (!drawer) { return; } " ;
echo " if (isMobileDetailMode() && !bestellungenOpeningMobileDetail ) { " ;
echo " if (isMobileDetailMode()) { " ;
echo " openMobileDetail(trigger); " ;
echo " return; " ;
echo " } " ;
@@ -998,7 +973,7 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best
echo " }); " ;
echo " }; " ;
echo " const restoreBestellungenList = () => { " ;
echo " if (bestellungenMobileDetailHost && bestellungenMobileDetailHost.parentNode) { const mobileDrawer = bestellungenMobileDetailHost.querySelector('[data-bestellungen-mobile-drawer]'); if (mobileDrawer) { contentRoot.appendChild(mobileDrawer); mobileDrawer.removeAttribute('data-bestellungen-mobile-drawer'); mobileDrawer.dataset.open = 'false'; mobileDrawer.setAttribute('aria-hidden', 'true'); } document.body.classList.remove('sg-card-list-page-drawer-open'); " ;
echo " if (bestellungenMobileDetailHost && bestellungenMobileDetailHost.parentNode) { " ;
echo " bestellungenMobileDetailHost.parentNode.removeChild(bestellungenMobileDetailHost); " ;
echo " } " ;
echo " bestellungenMobileDetailHost = null; " ;
@@ -1008,13 +983,14 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best
echo " }; " ;
echo " const openMobileDetail = (trigger) => { " ;
echo " restoreBestellungenList(); " ;
echo " const sourceDrawer = contentRoot.querySelector('[data-bestellungen-drawer]'); " ;
echo " if (!sourceDrawer) { return; } " ;
echo " const host = document.createElement('div'); " ;
echo " host.innerHTML = renderMobileDetail(); " ;
echo " host.innerHTML = renderMobileDetail(trigger ); " ;
echo " bestellungenMobileDetailHost = host.firstElementChild; " ;
echo " if (bestellungenMobileDetailHost) { const mobileDrawer = sourceDrawer; mobileDrawer.dataset.bestellungenMobileDrawer = 'true'; mobileDrawer.dataset.open = 'true'; mobileDrawer.setAttribute('aria-hidden', 'false'); bestellungenMobileDetailHost.appendChild(mobileDrawer); document.body.appendChild(bestellungenMobileDetailHost); document.body.classList.add('sg-bestellungen-mobile-detail-open'); } " ;
echo " bestellungenOpeningMobileDetail = true; openDrawer(trigger); bestellungenOpening MobileDetail = false ; " ;
echo " if (bestellungenMobileDetailHost) { " ;
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 " }; " ;
@@ -1168,7 +1144,7 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best
echo " closeMobileDetail(); " ;
echo " } " ;
echo " }); " ;
echo " documen t.addEventListener('click', (event) => { " ;
echo " contentRoo t.addEventListener('click', (event) => { " ;
echo " const openTrigger = event.target.closest('[data-order-drawer-open]'); " ;
echo " if (openTrigger) { " ;
echo " event.preventDefault(); " ;
@@ -1242,7 +1218,7 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best
echo " const houseNumberInput = form.querySelector('[data-otc-order-house-number]'); " ;
echo " const zipInput = form.querySelector('[data-otc-order-zip]'); " ;
echo " const cityInput = form.querySelector('[data-otc-order-city]'); " ;
echo " const submitBtn = overlay .querySelector('[data-otc-order-submit]'); " ;
echo " const submitBtn = form .querySelector('[data-otc-order-submit]'); " ;
echo " const errorEl = form.querySelector('[data-otc-order-error]'); " ;
echo " const successEl = form.querySelector('[data-otc-order-success]'); " ;
echo " const successDefaultText = successEl ? successEl.textContent : ''; " ;
@@ -1263,6 +1239,7 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best
echo " const clearSuccess = () => { " ;
echo " if (successEl) { successEl.textContent = successDefaultText; successEl.classList.add('hidden'); } " ;
echo " }; " ;
echo " let backdropPointerDown = false; " ;
echo " const getTodayValue = () => { " ;
echo " const now = new Date(); " ;
echo " const year = now.getFullYear(); " ;
@@ -1353,6 +1330,9 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best
echo " confirmationCard.hidden = false; " ;
echo " requestAnimationFrame(() => confirmationSubmit.focus()); " ;
echo " }; " ;
echo " overlay.addEventListener('pointerdown', (event) => { " ;
echo " backdropPointerDown = event.target === overlay; " ;
echo " }); " ;
echo " document.addEventListener('click', (event) => { " ;
echo " const openTrigger = event.target.closest('[data-otc-order-open]'); " ;
echo " if (openTrigger) { " ;
@@ -1366,6 +1346,17 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best
echo " toggleOverlay(false); " ;
echo " } " ;
echo " }); " ;
echo " overlay.addEventListener('click', (event) => { " ;
echo " if (event.target === overlay && backdropPointerDown) { " ;
echo " toggleOverlay(false); " ;
echo " } " ;
echo " backdropPointerDown = false; " ;
echo " }); " ;
echo " document.addEventListener('keydown', (event) => { " ;
echo " if (event.key === 'Escape' && overlay.dataset.open === 'true') { " ;
echo " toggleOverlay(false); " ;
echo " } " ;
echo " }); " ;
echo " [orderDateInput, firstNameInput, lastNameInput, streetInput, houseNumberInput, zipInput, cityInput].forEach((input) => { " ;
echo " if (!input) { return; } " ;
echo " input.addEventListener('input', updateFormState); " ;
@@ -1386,7 +1377,7 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best
echo " const row = document.createElement('div'); " ;
echo " row.className = 'sg-form-sections-card__field-group'; " ;
echo " row.dataset.otcPaymentRow = ''; " ;
echo " row.innerHTML = '<label class= \" sg-labeled-input-row \" ><span class= \" sg-label \" >Bezahlart</span ><select class= \" sg-interaction-element sg-input-single-line sg-input-single-line--inactive-selectable sg-form-inactive-selectable sg-pulldown \" id= \" otc-payment-method-' + number + ' \" data-otc-payment-method>' + paymentOptions + '</select></label>< label class= \" sg-labeled-input-row \" ><span class= \" sg-label \" >Betrag (CHF)</span ><input class= \" sg-interaction-element sg-input-single-line sg-input-single-line--inactive-selectable sg-form-inactive-selectable \" type= \" number \" id= \" otc-payment-amount-' + number + ' \" min= \" 0.01 \" step= \" 0.01 \" value= \" 0.00 \" data-otc-payment-amount></label>' ; " ;
echo " row.innerHTML = '<label class= \" sg-label \" for= \" otc-payment-method-' + number + ' \" >Bezahlart</label ><select class= \" sg-interaction-element sg-input-single-line \" id= \" otc-payment-method-' + number + ' \" data-otc-payment-method>' + paymentOptions + '</select><label class= \" sg-label \" for= \" otc-payment-amount-' + number + ' \" >Betrag (CHF)</label ><input class= \" sg-interaction-element sg-input-single-line \" type= \" number \" id= \" otc-payment-amount-' + number + ' \" min= \" 0.01 \" step= \" 0.01 \" value= \" 0.00 \" data-otc-payment-amount>' ; " ;
echo " row.querySelector('[data-otc-payment-method]').value = nextPaymentMethod; " ;
echo " paymentRows.appendChild(row); " ;
echo " bindPaymentRow(row); " ;