From 5549c67eb50c779873f8d6dcd9bd46406c157fba Mon Sep 17 00:00:00 2001 From: Edwin Noorlander Date: Wed, 12 Nov 2025 08:36:40 +0100 Subject: [PATCH] Replace sidebar menu with collapsible category tree showing items --- config.php | 29 ++++++++++++++++ public/js/app.js | 16 +++++++++ public/style.css | 26 ++++++++++++++ templates/partials/sidebar.twig | 34 +++++++++++++------ .../inspectionProfiles/Project_Default.xml | 0 vendor/chillerlan/php-qrcode/LICENSE | 0 vendor/chillerlan/php-qrcode/README.md | 0 vendor/chillerlan/php-qrcode/composer.json | 0 .../php-qrcode/src/Data/AlphaNum.php | 0 .../chillerlan/php-qrcode/src/Data/Byte.php | 0 .../chillerlan/php-qrcode/src/Data/Kanji.php | 0 .../php-qrcode/src/Data/MaskPatternTester.php | 0 .../chillerlan/php-qrcode/src/Data/Number.php | 0 .../src/Data/QRCodeDataException.php | 0 .../php-qrcode/src/Data/QRDataAbstract.php | 0 .../php-qrcode/src/Data/QRDataInterface.php | 0 .../php-qrcode/src/Helpers/BitBuffer.php | 0 .../php-qrcode/src/Helpers/Polynomial.php | 0 .../src/Output/QRCodeOutputException.php | 0 .../php-qrcode/src/Output/QRFpdf.php | 0 .../php-qrcode/src/Output/QRImage.php | 0 .../php-qrcode/src/Output/QRImagick.php | 0 .../php-qrcode/src/Output/QRMarkup.php | 0 .../src/Output/QROutputAbstract.php | 0 .../src/Output/QROutputInterface.php | 0 .../php-qrcode/src/Output/QRString.php | 0 .../php-qrcode/src/QRCodeException.php | 0 .../chillerlan/php-qrcode/src/QROptions.php | 0 .../php-qrcode/src/QROptionsTrait.php | 0 .../chillerlan/php-settings-container/LICENSE | 0 .../php-settings-container/README.md | 0 .../php-settings-container/composer.json | 0 .../rules-magic-access.neon | 0 .../src/SettingsContainerAbstract.php | 0 .../src/SettingsContainerInterface.php | 0 vendor/guzzlehttp/psr7/CHANGELOG.md | 0 vendor/guzzlehttp/psr7/LICENSE | 0 vendor/guzzlehttp/psr7/README.md | 0 vendor/guzzlehttp/psr7/composer.json | 0 vendor/guzzlehttp/psr7/src/AppendStream.php | 0 vendor/guzzlehttp/psr7/src/BufferStream.php | 0 vendor/guzzlehttp/psr7/src/CachingStream.php | 0 vendor/guzzlehttp/psr7/src/DroppingStream.php | 0 .../src/Exception/MalformedUriException.php | 0 vendor/guzzlehttp/psr7/src/FnStream.php | 0 vendor/guzzlehttp/psr7/src/Header.php | 0 vendor/guzzlehttp/psr7/src/HttpFactory.php | 0 vendor/guzzlehttp/psr7/src/InflateStream.php | 0 vendor/guzzlehttp/psr7/src/LazyOpenStream.php | 0 vendor/guzzlehttp/psr7/src/LimitStream.php | 0 vendor/guzzlehttp/psr7/src/Message.php | 0 vendor/guzzlehttp/psr7/src/MessageTrait.php | 0 vendor/guzzlehttp/psr7/src/MimeType.php | 0 .../guzzlehttp/psr7/src/MultipartStream.php | 0 vendor/guzzlehttp/psr7/src/NoSeekStream.php | 0 vendor/guzzlehttp/psr7/src/PumpStream.php | 0 vendor/guzzlehttp/psr7/src/Query.php | 0 vendor/guzzlehttp/psr7/src/Request.php | 0 vendor/guzzlehttp/psr7/src/Response.php | 0 vendor/guzzlehttp/psr7/src/Rfc7230.php | 0 vendor/guzzlehttp/psr7/src/ServerRequest.php | 0 vendor/guzzlehttp/psr7/src/Stream.php | 0 .../psr7/src/StreamDecoratorTrait.php | 0 vendor/guzzlehttp/psr7/src/StreamWrapper.php | 0 vendor/guzzlehttp/psr7/src/UploadedFile.php | 0 vendor/guzzlehttp/psr7/src/Uri.php | 0 vendor/guzzlehttp/psr7/src/UriComparator.php | 0 vendor/guzzlehttp/psr7/src/UriNormalizer.php | 0 vendor/guzzlehttp/psr7/src/UriResolver.php | 0 vendor/guzzlehttp/psr7/src/Utils.php | 0 vendor/psr/http-factory/LICENSE | 0 vendor/psr/http-factory/README.md | 0 vendor/psr/http-factory/composer.json | 0 .../src/RequestFactoryInterface.php | 0 .../src/ResponseFactoryInterface.php | 0 .../src/ServerRequestFactoryInterface.php | 0 .../src/StreamFactoryInterface.php | 0 .../src/UploadedFileFactoryInterface.php | 0 .../http-factory/src/UriFactoryInterface.php | 0 vendor/psr/http-message/CHANGELOG.md | 0 vendor/psr/http-message/LICENSE | 0 vendor/psr/http-message/README.md | 0 vendor/psr/http-message/composer.json | 0 .../psr/http-message/docs/PSR7-Interfaces.md | 0 vendor/psr/http-message/docs/PSR7-Usage.md | 0 .../psr/http-message/src/MessageInterface.php | 0 .../psr/http-message/src/RequestInterface.php | 0 .../http-message/src/ResponseInterface.php | 0 .../src/ServerRequestInterface.php | 0 .../psr/http-message/src/StreamInterface.php | 0 .../src/UploadedFileInterface.php | 0 vendor/psr/http-message/src/UriInterface.php | 0 vendor/ralouphie/getallheaders/LICENSE | 0 vendor/ralouphie/getallheaders/README.md | 0 vendor/ralouphie/getallheaders/composer.json | 0 .../getallheaders/src/getallheaders.php | 0 96 files changed, 95 insertions(+), 10 deletions(-) mode change 100644 => 100755 vendor/chillerlan/php-qrcode/.idea/inspectionProfiles/Project_Default.xml mode change 100644 => 100755 vendor/chillerlan/php-qrcode/LICENSE mode change 100644 => 100755 vendor/chillerlan/php-qrcode/README.md mode change 100644 => 100755 vendor/chillerlan/php-qrcode/composer.json mode change 100644 => 100755 vendor/chillerlan/php-qrcode/src/Data/AlphaNum.php mode change 100644 => 100755 vendor/chillerlan/php-qrcode/src/Data/Byte.php mode change 100644 => 100755 vendor/chillerlan/php-qrcode/src/Data/Kanji.php mode change 100644 => 100755 vendor/chillerlan/php-qrcode/src/Data/MaskPatternTester.php mode change 100644 => 100755 vendor/chillerlan/php-qrcode/src/Data/Number.php mode change 100644 => 100755 vendor/chillerlan/php-qrcode/src/Data/QRCodeDataException.php mode change 100644 => 100755 vendor/chillerlan/php-qrcode/src/Data/QRDataAbstract.php mode change 100644 => 100755 vendor/chillerlan/php-qrcode/src/Data/QRDataInterface.php mode change 100644 => 100755 vendor/chillerlan/php-qrcode/src/Helpers/BitBuffer.php mode change 100644 => 100755 vendor/chillerlan/php-qrcode/src/Helpers/Polynomial.php mode change 100644 => 100755 vendor/chillerlan/php-qrcode/src/Output/QRCodeOutputException.php mode change 100644 => 100755 vendor/chillerlan/php-qrcode/src/Output/QRFpdf.php mode change 100644 => 100755 vendor/chillerlan/php-qrcode/src/Output/QRImage.php mode change 100644 => 100755 vendor/chillerlan/php-qrcode/src/Output/QRImagick.php mode change 100644 => 100755 vendor/chillerlan/php-qrcode/src/Output/QRMarkup.php mode change 100644 => 100755 vendor/chillerlan/php-qrcode/src/Output/QROutputAbstract.php mode change 100644 => 100755 vendor/chillerlan/php-qrcode/src/Output/QROutputInterface.php mode change 100644 => 100755 vendor/chillerlan/php-qrcode/src/Output/QRString.php mode change 100644 => 100755 vendor/chillerlan/php-qrcode/src/QRCodeException.php mode change 100644 => 100755 vendor/chillerlan/php-qrcode/src/QROptions.php mode change 100644 => 100755 vendor/chillerlan/php-qrcode/src/QROptionsTrait.php mode change 100644 => 100755 vendor/chillerlan/php-settings-container/LICENSE mode change 100644 => 100755 vendor/chillerlan/php-settings-container/README.md mode change 100644 => 100755 vendor/chillerlan/php-settings-container/composer.json mode change 100644 => 100755 vendor/chillerlan/php-settings-container/rules-magic-access.neon mode change 100644 => 100755 vendor/chillerlan/php-settings-container/src/SettingsContainerAbstract.php mode change 100644 => 100755 vendor/chillerlan/php-settings-container/src/SettingsContainerInterface.php mode change 100644 => 100755 vendor/guzzlehttp/psr7/CHANGELOG.md mode change 100644 => 100755 vendor/guzzlehttp/psr7/LICENSE mode change 100644 => 100755 vendor/guzzlehttp/psr7/README.md mode change 100644 => 100755 vendor/guzzlehttp/psr7/composer.json mode change 100644 => 100755 vendor/guzzlehttp/psr7/src/AppendStream.php mode change 100644 => 100755 vendor/guzzlehttp/psr7/src/BufferStream.php mode change 100644 => 100755 vendor/guzzlehttp/psr7/src/CachingStream.php mode change 100644 => 100755 vendor/guzzlehttp/psr7/src/DroppingStream.php mode change 100644 => 100755 vendor/guzzlehttp/psr7/src/Exception/MalformedUriException.php mode change 100644 => 100755 vendor/guzzlehttp/psr7/src/FnStream.php mode change 100644 => 100755 vendor/guzzlehttp/psr7/src/Header.php mode change 100644 => 100755 vendor/guzzlehttp/psr7/src/HttpFactory.php mode change 100644 => 100755 vendor/guzzlehttp/psr7/src/InflateStream.php mode change 100644 => 100755 vendor/guzzlehttp/psr7/src/LazyOpenStream.php mode change 100644 => 100755 vendor/guzzlehttp/psr7/src/LimitStream.php mode change 100644 => 100755 vendor/guzzlehttp/psr7/src/Message.php mode change 100644 => 100755 vendor/guzzlehttp/psr7/src/MessageTrait.php mode change 100644 => 100755 vendor/guzzlehttp/psr7/src/MimeType.php mode change 100644 => 100755 vendor/guzzlehttp/psr7/src/MultipartStream.php mode change 100644 => 100755 vendor/guzzlehttp/psr7/src/NoSeekStream.php mode change 100644 => 100755 vendor/guzzlehttp/psr7/src/PumpStream.php mode change 100644 => 100755 vendor/guzzlehttp/psr7/src/Query.php mode change 100644 => 100755 vendor/guzzlehttp/psr7/src/Request.php mode change 100644 => 100755 vendor/guzzlehttp/psr7/src/Response.php mode change 100644 => 100755 vendor/guzzlehttp/psr7/src/Rfc7230.php mode change 100644 => 100755 vendor/guzzlehttp/psr7/src/ServerRequest.php mode change 100644 => 100755 vendor/guzzlehttp/psr7/src/Stream.php mode change 100644 => 100755 vendor/guzzlehttp/psr7/src/StreamDecoratorTrait.php mode change 100644 => 100755 vendor/guzzlehttp/psr7/src/StreamWrapper.php mode change 100644 => 100755 vendor/guzzlehttp/psr7/src/UploadedFile.php mode change 100644 => 100755 vendor/guzzlehttp/psr7/src/Uri.php mode change 100644 => 100755 vendor/guzzlehttp/psr7/src/UriComparator.php mode change 100644 => 100755 vendor/guzzlehttp/psr7/src/UriNormalizer.php mode change 100644 => 100755 vendor/guzzlehttp/psr7/src/UriResolver.php mode change 100644 => 100755 vendor/guzzlehttp/psr7/src/Utils.php mode change 100644 => 100755 vendor/psr/http-factory/LICENSE mode change 100644 => 100755 vendor/psr/http-factory/README.md mode change 100644 => 100755 vendor/psr/http-factory/composer.json mode change 100644 => 100755 vendor/psr/http-factory/src/RequestFactoryInterface.php mode change 100644 => 100755 vendor/psr/http-factory/src/ResponseFactoryInterface.php mode change 100644 => 100755 vendor/psr/http-factory/src/ServerRequestFactoryInterface.php mode change 100644 => 100755 vendor/psr/http-factory/src/StreamFactoryInterface.php mode change 100644 => 100755 vendor/psr/http-factory/src/UploadedFileFactoryInterface.php mode change 100644 => 100755 vendor/psr/http-factory/src/UriFactoryInterface.php mode change 100644 => 100755 vendor/psr/http-message/CHANGELOG.md mode change 100644 => 100755 vendor/psr/http-message/LICENSE mode change 100644 => 100755 vendor/psr/http-message/README.md mode change 100644 => 100755 vendor/psr/http-message/composer.json mode change 100644 => 100755 vendor/psr/http-message/docs/PSR7-Interfaces.md mode change 100644 => 100755 vendor/psr/http-message/docs/PSR7-Usage.md mode change 100644 => 100755 vendor/psr/http-message/src/MessageInterface.php mode change 100644 => 100755 vendor/psr/http-message/src/RequestInterface.php mode change 100644 => 100755 vendor/psr/http-message/src/ResponseInterface.php mode change 100644 => 100755 vendor/psr/http-message/src/ServerRequestInterface.php mode change 100644 => 100755 vendor/psr/http-message/src/StreamInterface.php mode change 100644 => 100755 vendor/psr/http-message/src/UploadedFileInterface.php mode change 100644 => 100755 vendor/psr/http-message/src/UriInterface.php mode change 100644 => 100755 vendor/ralouphie/getallheaders/LICENSE mode change 100644 => 100755 vendor/ralouphie/getallheaders/README.md mode change 100644 => 100755 vendor/ralouphie/getallheaders/composer.json mode change 100644 => 100755 vendor/ralouphie/getallheaders/src/getallheaders.php diff --git a/config.php b/config.php index a216718..399aa48 100755 --- a/config.php +++ b/config.php @@ -45,3 +45,32 @@ $twig->addGlobal('app_name', APP_NAME); // Add translated confirm messages for JS $twig->addGlobal('delete_part_confirm', $translator->trans('Are you sure you want to delete this part?')); $twig->addGlobal('delete_category_confirm', $translator->trans('Are you sure you want to delete this category?')); + +// Build category tree for sidebar +$db = App\Database\Database::getInstance(); +$categories = App\Models\Category::getAll($db); +$items = App\Models\Item::getAll($db); + +function buildTree($categories, $items, $parentId = null) { + $tree = []; + foreach ($categories as $cat) { + if ($cat['parent_id'] == $parentId) { + $node = [ + 'id' => $cat['id'], + 'name' => $cat['name'], + 'children' => buildTree($categories, $items, $cat['id']), + 'items' => [] + ]; + foreach ($items as $item) { + if ($item['category_id'] == $cat['id']) { + $node['items'][] = $item; + } + } + $tree[] = $node; + } + } + return $tree; +} + +$categoryTree = buildTree($categories, $items); +$twig->addGlobal('category_tree', $categoryTree); diff --git a/public/js/app.js b/public/js/app.js index 95a8fac..a01debc 100755 --- a/public/js/app.js +++ b/public/js/app.js @@ -2,6 +2,22 @@ document.addEventListener('DOMContentLoaded', function() { const mainContent = document.getElementById('main-content'); const appName = document.querySelector('.navbar-brand').textContent; + // Global function for editing item from tree + window.editItem = function(id) { + // Create a mock button to reuse handleEditItem + const mockBtn = { getAttribute: (attr) => attr === 'data-id' ? id : null }; + handleEditItem.call(mockBtn); + }; + + // Function to toggle category children + window.toggleCategory = function(span) { + const li = span.parentElement; + const ul = li.querySelector('ul'); // First ul is children + if (ul) { + ul.style.display = ul.style.display === 'none' ? 'block' : 'none'; + } + }; + // --- Helper Functions --- function setPageTitle(title) { document.title = `${appName} - ${title}`; diff --git a/public/style.css b/public/style.css index e69de29..1a5efcb 100755 --- a/public/style.css +++ b/public/style.css @@ -0,0 +1,26 @@ +.category-tree, .category-tree ul { + list-style: none; + padding-left: 20px; +} + +.category-tree li { + margin: 5px 0; +} + +.category { + font-weight: bold; + cursor: pointer; +} + +.items { + padding-left: 10px; +} + +.item-link { + color: #007bff; + text-decoration: none; +} + +.item-link:hover { + text-decoration: underline; +} \ No newline at end of file diff --git a/templates/partials/sidebar.twig b/templates/partials/sidebar.twig index 051c5dd..bb9312d 100755 --- a/templates/partials/sidebar.twig +++ b/templates/partials/sidebar.twig @@ -1,13 +1,27 @@ {% autoescape %} -