All checks were successful
Build and Deploy Nuxt / build (push) Successful in 2m1s
144 lines
2.8 KiB
Vue
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>
|