329 lines
11 KiB
HTML
329 lines
11 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<link rel="stylesheet" href="main.css">
|
|
<title>Search Inventory</title>
|
|
<style>
|
|
.search-container {
|
|
background: #f9f9f9;
|
|
padding: 20px;
|
|
border-radius: 8px;
|
|
margin-bottom: 30px;
|
|
}
|
|
|
|
.search-form {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 15px;
|
|
}
|
|
|
|
.form-group {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8px;
|
|
}
|
|
|
|
.form-group label {
|
|
font-weight: bold;
|
|
color: #333;
|
|
}
|
|
|
|
.form-group input,
|
|
.form-group select {
|
|
padding: 10px;
|
|
border: 1px solid #ddd;
|
|
border-radius: 4px;
|
|
font-size: 14px;
|
|
font-family: inherit;
|
|
}
|
|
|
|
.form-group input:focus,
|
|
.form-group select:focus {
|
|
outline: none;
|
|
border-color: #4CAF50;
|
|
box-shadow: 0 0 5px rgba(76, 175, 80, 0.3);
|
|
}
|
|
|
|
.quantity-range,
|
|
.date-range {
|
|
display: flex;
|
|
gap: 15px;
|
|
align-items: flex-end;
|
|
}
|
|
|
|
.quantity-range .form-group,
|
|
.date-range .form-group {
|
|
flex: 1;
|
|
}
|
|
|
|
.search-buttons {
|
|
display: flex;
|
|
gap: 10px;
|
|
}
|
|
|
|
.btn {
|
|
padding: 12px 20px;
|
|
border: none;
|
|
border-radius: 4px;
|
|
font-size: 14px;
|
|
font-weight: bold;
|
|
cursor: pointer;
|
|
transition: background-color 0.3s;
|
|
}
|
|
|
|
.btn-primary {
|
|
background-color: #4CAF50;
|
|
color: white;
|
|
}
|
|
|
|
.btn-primary:hover {
|
|
background-color: #45a049;
|
|
}
|
|
|
|
.btn-secondary {
|
|
background-color: #ddd;
|
|
color: #333;
|
|
}
|
|
|
|
.btn-secondary:hover {
|
|
background-color: #bbb;
|
|
}
|
|
|
|
.results-info {
|
|
text-align: center;
|
|
margin-bottom: 20px;
|
|
font-size: 16px;
|
|
color: #666;
|
|
}
|
|
|
|
.no-results {
|
|
text-align: center;
|
|
padding: 40px;
|
|
color: #999;
|
|
font-size: 18px;
|
|
}
|
|
|
|
.item-expiry-badge {
|
|
display: inline-block;
|
|
padding: 4px 8px;
|
|
border-radius: 4px;
|
|
font-size: 12px;
|
|
font-weight: bold;
|
|
margin-top: 4px;
|
|
}
|
|
|
|
.expiry-fresh {
|
|
background-color: #e8f5e9;
|
|
color: #2e7d32;
|
|
}
|
|
|
|
.expiry-soon {
|
|
background-color: #fff3e0;
|
|
color: #e65100;
|
|
}
|
|
|
|
.expiry-expired {
|
|
background-color: #ffebee;
|
|
color: #c62828;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="navbar-placeholder"></div>
|
|
<div id="page-content">
|
|
<h2>Search Inventory</h2>
|
|
<hr>
|
|
|
|
<div class="search-container">
|
|
<form class="search-form" id="search-form">
|
|
<div class="form-group">
|
|
<label for="search-name">Item Name:</label>
|
|
<input
|
|
type="text"
|
|
id="search-name"
|
|
placeholder="e.g., Milk, Pasta, Chicken..."
|
|
autocomplete="off"
|
|
>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="search-location">Storage Location:</label>
|
|
<select id="search-location">
|
|
<!-- Options populated by script -->
|
|
</select>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>Quantity Range:</label>
|
|
<div class="quantity-range">
|
|
<div class="form-group">
|
|
<label for="min-quantity" style="font-size: 12px;">Min:</label>
|
|
<input
|
|
type="number"
|
|
id="min-quantity"
|
|
min="0"
|
|
value="0"
|
|
placeholder="0"
|
|
>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="max-quantity" style="font-size: 12px;">Max:</label>
|
|
<input
|
|
type="number"
|
|
id="max-quantity"
|
|
min="0"
|
|
value="999"
|
|
placeholder="999"
|
|
>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>Expiry Date Range:</label>
|
|
<div class="date-range">
|
|
<div class="form-group">
|
|
<label for="min-expiry-date" style="font-size: 12px;">Start Date:</label>
|
|
<input
|
|
type="date"
|
|
id="min-expiry-date"
|
|
placeholder="Start date"
|
|
>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="max-expiry-date" style="font-size: 12px;">End Date:</label>
|
|
<input
|
|
type="date"
|
|
id="max-expiry-date"
|
|
placeholder="End date"
|
|
>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="search-buttons">
|
|
<button type="button" class="btn btn-primary" id="search-btn">Search</button>
|
|
<button type="button" class="btn btn-secondary" id="reset-btn">Reset</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<div id="results-container">
|
|
<div class="results-info" id="results-info"></div>
|
|
<div id="results-grid"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="navbar.js"></script>
|
|
<script type="module">
|
|
import { searchInventory, getLocations, formatDate, getExpiryStatus } from './search.js';
|
|
import createItemComponent from './item-component.js';
|
|
|
|
const searchForm = document.getElementById('search-form');
|
|
const searchNameInput = document.getElementById('search-name');
|
|
const locationSelect = document.getElementById('search-location');
|
|
const minQuantityInput = document.getElementById('min-quantity');
|
|
const maxQuantityInput = document.getElementById('max-quantity');
|
|
const minExpiryDateInput = document.getElementById('min-expiry-date');
|
|
const maxExpiryDateInput = document.getElementById('max-expiry-date');
|
|
const searchBtn = document.getElementById('search-btn');
|
|
const resetBtn = document.getElementById('reset-btn');
|
|
const resultsGrid = document.getElementById('results-grid');
|
|
const resultsInfo = document.getElementById('results-info');
|
|
|
|
// Populate location dropdown
|
|
function populateLocations() {
|
|
const locations = getLocations();
|
|
locationSelect.innerHTML = locations
|
|
.map(loc => `<option value="${loc}">${loc}</option>`)
|
|
.join('');
|
|
locationSelect.value = 'All';
|
|
}
|
|
|
|
// Get expiry status badge HTML
|
|
function getExpiryBadgeHtml(expiryDate) {
|
|
const status = getExpiryStatus(expiryDate);
|
|
const badgeClass = status.status === 'Expired' ? 'expiry-expired' :
|
|
status.status === 'Soon' || status.status === 'Today' ? 'expiry-soon' : 'expiry-fresh';
|
|
return `<div class="item-expiry-badge ${badgeClass}">${formatDate(expiryDate)}</div>`;
|
|
}
|
|
|
|
// Display search results
|
|
function displayResults(results) {
|
|
resultsGrid.innerHTML = '';
|
|
|
|
if (results.length === 0) {
|
|
resultsGrid.innerHTML = '<div class="no-results">No items found matching your search criteria.</div>';
|
|
resultsInfo.textContent = 'No results';
|
|
} else {
|
|
resultsGrid.className = 'item-component-grid';
|
|
results.forEach(item => {
|
|
const comp = createItemComponent({
|
|
imgSrc: item.img,
|
|
imgAlt: item.name,
|
|
text1: item.name,
|
|
text2: `${item.location} — ${item.quantity} ${item.unit}`,
|
|
text3: `Expires: ${formatDate(item.expiryDate)}`,
|
|
editable: false
|
|
});
|
|
|
|
// Add expiry badge
|
|
const badge = document.createElement('div');
|
|
badge.innerHTML = getExpiryBadgeHtml(item.expiryDate);
|
|
comp.appendChild(badge.firstChild);
|
|
|
|
resultsGrid.appendChild(comp);
|
|
});
|
|
resultsInfo.textContent = `Found ${results.length} item${results.length !== 1 ? 's' : ''}`;
|
|
}
|
|
}
|
|
|
|
// Perform search
|
|
function performSearch() {
|
|
const searchName = searchNameInput.value;
|
|
const location = locationSelect.value;
|
|
const minQty = parseInt(minQuantityInput.value) || 0;
|
|
const maxQty = parseInt(maxQuantityInput.value) || Infinity;
|
|
const minExpiry = minExpiryDateInput.value;
|
|
const maxExpiry = maxExpiryDateInput.value;
|
|
|
|
// Validate date range
|
|
if (minExpiry && maxExpiry && minExpiry > maxExpiry) {
|
|
alert('Start date cannot be after end date');
|
|
return;
|
|
}
|
|
|
|
const results = searchInventory(searchName, location, minQty, maxQty, minExpiry, maxExpiry);
|
|
displayResults(results);
|
|
}
|
|
|
|
// Reset form
|
|
function resetForm() {
|
|
searchForm.reset();
|
|
minQuantityInput.value = '0';
|
|
maxQuantityInput.value = '999';
|
|
locationSelect.value = 'All';
|
|
minExpiryDateInput.value = '';
|
|
maxExpiryDateInput.value = '';
|
|
resultsGrid.innerHTML = '';
|
|
resultsInfo.textContent = '';
|
|
}
|
|
|
|
// Event listeners
|
|
searchBtn.addEventListener('click', performSearch);
|
|
resetBtn.addEventListener('click', resetForm);
|
|
|
|
// Allow Enter key to search
|
|
searchNameInput.addEventListener('keypress', (e) => {
|
|
if (e.key === 'Enter') performSearch();
|
|
});
|
|
|
|
// Initialize
|
|
populateLocations();
|
|
displayResults(searchInventory());
|
|
</script>
|
|
</body>
|
|
</html>
|