Skip to content

Commit df48597

Browse files
restyle alert card
format date to show on card implemented visual configuration of style according to alert type
1 parent 5be95b1 commit df48597

2 files changed

Lines changed: 70 additions & 33 deletions

File tree

web/src/features/panels/zone/CurrentGridAlertsCard.tsx

Lines changed: 67 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,52 @@
11
import useGetZone from 'api/getZone';
22
import HorizontalDivider from 'components/HorizontalDivider';
33
import { useEffect, useState } from 'react';
4-
import { FiAlertTriangle } from 'react-icons/fi';
5-
6-
interface ZoneAlert {
7-
message: string;
8-
start_time: string;
9-
end_time: string | null;
10-
alert_type: 'action' | 'informational' | string;
11-
}
4+
import { FiAlertTriangle, FiInfo } from 'react-icons/fi';
5+
import { ZoneMessage } from 'types';
126

137
interface ZoneDetail {
14-
zoneMessage: ZoneAlert | null;
8+
zoneMessage: ZoneMessage | null;
159
}
1610

11+
// format date function to format date strings
12+
const formatDate = (dateString?: string) => {
13+
if (!dateString) {
14+
return 'N/A';
15+
}
16+
const date = new Date(dateString);
17+
return new Intl.DateTimeFormat('en-US', {
18+
dateStyle: 'medium',
19+
timeStyle: 'short',
20+
}).format(date);
21+
};
22+
23+
// Configuration for icons and colors based on alert type
24+
const alertTypeConfig: Record<
25+
string,
26+
{
27+
icon: JSX.Element;
28+
colorClass: string;
29+
}
30+
> = {
31+
action: {
32+
icon: <FiAlertTriangle className="inline" />,
33+
colorClass: 'bg-warning/10',
34+
},
35+
informational: {
36+
icon: <FiInfo className="inline" />,
37+
colorClass: 'text-neutral-600 dark:text-neutral-400',
38+
},
39+
default: {
40+
icon: <FiInfo className="inline" />,
41+
colorClass: 'text-neutral-600',
42+
},
43+
};
44+
1745
export default function CurrentGridAlertsCard() {
1846
const [zoneDetails, setZoneDetails] = useState<ZoneDetail[]>([]);
1947
const [loading, setLoading] = useState(true);
2048

49+
// Fetch zone details using the custom hook
2150
const { data, isLoading: isZoneLoading } = useGetZone();
2251

2352
useEffect(() => {
@@ -29,12 +58,7 @@ export default function CurrentGridAlertsCard() {
2958
setLoading(true);
3059
try {
3160
const zoneMessage = data.zoneMessage || null;
32-
33-
if (zoneMessage) {
34-
setZoneDetails([{ zoneMessage }]);
35-
} else {
36-
setZoneDetails([]);
37-
}
61+
setZoneDetails(zoneMessage ? [{ zoneMessage }] : []);
3862
} catch (error) {
3963
console.error('Error fetching grid state or zone details:', error);
4064
setZoneDetails([]);
@@ -48,28 +72,37 @@ export default function CurrentGridAlertsCard() {
4872

4973
const isLoading = loading || isZoneLoading;
5074

51-
// Return nothing if not loading and no alerts
75+
// Nothing to show
5276
if (!isLoading && zoneDetails.length === 0) {
5377
return null;
5478
}
5579

56-
// If there are alerts, show the card
80+
// At least one alert action type
81+
const isAction = zoneDetails.some((z) => z.zoneMessage?.alert_type === 'action');
82+
5783
return (
5884
<section>
5985
<div
6086
className={`mb-2 rounded-2xl border ${
61-
zoneDetails.some((z) => z.zoneMessage?.alert_type === 'action')
87+
isAction
6288
? 'border-warning bg-warning/10 dark:border-warning/60 dark:bg-warning/20'
6389
: 'border-neutral-200 bg-white/60 dark:border-neutral-700/80 dark:bg-neutral-800/60'
6490
} p-0`}
6591
>
6692
<div className="flex flex-col items-center gap-2 rounded-2xl bg-sunken p-4 dark:bg-sunken-dark">
6793
{isLoading ? (
6894
<p className="text-center text-xs">Loading grid alerts...</p>
69-
) : (zoneDetails.length === 0 ? null : ( // Nothing shown when no alerts, or you can add a placeholder if you want
95+
) : (
7096
<ul className="w-full">
71-
{zoneDetails.map(({ zoneMessage }, index) =>
72-
zoneMessage ? (
97+
{zoneDetails.map(({ zoneMessage }, index) => {
98+
if (!zoneMessage) {
99+
return null;
100+
}
101+
102+
const alertConfig = alertTypeConfig[zoneMessage.alert_type ?? 'default'];
103+
const [title, ...rest] = zoneMessage.message.split('\n');
104+
105+
return (
73106
<li
74107
key={`${zoneMessage.start_time}-${
75108
zoneMessage.end_time ?? 'no-end'
@@ -90,8 +123,10 @@ export default function CurrentGridAlertsCard() {
90123
wordWrap: 'break-word',
91124
}}
92125
>
93-
<FiAlertTriangle className="inline" />{' '}
94-
{zoneMessage.message.split('\n')[0]}
126+
{alertConfig.icon}{' '}
127+
<span className={`font-semibold ${alertConfig.colorClass}`}>
128+
{title}
129+
</span>
95130
</div>
96131
<div
97132
style={{
@@ -101,12 +136,14 @@ export default function CurrentGridAlertsCard() {
101136
fontSize: 12,
102137
fontFamily: 'Inter',
103138
fontWeight: '400',
104-
lineHeight: 4,
139+
lineHeight: 2,
105140
wordWrap: 'break-word',
106141
}}
107142
>
108-
From: {zoneMessage.start_time}
109-
{zoneMessage.end_time && <> &mdash; To: {zoneMessage.end_time}</>}
143+
From: {formatDate(zoneMessage.start_time)}
144+
{zoneMessage.end_time && (
145+
<> &mdash; To: {formatDate(zoneMessage.end_time)}</>
146+
)}
110147
</div>
111148
<div className="flex items-center justify-between font-bold">
112149
<span className="text-xs uppercase opacity-70">
@@ -126,13 +163,13 @@ export default function CurrentGridAlertsCard() {
126163
wordWrap: 'break-word',
127164
}}
128165
>
129-
{zoneMessage.message.split('\n').slice(1).join('\n')}
166+
{rest.join('\n')}
130167
</div>
131168
</li>
132-
) : null
133-
)}
169+
);
170+
})}
134171
</ul>
135-
))}
172+
)}
136173
</div>
137174
</div>
138175
</section>

web/src/types.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,9 @@ export interface ZoneDetails {
177177
export interface ZoneMessage {
178178
message: string;
179179
issue?: string;
180-
startTime?: datetime;
181-
endTime?: datetime;
182-
alertType?: string;
180+
start_time?: string;
181+
end_time?: string;
182+
alert_type?: string;
183183
}
184184

185185
export interface GeometryProperties {

0 commit comments

Comments
 (0)