74 lines
2.1 KiB
Vue
Raw Normal View History

2025-12-18 01:13:04 -03:00
<template>
<div class="app-shell">
<TopBar />
<router-view
:lab-data="labData"
:lab-status="labStatus"
:service-data="serviceData"
:network-data="networkData"
:metrics-data="metricsData"
:loading="statusLoading"
:error="statusError"
/>
</div>
</template>
<script setup>
import { onMounted, ref } from "vue";
import TopBar from "./components/TopBar.vue";
import { fallbackHardware, fallbackServices, fallbackNetwork, fallbackMetrics } from "./data/sample.js";
const labData = ref(fallbackHardware());
const labStatus = ref(null);
const serviceData = ref(fallbackServices());
const networkData = ref(fallbackNetwork());
const metricsData = ref(fallbackMetrics());
const statusLoading = ref(true);
const statusFetching = ref(false);
2025-12-18 01:13:04 -03:00
const statusError = ref("");
async function refreshLabStatus() {
if (statusFetching.value) return;
statusFetching.value = true;
const controller = new AbortController();
const timeoutId = window.setTimeout(() => controller.abort(), 6000);
2025-12-18 01:13:04 -03:00
try {
const resp = await fetch("/api/lab/status", {
headers: { Accept: "application/json" },
signal: controller.signal,
});
2025-12-18 01:13:04 -03:00
if (!resp.ok) throw new Error(`status ${resp.status}`);
labStatus.value = await resp.json();
statusError.value = "";
} catch (err) {
labStatus.value = null;
if (err?.name === "AbortError") {
statusError.value = "Live data timed out";
} else {
statusError.value = "Live data unavailable";
}
2025-12-18 01:13:04 -03:00
} finally {
window.clearTimeout(timeoutId);
2025-12-18 01:13:04 -03:00
statusLoading.value = false;
statusFetching.value = false;
2025-12-18 01:13:04 -03:00
}
}
onMounted(() => {
refreshLabStatus();
window.setInterval(refreshLabStatus, 30000);
});
</script>
<style scoped>
.app-shell {
min-height: 100vh;
background: radial-gradient(circle at 8% 12%, rgba(55, 135, 255, 0.08), transparent 20%),
radial-gradient(circle at 90% 20%, rgba(0, 255, 182, 0.07), transparent 25%),
radial-gradient(circle at 18% 84%, rgba(255, 75, 135, 0.06), transparent 24%),
var(--bg-deep);
color: var(--text-primary);
}
</style>