From 7f5cb27f1aea8e14f597f918430e4319c54c7f3b Mon Sep 17 00:00:00 2001 From: Luca Haid Date: Fri, 5 Dec 2025 13:57:38 +0000 Subject: [PATCH] Warehouse article/improve modal --- application/Termination/Termination.php | 11 +- .../WarehouseArticle/WarehouseArticle.css | 469 ++++++++++++- .../WarehouseArticle/WarehouseArticle.js | 614 +++++++++++++++--- public/plugins/vue/tt-components/tt-input.js | 3 +- public/plugins/vue/tt-components/tt-modal.js | 135 ++-- 5 files changed, 1057 insertions(+), 175 deletions(-) diff --git a/application/Termination/Termination.php b/application/Termination/Termination.php index 112a0b3df..0d6b830e5 100644 --- a/application/Termination/Termination.php +++ b/application/Termination/Termination.php @@ -241,12 +241,13 @@ class Termination extends mfBaseModel { $this->log->debug("is range"); $port_parts = explode("-", $ports); if(is_array($port_parts) && count($port_parts) == 2) { - $from = $port_parts[0]; - $to = $port_parts[1]; + $from = intval($port_parts[0]); + $to = intval($port_parts[1]); - if($port_parts[0] > $port_parts[1]) { - $from = $port_parts[1]; - $to = $port_parts[0]; + if($from > $to) { + $tmp = $from; + $from = $to; + $to = $tmp; } $range = []; diff --git a/public/js/pages/WarehouseArticle/WarehouseArticle.css b/public/js/pages/WarehouseArticle/WarehouseArticle.css index cdcefa24d..2dd411fa9 100644 --- a/public/js/pages/WarehouseArticle/WarehouseArticle.css +++ b/public/js/pages/WarehouseArticle/WarehouseArticle.css @@ -1,43 +1,464 @@ +/* End of Life Row Highlighting */ .end-of-life { background-color: #f8d7da !important; } -.warehouse-article-prices > div, -.warehouse-article-distributor > div { +/* + * Modal Layout + */ +.modal-body { + overflow-x: hidden; +} + +.wa-modal-content { + display: flex; + flex-direction: column; + gap: 16px; + overflow-x: hidden; + max-width: 100%; +} + +.wa-modal-content .row { + margin-left: 0; + margin-right: 0; +} + +.wa-modal-content .row > [class*="col-"] { + padding-left: 8px; + padding-right: 8px; +} + +.wa-section { + background: #f8f9fa; + border: 1px solid #e9ecef; + border-radius: 6px; + padding: 12px; +} + +.wa-section-title { + font-size: 0.9rem; + font-weight: 600; + color: #495057; + margin-bottom: 12px; + padding-bottom: 8px; + border-bottom: 1px solid #dee2e6; +} + +/* + * Article Prices Section - Dense 2-Column Layout + */ +.wa-prices-section { + background: #f8f9fa; + border: 1px solid #e9ecef; + border-radius: 6px; + padding: 12px; +} + +.wa-prices-grid-dense { display: grid; - grid-template-columns: repeat(3, minmax(150px, 1fr)) 120px; - gap: 12px; + grid-template-columns: repeat(2, 1fr); + gap: 10px; +} + +.wa-price-item { + background: white; + border: 1px solid #dee2e6; + border-radius: 4px; + padding: 8px; + transition: box-shadow 0.15s ease; +} + +.wa-price-item:hover { + box-shadow: 0 2px 4px rgba(0,0,0,0.1); +} + +.wa-price-header { + display: flex; + align-items: center; + padding-bottom: 6px; + border-bottom: 1px solid #e9ecef; margin-bottom: 8px; } -.warehouse-article-prices .form-group, -.warehouse-article-distributor .form-group { +.wa-price-body { + display: grid; + grid-template-columns: 1fr 1fr auto; + gap: 6px; + align-items: center; +} + +.wa-price-actions { + display: flex; + align-items: center; + gap: 3px; +} + +.wa-price-actions .btn { + padding: 4px 8px; + font-size: 0.75rem; + min-width: 32px; +} + +.wa-price-actions .btn:disabled { + opacity: 0.4; + cursor: not-allowed; +} + +/* + * Section Title with Action Button + */ +.wa-section-title-with-action { + display: flex; + align-items: center; + justify-content: space-between; + padding: 8px 12px; + margin: -12px -12px 12px -12px; + background: linear-gradient(to bottom, #ffffff, #f8f9fa); + border-bottom: 1px solid #e9ecef; + border-radius: 6px 6px 0 0; +} + +/* + * Distributor Section - With Modal Directory + */ +.wa-distributors-section { + background: #f8f9fa; + border: 1px solid #e9ecef; + border-radius: 6px; + padding: 12px; +} + +.wa-directory-header { + display: flex; + align-items: center; + padding: 0; +} + +.wa-directory-list { + max-height: 300px; + overflow-y: auto; + padding: 8px; +} + +.wa-directory-group { + margin-bottom: 12px; +} + +.wa-directory-group:last-child { margin-bottom: 0; } -@media (max-width: 992px) { - .warehouse-article-prices > div, - .warehouse-article-distributor > div { - display: block; - border: 1px solid #eee; - padding: 10px; +.wa-directory-letter { + font-size: 0.9rem; + font-weight: 700; + color: #007bff; + padding: 4px 8px; + background: #e7f3ff; + border-left: 3px solid #007bff; + margin-bottom: 6px; +} + +.wa-directory-items { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); + gap: 6px; + padding-left: 8px; +} + +.wa-directory-item { + display: flex; + align-items: center; + justify-content: space-between; + padding: 6px 10px; + background: white; + border: 1px solid #ced4da; + border-radius: 4px; + font-size: 0.8rem; + cursor: pointer; + transition: all 0.15s ease; + color: #495057; +} + +.wa-directory-item:hover:not(:disabled) { + background: #007bff; + border-color: #007bff; + color: white; +} + +.wa-directory-item.active { + background: #28a745; + border-color: #28a745; + color: white; + cursor: default; +} + +.wa-directory-item:disabled { + opacity: 0.6; + cursor: not-allowed; +} + +.wa-distributors-grid { + display: flex; + flex-direction: column; + gap: 8px; + margin-top: 12px; +} + +.wa-distributor-row { + display: grid; + grid-template-columns: 180px 1fr auto; + gap: 10px; + align-items: center; + background: white; + border: 1px solid #dee2e6; + border-radius: 4px; + padding: 8px; + transition: box-shadow 0.15s ease; +} + +.wa-distributor-row:hover { + box-shadow: 0 2px 4px rgba(0,0,0,0.1); +} + +.wa-distributor-name { + font-size: 0.8rem; + color: #495057; + font-weight: 500; + display: flex; + align-items: center; +} + +.wa-distributor-inputs { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 6px; +} + +.wa-distributor-actions { + display: flex; + align-items: center; + gap: 3px; +} + +.wa-distributor-actions .btn { + padding: 4px 8px; + font-size: 0.75rem; + min-width: 32px; +} + +.wa-distributor-actions .btn:disabled { + opacity: 0.4; + cursor: not-allowed; +} + +/* + * Custom Checkboxes - Similar to WorkorderMphBase + */ +.wa-checkbox-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 8px; + margin-top: 8px; +} + +.wa-checkbox-item { + display: flex; + align-items: center; + padding: 8px 10px; + background: #f8f9fa; + border: 1px solid #e9ecef; + border-radius: 4px; + cursor: pointer; + transition: all 0.15s ease; + user-select: none; +} + +.wa-checkbox-item:hover { + background: #e9ecef; + border-color: #ced4da; +} + +.wa-checkbox-item input[type="checkbox"] { + position: absolute; + opacity: 0; + cursor: pointer; +} + +.wa-checkmark { + position: relative; + height: 16px; + width: 16px; + min-width: 16px; + background-color: #fff; + border: 2px solid #adb5bd; + border-radius: 3px; + margin-right: 8px; + transition: all 0.2s ease; +} + +.wa-checkbox-item input[type="checkbox"]:checked ~ .wa-checkmark { + background-color: #28a745; + border-color: #28a745; +} + +.wa-checkmark:after { + content: ""; + position: absolute; + display: none; + left: 4px; + top: 0px; + width: 4px; + height: 8px; + border: solid white; + border-width: 0 2px 2px 0; + transform: rotate(45deg); +} + +.wa-checkbox-item input[type="checkbox"]:checked ~ .wa-checkmark:after { + display: block; +} + +.wa-checkbox-label { + font-size: 0.8rem; + line-height: 1.2; +} + +/* + * Form Controls - Dense Sizing (Desktop Only) + */ +@media (min-width: 768px) { + .wa-modal-content .form-group { margin-bottom: 10px; } - .warehouse-article-prices > div > *, - .warehouse-article-distributor > div > * { - display: block; - margin-bottom: 10px !important; + .wa-modal-content label { + font-size: 0.8rem; + font-weight: 500; + color: #495057; + margin-bottom: 3px; } - .warehouse-article-prices > div > div:last-child, - .warehouse-article-distributor > div > div:last-child { - text-align: right; - margin-bottom: 0 !important; + .wa-modal-content .form-control-sm, + .wa-modal-content .tt-select-trigger.sm { + height: 30px; + font-size: 0.8rem; + padding: 4px 8px; } - .warehouse-article-prices > div > div:last-child > *, - .warehouse-article-distributor > div > div:last-child > * { - margin-left: 5px; + /* Ensure tt-select aligns with tt-input */ + .wa-modal-content .tt-select-modern { + display: flex; + flex-direction: column; } -} \ No newline at end of file + + .wa-modal-content .tt-select-modern .form-group { + display: flex; + flex-direction: column; + margin-bottom: 10px; + } + + .wa-modal-content .tt-select-modern label { + order: -1; + } + + .wa-modal-content textarea.form-control { + min-height: 60px; + font-size: 0.8rem; + padding: 6px 8px; + } +} + +/* + * Additional Attributes Section + */ +.wa-attributes-section { + background: #f8f9fa; + border: 1px solid #e9ecef; + border-radius: 6px; + padding: 12px; +} + +.wa-attributes-grid { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 12px; +} + +/* + * Responsive Design + */ +@media (max-width: 992px) { + .wa-prices-grid-dense { + grid-template-columns: 1fr; + } + + .wa-directory-items { + grid-template-columns: 1fr; + } + + .wa-checkbox-grid { + grid-template-columns: repeat(2, 1fr); + } +} + +@media (max-width: 768px) { + .wa-modal-content .row > [class*="col-"] { + padding-left: 12px; + padding-right: 12px; + } + + .wa-price-body { + grid-template-columns: 1fr; + gap: 8px; + } + + .wa-price-actions { + justify-content: flex-end; + padding-top: 4px; + border-top: 1px solid #e9ecef; + } + + .wa-distributor-row { + grid-template-columns: 1fr; + gap: 8px; + } + + .wa-distributor-name { + padding-bottom: 4px; + border-bottom: 1px solid #e9ecef; + } + + .wa-distributor-inputs { + grid-template-columns: 1fr; + } + + .wa-distributor-actions { + justify-content: flex-end; + padding-top: 4px; + border-top: 1px solid #e9ecef; + } + + .wa-checkbox-grid { + grid-template-columns: 1fr; + } +} + +@media (max-width: 576px) { + .wa-section-title { + font-size: 0.85rem; + } + + .wa-modal-content { + gap: 10px; + } + + .wa-section { + padding: 10px; + } + + .wa-section-title-with-action { + flex-direction: column; + align-items: flex-start; + gap: 8px; + } +} diff --git a/public/js/pages/WarehouseArticle/WarehouseArticle.js b/public/js/pages/WarehouseArticle/WarehouseArticle.js index bfe645844..1cd04733d 100644 --- a/public/js/pages/WarehouseArticle/WarehouseArticle.js +++ b/public/js/pages/WarehouseArticle/WarehouseArticle.js @@ -16,29 +16,55 @@ async function handleApiResponse(responsePromise) { Vue.component('warehouse-article-prices', { props: {id: {type: Number, required: true}}, template: ` - -

Artikelpreise überschreiben

-
-
-
- {{ typeTitle }} +