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 %}
-
- -
- {{ trans('Overview') }}
-
- -
- {{ trans('Categories') }}
-
- -
- {{ trans('Parts') }}
-
+{% macro render_node(node) %}
+-
+ {{ node.name }}
+ {% if node.children %}
+
+ {% for child in node.children %}
+ {{ _self.render_node(child) }}
+ {% endfor %}
+
+ {% endif %}
+ {% if node.items %}
+
+ {% endif %}
+
+{% endmacro %}
+
+
+{% for node in category_tree %}
+ {{ _self.render_node(node) }}
+{% endfor %}
{% endautoescape %}
\ No newline at end of file
diff --git a/vendor/chillerlan/php-qrcode/.idea/inspectionProfiles/Project_Default.xml b/vendor/chillerlan/php-qrcode/.idea/inspectionProfiles/Project_Default.xml
old mode 100644
new mode 100755
diff --git a/vendor/chillerlan/php-qrcode/LICENSE b/vendor/chillerlan/php-qrcode/LICENSE
old mode 100644
new mode 100755
diff --git a/vendor/chillerlan/php-qrcode/README.md b/vendor/chillerlan/php-qrcode/README.md
old mode 100644
new mode 100755
diff --git a/vendor/chillerlan/php-qrcode/composer.json b/vendor/chillerlan/php-qrcode/composer.json
old mode 100644
new mode 100755
diff --git a/vendor/chillerlan/php-qrcode/src/Data/AlphaNum.php b/vendor/chillerlan/php-qrcode/src/Data/AlphaNum.php
old mode 100644
new mode 100755
diff --git a/vendor/chillerlan/php-qrcode/src/Data/Byte.php b/vendor/chillerlan/php-qrcode/src/Data/Byte.php
old mode 100644
new mode 100755
diff --git a/vendor/chillerlan/php-qrcode/src/Data/Kanji.php b/vendor/chillerlan/php-qrcode/src/Data/Kanji.php
old mode 100644
new mode 100755
diff --git a/vendor/chillerlan/php-qrcode/src/Data/MaskPatternTester.php b/vendor/chillerlan/php-qrcode/src/Data/MaskPatternTester.php
old mode 100644
new mode 100755
diff --git a/vendor/chillerlan/php-qrcode/src/Data/Number.php b/vendor/chillerlan/php-qrcode/src/Data/Number.php
old mode 100644
new mode 100755
diff --git a/vendor/chillerlan/php-qrcode/src/Data/QRCodeDataException.php b/vendor/chillerlan/php-qrcode/src/Data/QRCodeDataException.php
old mode 100644
new mode 100755
diff --git a/vendor/chillerlan/php-qrcode/src/Data/QRDataAbstract.php b/vendor/chillerlan/php-qrcode/src/Data/QRDataAbstract.php
old mode 100644
new mode 100755
diff --git a/vendor/chillerlan/php-qrcode/src/Data/QRDataInterface.php b/vendor/chillerlan/php-qrcode/src/Data/QRDataInterface.php
old mode 100644
new mode 100755
diff --git a/vendor/chillerlan/php-qrcode/src/Helpers/BitBuffer.php b/vendor/chillerlan/php-qrcode/src/Helpers/BitBuffer.php
old mode 100644
new mode 100755
diff --git a/vendor/chillerlan/php-qrcode/src/Helpers/Polynomial.php b/vendor/chillerlan/php-qrcode/src/Helpers/Polynomial.php
old mode 100644
new mode 100755
diff --git a/vendor/chillerlan/php-qrcode/src/Output/QRCodeOutputException.php b/vendor/chillerlan/php-qrcode/src/Output/QRCodeOutputException.php
old mode 100644
new mode 100755
diff --git a/vendor/chillerlan/php-qrcode/src/Output/QRFpdf.php b/vendor/chillerlan/php-qrcode/src/Output/QRFpdf.php
old mode 100644
new mode 100755
diff --git a/vendor/chillerlan/php-qrcode/src/Output/QRImage.php b/vendor/chillerlan/php-qrcode/src/Output/QRImage.php
old mode 100644
new mode 100755
diff --git a/vendor/chillerlan/php-qrcode/src/Output/QRImagick.php b/vendor/chillerlan/php-qrcode/src/Output/QRImagick.php
old mode 100644
new mode 100755
diff --git a/vendor/chillerlan/php-qrcode/src/Output/QRMarkup.php b/vendor/chillerlan/php-qrcode/src/Output/QRMarkup.php
old mode 100644
new mode 100755
diff --git a/vendor/chillerlan/php-qrcode/src/Output/QROutputAbstract.php b/vendor/chillerlan/php-qrcode/src/Output/QROutputAbstract.php
old mode 100644
new mode 100755
diff --git a/vendor/chillerlan/php-qrcode/src/Output/QROutputInterface.php b/vendor/chillerlan/php-qrcode/src/Output/QROutputInterface.php
old mode 100644
new mode 100755
diff --git a/vendor/chillerlan/php-qrcode/src/Output/QRString.php b/vendor/chillerlan/php-qrcode/src/Output/QRString.php
old mode 100644
new mode 100755
diff --git a/vendor/chillerlan/php-qrcode/src/QRCodeException.php b/vendor/chillerlan/php-qrcode/src/QRCodeException.php
old mode 100644
new mode 100755
diff --git a/vendor/chillerlan/php-qrcode/src/QROptions.php b/vendor/chillerlan/php-qrcode/src/QROptions.php
old mode 100644
new mode 100755
diff --git a/vendor/chillerlan/php-qrcode/src/QROptionsTrait.php b/vendor/chillerlan/php-qrcode/src/QROptionsTrait.php
old mode 100644
new mode 100755
diff --git a/vendor/chillerlan/php-settings-container/LICENSE b/vendor/chillerlan/php-settings-container/LICENSE
old mode 100644
new mode 100755
diff --git a/vendor/chillerlan/php-settings-container/README.md b/vendor/chillerlan/php-settings-container/README.md
old mode 100644
new mode 100755
diff --git a/vendor/chillerlan/php-settings-container/composer.json b/vendor/chillerlan/php-settings-container/composer.json
old mode 100644
new mode 100755
diff --git a/vendor/chillerlan/php-settings-container/rules-magic-access.neon b/vendor/chillerlan/php-settings-container/rules-magic-access.neon
old mode 100644
new mode 100755
diff --git a/vendor/chillerlan/php-settings-container/src/SettingsContainerAbstract.php b/vendor/chillerlan/php-settings-container/src/SettingsContainerAbstract.php
old mode 100644
new mode 100755
diff --git a/vendor/chillerlan/php-settings-container/src/SettingsContainerInterface.php b/vendor/chillerlan/php-settings-container/src/SettingsContainerInterface.php
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/CHANGELOG.md b/vendor/guzzlehttp/psr7/CHANGELOG.md
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/LICENSE b/vendor/guzzlehttp/psr7/LICENSE
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/README.md b/vendor/guzzlehttp/psr7/README.md
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/composer.json b/vendor/guzzlehttp/psr7/composer.json
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/src/AppendStream.php b/vendor/guzzlehttp/psr7/src/AppendStream.php
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/src/BufferStream.php b/vendor/guzzlehttp/psr7/src/BufferStream.php
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/src/CachingStream.php b/vendor/guzzlehttp/psr7/src/CachingStream.php
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/src/DroppingStream.php b/vendor/guzzlehttp/psr7/src/DroppingStream.php
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/src/Exception/MalformedUriException.php b/vendor/guzzlehttp/psr7/src/Exception/MalformedUriException.php
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/src/FnStream.php b/vendor/guzzlehttp/psr7/src/FnStream.php
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/src/Header.php b/vendor/guzzlehttp/psr7/src/Header.php
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/src/HttpFactory.php b/vendor/guzzlehttp/psr7/src/HttpFactory.php
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/src/InflateStream.php b/vendor/guzzlehttp/psr7/src/InflateStream.php
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/src/LazyOpenStream.php b/vendor/guzzlehttp/psr7/src/LazyOpenStream.php
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/src/LimitStream.php b/vendor/guzzlehttp/psr7/src/LimitStream.php
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/src/Message.php b/vendor/guzzlehttp/psr7/src/Message.php
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/src/MessageTrait.php b/vendor/guzzlehttp/psr7/src/MessageTrait.php
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/src/MimeType.php b/vendor/guzzlehttp/psr7/src/MimeType.php
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/src/MultipartStream.php b/vendor/guzzlehttp/psr7/src/MultipartStream.php
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/src/NoSeekStream.php b/vendor/guzzlehttp/psr7/src/NoSeekStream.php
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/src/PumpStream.php b/vendor/guzzlehttp/psr7/src/PumpStream.php
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/src/Query.php b/vendor/guzzlehttp/psr7/src/Query.php
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/src/Request.php b/vendor/guzzlehttp/psr7/src/Request.php
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/src/Response.php b/vendor/guzzlehttp/psr7/src/Response.php
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/src/Rfc7230.php b/vendor/guzzlehttp/psr7/src/Rfc7230.php
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/src/ServerRequest.php b/vendor/guzzlehttp/psr7/src/ServerRequest.php
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/src/Stream.php b/vendor/guzzlehttp/psr7/src/Stream.php
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/src/StreamDecoratorTrait.php b/vendor/guzzlehttp/psr7/src/StreamDecoratorTrait.php
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/src/StreamWrapper.php b/vendor/guzzlehttp/psr7/src/StreamWrapper.php
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/src/UploadedFile.php b/vendor/guzzlehttp/psr7/src/UploadedFile.php
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/src/Uri.php b/vendor/guzzlehttp/psr7/src/Uri.php
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/src/UriComparator.php b/vendor/guzzlehttp/psr7/src/UriComparator.php
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/src/UriNormalizer.php b/vendor/guzzlehttp/psr7/src/UriNormalizer.php
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/src/UriResolver.php b/vendor/guzzlehttp/psr7/src/UriResolver.php
old mode 100644
new mode 100755
diff --git a/vendor/guzzlehttp/psr7/src/Utils.php b/vendor/guzzlehttp/psr7/src/Utils.php
old mode 100644
new mode 100755
diff --git a/vendor/psr/http-factory/LICENSE b/vendor/psr/http-factory/LICENSE
old mode 100644
new mode 100755
diff --git a/vendor/psr/http-factory/README.md b/vendor/psr/http-factory/README.md
old mode 100644
new mode 100755
diff --git a/vendor/psr/http-factory/composer.json b/vendor/psr/http-factory/composer.json
old mode 100644
new mode 100755
diff --git a/vendor/psr/http-factory/src/RequestFactoryInterface.php b/vendor/psr/http-factory/src/RequestFactoryInterface.php
old mode 100644
new mode 100755
diff --git a/vendor/psr/http-factory/src/ResponseFactoryInterface.php b/vendor/psr/http-factory/src/ResponseFactoryInterface.php
old mode 100644
new mode 100755
diff --git a/vendor/psr/http-factory/src/ServerRequestFactoryInterface.php b/vendor/psr/http-factory/src/ServerRequestFactoryInterface.php
old mode 100644
new mode 100755
diff --git a/vendor/psr/http-factory/src/StreamFactoryInterface.php b/vendor/psr/http-factory/src/StreamFactoryInterface.php
old mode 100644
new mode 100755
diff --git a/vendor/psr/http-factory/src/UploadedFileFactoryInterface.php b/vendor/psr/http-factory/src/UploadedFileFactoryInterface.php
old mode 100644
new mode 100755
diff --git a/vendor/psr/http-factory/src/UriFactoryInterface.php b/vendor/psr/http-factory/src/UriFactoryInterface.php
old mode 100644
new mode 100755
diff --git a/vendor/psr/http-message/CHANGELOG.md b/vendor/psr/http-message/CHANGELOG.md
old mode 100644
new mode 100755
diff --git a/vendor/psr/http-message/LICENSE b/vendor/psr/http-message/LICENSE
old mode 100644
new mode 100755
diff --git a/vendor/psr/http-message/README.md b/vendor/psr/http-message/README.md
old mode 100644
new mode 100755
diff --git a/vendor/psr/http-message/composer.json b/vendor/psr/http-message/composer.json
old mode 100644
new mode 100755
diff --git a/vendor/psr/http-message/docs/PSR7-Interfaces.md b/vendor/psr/http-message/docs/PSR7-Interfaces.md
old mode 100644
new mode 100755
diff --git a/vendor/psr/http-message/docs/PSR7-Usage.md b/vendor/psr/http-message/docs/PSR7-Usage.md
old mode 100644
new mode 100755
diff --git a/vendor/psr/http-message/src/MessageInterface.php b/vendor/psr/http-message/src/MessageInterface.php
old mode 100644
new mode 100755
diff --git a/vendor/psr/http-message/src/RequestInterface.php b/vendor/psr/http-message/src/RequestInterface.php
old mode 100644
new mode 100755
diff --git a/vendor/psr/http-message/src/ResponseInterface.php b/vendor/psr/http-message/src/ResponseInterface.php
old mode 100644
new mode 100755
diff --git a/vendor/psr/http-message/src/ServerRequestInterface.php b/vendor/psr/http-message/src/ServerRequestInterface.php
old mode 100644
new mode 100755
diff --git a/vendor/psr/http-message/src/StreamInterface.php b/vendor/psr/http-message/src/StreamInterface.php
old mode 100644
new mode 100755
diff --git a/vendor/psr/http-message/src/UploadedFileInterface.php b/vendor/psr/http-message/src/UploadedFileInterface.php
old mode 100644
new mode 100755
diff --git a/vendor/psr/http-message/src/UriInterface.php b/vendor/psr/http-message/src/UriInterface.php
old mode 100644
new mode 100755
diff --git a/vendor/ralouphie/getallheaders/LICENSE b/vendor/ralouphie/getallheaders/LICENSE
old mode 100644
new mode 100755
diff --git a/vendor/ralouphie/getallheaders/README.md b/vendor/ralouphie/getallheaders/README.md
old mode 100644
new mode 100755
diff --git a/vendor/ralouphie/getallheaders/composer.json b/vendor/ralouphie/getallheaders/composer.json
old mode 100644
new mode 100755
diff --git a/vendor/ralouphie/getallheaders/src/getallheaders.php b/vendor/ralouphie/getallheaders/src/getallheaders.php
old mode 100644
new mode 100755