diff --git a/src/app/call/[id].tsx b/src/app/call/[id].tsx
index 172bb3d1..0bcc6b2f 100644
--- a/src/app/call/[id].tsx
+++ b/src/app/call/[id].tsx
@@ -657,7 +657,7 @@ export default function CallDetail() {
{/* Tabs */}
-
+
setIsNotesModalOpen(false)} callId={callId} />
diff --git a/src/app/weather-alert/[id].tsx b/src/app/weather-alert/[id].tsx
index b511780f..e368792c 100644
--- a/src/app/weather-alert/[id].tsx
+++ b/src/app/weather-alert/[id].tsx
@@ -37,7 +37,7 @@ export default function WeatherAlertDetail() {
}, [alertId, fetchAlertDetail]);
const severityColor = useMemo(() => (alert ? getSeverityColor(alert.Severity) : '#9E9E9E'), [alert]);
- const CategoryIcon = useMemo(() => (alert ? getCategoryIcon(alert.Category) : null), [alert]);
+ const CategoryIcon = useMemo(() => (alert ? getCategoryIcon(alert.AlertCategory) : null), [alert]);
const formatDate = (dateStr: string) => {
if (!dateStr) return t('call_detail.not_available');
@@ -90,19 +90,19 @@ export default function WeatherAlertDetail() {
{alert.EffectiveUtc ? (
{t('weather_alerts.detail.effective')}
- {formatDate(alert.EffectiveUtc)}
+ {formatDate(alert.EffectiveOnUtc || alert.EffectiveUtc)}
) : null}
{alert.OnsetUtc ? (
{t('weather_alerts.detail.onset')}
- {formatDate(alert.OnsetUtc)}
+ {formatDate(alert.OnsetOnUtc || alert.OnsetUtc)}
) : null}
{alert.ExpiresUtc ? (
{t('weather_alerts.detail.expires')}
- {formatDate(alert.ExpiresUtc)}
+ {formatDate(alert.ExpiresOnUtc || alert.ExpiresUtc)}
) : null}
@@ -125,10 +125,10 @@ export default function WeatherAlertDetail() {
) : null}
{/* Instructions */}
- {alert.Instructions ? (
+ {alert.Instruction ? (
{t('weather_alerts.detail.instructions')}
- {alert.Instructions}
+ {alert.Instruction}
) : null}
@@ -143,10 +143,10 @@ export default function WeatherAlertDetail() {
{/* Metadata */}
- {alert.SenderName ? (
+ {alert.Sender ? (
{t('weather_alerts.detail.sender')}
- {alert.SenderName}
+ {alert.Sender}
) : null}
diff --git a/src/components/weather-alerts/__tests__/weather-alert-banner.test.tsx b/src/components/weather-alerts/__tests__/weather-alert-banner.test.tsx
index ee35bc66..d54a4a39 100644
--- a/src/components/weather-alerts/__tests__/weather-alert-banner.test.tsx
+++ b/src/components/weather-alerts/__tests__/weather-alert-banner.test.tsx
@@ -19,27 +19,27 @@ const createMockAlert = (overrides = {}) => ({
Event: 'Tornado Warning',
Headline: 'Tornado Warning for County',
Description: '',
- Instructions: '',
+ Instruction: '',
Severity: 0,
- Category: 0,
+ AlertCategory: 0,
Urgency: 0,
Certainty: 0,
Status: 0,
- SourceType: 0,
- SourceAlertId: '',
- SenderName: '',
+ Sender: '',
AreaDescription: '',
Polygon: '',
CenterGeoLocation: '',
EffectiveUtc: '',
OnsetUtc: '',
ExpiresUtc: '',
- Ends: '',
- ReceivedOnUtc: '',
- UpdatedOnUtc: '',
- WebUrl: '',
- ZoneCode: '',
- MessageType: '',
+ WeatherAlertSourceId: '',
+ ExternalId: '',
+ Geocodes: '',
+ SentUtc: '',
+ FirstSeenUtc: '',
+ LastUpdatedUtc: '',
+ ReferencesExternalId: '',
+ NotificationSent: false,
...overrides,
});
diff --git a/src/components/weather-alerts/__tests__/weather-alert-card.test.tsx b/src/components/weather-alerts/__tests__/weather-alert-card.test.tsx
index 8a543b3c..34988450 100644
--- a/src/components/weather-alerts/__tests__/weather-alert-card.test.tsx
+++ b/src/components/weather-alerts/__tests__/weather-alert-card.test.tsx
@@ -29,27 +29,27 @@ const createMockAlert = (overrides = {}) => ({
Event: 'Tornado Warning',
Headline: 'Tornado Warning for County',
Description: 'A tornado has been spotted.',
- Instructions: 'Take shelter.',
+ Instruction: 'Take shelter.',
Severity: 1,
- Category: 0,
+ AlertCategory: 0,
Urgency: 0,
Certainty: 0,
Status: 0,
- SourceType: 0,
- SourceAlertId: '',
- SenderName: 'NWS',
+ Sender: 'NWS',
AreaDescription: 'County A',
Polygon: '',
CenterGeoLocation: '',
EffectiveUtc: '2026-04-15T10:00:00Z',
OnsetUtc: '',
ExpiresUtc: '2026-04-15T14:00:00Z',
- Ends: '',
- ReceivedOnUtc: '',
- UpdatedOnUtc: '',
- WebUrl: '',
- ZoneCode: '',
- MessageType: '',
+ WeatherAlertSourceId: '',
+ ExternalId: '',
+ Geocodes: '',
+ SentUtc: '',
+ FirstSeenUtc: '',
+ LastUpdatedUtc: '',
+ ReferencesExternalId: '',
+ NotificationSent: false,
...overrides,
});
diff --git a/src/components/weather-alerts/weather-alert-card.tsx b/src/components/weather-alerts/weather-alert-card.tsx
index bca69cb4..6d083e40 100644
--- a/src/components/weather-alerts/weather-alert-card.tsx
+++ b/src/components/weather-alerts/weather-alert-card.tsx
@@ -17,9 +17,11 @@ interface WeatherAlertCardProps {
const WeatherAlertCardComponent: React.FC = ({ alert }) => {
const { t } = useTranslation();
const severityColor = getSeverityColor(alert.Severity);
- const CategoryIcon = getCategoryIcon(alert.Category);
- const effectiveDate = parseWeatherAlertDate(alert.EffectiveUtc);
- const expiresDate = parseWeatherAlertDate(alert.ExpiresUtc);
+ const CategoryIcon = getCategoryIcon(alert.AlertCategory);
+ // Prefer the real UTC instants; the *Utc strings are department-local display values that
+ // read hours off when treated as timestamps. Older servers only send the display strings.
+ const effectiveDate = parseWeatherAlertDate(alert.EffectiveOnUtc || alert.EffectiveUtc);
+ const expiresDate = parseWeatherAlertDate(alert.ExpiresOnUtc || alert.ExpiresUtc);
return (
diff --git a/src/lib/weather-alert-utils.ts b/src/lib/weather-alert-utils.ts
index 9ebdc0ed..86333806 100644
--- a/src/lib/weather-alert-utils.ts
+++ b/src/lib/weather-alert-utils.ts
@@ -200,16 +200,16 @@ export const parseWeatherAlertDate = (dateStr: string): Date | null => {
export const sortAlertsBySeverity = (alerts: WeatherAlertResultData[]): WeatherAlertResultData[] => {
return [...alerts].sort((a, b) => {
if (a.Severity !== b.Severity) return a.Severity - b.Severity;
- const bEffectiveTime = parseWeatherAlertDate(b.EffectiveUtc)?.getTime() ?? 0;
- const aEffectiveTime = parseWeatherAlertDate(a.EffectiveUtc)?.getTime() ?? 0;
+ const bEffectiveTime = parseWeatherAlertDate(b.EffectiveOnUtc || b.EffectiveUtc)?.getTime() ?? 0;
+ const aEffectiveTime = parseWeatherAlertDate(a.EffectiveOnUtc || a.EffectiveUtc)?.getTime() ?? 0;
return bEffectiveTime - aEffectiveTime;
});
};
export const isAlertActive = (alert: WeatherAlertResultData): boolean => {
if (alert.Status !== WeatherAlertStatus.Active) return false;
- if (alert.ExpiresUtc) {
- const expiration = parseWeatherAlertDate(alert.ExpiresUtc);
+ if (alert.ExpiresOnUtc || alert.ExpiresUtc) {
+ const expiration = parseWeatherAlertDate(alert.ExpiresOnUtc || alert.ExpiresUtc);
return expiration ? expiration.getTime() > Date.now() : true;
}
return true;
diff --git a/src/models/v4/weatherAlerts/weatherAlertResultData.ts b/src/models/v4/weatherAlerts/weatherAlertResultData.ts
index 4aa0596a..b943e093 100644
--- a/src/models/v4/weatherAlerts/weatherAlertResultData.ts
+++ b/src/models/v4/weatherAlerts/weatherAlertResultData.ts
@@ -1,28 +1,37 @@
+// Mirrors Resgrid Core's v4 WeatherAlertResultData (Web/Resgrid.Web.Services/Models/v4/WeatherAlerts).
+// Enum-valued fields are ints (see WeatherAlertSeverity/Category/Urgency/Certainty/Status in Core).
export class WeatherAlertResultData {
public WeatherAlertId: string = '';
public DepartmentId: number = 0;
+ public WeatherAlertSourceId: string = '';
+ public ExternalId: string = '';
+ public Sender: string = '';
public Event: string = '';
+ public AlertCategory: number = 4; // Other
+ public Severity: number = 4; // Unknown
+ public Urgency: number = 4; // Unknown
+ public Certainty: number = 4; // Unknown
+ public Status: number = 0; // Active
public Headline: string = '';
public Description: string = '';
- public Instructions: string = '';
- public Severity: number = 4;
- public Category: number = 4;
- public Urgency: number = 4;
- public Certainty: number = 4;
- public Status: number = 0;
- public SourceType: number = 0;
- public SourceAlertId: string = '';
- public SenderName: string = '';
+ public Instruction: string = '';
public AreaDescription: string = '';
public Polygon: string = '';
+ public Geocodes: string = '';
public CenterGeoLocation: string = '';
- public EffectiveUtc: string = '';
+ // Department-local display strings (despite the Utc names) — render verbatim only.
public OnsetUtc: string = '';
public ExpiresUtc: string = '';
- public Ends: string = '';
- public ReceivedOnUtc: string = '';
- public UpdatedOnUtc: string = '';
- public WebUrl: string = '';
- public ZoneCode: string = '';
- public MessageType: string = '';
+ public EffectiveUtc: string = '';
+ public SentUtc: string = '';
+ public FirstSeenUtc: string = '';
+ public LastUpdatedUtc: string = '';
+ // Real UTC instants with explicit "Z" — use these for any date math. Empty on older servers.
+ public EffectiveOnUtc?: string = '';
+ public OnsetOnUtc?: string = '';
+ public ExpiresOnUtc?: string = '';
+ public SentOnUtc?: string = '';
+ public ReferencesExternalId: string = '';
+ public NotificationSent: boolean = false;
+ public SystemMessageId?: number;
}
diff --git a/src/stores/weather-alerts/__tests__/store.test.ts b/src/stores/weather-alerts/__tests__/store.test.ts
index c5705e82..3e92081b 100644
--- a/src/stores/weather-alerts/__tests__/store.test.ts
+++ b/src/stores/weather-alerts/__tests__/store.test.ts
@@ -13,27 +13,27 @@ const createMockAlert = (overrides = {}) => ({
Event: 'Tornado Warning',
Headline: 'Tornado Warning for County',
Description: 'A tornado has been spotted.',
- Instructions: 'Take shelter immediately.',
+ Instruction: 'Take shelter immediately.',
Severity: 0,
- Category: 0,
+ AlertCategory: 0,
Urgency: 0,
Certainty: 0,
Status: 0,
- SourceType: 0,
- SourceAlertId: 'nws-1',
- SenderName: 'NWS',
+ Sender: 'NWS',
AreaDescription: 'County A',
Polygon: '',
CenterGeoLocation: '35.0,-97.0',
EffectiveUtc: '2026-04-15T10:00:00Z',
OnsetUtc: '2026-04-15T10:00:00Z',
ExpiresUtc: '2026-04-15T14:00:00Z',
- Ends: '',
- ReceivedOnUtc: '2026-04-15T10:00:00Z',
- UpdatedOnUtc: '',
- WebUrl: '',
- ZoneCode: 'OKC001',
- MessageType: 'Alert',
+ WeatherAlertSourceId: '',
+ ExternalId: '',
+ Geocodes: '',
+ SentUtc: '',
+ FirstSeenUtc: '',
+ LastUpdatedUtc: '',
+ ReferencesExternalId: '',
+ NotificationSent: false,
...overrides,
});