113 lines
3.7 KiB
PHP
113 lines
3.7 KiB
PHP
<h2 class="text-2xl font-bold mb-6 text-gray-700">Riwayat Sensor</h2>
|
|
|
|
<div class="bg-white p-6 rounded-2xl shadow hover:shadow-xl transition">
|
|
|
|
<!-- HEADER -->
|
|
<div class="flex flex-col md:flex-row md:justify-between md:items-center gap-3 mb-4">
|
|
|
|
<div>
|
|
<p class="text-gray-700 font-semibold">Data Sensor</p>
|
|
<p class="text-gray-400 text-sm">Realtime dari perangkat IoT</p>
|
|
</div>
|
|
|
|
<input type="text" placeholder="🔍 Cari data..."
|
|
class="border border-gray-200 px-4 py-2 rounded-xl text-sm focus:ring-2 focus:ring-blue-400 outline-none w-full md:w-64">
|
|
</div>
|
|
|
|
<!-- TABLE -->
|
|
<div class="overflow-y-auto max-h-72 rounded-xl border border-gray-100">
|
|
|
|
<table class="w-full text-sm">
|
|
|
|
<thead class="bg-gray-50 text-gray-500 uppercase text-xs sticky top-0">
|
|
<tr>
|
|
<th>Waktu</th>
|
|
<th>Suhu</th>
|
|
<th>Kelembaban</th>
|
|
<th>Heater</th>
|
|
<th>Fan</th>
|
|
<th>Mode</th>
|
|
<th>Active</th>
|
|
</tr>
|
|
</thead>
|
|
|
|
<tbody id="historyTable" class="divide-y text-gray-600">
|
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
<script type="module">
|
|
import { initializeApp } from "https://www.gstatic.com/firebasejs/10.12.2/firebase-app.js";
|
|
import { getDatabase, ref, onValue } from "https://www.gstatic.com/firebasejs/10.12.2/firebase-database.js";
|
|
|
|
const firebaseConfig = {
|
|
apiKey: "AIzaSyC-Wdu6vNC0dRyF33S3_C2wpVt9I6wnp0w",
|
|
authDomain: "smartoven-f9fdd.firebaseapp.com",
|
|
databaseURL: "https://smartoven-f9fdd-default-rtdb.firebaseio.com/",
|
|
projectId: "smartoven-f9fdd",
|
|
appId: "1:1005261996032:web:1bcb483b922275f08f98e5"
|
|
};
|
|
|
|
const app = initializeApp(firebaseConfig);
|
|
const db = getDatabase(app);
|
|
|
|
const table = document.getElementById("historyTable");
|
|
|
|
function fmtDateTime(epochSec) {
|
|
const d = new Date(Number(epochSec) * 1000);
|
|
// contoh: 20/05/2026 14.32.10 (format lokal)
|
|
return d.toLocaleString('id-ID');
|
|
}
|
|
|
|
function fmtNum(n, digits = 1) {
|
|
const x = Number(n);
|
|
if (!Number.isFinite(x)) return '--';
|
|
return x.toFixed(digits);
|
|
}
|
|
|
|
// ==========================
|
|
// 🔥 LOAD HISTORY
|
|
// ==========================
|
|
onValue(ref(db, 'history'), (snapshot) => {
|
|
const data = snapshot.val();
|
|
if (!data) {
|
|
table.innerHTML = `
|
|
<tr>
|
|
<td colspan="7" class="text-center py-4 text-gray-400">
|
|
Belum ada data
|
|
</td>
|
|
</tr>
|
|
`;
|
|
return;
|
|
}
|
|
table.innerHTML = "";
|
|
|
|
const rows = Object.keys(data)
|
|
.map((key) => ({ key, ...data[key] }))
|
|
.filter((r) => r && r.ts != null)
|
|
.sort((a, b) => Number(b.ts) - Number(a.ts));
|
|
|
|
rows.forEach((r) => {
|
|
const modeText = Number(r.mode) === 1 ? 'MANUAL' : 'AUTO';
|
|
const heaterText = Number(r.heater) === 1 ? 'ON' : 'OFF';
|
|
const fanText = Number(r.fan) === 1 ? 'ON' : 'OFF';
|
|
const activeText = Number(r.active) === 1 ? 'YA' : 'TIDAK';
|
|
|
|
table.innerHTML += `
|
|
<tr class="hover:bg-gray-50">
|
|
<td class="px-4 py-2 whitespace-nowrap">${fmtDateTime(r.ts)}</td>
|
|
<td class="px-4 py-2 whitespace-nowrap">${fmtNum(r.temp)} °C</td>
|
|
<td class="px-4 py-2 whitespace-nowrap">${fmtNum(r.hum)} %</td>
|
|
<td class="px-4 py-2 whitespace-nowrap">${heaterText}</td>
|
|
<td class="px-4 py-2 whitespace-nowrap">${fanText}</td>
|
|
<td class="px-4 py-2 whitespace-nowrap">${modeText}</td>
|
|
<td class="px-4 py-2 whitespace-nowrap">${activeText}</td>
|
|
</tr>
|
|
`;
|
|
});
|
|
});
|
|
</script> |