Refactor Admin Dashboard and organize Counts module
This commit is contained in:
202
templates/counts/my_counts.html
Normal file
202
templates/counts/my_counts.html
Normal file
@@ -0,0 +1,202 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}My Counts - {{ count_session.session_name }} - ScanLook{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="dashboard-container">
|
||||
<div class="page-header">
|
||||
<div>
|
||||
<a href="{{ url_for('counting.index') }}" class="breadcrumb">← Back to Sessions</a>
|
||||
<h1 class="page-title">My Active Counts</h1>
|
||||
<p class="page-subtitle">{{ count_session.session_name }}</p>
|
||||
{% if not count_session.master_baseline_timestamp %}
|
||||
<p class="page-subtitle">Master File not uploaded yet. Please contact an admin before starting bins.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if count_session.master_baseline_timestamp %}
|
||||
<button class="btn btn-primary" onclick="showStartBinModal()">
|
||||
<span class="btn-icon">+</span> Start New Bin
|
||||
</button>
|
||||
{% else %}
|
||||
<button class="btn btn-primary" disabled title="Upload a Master File to start bins">
|
||||
<span class="btn-icon">+</span> Start New Bin
|
||||
</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Active Bins -->
|
||||
{% if active_bins %}
|
||||
<div class="section-card">
|
||||
<h2 class="section-title">🔄 Active Bins (In Progress)</h2>
|
||||
<div class="bins-grid">
|
||||
{% for bin in active_bins %}
|
||||
<div class="bin-card bin-active">
|
||||
<div class="bin-header">
|
||||
<h3 class="bin-name">{{ bin.location_name }}</h3>
|
||||
<span class="bin-status status-progress">In Progress</span>
|
||||
</div>
|
||||
<div class="bin-stats">
|
||||
<div class="bin-stat">
|
||||
<span class="stat-label">Scanned:</span>
|
||||
<span class="stat-value">{{ bin.scan_count or 0 }}</span>
|
||||
</div>
|
||||
<div class="bin-stat">
|
||||
<span class="stat-label">Started:</span>
|
||||
<span class="stat-value">{{ bin.start_timestamp[11:16] if bin.start_timestamp else '-' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bin-actions">
|
||||
<a href="{{ url_for('counting.count_location', session_id=count_session.session_id, location_count_id=bin.location_count_id) }}" class="btn btn-primary btn-block">
|
||||
Resume Counting
|
||||
</a>
|
||||
<div class="bin-actions-row">
|
||||
<button class="btn btn-secondary" onclick="markComplete('{{ bin.location_count_id }}')">
|
||||
✓ Mark Complete
|
||||
</button>
|
||||
<button class="btn btn-danger" onclick="deleteBinCount('{{ bin.location_count_id }}', '{{ bin.location_name }}')">
|
||||
🗑️ Delete
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Completed Bins -->
|
||||
{% if completed_bins %}
|
||||
<div class="section-card">
|
||||
<h2 class="section-title">✅ Completed Bins</h2>
|
||||
<div class="bins-grid">
|
||||
{% for bin in completed_bins %}
|
||||
<div class="bin-card bin-completed">
|
||||
<div class="bin-header">
|
||||
<h3 class="bin-name">{{ bin.location_name }}</h3>
|
||||
<span class="bin-status status-success">Completed</span>
|
||||
</div>
|
||||
<div class="bin-stats">
|
||||
<div class="bin-stat">
|
||||
<span class="stat-label">Scanned:</span>
|
||||
<span class="stat-value">{{ bin.scan_count or 0 }}</span>
|
||||
</div>
|
||||
<div class="bin-stat">
|
||||
<span class="stat-label">Completed:</span>
|
||||
<span class="stat-value">{{ bin.end_timestamp[11:16] if bin.end_timestamp else '-' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bin-actions">
|
||||
<button class="btn btn-secondary btn-block" disabled title="This bin has been finalized">
|
||||
🔒 Finalized (Read-Only)
|
||||
</button>
|
||||
<p class="bin-note">Contact an admin to view details</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if not active_bins and not completed_bins %}
|
||||
<div class="empty-state">
|
||||
<div class="empty-icon">📦</div>
|
||||
<h2 class="empty-title">No Bins Started Yet</h2>
|
||||
<p class="empty-text">Click "Start New Bin" to begin counting</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Start New Bin Modal -->
|
||||
<div id="startBinModal" class="modal">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header-bar">
|
||||
<h3 class="modal-title">Start New Bin</h3>
|
||||
<button type="button" class="btn-close-modal" onclick="closeStartBinModal()">✕</button>
|
||||
</div>
|
||||
|
||||
<form id="startBinForm" action="{{ url_for('counting.start_bin_count', session_id=count_session.session_id) }}" method="POST">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Bin Number *</label>
|
||||
<input type="text" name="location_name" class="form-input scan-input" required autofocus placeholder="Scan or type bin number">
|
||||
</div>
|
||||
|
||||
<div class="modal-actions">
|
||||
<button type="button" class="btn btn-secondary" onclick="closeStartBinModal()">Cancel</button>
|
||||
<button type="submit" class="btn btn-primary">Start Counting</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function showStartBinModal() {
|
||||
document.getElementById('startBinModal').style.display = 'flex';
|
||||
document.querySelector('#startBinForm input[name="location_name"]').focus();
|
||||
}
|
||||
|
||||
function closeStartBinModal() {
|
||||
document.getElementById('startBinModal').style.display = 'none';
|
||||
document.getElementById('startBinForm').reset();
|
||||
}
|
||||
|
||||
function markComplete(locationCountId) {
|
||||
if (!confirm('Mark this bin as complete? You can still view it later.')) {
|
||||
return;
|
||||
}
|
||||
|
||||
fetch(`/location/${locationCountId}/complete`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
location.reload();
|
||||
} else {
|
||||
alert(data.message || 'Error marking bin as complete');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
alert('Error: ' + error.message);
|
||||
});
|
||||
}
|
||||
|
||||
function deleteBinCount(locationCountId, binName) {
|
||||
if (!confirm(`Delete ALL counts for bin "${binName}"?\n\nThis will remove all scanned entries for this bin. This action cannot be undone.`)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Double confirmation for safety
|
||||
if (!confirm('Are you absolutely sure? All data for this bin will be lost.')) {
|
||||
return;
|
||||
}
|
||||
|
||||
fetch(`/location/${locationCountId}/delete`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
location.reload();
|
||||
} else {
|
||||
alert(data.message || 'Error deleting bin count');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
alert('Error: ' + error.message);
|
||||
});
|
||||
}
|
||||
|
||||
// Close modal on escape
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Escape') {
|
||||
closeStartBinModal();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user