Files
2026-06-02 15:22:08 +07:00

579 lines
20 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Karung Counter Dashboard</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: #f5f5f5;
padding: 20px;
}
h1 {
text-align: center;
color: #333;
margin-bottom: 30px;
}
.container {
max-width: 1400px;
margin: 0 auto;
}
.selected-cycle {
background: linear-gradient(135deg, #2c3e50 0%, #3498db 100%);
color: white;
border-radius: 10px;
padding: 18px 20px;
margin-bottom: 30px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.selected-cycle h2 {
margin-bottom: 12px;
font-size: 20px;
}
.selected-cycle-details {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 12px;
}
.selected-cycle-label {
display: block;
font-size: 12px;
opacity: 0.8;
margin-bottom: 4px;
}
.selected-cycle-value {
font-size: 18px;
font-weight: 700;
word-break: break-word;
}
.selected-cycle-form {
display: flex;
gap: 8px;
}
.selected-cycle-select {
flex: 1;
min-width: 0;
padding: 8px;
border: none;
border-radius: 5px;
font-size: 16px;
}
.selected-cycle-button {
background-color: #27ae60;
color: white;
border: none;
border-radius: 5px;
padding: 8px 12px;
cursor: pointer;
font-weight: 700;
}
.selected-cycle-button:hover {
background-color: #219653;
}
.section {
background: white;
border-radius: 10px;
padding: 20px;
margin-bottom: 30px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.section h2 {
color: #2c3e50;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 3px solid #3498db;
}
.section h2.tuang {
border-bottom-color: #e74c3c;
}
.section h2.masuk {
border-bottom-color: #27ae60;
}
.historical-summary {
display: flex;
justify-content: space-between;
align-items: center;
gap: 12px;
cursor: pointer;
list-style: none;
}
.historical-summary::-webkit-details-marker {
display: none;
}
.historical-summary h2 {
margin-bottom: 0;
padding-bottom: 0;
border-bottom: none;
}
.historical-toggle-label {
background-color: #3498db;
color: white;
border-radius: 5px;
padding: 8px 12px;
font-weight: 700;
white-space: nowrap;
}
.historical-toggle-label::after {
content: "Expand";
}
.historical-section[open] .historical-toggle-label::after {
content: "Collapse";
}
.historical-content {
margin-top: 20px;
}
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
margin-bottom: 30px;
}
.settings-form {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 15px;
align-items: end;
}
.form-group {
display: flex;
flex-direction: column;
gap: 6px;
}
.form-group label {
color: #2c3e50;
font-weight: 600;
}
.settings-input {
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
font-size: 14px;
}
.settings-button {
background-color: #2c3e50;
color: white;
border: none;
border-radius: 5px;
padding: 11px 16px;
cursor: pointer;
font-weight: 600;
}
.settings-button:hover {
background-color: #1f2d3a;
}
.settings-hint {
color: #7f8c8d;
margin-top: 12px;
font-size: 14px;
}
.card {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 20px;
border-radius: 10px;
text-align: center;
}
.card.tuang {
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
}
.card.masuk {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
}
.card.balance {
background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
}
.card h3 {
font-size: 14px;
margin-bottom: 10px;
opacity: 0.9;
}
.card .value {
font-size: 36px;
font-weight: bold;
}
.card .text-value {
font-size: 24px;
word-break: break-word;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
th, td {
padding: 12px 15px;
text-align: left;
border-bottom: 1px solid #ddd;
}
th {
background-color: #34495e;
color: white;
font-weight: 600;
}
tr:hover {
background-color: #f8f9fa;
}
.badge {
display: inline-block;
padding: 5px 10px;
border-radius: 5px;
font-size: 12px;
font-weight: bold;
}
.badge-tuang {
background-color: #ffeaa7;
color: #d63031;
}
.badge-masuk {
background-color: #a8e6cf;
color: #00b894;
}
.json-section {
background-color: #f8f9fa;
border-left: 4px solid #3498db;
padding: 15px;
margin-bottom: 20px;
border-radius: 5px;
}
.json-section h3 {
margin-bottom: 15px;
color: #2c3e50;
}
.camera-list {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
}
.camera-item {
background: white;
padding: 15px;
border-radius: 8px;
border: 2px solid #e0e0e0;
}
.camera-item .camera-name {
font-size: 12px;
color: #7f8c8d;
margin-bottom: 5px;
word-break: break-all;
}
.camera-item .karung-count {
font-size: 24px;
font-weight: bold;
color: #2c3e50;
}
.no-data {
text-align: center;
color: #7f8c8d;
padding: 30px;
font-style: italic;
}
.filter-note {
color: #7f8c8d;
margin-bottom: 15px;
}
.date-badge {
display: inline-block;
background-color: #3498db;
color: white;
padding: 5px 15px;
border-radius: 20px;
font-size: 14px;
margin-bottom: 15px;
}
.edit-input {
width: 100%;
min-width: 120px;
padding: 8px;
border: 1px solid #ccc;
border-radius: 5px;
}
.edit-input:disabled {
background-color: #f3f4f6;
color: #555;
}
.edit-input.count {
min-width: 80px;
}
.action-buttons {
display: flex;
gap: 8px;
}
.table-header {
display: flex;
justify-content: space-between;
align-items: center;
gap: 15px;
}
.edit-button {
background-color: #3498db;
color: white;
border: none;
border-radius: 5px;
padding: 8px 12px;
cursor: pointer;
font-weight: 600;
}
.edit-button:hover {
background-color: #2980b9;
}
.save-button {
background-color: #27ae60;
}
.save-button:hover {
background-color: #219653;
}
.save-button:disabled {
background-color: #bdc3c7;
cursor: not-allowed;
}
.save-button:disabled:hover {
background-color: #bdc3c7;
}
</style>
</head>
<body>
<div class="container">
<h1>📊 Karung Counter Dashboard</h1>
<div class="selected-cycle">
<h2>Selected Cycle</h2>
<div class="selected-cycle-details">
<div>
<span class="selected-cycle-label">Cycle Name</span>
<form class="selected-cycle-form" action="{{ url_for('select_dashboard_cycle') }}" method="post">
<select class="selected-cycle-select" name="cycle_name" required>
{% for cycle in cycle_options %}
<option value="{{ cycle.cycle_name }}" {% if cycle.cycle_name == dashboard_settings.cycle_name %}selected{% endif %}>{{ cycle.cycle_name }}</option>
{% endfor %}
</select>
<button class="selected-cycle-button" type="submit">Pilih</button>
</form>
</div>
<div>
<span class="selected-cycle-label">Range</span>
<span class="selected-cycle-value">{{ dashboard_settings.cycle_start or 'awal data' }} - {{ dashboard_settings.cycle_end or 'akhir data' }}</span>
</div>
<div>
<span class="selected-cycle-label">Saldo Awal</span>
<span class="selected-cycle-value">{{ dashboard_settings.saldo_awal }}</span>
</div>
</div>
</div>
<!-- Summary Cards -->
<div class="cards">
<div class="card balance">
<h3>Cycle Name</h3>
<div class="value text-value">{{ dashboard_settings.cycle_name }}</div>
</div>
<div class="card tuang">
<h3>Karung Tuang Hari Ini (JSON)</h3>
<div class="value">{{ tuang_json_total }}</div>
</div>
<div class="card masuk">
<h3>Karung Masuk Hari Ini (JSON)</h3>
<div class="value">{{ masuk_json_total }}</div>
</div>
<div class="card tuang">
<h3>Total Karung Tuang (Siklus)</h3>
<div class="value">{{ tuang_db_total }}</div>
</div>
<div class="card masuk">
<h3>Total Karung Masuk (Siklus)</h3>
<div class="value">{{ masuk_db_total }}</div>
</div>
<div class="card balance">
<h3>Saldo Awal</h3>
<div class="value">{{ dashboard_settings.saldo_awal }}</div>
</div>
<div class="card balance">
<h3>Saldo Akhir</h3>
<div class="value">{{ saldo_akhir }}</div>
</div>
</div>
<!-- Current Date Data from JSON -->
<div class="section">
<h2>📅 Data Hari Ini ({{ current_date }}) - Dari JSON</h2>
<h3>Karung Tuang</h3>
{% if tuang_json_data %}
<div class="camera-list">
{% for camera, data in tuang_json_data.items() %}
<div class="camera-item">
<div class="camera-name">{{ camera }}</div>
<div class="karung-count">{{ data.karung|default(0) }} karung</div>
</div>
{% endfor %}
</div>
{% else %}
<p class="no-data">Tidak ada data karung tuang untuk hari ini</p>
{% endif %}
<h3 style="margin-top: 30px;">Karung Masuk</h3>
{% if masuk_json_data %}
<div class="camera-list">
{% for camera, data in masuk_json_data.items() %}
<div class="camera-item">
<div class="camera-name">{{ camera }}</div>
<div class="karung-count">{{ data.karung|default(0) }} karung</div>
</div>
{% endfor %}
</div>
{% else %}
<p class="no-data">Tidak ada data karung masuk untuk hari ini</p>
{% endif %}
</div>
<!-- Historical Data from Database -->
<details class="section historical-section" open>
<summary class="historical-summary">
<h2>🗄️ Data Historis - Dari Database</h2>
<span class="historical-toggle-label"></span>
</summary>
<div class="historical-content">
<p class="filter-note">
Siklus aktif:
{{ dashboard_settings.cycle_name }}.
Rentang:
{{ dashboard_settings.cycle_start }}
sampai
{{ dashboard_settings.cycle_end }}
</p>
<div class="section">
<div class="table-header">
<h3 class="tuang">Karung Tuang</h3>
{% if tuang_db_data %}
<div class="action-buttons">
<button class="edit-button" type="button" onclick="enableTableEditor('tuang')">Edit</button>
<button id="tuang-save" class="edit-button save-button" form="tuang-edit-form" type="submit" disabled>Simpan</button>
</div>
{% endif %}
</div>
{% if tuang_db_data %}
<form id="tuang-edit-form" action="{{ url_for('edit_db_rows', db_name='tuang') }}" method="post">
<table>
<thead>
<tr>
<th>Camera Name</th>
<th>Tanggal</th>
<th>Jumlah Karung</th>
</tr>
</thead>
<tbody>
{% for item in tuang_db_data %}
<tr>
<td>
<span class="badge badge-tuang">TUANG</span> {{ item.camera_name }}
</td>
<td>
{{ item.display_date }}
</td>
<td>
<input class="edit-input count tuang-counter-input" type="number" name="counter_value_{{ item.id }}" value="{{ item.counter_value }}" min="0" required disabled>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</form>
{% else %}
<p class="no-data">Tidak ada data historis karung tuang</p>
{% endif %}
</div>
<div class="section">
<div class="table-header">
<h3 class="masuk">Karung Masuk</h3>
{% if masuk_db_data %}
<div class="action-buttons">
<button class="edit-button" type="button" onclick="enableTableEditor('masuk')">Edit</button>
<button id="masuk-save" class="edit-button save-button" form="masuk-edit-form" type="submit" disabled>Simpan</button>
</div>
{% endif %}
</div>
{% if masuk_db_data %}
<form id="masuk-edit-form" action="{{ url_for('edit_db_rows', db_name='masuk') }}" method="post">
<table>
<thead>
<tr>
<th>Camera Name</th>
<th>Tanggal</th>
<th>Jumlah Karung</th>
</tr>
</thead>
<tbody>
{% for item in masuk_db_data %}
<tr>
<td>
<span class="badge badge-masuk">MASUK</span> {{ item.camera_name }}
</td>
<td>
{{ item.date }}
</td>
<td>
<input class="edit-input count masuk-counter-input" type="number" name="counter_value_{{ item.id }}" value="{{ item.counter_value }}" min="0" required disabled>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</form>
{% else %}
<p class="no-data">Tidak ada data historis karung masuk</p>
{% endif %}
</div>
</div>
</details>
<!-- Cycle Settings -->
<div class="section">
<h2>⚙️ Pengaturan Siklus</h2>
<form class="settings-form" action="{{ url_for('update_dashboard_settings') }}" method="post">
<div class="form-group">
<label for="cycle_name">Cycle Name</label>
<input id="cycle_name" class="settings-input" type="text" name="cycle_name" value="{{ dashboard_settings.cycle_name }}" required>
</div>
<div class="form-group">
<label for="cycle_start">Cycle Start</label>
<input id="cycle_start" class="settings-input" type="date" name="cycle_start" value="{{ cycle_start_picker_value }}" required>
</div>
<div class="form-group">
<label for="cycle_end">Cycle End</label>
<input id="cycle_end" class="settings-input" type="date" name="cycle_end" value="{{ cycle_end_picker_value }}" required>
</div>
<div class="form-group">
<label for="saldo_awal">Saldo Awal</label>
<input id="saldo_awal" class="settings-input" type="number" name="saldo_awal" value="{{ dashboard_settings.saldo_awal }}" min="0" step="1" required>
</div>
<button class="settings-button" type="submit">Simpan Pengaturan</button>
</form>
<p class="settings-hint">Data historis hanya menampilkan data dalam rentang siklus.</p>
</div>
</div>
<script>
function enableTableEditor(tableKey) {
const counterInputs = document.querySelectorAll(`.${tableKey}-counter-input`);
const saveButton = document.getElementById(`${tableKey}-save`);
counterInputs.forEach((counterInput) => {
counterInput.disabled = false;
});
saveButton.disabled = false;
if (counterInputs.length > 0) {
counterInputs[0].focus();
counterInputs[0].select();
}
}
</script>
</body>
</html>