Skip to content

Commit 1cc6fbf

Browse files
CopilotAlexLipp
andcommitted
Add Offline History tab to discharge popup
Co-authored-by: AlexLipp <10188895+AlexLipp@users.noreply.github.com> Agent-Logs-Url: https://github.com/JonnyDawe/UK-Sewage-Map/sessions/6e1308d7-2622-45d8-ba5f-b150045af4dc
1 parent 97cacbb commit 1cc6fbf

2 files changed

Lines changed: 186 additions & 1 deletion

File tree

src/components/DischargePopup/DischargeTimeline/DischargeTimeline.tsx

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,34 @@ const CustomChart = styled(Chart)`
4848
}
4949
`;
5050

51+
const CustomOfflineChart = styled(Chart)`
52+
svg {
53+
// Background Color
54+
g:nth-child(2) {
55+
rect {
56+
fill: var(--gray-a2);
57+
}
58+
path {
59+
stroke: var(--gray-4);
60+
}
61+
}
62+
63+
// Text
64+
g:nth-child(3) {
65+
text {
66+
fill: var(--gray-12);
67+
}
68+
}
69+
70+
// Fill
71+
g:nth-child(5) {
72+
rect {
73+
fill: var(--gray-8);
74+
}
75+
}
76+
}
77+
`;
78+
5179
function getFilteredDischarges(
5280
dischargeData: DischargeHistoricalData,
5381
period: DischargeHistoryPeriod,
@@ -312,6 +340,108 @@ function DischargeTimeline({ locationName }: { locationName: string }) {
312340
);
313341
}
314342

343+
function OfflineTimeline({ locationName }: { locationName: string }) {
344+
const [selectedPeriod, setSelectedPeriod] = React.useState<DischargeHistoryPeriod>(
345+
DischargeHistoryPeriod.Last6Months,
346+
);
347+
348+
const {
349+
data: historicOfflineDataJSON,
350+
isLoading,
351+
error,
352+
} = useSWR(
353+
'https://d1kmd884co9q6x.cloudfront.net/discharges_to_date/up_to_now_offline.json',
354+
fetchHistoricDischargeData,
355+
);
356+
357+
const { data: lastUpdatedDate, isLoading: lastUpdatedLoading } = useSWR(
358+
'https://d1kmd884co9q6x.cloudfront.net/discharges_to_date/timestamp.txt',
359+
fetchTimeStamp,
360+
);
361+
362+
if (isLoading || lastUpdatedLoading) {
363+
return <p>Loading...</p>;
364+
}
365+
366+
if (error) {
367+
return <p>Failed to load offline monitor data.</p>;
368+
}
369+
370+
const locationData = processDataForLocation(historicOfflineDataJSON, locationName, selectedPeriod);
371+
const { dischargeChartData, totalDischarge: totalOfflineDuration } = locationData;
372+
373+
const offlineStartDate = getDischargeDateObject(
374+
getStartDateOfInterest(selectedPeriod) ?? new Date(),
375+
);
376+
377+
return (
378+
<TimeLineWrapper>
379+
<Text size={'2'}>
380+
Offline periods from the:{' '}
381+
<InLineSelect
382+
options={[
383+
{ value: DischargeHistoryPeriod.Last3Months, label: 'Last 3 months' },
384+
{ value: DischargeHistoryPeriod.Last6Months, label: 'Last 6 months' },
385+
{ value: DischargeHistoryPeriod.Last12Months, label: 'Last 12 months' },
386+
{ value: DischargeHistoryPeriod.StartOf2023, label: 'Entirety of 2023' },
387+
{ value: DischargeHistoryPeriod.StartOf2024, label: 'Entirety of 2024' },
388+
{ value: DischargeHistoryPeriod.StartOf2025, label: 'Start of the Year' },
389+
]}
390+
value={selectedPeriod}
391+
onChange={(selectedPeriod) => {
392+
setSelectedPeriod(selectedPeriod as DischargeHistoryPeriod);
393+
}}
394+
/>
395+
</Text>
396+
{dischargeChartData.length === 1 ? (
397+
<Text size={'2'}>
398+
No Recorded Offline Periods since {offlineStartDate.day} {offlineStartDate.month}{' '}
399+
{offlineStartDate.year}
400+
</Text>
401+
) : (
402+
<CustomOfflineChart
403+
chartType="Timeline"
404+
data={dischargeChartData}
405+
width="100%"
406+
height="120px"
407+
options={{
408+
timeline: {
409+
showRowLabels: false,
410+
singleColor: '#808080',
411+
barLabelStyle: {
412+
fontSize: 20,
413+
},
414+
},
415+
hAxis: {
416+
minValue: getStartDateOfInterest(selectedPeriod),
417+
maxValue: getEndDateOfInterest(selectedPeriod),
418+
},
419+
tooltip: { html: true },
420+
avoidOverlappingGridLines: false,
421+
}}
422+
></CustomOfflineChart>
423+
)}
424+
<Flex
425+
direction={'row'}
426+
justify={'between'}
427+
style={{
428+
containerType: 'inline-size',
429+
}}
430+
mt={'-4'}
431+
>
432+
{lastUpdatedDate && (
433+
<SubText>
434+
Last Updated <b>{formatDate(lastUpdatedDate, 'full')}</b>
435+
</SubText>
436+
)}
437+
<SubText>
438+
Total Duration <b>{formatTime(totalOfflineDuration, false)}</b>
439+
</SubText>
440+
</Flex>
441+
</TimeLineWrapper>
442+
);
443+
}
444+
315445
const BulletPoint = styled.li`
316446
font-size: 14px;
317447
`;
@@ -358,4 +488,51 @@ function HistoricDischarges({ company, locationName }: { company: string; locati
358488
);
359489
}
360490

491+
export function HistoricOfflinePeriods({
492+
company,
493+
locationName,
494+
}: {
495+
company: string;
496+
locationName: string;
497+
}) {
498+
if (company === 'Thames Water') {
499+
return <OfflineTimeline locationName={locationName} />;
500+
}
501+
502+
const message =
503+
company === 'Southern Water'
504+
? `${company} provides live historical sewage spill data on their <a href="https://www.southernwater.co.uk/our-region/clean-rivers-and-seas-task-force/rivers-and-seas-watch/" target="_blank" rel="noopener noreferrer">website</a> but does not make it available via an API for third-party applications. 🔒`
505+
: `${company} has chosen not to share live historical sewage spill data with the public. 🙄`;
506+
507+
return (
508+
<>
509+
<Blockquote mb={'2'} size={'2'}>
510+
<span dangerouslySetInnerHTML={{ __html: message }} />
511+
<br />
512+
Find information from last year at:{' '}
513+
<Link href="https://top-of-the-poops.org">top-of-the-poops.org</Link>
514+
</Blockquote>
515+
516+
<Heading as="h4" size="2">
517+
Want to help? You can:
518+
</Heading>
519+
<ul>
520+
<BulletPoint>
521+
<Text size={'2'}>Contact {company} to request data transparency</Text>
522+
</BulletPoint>
523+
<BulletPoint>
524+
<Link href="https://writetothem.com" size={'2'}>
525+
Tell your local MP why this data matters to you
526+
</Link>
527+
</BulletPoint>
528+
<BulletPoint>
529+
<Link href="https://theconversation.com/water-companies-now-have-to-release-live-sewage-spill-data-heres-why-more-transparency-is-the-key-to-cleaner-rivers-239444">
530+
Learn more about the importance of open environmental data
531+
</Link>
532+
</BulletPoint>
533+
</ul>
534+
</>
535+
);
536+
}
537+
361538
export default HistoricDischarges;

src/components/DischargePopup/PopUpContent/PopUpBody.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ import { usePrefersReducedMotion } from '../../../lib/hooks/usePrefersReducedMot
66
import { AlertStatus, DischargeInterval } from '../../../utils/discharge/types';
77
import Tabs from '../../common/Tabs/Tabs';
88
import { DischargeInfoCard } from '../DischargeInfoCard/DischargeInfoCard';
9-
import HistoricDischarges from '../DischargeTimeline/DischargeTimeline';
9+
import HistoricDischarges, {
10+
HistoricOfflinePeriods,
11+
} from '../DischargeTimeline/DischargeTimeline';
1012

1113
const ContentWrapper = styled(Box)`
1214
width: 100%;
@@ -99,6 +101,7 @@ export function PopUpBody({
99101
<Tabs.List>
100102
<Tabs.Trigger value="latest">Latest</Tabs.Trigger>
101103
<Tabs.Trigger value="history">History</Tabs.Trigger>
104+
<Tabs.Trigger value="offline">Offline History</Tabs.Trigger>
102105
</Tabs.List>
103106
<Box pt={'3'}>
104107
<Tabs.Content value="latest">
@@ -116,6 +119,11 @@ export function PopUpBody({
116119
<HistoricDischarges company={company} locationName={locationName} />
117120
</DataCardWrapper>
118121
</Tabs.Content>
122+
<Tabs.Content value="offline">
123+
<DataCardWrapper>
124+
<HistoricOfflinePeriods company={company} locationName={locationName} />
125+
</DataCardWrapper>
126+
</Tabs.Content>
119127
</Box>
120128
</Tabs.Root>
121129
</ContentWrapper>

0 commit comments

Comments
 (0)