first commit
This commit is contained in:
81
templates/categories.twig
Executable file
81
templates/categories.twig
Executable file
@@ -0,0 +1,81 @@
|
||||
{% autoescape %}
|
||||
<h1>{{ trans('Categories Overview') }}</h1>
|
||||
|
||||
<!-- Add Category Form -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">{{ trans('Manage Categories') }}</div>
|
||||
<div class="card-body">
|
||||
<form id="addCategoryForm">
|
||||
<div class="mb-3">
|
||||
<label for="new_category_name" class="form-label">{{ trans('Category Name') }}</label>
|
||||
<input type="text" class="form-control" id="new_category_name" name="new_category_name" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="parent_category_id" class="form-label">{{ trans('Parent Category') }} ({{ trans('Optional') }})</label>
|
||||
<select class="form-select" id="parent_category_id" name="parent_category_id">
|
||||
<option value="">{{ trans('-- No Parent --') }}</option>
|
||||
{% for category in categories %}
|
||||
<option value="{{ category.id }}">{{ category.path }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">{{ trans('Add Category') }}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Categories List -->
|
||||
<h2>{{ trans('All Categories') }}</h2>
|
||||
<ul id="categoriesList" class="list-group">
|
||||
{% if categories %}
|
||||
{% for category in categories %}
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<strong>{{ category.path }}</strong>
|
||||
</div>
|
||||
<div>
|
||||
<button class="btn btn-sm btn-warning me-2 edit-category-btn" data-id="{{ category.id }}">Edit</button>
|
||||
<button class="btn btn-sm btn-danger delete-category-btn" data-id="{{ category.id }}">Delete</button>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<li class="list-group-item">{{ trans('No categories found.') }}</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
<!-- Edit Category Modal -->
|
||||
<div class="modal fade" id="editCategoryModal" tabindex="-1" aria-labelledby="editCategoryModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="editCategoryModalLabel">{{ trans('Edit Category') }}</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="editCategoryForm">
|
||||
<input type="hidden" id="edit_category_id" name="id">
|
||||
<div class="mb-3">
|
||||
<label for="edit_category_name" class="form-label">{{ trans('Category Name') }}</label>
|
||||
<input type="text" class="form-control" id="edit_category_name" name="category_name" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="edit_parent_category_id" class="form-label">{{ trans('Parent Category') }} ({{ trans('Optional') }})</label>
|
||||
<select class="form-select" id="edit_parent_category_id" name="parent_category_id">
|
||||
<option value="">{{ trans('-- No Parent --') }}</option>
|
||||
{% for category in categories %}
|
||||
<option value="{{ category.id }}">{{ category.path }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ trans('Cancel') }}</button>
|
||||
<button type="button" class="btn btn-primary" id="saveEditCategoryBtn">{{ trans('Save Changes') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endautoescape %}
|
||||
152
templates/index.mustache
Executable file
152
templates/index.mustache
Executable file
@@ -0,0 +1,152 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Collection Manager - Add Item</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Add New Item</h1>
|
||||
|
||||
<nav>
|
||||
<a href="index.php">Add Item</a> | <a href="search.php">Search/Overview</a>
|
||||
</nav>
|
||||
|
||||
<form action="index.php" method="post">
|
||||
<input type="hidden" name="action" value="add_item">
|
||||
<div>
|
||||
<label for="item_name">Item Name:</label>
|
||||
<input type="text" id="item_name" name="item_name" required>
|
||||
</div>
|
||||
<div>
|
||||
<label for="item_description">Description:</label>
|
||||
<textarea id="item_description" name="item_description" rows="3"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<label for="category_id">Category:</label>
|
||||
<select id="category_id" name="category_id" required>
|
||||
<option value="">-- Select Category --</option>
|
||||
{{#categories}}
|
||||
<option value="{{id}}">{{name}}</option>
|
||||
{{/categories}}
|
||||
</select>
|
||||
<button type="button" id="showAddCategoryFormBtn">+</button>
|
||||
</div>
|
||||
<div id="addCategoryForm" style="display: none;">
|
||||
<label for="new_category_name">New Category:</label>
|
||||
<input type="text" id="new_category_name" name="new_category_name">
|
||||
<button type="button" id="addCategoryBtn">Add Category</button>
|
||||
</div>
|
||||
<button type="submit">Add Item</button>
|
||||
</form>
|
||||
|
||||
<h2>Existing Items</h2>
|
||||
<ul>
|
||||
{{#items}}
|
||||
<li>
|
||||
<h3>{{name}}</h3>
|
||||
<p>Category: {{category_name}}</p>
|
||||
<p>{{description}}</p>
|
||||
</li>
|
||||
{{/items}}
|
||||
{{^items}}
|
||||
<li>No items yet.</li>
|
||||
{{/items}}
|
||||
</ul>
|
||||
|
||||
<h2>Categories</h2>
|
||||
<ul>
|
||||
{{#categories}}
|
||||
<li>{{name}}</li>
|
||||
{{/categories}}
|
||||
</ul>
|
||||
<div class="add-category-section">
|
||||
<label for="new_category_name_direct">New Category:</label>
|
||||
<input type="text" id="new_category_name_direct" name="new_category_name_direct">
|
||||
<button id="addCategoryDirectBtn">Add Category</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// JavaScript for dynamic category adding and potentially drag/drop later
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const showAddCategoryFormBtn = document.getElementById('showAddCategoryFormBtn');
|
||||
const addCategoryForm = document.getElementById('addCategoryForm');
|
||||
const newCategoryNameInput = document.getElementById('new_category_name');
|
||||
const addCategoryBtn = document.getElementById('addCategoryBtn');
|
||||
const newCategoryNameDirectInput = document.getElementById('new_category_name_direct');
|
||||
const addCategoryDirectBtn = document.getElementById('addCategoryDirectBtn');
|
||||
|
||||
showAddCategoryFormBtn.addEventListener('click', function() { addCategoryForm.style.display = addCategoryForm.style.display === 'none' ? 'block' : 'none'; });
|
||||
|
||||
function addCategory(name, isDirect) {
|
||||
const formData = new FormData();
|
||||
formData.append('action', 'add_category');
|
||||
formData.append('category_name', name);
|
||||
|
||||
fetch(window.location.href, {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
alert(data.message);
|
||||
if (data.success) {
|
||||
if (isDirect) {
|
||||
newCategoryNameDirectInput.value = '';
|
||||
} else {
|
||||
newCategoryNameInput.value = '';
|
||||
addCategoryForm.style.display = 'none';
|
||||
}
|
||||
// Refresh categories
|
||||
fetchCategories();
|
||||
}
|
||||
})
|
||||
.catch(error => console.error('Error:', error));
|
||||
}
|
||||
|
||||
addCategoryBtn.addEventListener('click', () => addCategory(newCategoryNameInput.value, false));
|
||||
addCategoryDirectBtn.addEventListener('click', () => addCategory(newCategoryNameDirectInput.value, true));
|
||||
|
||||
// Function to fetch and update categories in UI
|
||||
function fetchCategories() {
|
||||
fetch(window.location.href + '?action=get_categories')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success && data.categories) {
|
||||
const categorySelect = document.getElementById('category_id');
|
||||
const searchCategorySelect = document.getElementById('search_category_id'); // Assuming this exists on search page
|
||||
const categoryListUl = document.querySelector('.category-management ul'); // Assuming this exists on index page
|
||||
|
||||
// Clear existing options/list items
|
||||
categorySelect.innerHTML = '<option value="">-- Select Category --</option>';
|
||||
if (searchCategorySelect) searchCategorySelect.innerHTML = '<option value="">-- All Categories --</option>';
|
||||
if (categoryListUl) categoryListUl.innerHTML = '';
|
||||
|
||||
data.categories.forEach(cat => {
|
||||
const opt1 = document.createElement('option');
|
||||
opt1.value = cat.id;
|
||||
opt1.textContent = cat.name;
|
||||
categorySelect.appendChild(opt1);
|
||||
|
||||
if (searchCategorySelect) {
|
||||
const opt2 = document.createElement('option');
|
||||
opt2.value = cat.id;
|
||||
opt2.textContent = cat.name;
|
||||
searchCategorySelect.appendChild(opt2);
|
||||
}
|
||||
|
||||
if (categoryListUl) {
|
||||
const li = document.createElement('li');
|
||||
li.textContent = cat.name;
|
||||
categoryListUl.appendChild(li);
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(error => console.error('Error fetching categories:', error));
|
||||
}
|
||||
|
||||
// Initial fetch
|
||||
fetchCategories();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
90
templates/items.twig
Executable file
90
templates/items.twig
Executable file
@@ -0,0 +1,90 @@
|
||||
{% autoescape %}
|
||||
<h1>{{ trans('Parts Overview') }}</h1>
|
||||
|
||||
<!-- Filter and Search Form -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">{{ trans('Filter and Search') }}</div>
|
||||
<div class="card-body">
|
||||
<form id="filterForm">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label for="search" class="form-label">{{ trans('Search') }}</label>
|
||||
<input type="text" class="form-control" id="search" name="search" value="{{ search }}" placeholder="{{ trans('Search by name') }}">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label for="category_filter" class="form-label">{{ trans('Category') }}</label>
|
||||
<select class="form-select" id="category_filter" name="category_id">
|
||||
<option value="">{{ trans('-- All Categories --') }}</option>
|
||||
{% for category in categories %}
|
||||
<option value="{{ category.id }}" {% if selected_category == category.id %}selected{% endif %}>{{ category.path }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2 d-flex align-items-end">
|
||||
<button type="submit" class="btn btn-primary">{{ trans('Filter') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Items List -->
|
||||
<ul id="itemsList" class="list-group mb-4">
|
||||
{% if items %}
|
||||
{% for item in items %}
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h5>{{ item.name }}</h5>
|
||||
<p class="text-muted">{{ trans('Category') }}: {{ item.category_name ?: trans('Uncategorized') }}</p>
|
||||
<p>{{ item.description }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<button class="btn btn-sm btn-warning me-2 edit-btn" data-id="{{ item.id }}">Edit</button>
|
||||
<button class="btn btn-sm btn-danger delete-btn" data-id="{{ item.id }}">Delete</button>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<li class="list-group-item">{{ trans('No items found.') }}</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
<!-- Edit Item Modal -->
|
||||
<div class="modal fade" id="editItemModal" tabindex="-1" aria-labelledby="editItemModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="editItemModalLabel">{{ trans('Edit Part') }}</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="editItemForm">
|
||||
<input type="hidden" id="edit_item_id" name="id">
|
||||
<div class="mb-3">
|
||||
<label for="edit_item_name" class="form-label">{{ trans('Part Name') }}</label>
|
||||
<input type="text" class="form-control" id="edit_item_name" name="item_name" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="edit_item_description" class="form-label">{{ trans('Description') }}</label>
|
||||
<textarea class="form-control" id="edit_item_description" name="item_description" rows="3"></textarea>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="edit_item_category_id" class="form-label">{{ trans('Category') }}</label>
|
||||
<select class="form-select" id="edit_item_category_id" name="category_id">
|
||||
<option value="">{{ trans('-- Select Category --') }}</option>
|
||||
{% for category in categories %}
|
||||
<option value="{{ category.id }}">{{ category.path }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ trans('Cancel') }}</button>
|
||||
<button type="button" class="btn btn-primary" id="saveEditItemBtn">{{ trans('Save Changes') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endautoescape %}
|
||||
37
templates/layout.twig
Executable file
37
templates/layout.twig
Executable file
@@ -0,0 +1,37 @@
|
||||
{% autoescape %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ current_locale }}">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{ app_name }}</title>
|
||||
<!-- Bootstrap CSS -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="style.css"> <!-- Custom CSS -->
|
||||
</head>
|
||||
<body>
|
||||
|
||||
{% include 'partials/navbar.twig' %}
|
||||
|
||||
<div class="container-fluid mt-4">
|
||||
<div class="row">
|
||||
<div class="col-md-3 col-lg-2 d-none d-md-block sidebar">
|
||||
{% include 'partials/sidebar.twig' %}
|
||||
</div>
|
||||
<div class="col-md-9 col-lg-10 content">
|
||||
<div id="main-content">
|
||||
{% block content %}
|
||||
<!-- Content will be loaded here via AJAX -->
|
||||
{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bootstrap JS Bundle -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2AEu8T+c+7f+z/j43" crossorigin="anonymous"></script>
|
||||
<!-- Custom JS -->
|
||||
<script src="js/app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
{% endautoescape %}
|
||||
53
templates/overview.twig
Normal file
53
templates/overview.twig
Normal file
@@ -0,0 +1,53 @@
|
||||
{% autoescape %}
|
||||
<h1>{{ trans('Overview') }}</h1>
|
||||
|
||||
<!-- Filter and Search Form -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">{{ trans('Filter and Search') }}</div>
|
||||
<div class="card-body">
|
||||
<form id="filterForm">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label for="search" class="form-label">{{ trans('Search') }}</label>
|
||||
<input type="text" class="form-control" id="search" name="search" value="{{ search }}" placeholder="{{ trans('Search by name') }}">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label for="category_filter" class="form-label">{{ trans('Category') }}</label>
|
||||
<select class="form-select" id="category_filter" name="category_id">
|
||||
<option value="">{{ trans('-- All Categories --') }}</option>
|
||||
{% for category in categories %}
|
||||
<option value="{{ category.id }}" {% if selected_category == category.id %}selected{% endif %}>{{ category.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2 d-flex align-items-end">
|
||||
<button type="submit" class="btn btn-primary">{{ trans('Filter') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Items List -->
|
||||
<h2>{{ trans('All Parts') }}</h2>
|
||||
<ul id="itemsList" class="list-group mb-4">
|
||||
{% if items %}
|
||||
{% for item in items %}
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h5>{{ item.name }}</h5>
|
||||
<p class="text-muted">{{ trans('Category') }}: {{ item.category_name ?: trans('Uncategorized') }}</p>
|
||||
<p>{{ item.description }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<button class="btn btn-sm btn-warning me-2 edit-btn" data-id="{{ item.id }}">Edit</button>
|
||||
<button class="btn btn-sm btn-danger delete-btn" data-id="{{ item.id }}">Delete</button>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<li class="list-group-item">{{ trans('No items found.') }}</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
{% endautoescape %}
|
||||
32
templates/partials/navbar.twig
Executable file
32
templates/partials/navbar.twig
Executable file
@@ -0,0 +1,32 @@
|
||||
{% autoescape %}
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark mb-4">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="#" data-route="/">{{app_name}}</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" aria-current="page" href="#" data-route="/">{{ trans('Overview') }}</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#" data-route="/categories">{{ trans('Categories') }}</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#" data-route="/parts">{{ trans('Parts') }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<select class="form-select form-select-sm" onchange="window.location.href='/lang/' + this.value">
|
||||
{% for locale in supported_locales %}
|
||||
<option value="{{ locale }}" {% if current_locale == locale %}selected{% endif %}>{{ trans('language_' ~ locale) }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
{% endautoescape %}
|
||||
13
templates/partials/sidebar.twig
Executable file
13
templates/partials/sidebar.twig
Executable file
@@ -0,0 +1,13 @@
|
||||
{% autoescape %}
|
||||
<ul class="nav flex-column nav-pills">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if active_page == 'overview' %}active{% endif %}" href="#" data-route="/">{{ trans('Overview') }}</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if active_page == 'categories' %}active{% endif %}" href="#" data-route="/categories">{{ trans('Categories') }}</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if active_page == 'parts' %}active{% endif %}" href="#" data-route="/parts">{{ trans('Parts') }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endautoescape %}
|
||||
30
templates/parts.twig
Normal file
30
templates/parts.twig
Normal file
@@ -0,0 +1,30 @@
|
||||
{% autoescape %}
|
||||
<h1>{{ trans('Add New Part') }}</h1>
|
||||
|
||||
<div class="card mb-4">
|
||||
<div class="card-body">
|
||||
<form id="addItemForm">
|
||||
<input type="hidden" name="action" value="add_item">
|
||||
<div class="mb-3">
|
||||
<label for="item_name" class="form-label">{{ trans('Part Name') }}</label>
|
||||
<input type="text" class="form-control" id="item_name" name="item_name" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="item_description" class="form-label">{{ trans('Description') }}</label>
|
||||
<textarea class="form-control" id="item_description" name="item_description" rows="3"></textarea>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="category_id" class="form-label">{{ trans('Category') }}</label>
|
||||
<select class="form-select" id="category_id" name="category_id" required>
|
||||
<option value="">{{ trans('-- Select Category --') }}</option>
|
||||
{% for category in categories %}
|
||||
<option value="{{ category.id }}">{{ category.path }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">{{ trans('Add Part') }}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endautoescape %}
|
||||
114
templates/search.mustache
Executable file
114
templates/search.mustache
Executable file
@@ -0,0 +1,114 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Collection Manager - Search</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Search Items</h1>
|
||||
|
||||
<nav>
|
||||
<a href="index.php">Add Item</a> | <a href="search.php">Search/Overview</a>
|
||||
</nav>
|
||||
|
||||
<form id="searchForm">
|
||||
<input type="hidden" name="action" value="search_items">
|
||||
<div>
|
||||
<label for="search_term">Search by Name:</label>
|
||||
<input type="text" id="search_term" name="q">
|
||||
</div>
|
||||
<div>
|
||||
<label for="search_category_id">Filter by Category:</label>
|
||||
<select id="search_category_id" name="category_id">
|
||||
<option value="">-- All Categories --</option>
|
||||
{{#categories}}
|
||||
<option value="{{id}}">{{name}}</option>
|
||||
{{/categories}}
|
||||
</select>
|
||||
</div>
|
||||
<button type="submit">Search</button>
|
||||
</form>
|
||||
|
||||
<h2>Search Results</h2>
|
||||
<ul id="searchResultsList">
|
||||
{{#items}}
|
||||
<li>
|
||||
<h3>{{name}}</h3>
|
||||
<p>Category: {{category_name}}</p>
|
||||
<p>{{description}}</p>
|
||||
</li>
|
||||
{{/items}}
|
||||
{{^items}}
|
||||
<li>No items found.</li>
|
||||
{{/items}}
|
||||
</ul>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const searchForm = document.getElementById('searchForm');
|
||||
const searchResultsList = document.getElementById('searchResultsList');
|
||||
const searchCategoryIdSelect = document.getElementById('search_category_id');
|
||||
|
||||
// Function to fetch categories (needed for the dropdown)
|
||||
function fetchCategories() {
|
||||
// Use the same endpoint as index.php to get categories
|
||||
fetch('index.php?action=get_categories')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success && data.categories) {
|
||||
searchCategoryIdSelect.innerHTML = '<option value="">-- All Categories --</option>'; // Reset
|
||||
data.categories.forEach(cat => {
|
||||
const option = document.createElement('option');
|
||||
option.value = cat.id;
|
||||
option.textContent = cat.name;
|
||||
searchCategoryIdSelect.appendChild(option);
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(error => console.error('Error fetching categories:', error));
|
||||
}
|
||||
|
||||
// Handle search form submission
|
||||
searchForm.addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
const formData = new FormData(searchForm);
|
||||
const params = new URLSearchParams();
|
||||
formData.forEach((value, key) => {
|
||||
params.append(key, value);
|
||||
});
|
||||
params.append('action', 'search_items'); // Ensure action is set
|
||||
|
||||
fetch('index.php?' + params.toString(), {
|
||||
method: 'GET'
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
displayResults(data.items || []);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error searching items:', error);
|
||||
searchResultsList.innerHTML = '<li>Error searching items.</li>';
|
||||
});
|
||||
});
|
||||
|
||||
// Display Search Results
|
||||
function displayResults(items) {
|
||||
searchResultsList.innerHTML = ''; // Clear previous results
|
||||
if (items.length === 0) {
|
||||
searchResultsList.innerHTML = '<li>No items found.</li>';
|
||||
return;
|
||||
}
|
||||
items.forEach(item => {
|
||||
const li = document.createElement('li');
|
||||
li.innerHTML = `<h3>${item.name}</h3>
|
||||
<p>Category: ${item.category_name || 'Uncategorized'}</p>
|
||||
<p>${item.description || 'No description available.'}</p>`;
|
||||
searchResultsList.appendChild(li);
|
||||
});
|
||||
}
|
||||
|
||||
// Initial fetch of categories for the dropdown
|
||||
fetchCategories();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user