diff --git a/src/entities/current/types.ts b/src/entities/current/types.ts index bfa31cf..bf97b7c 100644 --- a/src/entities/current/types.ts +++ b/src/entities/current/types.ts @@ -1,7 +1,7 @@ export type CurrentItem = { edge: string; tag: string; - value: number; + value: number | null; createdAt: string; updatedAt: string; time: string; diff --git a/src/features/edge-detail/components/ArchiveView.tsx b/src/features/edge-detail/components/ArchiveView.tsx index 9c5909d..ce4dbfd 100644 --- a/src/features/edge-detail/components/ArchiveView.tsx +++ b/src/features/edge-detail/components/ArchiveView.tsx @@ -5,7 +5,7 @@ import { CalendarDays, CalendarClock, Check, ChevronDown, Clock3, DatabaseZap, S import type { CurrentItem } from '../../../entities/current/types'; import { HistoryChart } from '../../../features/history-chart/HistoryChart'; import { RANGE_PRESETS, createRange, type DateRangeState } from '../../../features/history/dateRange'; -import { toIsoFromInput } from '../../../utils/format'; +import { formatNumber, toIsoFromInput } from '../../../utils/format'; import type { HistoryGranularity } from '../../../utils/historyGranularity'; type ArchiveViewProps = { @@ -191,7 +191,7 @@ export function ArchiveView({ {label !== item.tag ? {item.tag} : null} - {item.value.toLocaleString('ru-RU', { maximumFractionDigits: item.precision ?? 3 })} + {formatNumber(item.value)} {selected ? : null} diff --git a/src/features/electrical-schematics/ElectricalNode.tsx b/src/features/electrical-schematics/ElectricalNode.tsx index 3b51f56..bf9dfb7 100644 --- a/src/features/electrical-schematics/ElectricalNode.tsx +++ b/src/features/electrical-schematics/ElectricalNode.tsx @@ -29,8 +29,8 @@ export function ElectricalNode({ liveValues, node, ownerEdgeId }: ElectricalNode ? getLiveValue(liveValues, node.edgeId || ownerEdgeId, node.tagId) : getLiveValue(liveValues, bindingEdgeId, bindings?.stateTagId); const alarmValue = node.kind === 'decoration' ? getLiveValue(liveValues, bindingEdgeId, bindings?.alarmTagId) : undefined; - const alarmActive = Boolean(alarmValue && Number(alarmValue.value) !== 0); - const stateActive = Boolean(mainValue && Number(mainValue.value) !== 0); + const alarmActive = Boolean(alarmValue && alarmValue.value !== null && alarmValue.value !== 0); + const stateActive = Boolean(mainValue && mainValue.value !== null && mainValue.value !== 0); const title = getNodeTitle(node, mainValue); const style: CSSProperties = { left: node.position.x, diff --git a/src/utils/format.ts b/src/utils/format.ts index 2f27483..e5e81f2 100644 --- a/src/utils/format.ts +++ b/src/utils/format.ts @@ -1,7 +1,7 @@ /** Форматирует числовое значение показателя для карточек и мини-плиток. */ -export function formatNumber(value: number): string { - if (!Number.isFinite(value)) { - return '-'; +export function formatNumber(value: number | null): string { + if (value === null || !Number.isFinite(value)) { + return '—'; } return new Intl.NumberFormat('ru-RU', { diff --git a/src/utils/metricStatus.ts b/src/utils/metricStatus.ts index 10be0bd..6c246d4 100644 --- a/src/utils/metricStatus.ts +++ b/src/utils/metricStatus.ts @@ -16,8 +16,9 @@ function isConfiguredLimit(value: number | null): value is number { export function getMetricStatus(item: CurrentItem, now = Date.now()): MetricStatusInfo { const measuredAt = new Date(item.time).getTime(); const ageSeconds = Number.isFinite(measuredAt) ? Math.max(0, Math.round((now - measuredAt) / 1000)) : Number.POSITIVE_INFINITY; - const belowMin = isConfiguredLimit(item.min) && item.value < item.min; - const aboveMax = isConfiguredLimit(item.max) && item.value > item.max; + const value = item.value; + const belowMin = isConfiguredLimit(value) && isConfiguredLimit(item.min) && value < item.min; + const aboveMax = isConfiguredLimit(value) && isConfiguredLimit(item.max) && value > item.max; if (belowMin || aboveMax) { return { status: 'critical', label: 'за пределами уставки', ageSeconds };