Files
aranroig.com/frontend/app/components/parts/ServerStatus.vue
BinarySandia04 6e4a9ac967
All checks were successful
Build and Deploy Nuxt / build (push) Successful in 2m1s
Place
2026-06-11 23:47:37 +02:00

144 lines
2.8 KiB
Vue

<script setup lang="ts">
const { get } = useApi();
const { t } = useI18n();
const status = ref<{
status: string;
uptime: string;
memory: { rss: string; heapUsed: string };
mongo: string;
} | null>(null);
const loading = ref(true);
onMounted(async () => {
try {
status.value = await get('/status');
} catch (e) {
console.error('Status fetch error:', e);
} finally {
loading.value = false;
}
});
const online = computed(() => status.value?.mongo === 'connected');
</script>
<template>
<div class="server-status-card">
<div class="monitor-bar">
<span class="monitor-label">STATUS</span>
<span v-if="loading" class="monitor-blink"></span>
<span v-else class="monitor-dot" :class="online ? 'green' : 'red'"></span>
</div>
<div class="monitor-screen">
<div class="screen-grid">
<div class="screen-line">
<span>Everything OK!</span>
</div>
<div class="screen-line">
<span class="screen-key">UPTIME</span>
<span class="screen-val">{{ loading ? '.......' : status?.uptime || '--' }}</span>
</div>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.server-status-card {
position: relative;
background: var(--color-background-fore);
box-shadow: 4px -4px 0px 0px var(--color-container-shadow);
display: flex;
flex-direction: column;
width: 100%;
min-height: 100%;
}
.monitor-bar {
display: flex;
align-items: center;
justify-content: space-between;
padding: 6px 10px;
background: #0e0e0e;
color: #d4d4d4;
font-family: 'Hurmit', monospace;
letter-spacing: 2px;
text-transform: uppercase;
border-bottom: 2px solid #3a3a3a;
.monitor-blink {
animation: blink-cursor 0.8s steps(1) infinite;
}
}
.monitor-dot {
width: 7px;
height: 7px;
display: inline-block;
shape-rendering: pixelated;
&.green {
background-color: #4ade80;
box-shadow: 0 0 6px #4ade80, 0 0 12px rgba(74, 222, 128, 0.4);
}
&.red {
background-color: #ef4444;
box-shadow: 0 0 6px #ef4444, 0 0 12px rgba(239, 68, 68, 0.4);
}
}
.monitor-screen {
flex: 1;
padding: 10px;
display: flex;
flex-direction: column;
justify-content: center;
}
.screen-grid {
display: flex;
flex-direction: column;
gap: 4px;
}
.screen-line {
display: flex;
justify-content: space-between;
align-items: baseline;
gap: 8px;
padding: 2px 0;
}
.screen-key {
font-family: 'Hurmit', monospace;
color: var(--color-text);
opacity: 0.4;
letter-spacing: 1px;
text-transform: uppercase;
}
.screen-val {
font-family: 'Hurmit', monospace;
color: var(--color-link);
letter-spacing: 0.5px;
&.ok {
color: #4ade80;
}
&.err {
color: #ef4444;
}
}
@keyframes blink-cursor {
0%, 50% { opacity: 1; }
51%, 100% { opacity: 0; }
}
</style>