feat(channel-monitor): redesign user dashboard as card grid
Reference check-cx UI: INTELLIGENCE MONITOR hero + 3-column card grid with 60-point timeline bars. Backend: - Add PrimaryPingLatencyMs + Timeline[60] to UserMonitorView - ListRecentHistoryForMonitors: batch CTE + ROW_NUMBER() window query - indexLatestByModel / indexAvailabilityByModel helpers Frontend: - 7 new components: ProviderIcon, MonitorMetricPair, MonitorAvailabilityRow, MonitorTimeline, MonitorHero, MonitorCard, MonitorCardGrid - ChannelStatusView 381→~180 lines (delegated to subcomponents) - AbortController reload concurrency protection - HSL 0-120° availability color mapping - Replace emoji with Icon component (bolt / globe) - i18n: monitorCommon.* shared namespace, channelStatus.hero.* Bump VERSION to 0.1.114.24
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<div class="mt-3 flex items-end justify-between">
|
||||
<div class="text-[11px] uppercase tracking-widest text-gray-400">
|
||||
{{ windowLabel }}
|
||||
</div>
|
||||
<div class="flex items-baseline gap-0.5">
|
||||
<span
|
||||
class="text-3xl font-bold tabular-nums leading-none"
|
||||
:style="colorStyle"
|
||||
>
|
||||
{{ displayValue }}
|
||||
</span>
|
||||
<span
|
||||
class="text-base font-semibold leading-none"
|
||||
:style="colorStyle"
|
||||
>%</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="samplesLabel"
|
||||
class="mt-1 text-[11px] text-gray-400 text-right"
|
||||
>
|
||||
{{ samplesLabel }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { hslForPct } from '@/composables/useChannelMonitorFormat'
|
||||
|
||||
const props = defineProps<{
|
||||
windowLabel: string
|
||||
value: number | null
|
||||
samplesLabel?: string
|
||||
}>()
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const displayValue = computed(() => {
|
||||
if (props.value === null || Number.isNaN(props.value)) return t('monitorCommon.latencyEmpty')
|
||||
return props.value.toFixed(2)
|
||||
})
|
||||
|
||||
const colorStyle = computed(() => {
|
||||
const colour = hslForPct(props.value)
|
||||
return colour ? { color: colour } : { color: 'rgb(156 163 175)' }
|
||||
})
|
||||
</script>
|
||||
Reference in New Issue
Block a user