349 lines
8.5 KiB
HTML
349 lines
8.5 KiB
HTML
{% extends "base.html" %}
|
|
{% block title %}Warehouse Inventory{% endblock %}
|
|
|
|
{% block head %}
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/warehouse.css') }}">
|
|
<style>
|
|
.inventory-container {
|
|
width: 100%;
|
|
padding: 20px;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.inventory-container h2 {
|
|
color: #1e293b;
|
|
}
|
|
|
|
.inventory-table-container h3 {
|
|
color: #1e293b;
|
|
}
|
|
|
|
body.dark-mode .inventory-container h2 {
|
|
color: #e2e8f0;
|
|
}
|
|
|
|
body.dark-mode .inventory-table-container h3 {
|
|
color: #e2e8f0;
|
|
}
|
|
|
|
.search-panel {
|
|
background: #f8fafc;
|
|
padding: 20px;
|
|
border-radius: 8px;
|
|
margin-bottom: 20px;
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
border: 1px solid #e2e8f0;
|
|
}
|
|
|
|
.search-panel h3 {
|
|
margin-top: 0;
|
|
margin-bottom: 15px;
|
|
color: #1e293b;
|
|
}
|
|
|
|
.search-form {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
|
gap: 15px;
|
|
align-items: end;
|
|
}
|
|
|
|
.search-field {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.search-field label {
|
|
font-weight: bold;
|
|
margin-bottom: 5px;
|
|
color: #334155;
|
|
font-size: 0.9em;
|
|
}
|
|
|
|
.search-field input {
|
|
padding: 8px 12px;
|
|
border: 1px solid #cbd5e1;
|
|
border-radius: 4px;
|
|
font-size: 0.95em;
|
|
background: white;
|
|
color: #1e293b;
|
|
}
|
|
|
|
/* Dark mode styles */
|
|
body.dark-mode .search-panel {
|
|
background: #1e293b;
|
|
border: 1px solid #334155;
|
|
}
|
|
|
|
body.dark-mode .search-panel h3 {
|
|
color: #e2e8f0;
|
|
}
|
|
|
|
body.dark-mode .search-field label {
|
|
color: #cbd5e1;
|
|
}
|
|
|
|
body.dark-mode .search-field input {
|
|
background: #0f172a;
|
|
border: 1px solid #334155;
|
|
color: #e2e8f0;
|
|
}
|
|
|
|
body.dark-mode .search-field input::placeholder {
|
|
color: #64748b;
|
|
}
|
|
|
|
.search-buttons {
|
|
display: flex;
|
|
gap: 10px;
|
|
}
|
|
|
|
.inventory-table-container {
|
|
background: #f8fafc;
|
|
padding: 20px;
|
|
border-radius: 8px;
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
overflow-x: auto;
|
|
border: 1px solid #e2e8f0;
|
|
}
|
|
|
|
body.dark-mode .inventory-table-container {
|
|
background: #1e293b;
|
|
border: 1px solid #334155;
|
|
}
|
|
|
|
.inventory-table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
margin-top: 10px;
|
|
font-size: 13px;
|
|
}
|
|
|
|
.inventory-table th,
|
|
.inventory-table td {
|
|
border: 1px solid #cbd5e1;
|
|
padding: 10px;
|
|
text-align: left;
|
|
color: #1e293b;
|
|
}
|
|
|
|
.inventory-table th {
|
|
background-color: #e2e8f0;
|
|
font-weight: bold;
|
|
color: #334155;
|
|
position: sticky;
|
|
top: 0;
|
|
}
|
|
|
|
.inventory-table tbody tr:hover {
|
|
background-color: #f1f5f9;
|
|
}
|
|
|
|
body.dark-mode .inventory-table th,
|
|
body.dark-mode .inventory-table td {
|
|
border: 1px solid #334155;
|
|
color: #e2e8f0;
|
|
}
|
|
|
|
body.dark-mode .inventory-table th {
|
|
background-color: #0f172a;
|
|
color: #cbd5e1;
|
|
}
|
|
|
|
body.dark-mode .inventory-table tbody tr:hover {
|
|
background-color: #334155;
|
|
}
|
|
|
|
.status-badge {
|
|
display: inline-block;
|
|
padding: 3px 8px;
|
|
border-radius: 3px;
|
|
font-size: 0.85em;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.status-open {
|
|
background-color: #d4edda;
|
|
color: #155724;
|
|
}
|
|
|
|
.status-closed {
|
|
background-color: #f8d7da;
|
|
color: #721c24;
|
|
}
|
|
|
|
.status-active {
|
|
background-color: #d1ecf1;
|
|
color: #0c5460;
|
|
}
|
|
|
|
.no-data {
|
|
text-align: center;
|
|
padding: 40px;
|
|
color: #64748b;
|
|
font-style: italic;
|
|
}
|
|
|
|
body.dark-mode .no-data {
|
|
color: #94a3b8;
|
|
}
|
|
|
|
.summary-stats {
|
|
display: flex;
|
|
gap: 20px;
|
|
margin-bottom: 15px;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.stat-card {
|
|
background: white;
|
|
padding: 10px 15px;
|
|
border-radius: 5px;
|
|
border-left: 4px solid #007bff;
|
|
flex: 1;
|
|
min-width: 150px;
|
|
border: 1px solid #e2e8f0;
|
|
}
|
|
|
|
.stat-card h4 {
|
|
margin: 0;
|
|
font-size: 0.85em;
|
|
color: #64748b;
|
|
}
|
|
|
|
.stat-card .stat-value {
|
|
font-size: 1.5em;
|
|
font-weight: bold;
|
|
color: #1e293b;
|
|
margin-top: 5px;
|
|
}
|
|
|
|
body.dark-mode .stat-card {
|
|
background: #0f172a;
|
|
border: 1px solid #334155;
|
|
}
|
|
|
|
body.dark-mode .stat-card h4 {
|
|
color: #94a3b8;
|
|
}
|
|
|
|
body.dark-mode .stat-card .stat-value {
|
|
color: #e2e8f0;
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="inventory-container">
|
|
<h2>Warehouse Inventory - Products/Boxes/Locations</h2>
|
|
|
|
<!-- Search Panel -->
|
|
<div class="search-panel">
|
|
<h3>🔍 Search Inventory</h3>
|
|
<form method="GET" class="search-form">
|
|
<div class="search-field">
|
|
<label for="search_cp">CP Code:</label>
|
|
<input type="text" id="search_cp" name="search_cp" value="{{ search_cp }}" placeholder="Search by CP code...">
|
|
</div>
|
|
|
|
<div class="search-field">
|
|
<label for="search_box">Box Number:</label>
|
|
<input type="text" id="search_box" name="search_box" value="{{ search_box }}" placeholder="Search by box number...">
|
|
</div>
|
|
|
|
<div class="search-field">
|
|
<label for="search_location">Location:</label>
|
|
<input type="text" id="search_location" name="search_location" value="{{ search_location }}" placeholder="Search by location...">
|
|
</div>
|
|
|
|
<div class="search-buttons">
|
|
<button type="submit" class="btn" style="background: #007bff;">Search</button>
|
|
<a href="{{ url_for('warehouse.warehouse_inventory') }}" class="btn" style="background: #6c757d;">Clear</a>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<!-- Summary Statistics -->
|
|
{% if inventory_data %}
|
|
<div class="summary-stats">
|
|
<div class="stat-card">
|
|
<h4>Total Records</h4>
|
|
<div class="stat-value">{{ inventory_data|length }}</div>
|
|
</div>
|
|
<div class="stat-card" style="border-left-color: #28a745;">
|
|
<h4>Unique CP Codes</h4>
|
|
<div class="stat-value">{{ inventory_data|map(attribute=0)|unique|list|length }}</div>
|
|
</div>
|
|
<div class="stat-card" style="border-left-color: #ffc107;">
|
|
<h4>Unique Boxes</h4>
|
|
<div class="stat-value">{{ inventory_data|map(attribute=1)|unique|list|length }}</div>
|
|
</div>
|
|
<div class="stat-card" style="border-left-color: #17a2b8;">
|
|
<h4>Locations Used</h4>
|
|
<div class="stat-value">{{ inventory_data|map(attribute=2)|select|unique|list|length }}</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Inventory Table -->
|
|
<div class="inventory-table-container">
|
|
<h3>Inventory Details</h3>
|
|
|
|
{% if inventory_data %}
|
|
<table class="inventory-table">
|
|
<thead>
|
|
<tr>
|
|
<th>CP Code</th>
|
|
<th>Box Number</th>
|
|
<th>Location</th>
|
|
<th>Scanned At</th>
|
|
<th>Scanned By</th>
|
|
<th>Placed At Location</th>
|
|
<th>Placed By</th>
|
|
<th>Box Status</th>
|
|
<th>Location Status</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for row in inventory_data %}
|
|
<tr>
|
|
<td><strong>{{ row[0] }}</strong></td>
|
|
<td>{{ row[1] }}</td>
|
|
<td>{{ row[2] or '<span style="color: #999;">Not assigned</span>'|safe }}</td>
|
|
<td>{{ row[3].strftime('%Y-%m-%d %H:%M') if row[3] else '' }}</td>
|
|
<td>{{ row[4] or '' }}</td>
|
|
<td>{{ row[5].strftime('%Y-%m-%d %H:%M') if row[5] else '' }}</td>
|
|
<td>{{ row[6] or '' }}</td>
|
|
<td>
|
|
<span class="status-badge status-{{ row[7] }}">
|
|
{{ row[7]|upper if row[7] else 'N/A' }}
|
|
</span>
|
|
</td>
|
|
<td>
|
|
{% if row[8] %}
|
|
<span class="status-badge status-{{ row[8] }}">
|
|
{{ row[8]|upper }}
|
|
</span>
|
|
{% else %}
|
|
<span style="color: #999;">-</span>
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
{% else %}
|
|
<div class="no-data">
|
|
<p>📦 No inventory data found</p>
|
|
{% if search_cp or search_box or search_location %}
|
|
<p>Try adjusting your search criteria</p>
|
|
{% else %}
|
|
<p>Start scanning products to boxes to populate inventory</p>
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|