diff --git a/messages/en.json b/messages/en.json index 17920c11..2054ca95 100644 --- a/messages/en.json +++ b/messages/en.json @@ -749,6 +749,9 @@ "devices_device_type_placeholder": "Select a device type...", "devices_device_type_required": "Device type id is required.", "devices_download_pdf": "Download PDF", + "devices_error_status_body": "This sensor has reported an error and may need to be replaced. Please contact support so we can help get it back online.", + "devices_error_status_detail": "Reported status: {status}", + "devices_error_status_title": "Sensor error detected", "devices_export_dialog_title": "Export Telemetry Data", "devices_export_failed": "Unable to export telemetry for the selected range.", "devices_export_no_data": "No telemetry was found for the selected date range.", diff --git a/messages/ja.json b/messages/ja.json index 5708fc87..dbcc6c2b 100644 --- a/messages/ja.json +++ b/messages/ja.json @@ -764,6 +764,9 @@ "devices_device_type_placeholder": "デバイスタイプを選択してください...", "devices_device_type_required": "デバイスタイプ ID は必須です。", "devices_download_pdf": "PDF をダウンロード", + "devices_error_status_body": "このセンサーはエラーを報告しており、交換が必要な可能性があります。オンラインに復旧できるよう、サポートまでお問い合わせください。", + "devices_error_status_detail": "報告されたステータス: {status}", + "devices_error_status_title": "センサーエラーが検出されました", "devices_export_dialog_title": "テレメトリデータをエクスポート", "devices_export_failed": "選択した範囲のテレメトリをエクスポートできませんでした。", "devices_export_no_data": "選択した日付範囲にテレメトリが見つかりませんでした。", diff --git a/src/lib/interfaces/CwDevice.interface.ts b/src/lib/interfaces/CwDevice.interface.ts index 9c20c379..94423c51 100644 --- a/src/lib/interfaces/CwDevice.interface.ts +++ b/src/lib/interfaces/CwDevice.interface.ts @@ -20,6 +20,7 @@ export interface CwDevice { primary_data?: string | null; secondary_data?: string | null; group?: string | null; + error_status?: string | null; created_at?: string | null; location_name?: string; has_primary_data?: boolean; diff --git a/src/routes/locations/[location_id]/devices/[dev_eui]/+page.svelte b/src/routes/locations/[location_id]/devices/[dev_eui]/+page.svelte index a53e735d..7077f5bf 100644 --- a/src/routes/locations/[location_id]/devices/[dev_eui]/+page.svelte +++ b/src/routes/locations/[location_id]/devices/[dev_eui]/+page.svelte @@ -11,7 +11,13 @@ } from '$lib/devices/relay-control'; import { type RelayNumber, type RelayTargetState } from '$lib/devices/relay-types'; import { m } from '$lib/paraglide/messages.js'; - import { CwCard, CwResponsiveLineChart, useCwToast } from '@cropwatchdevelopment/cwui'; + import { + CwButton, + CwCard, + CwDialog, + CwResponsiveLineChart, + useCwToast + } from '@cropwatchdevelopment/cwui'; import { cwResponsiveLineChartLabels } from '$lib/i18n/cwuiLabels'; import { appTheme } from '$lib/theme/appTheme.svelte'; import { resolveExportTimeZone } from './csvExport'; @@ -137,6 +143,24 @@ displayHistoricalData.length === 0 ); + // A non-empty `error_status` on the device row means the sensor has reported a + // fault and likely needs replacing. Surface it in an auto-opening dialog. + let deviceErrorStatus = $derived( + typeof data.device?.error_status === 'string' ? data.device.error_status.trim() : '' + ); + let errorDialogOpen = $state(false); + let errorDialogRouteKey = ''; + + // Auto-open the error dialog whenever we land on a device that has an error + // status set. Keyed on `routeKey` so it re-opens when navigating between + // devices, but stays closed once the user dismisses it for the current one. + $effect(() => { + if (deviceErrorStatus && errorDialogRouteKey !== routeKey) { + errorDialogRouteKey = routeKey; + errorDialogOpen = true; + } + }); + afterNavigate(() => { const key = routeKey; if (isRelayDevice && authToken) { @@ -398,6 +422,20 @@ + {#if deviceErrorStatus} + +

{m.devices_error_status_body()}

+

+ {m.devices_error_status_detail({ status: deviceErrorStatus })} +

+ {#snippet actions()} + (errorDialogOpen = false)}> + {m.action_close()} + + {/snippet} +
+ {/if} +