114 lines
5.4 KiB
JavaScript
114 lines
5.4 KiB
JavaScript
document.addEventListener('DOMContentLoaded', () => {
|
|
// --- DOM ELEMENTS ---
|
|
const stationsGrid = document.getElementById('stations-grid');
|
|
const stationTemplate = document.getElementById('stationCardTemplate');
|
|
const errorMessage = document.getElementById('error-message');
|
|
const stationCountEl = document.getElementById('station-count');
|
|
// Note: SocketIO is not needed on this page anymore
|
|
|
|
let allStations = []; // To store the master list of stations
|
|
|
|
// --- AUTHENTICATION & USER INFO (Your existing code is perfect) ---
|
|
const user = JSON.parse(localStorage.getItem('user'));
|
|
if (!user) {
|
|
window.location.href = 'index.html'; // Redirect if not logged in
|
|
return;
|
|
}
|
|
|
|
// User info and logout button logic... (omitted for brevity, no changes needed)
|
|
|
|
// --- ADMIN FEATURES (Your existing code is perfect) ---
|
|
// Admin button and add station card logic... (omitted for brevity, no changes needed)
|
|
|
|
|
|
// --- HELPER FUNCTIONS ---
|
|
const getStatusAttributes = (status) => {
|
|
switch (status) {
|
|
case 'Online': return { color: 'text-green-500', bgColor: 'bg-green-100/60 dark:bg-green-500/10', icon: 'power' };
|
|
case 'Offline': return { color: 'text-red-500', bgColor: 'bg-red-100/60 dark:bg-red-500/10', icon: 'power-off' };
|
|
default: return { color: 'text-gray-500', bgColor: 'bg-gray-100/60 dark:bg-gray-500/10', icon: 'help-circle' };
|
|
}
|
|
};
|
|
|
|
const handleStationSelect = (stationId) => {
|
|
window.location.href = `dashboard.html?station_id=${stationId}`;
|
|
};
|
|
|
|
// This function now only renders the initial grid
|
|
const renderStations = (stations) => {
|
|
stationsGrid.innerHTML = '';
|
|
stationCountEl.textContent = `${stations.length} stations found. Select one to monitor.`;
|
|
|
|
stations.forEach(station => {
|
|
const status = getStatusAttributes(station.status);
|
|
const card = document.createElement('div');
|
|
card.className = "group bg-gray-900/60 backdrop-blur-xl rounded-2xl shadow-lg border border-gray-700 transition-transform duration-300 ease-out cursor-pointer flex flex-col justify-between hover:-translate-y-1.5 hover:border-emerald-400/60 hover:shadow-[0_0_0_1px_rgba(16,185,129,0.25),0_20px_40px_rgba(0,0,0,0.45)]";
|
|
card.id = `station-${station.id}`;
|
|
card.onclick = () => handleStationSelect(station.id);
|
|
|
|
card.innerHTML = `
|
|
<div class="p-5">
|
|
<div class="flex justify-between items-start">
|
|
<h3 class="text-lg font-bold text-white pr-2">${station.name}</h3>
|
|
<div class="status-badge flex items-center text-xs font-semibold px-3 py-1 rounded-full ${status.bgColor} ${status.color}">
|
|
<i data-lucide="${status.icon}" class="w-4 h-4 mr-1.5"></i>
|
|
<span class="status-text">${station.status}</span>
|
|
</div>
|
|
</div>
|
|
<p class="text-sm text-gray-400 mt-1">${station.id}</p>
|
|
</div>
|
|
`;
|
|
stationsGrid.appendChild(card);
|
|
});
|
|
lucide.createIcons();
|
|
};
|
|
|
|
// --- NEW: Function to update statuses without redrawing everything ---
|
|
const updateStationStatuses = (stations) => {
|
|
stations.forEach(station => {
|
|
const card = document.getElementById(`station-${station.id}`);
|
|
if (card) {
|
|
const status = getStatusAttributes(station.status);
|
|
const statusBadge = card.querySelector('.status-badge');
|
|
const statusText = card.querySelector('.status-text');
|
|
const statusIcon = card.querySelector('i[data-lucide]');
|
|
|
|
if (statusBadge && statusText && statusIcon) {
|
|
statusBadge.className = `status-badge flex items-center text-xs font-semibold px-3 py-1 rounded-full ${status.bgColor} ${status.color}`;
|
|
statusText.textContent = station.status;
|
|
statusIcon.setAttribute('data-lucide', status.icon);
|
|
}
|
|
}
|
|
});
|
|
lucide.createIcons(); // Re-render icons if any changed
|
|
};
|
|
|
|
// --- DATA FETCHING & STATUS POLLING ---
|
|
const loadAndPollStations = async () => {
|
|
try {
|
|
const response = await fetch('http://localhost:5000/api/stations');
|
|
if (!response.ok) throw new Error('Failed to fetch stations');
|
|
const stations = await response.json();
|
|
|
|
// Check if this is the first time loading data
|
|
if (allStations.length === 0) {
|
|
allStations = stations;
|
|
renderStations(allStations); // Initial full render
|
|
} else {
|
|
allStations = stations;
|
|
updateStationStatuses(allStations); // Subsequent, efficient updates
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error(error);
|
|
stationCountEl.textContent = 'Could not load stations. Is the backend running?';
|
|
// Stop polling on error
|
|
if (pollingInterval) clearInterval(pollingInterval);
|
|
}
|
|
};
|
|
|
|
// --- INITIALIZATION ---
|
|
loadAndPollStations(); // Load immediately on page start
|
|
// Then, set an interval to refresh the statuses every 10 seconds
|
|
const pollingInterval = setInterval(loadAndPollStations, 10000);
|
|
}); |