1- import { Text , VStack , Badge , HStack , Card } from '@chakra-ui/react' ;
1+ import { Text , VStack , Badge , HStack , Card , Skeleton } from '@chakra-ui/react' ;
22import { CloudOff } from 'lucide-react' ;
33import { formatDistanceToNow } from 'date-fns' ;
44import type { Outage } from '@/api/types' ;
55
66interface OutagesListProps {
7- outages : Outage [ ] ;
7+ outages : Outage [ ] | undefined ;
8+ isLoading : boolean ;
89}
910
1011function formatDuration ( seconds ?: number | null ) : string {
@@ -18,8 +19,8 @@ function formatDuration(seconds?: number | null): string {
1819 return minutes > 0 ? `${ hours } h ${ minutes } m` : `${ hours } h` ;
1920}
2021
21- export function OutagesList ( { outages } : OutagesListProps ) {
22- if ( outages . length === 0 ) {
22+ export function OutagesList ( { outages, isLoading } : OutagesListProps ) {
23+ if ( outages ? .length === 0 ) {
2324 return (
2425 < VStack
2526 justify = 'center'
@@ -38,44 +39,59 @@ export function OutagesList({ outages }: OutagesListProps) {
3839 ) ;
3940 }
4041
42+ function capitalizeFirstLetter ( text : string ) {
43+ if ( ! text ) return '' ;
44+ return text . charAt ( 0 ) . toUpperCase ( ) + text . slice ( 1 ) ;
45+ }
46+
47+ const sortedOutages = outages
48+ ? [ ...outages ] . sort ( ( a , b ) => {
49+ if ( ! a . endedTs && b . endedTs ) return - 1 ;
50+ if ( a . endedTs && ! b . endedTs ) return 1 ;
51+ return new Date ( b . startedTs ) . getTime ( ) - new Date ( a . startedTs ) . getTime ( ) ;
52+ } )
53+ : [ ] ;
54+
4155 return (
4256 < VStack gap = { 4 } align = 'stretch' >
43- { outages . slice ( 0 , 5 ) . map ( ( outage , index ) => (
44- < Card . Root key = { `${ outage . startedTs } -${ index } ` } variant = 'outline' >
45- < Card . Body >
46- < VStack gap = { 2 } align = 'stretch' >
47- < HStack justify = 'space-between' >
48- < Text fontSize = 'sm' fontWeight = 'medium' >
49- { formatDistanceToNow ( new Date ( outage . startedTs ) , { addSuffix : true } ) }
50- </ Text >
51- < Badge colorPalette = { outage . endedTs ? 'gray' : 'red' } size = 'sm' >
52- { outage . endedTs ? 'Resolved' : 'Ongoing' }
53- </ Badge >
54- </ HStack >
55- < HStack justify = 'space-between' >
56- < Text fontSize = 'sm' color = 'gray.600' >
57- Duration: { formatDuration ( outage . durationS ) }
58- </ Text >
59- { outage . endedTs && (
57+ { sortedOutages . map ( ( outage , index ) => (
58+ < Skeleton loading = { isLoading } >
59+ < Card . Root key = { `${ outage . startedTs } -${ index } ` } size = { 'sm' } >
60+ < Card . Body p = { 3 } >
61+ < VStack gap = { 2 } align = 'stretch' >
62+ < HStack justify = 'space-between' >
63+ < Text fontSize = 'sm' fontWeight = 'medium' >
64+ { capitalizeFirstLetter (
65+ formatDistanceToNow ( new Date ( outage . startedTs ) , { addSuffix : true } )
66+ ) }
67+ </ Text >
68+ < Badge colorPalette = { outage . endedTs ? 'green' : 'red' } size = 'sm' >
69+ { outage . endedTs ? 'Resolved' : 'Ongoing' }
70+ </ Badge >
71+ </ HStack >
72+ < HStack justify = 'space-between' >
6073 < Text fontSize = 'sm' color = 'gray.600' >
61- Ended: { formatDistanceToNow ( new Date ( outage . endedTs ) , { addSuffix : true } ) }
74+ Duration: { formatDuration ( outage . durationS ) }
75+ </ Text >
76+ < Text fontSize = 'sm' color = 'gray.600' >
77+ Ended:{ ' ' }
78+ { outage . endedTs
79+ ? capitalizeFirstLetter (
80+ formatDistanceToNow ( new Date ( outage . endedTs ) , { addSuffix : true } )
81+ )
82+ : 'Unknown' }
83+ </ Text >
84+ </ HStack >
85+ { outage . lastError && (
86+ < Text fontSize = 'sm' color = 'red.600' _dark = { { color : 'red.400' } } lineClamp = { 2 } >
87+ { outage . lastError }
6288 </ Text >
6389 ) }
64- </ HStack >
65- { outage . lastError && (
66- < Text fontSize = 'sm' color = 'red.600' _dark = { { color : 'red.400' } } lineClamp = { 2 } >
67- { outage . lastError }
68- </ Text >
69- ) }
70- </ VStack >
71- </ Card . Body >
72- </ Card . Root >
90+ </ VStack >
91+ </ Card . Body >
92+ </ Card . Root >
93+ </ Skeleton >
7394 ) ) }
74- { outages . length > 5 && (
75- < Text fontSize = 'sm' color = 'gray.500' textAlign = 'center' >
76- Showing 5 of { outages . length } recent outages
77- </ Text >
78- ) }
7995 </ VStack >
8096 ) ;
8197}
0 commit comments