diff --git a/collections.sqlite.old b/collections.sqlite.old new file mode 100644 index 0000000..240e16e Binary files /dev/null and b/collections.sqlite.old differ diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..7207508 --- /dev/null +++ b/public/favicon.ico @@ -0,0 +1,58 @@ +.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; +} + +/* Tree structure styling */ +.category-link { + font-weight: 600; + color: #495057 !important; + background-color: #f8f9fa !important; + border: 1px solid #dee2e6; + border-radius: 4px; + margin: 2px 0; +} + +.category-link:hover { + background-color: #e9ecef !important; + color: #212529 !important; +} + +.item-link { + font-weight: 400; + color: #6c757d !important; + background-color: transparent !important; + border-left: 3px solid #007bff; + margin-left: 8px; +} + +.item-link:hover { + background-color: #f8f9fa !important; + color: #007bff !important; +} + +.bi { + margin-right: 5px; +} \ No newline at end of file diff --git a/public/js/app.js.backup b/public/js/app.js.backup new file mode 100644 index 0000000..05684cc --- /dev/null +++ b/public/js/app.js.backup @@ -0,0 +1,537 @@ +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 tree nodes + window.toggleNode = function(element) { + const li = element.closest('li'); + const childUl = li.querySelector(':scope > ul'); + if (childUl) { + const isHidden = childUl.style.display === 'none'; + childUl.style.display = isHidden ? 'block' : 'none'; + + // Update the icon + const icon = element.querySelector('i'); + if (icon) { + if (isHidden) { + icon.className = 'bi bi-folder-fill text-warning'; + } else { + icon.className = 'bi bi-folder text-warning'; + } + } + } + }; + + // --- Helper Functions --- + function setPageTitle(title) { + document.title = `${appName} - ${title}`; + } + + function showLoading() { + mainContent.innerHTML = '
Huidige afbeelding:
Geen afbeelding
'; + } + // Populate category select + const categorySelect = document.getElementById('edit_item_category_id'); + categorySelect.innerHTML = ''; + fetch('/api/categories/list') + .then(resp => resp.json()) + .then(categories => { + categories.forEach(cat => { + const option = document.createElement('option'); + option.value = cat.id; + option.textContent = cat.path; + categorySelect.appendChild(option); + }); + categorySelect.value = data.category_id || ''; + const modal = new bootstrap.Modal(document.getElementById('editItemModal')); + modal.show(); + }); + } else { + alert('Part not found'); + } + }) + .catch(error => { + console.error('Error:', error); + alert('Error fetching part'); + }); + } + + function handleDeleteItem() { + const id = this.getAttribute('data-id'); + if (confirm(window.translations.deletePartConfirm)) { + fetch('/api/items/' + id, { + method: 'DELETE' + }) + .then(response => response.json()) + .then(data => { + if (data.success) { + this.closest('li').remove(); + } else { + alert(data.error || 'Error deleting part'); + } + }) + .catch(error => { + console.error('Error:', error); + alert('Error deleting part'); + }); + } + + function handleAddCategory() { + const formData = new FormData(this); + fetch('/api/categories', { + method: 'POST', + body: formData + }) + .then(response => response.json()) + .then(data => { + if (data.success) { + fetchContent('/categories', false); + } else { + alert(data.error || 'Error adding category'); + } + }) + .catch(error => { + console.error('Error:', error); + alert('Error adding category'); + }); + } + + function handleSaveEditItem() { + const id = document.getElementById('edit_item_id').value; + const name = document.getElementById('edit_item_name').value.trim(); + const description = document.getElementById('edit_item_description').value; + const categoryId = document.getElementById('edit_item_category_id').value; + const location = document.getElementById('edit_location').value.trim(); + const imageFile = document.getElementById('edit_image').files[0]; + + if (!name) { + alert('Part name is required'); + return; + } + + const formData = new FormData(); + formData.append('item_name', name); + formData.append('item_description', description); + formData.append('category_id', categoryId || ''); + formData.append('location', location); + if (imageFile) { + formData.append('image', imageFile); + } + + fetch('/api/items/' + id, { + method: 'POST', + body: formData + }) + .then(response => response.json()) + .then(data => { + if (data.success) { + const modalElement = document.getElementById('editItemModal'); + const modalInstance = bootstrap.Modal.getInstance(modalElement); + if (modalInstance) { + modalInstance.hide(); + } else { + modalElement.classList.remove('show'); + modalElement.style.display = 'none'; + document.body.classList.remove('modal-open'); + const backdrop = document.querySelector('.modal-backdrop'); + if (backdrop) backdrop.remove(); + } + fetchContent('/', false); + } else { + alert(data.error || 'Error updating part'); + } + }) + .catch(error => { + console.error('Update error:', error); + alert('Error updating part: ' + error.message); + }); + } + function handleSaveEditCategory() { + const id = document.getElementById('edit_category_id').value; + const name = document.getElementById('edit_category_name').value.trim(); + const parentId = document.getElementById('edit_parent_category_id').value; + + if (!name) { + alert('Category name is required'); + return; + } + + const data = { + category_name: name, + parent_category_id: parentId || null + }; + + fetch('/api/categories/' + id, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(data) + }) + .then(response => response.json()) + .then(data => { + if (data.success) { + const modalElement = document.getElementById('editCategoryModal'); + const modalInstance = bootstrap.Modal.getInstance(modalElement); + if (modalInstance) { + modalInstance.hide(); + } else { + modalElement.classList.remove('show'); + modalElement.style.display = 'none'; + document.body.classList.remove('modal-open'); + const backdrop = document.querySelector('.modal-backdrop'); + if (backdrop) backdrop.remove(); + } + fetchContent('/categories', false); + } else { + alert(data.error || 'Error updating category'); + } + }) + .catch(error => { + console.error('Update error:', error); + alert('Error updating category: ' + error.message); + }); + } + function handleEditCategory() { + const id = this.getAttribute('data-id'); + // Fetch current category data + fetch('/api/categories/' + id) + .then(response => { + if (!response.ok) { + throw new Error('HTTP ' + response.status + ': ' + response.statusText); + } + return response.json(); + }) + .then(data => { + if (data && !data.error) { + document.getElementById('edit_category_id').value = data.id; + document.getElementById('edit_category_name').value = data.name; + // Populate parent select, excluding current category + const parentSelect = document.getElementById('edit_parent_category_id'); + parentSelect.innerHTML = ''; + fetch('/api/categories/list') + .then(resp => resp.json()) + .then(categories => { + categories.forEach(cat => { + if (cat.id != data.id) { + const option = document.createElement('option'); + option.value = cat.id; + option.textContent = cat.path; + parentSelect.appendChild(option); + } + }); + parentSelect.value = data.parent_id || ''; + const modal = new bootstrap.Modal(document.getElementById('editCategoryModal')); + modal.show(); + }); + } else { + alert(data.error || 'Category not found'); + } + }) + .catch(error => { + console.error('Error:', error); + alert('Error fetching category: ' + error.message); + }); + } + + function handleDeleteCategory() { + const id = this.getAttribute('data-id'); + if (confirm(window.translations.deleteCategoryConfirm)) { + fetch('/api/categories/' + id, { + method: 'DELETE' + }) + .then(response => response.json()) + .then(data => { + if (data.success) { + this.closest('li').remove(); + } else { + alert(data.error || 'Error deleting category'); + } + }) + .catch(error => { + console.error('Error:', error); + alert('Error deleting category'); + }); + } + } +}); diff --git a/public/uploads/69149ec32f098_IMG_3901.jpeg b/public/uploads/69149ec32f098_IMG_3901.jpeg new file mode 100644 index 0000000..4b12fcd Binary files /dev/null and b/public/uploads/69149ec32f098_IMG_3901.jpeg differ diff --git a/public/uploads/69149f1c1e92a_pexels-marta-nogueira-589022975-17151646.jpg b/public/uploads/69149f1c1e92a_pexels-marta-nogueira-589022975-17151646.jpg new file mode 100644 index 0000000..2a8682e Binary files /dev/null and b/public/uploads/69149f1c1e92a_pexels-marta-nogueira-589022975-17151646.jpg differ diff --git a/public/uploads/69149f23209a8_pexels-rodrigo-ortega-2044210904-29161722.jpg b/public/uploads/69149f23209a8_pexels-rodrigo-ortega-2044210904-29161722.jpg new file mode 100644 index 0000000..5c984ad Binary files /dev/null and b/public/uploads/69149f23209a8_pexels-rodrigo-ortega-2044210904-29161722.jpg differ diff --git a/public/uploads/6914a2f617afa_pexels-rodrigo-ortega-2044210904-29161722.jpg b/public/uploads/6914a2f617afa_pexels-rodrigo-ortega-2044210904-29161722.jpg new file mode 100644 index 0000000..5c984ad Binary files /dev/null and b/public/uploads/6914a2f617afa_pexels-rodrigo-ortega-2044210904-29161722.jpg differ diff --git a/public/uploads/6914a5e96e286_pexels-rodrigo-ortega-2044210904-29161722.jpg b/public/uploads/6914a5e96e286_pexels-rodrigo-ortega-2044210904-29161722.jpg new file mode 100644 index 0000000..5c984ad Binary files /dev/null and b/public/uploads/6914a5e96e286_pexels-rodrigo-ortega-2044210904-29161722.jpg differ diff --git a/public/uploads/6914a65007e06_pexels-marta-nogueira-589022975-17151646.jpg b/public/uploads/6914a65007e06_pexels-marta-nogueira-589022975-17151646.jpg new file mode 100644 index 0000000..2a8682e Binary files /dev/null and b/public/uploads/6914a65007e06_pexels-marta-nogueira-589022975-17151646.jpg differ diff --git a/public/uploads/6914aa822cf9c_pexels-rodrigo-ortega-2044210904-29161722.jpg b/public/uploads/6914aa822cf9c_pexels-rodrigo-ortega-2044210904-29161722.jpg new file mode 100644 index 0000000..5c984ad Binary files /dev/null and b/public/uploads/6914aa822cf9c_pexels-rodrigo-ortega-2044210904-29161722.jpg differ diff --git a/public/uploads/6914ab80de508_IMG_3901.jpeg b/public/uploads/6914ab80de508_IMG_3901.jpeg new file mode 100644 index 0000000..4b12fcd Binary files /dev/null and b/public/uploads/6914ab80de508_IMG_3901.jpeg differ diff --git a/public/uploads/6914aba8ca17f_IMG_3901.jpeg b/public/uploads/6914aba8ca17f_IMG_3901.jpeg new file mode 100644 index 0000000..4b12fcd Binary files /dev/null and b/public/uploads/6914aba8ca17f_IMG_3901.jpeg differ diff --git a/public/uploads/6914b0c9b5723_pexels-rodrigo-ortega-2044210904-29161722.jpg b/public/uploads/6914b0c9b5723_pexels-rodrigo-ortega-2044210904-29161722.jpg new file mode 100644 index 0000000..5c984ad Binary files /dev/null and b/public/uploads/6914b0c9b5723_pexels-rodrigo-ortega-2044210904-29161722.jpg differ diff --git a/public/uploads/6914b0fc0507a_pexels-rodrigo-ortega-2044210904-29161722.jpg b/public/uploads/6914b0fc0507a_pexels-rodrigo-ortega-2044210904-29161722.jpg new file mode 100644 index 0000000..5c984ad Binary files /dev/null and b/public/uploads/6914b0fc0507a_pexels-rodrigo-ortega-2044210904-29161722.jpg differ diff --git a/public/uploads/6914b10675315_r_D.jpg b/public/uploads/6914b10675315_r_D.jpg new file mode 100644 index 0000000..7a25cd0 Binary files /dev/null and b/public/uploads/6914b10675315_r_D.jpg differ diff --git a/public/uploads/6914b1160357d_r_D.jpg b/public/uploads/6914b1160357d_r_D.jpg new file mode 100644 index 0000000..7a25cd0 Binary files /dev/null and b/public/uploads/6914b1160357d_r_D.jpg differ diff --git a/public/uploads/qr/06F0FF92.svg b/public/uploads/qr/06F0FF92.svg new file mode 100644 index 0000000..a268aec --- /dev/null +++ b/public/uploads/qr/06F0FF92.svg @@ -0,0 +1,4 @@ + + diff --git a/public/uploads/qr/0FBBA098.svg b/public/uploads/qr/0FBBA098.svg new file mode 100644 index 0000000..506a5ba --- /dev/null +++ b/public/uploads/qr/0FBBA098.svg @@ -0,0 +1,4 @@ + + diff --git a/public/uploads/qr/155488D0.svg b/public/uploads/qr/155488D0.svg new file mode 100644 index 0000000..46f1035 --- /dev/null +++ b/public/uploads/qr/155488D0.svg @@ -0,0 +1,4 @@ + + diff --git a/public/uploads/qr/7B1EC871.svg b/public/uploads/qr/7B1EC871.svg new file mode 100644 index 0000000..16c20b3 --- /dev/null +++ b/public/uploads/qr/7B1EC871.svg @@ -0,0 +1,4 @@ + + diff --git a/public/uploads/qr/80A9EBF2.svg b/public/uploads/qr/80A9EBF2.svg new file mode 100644 index 0000000..1c27bb6 --- /dev/null +++ b/public/uploads/qr/80A9EBF2.svg @@ -0,0 +1,4 @@ + + diff --git a/public/uploads/qr/A28E2207.svg b/public/uploads/qr/A28E2207.svg new file mode 100644 index 0000000..0d784f8 --- /dev/null +++ b/public/uploads/qr/A28E2207.svg @@ -0,0 +1,4 @@ + + diff --git a/public/uploads/qr/BEB4BE8F.svg b/public/uploads/qr/BEB4BE8F.svg new file mode 100644 index 0000000..ddd2e6c --- /dev/null +++ b/public/uploads/qr/BEB4BE8F.svg @@ -0,0 +1,4 @@ + + diff --git a/public/uploads/qr/C2254256.svg b/public/uploads/qr/C2254256.svg new file mode 100644 index 0000000..d4d2119 --- /dev/null +++ b/public/uploads/qr/C2254256.svg @@ -0,0 +1,4 @@ + + diff --git a/public/uploads/qr/ED39CE82.svg b/public/uploads/qr/ED39CE82.svg new file mode 100644 index 0000000..81171af --- /dev/null +++ b/public/uploads/qr/ED39CE82.svg @@ -0,0 +1,4 @@ + +