Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ASA Advisory Status Bar #3980

Merged
merged 10 commits into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion web/src/features/fba/components/infoPanel/AdvisoryReport.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { calculateStatusText } from '@/features/fba/calculateZoneStatus'
import { useFireCentreDetails } from '@/features/fba/hooks/useFireCentreDetails'
import { Box, Tabs, Tab, Grid } from '@mui/material'
import { FireCenter, FireShape } from 'api/fbaAPI'
import { INFO_PANEL_CONTENT_BACKGROUND } from 'app/theme'
Expand Down Expand Up @@ -28,19 +30,32 @@ const TabPanel = ({ children, index, value }: TabPanelProps) => {
)
}

const AdvisoryReport = ({ issueDate, forDate, advisoryThreshold, selectedFireCenter, selectedFireZoneUnit }: AdvisoryReportProps) => {
const AdvisoryReport = ({
issueDate,
forDate,
advisoryThreshold,
selectedFireCenter,
selectedFireZoneUnit
}: AdvisoryReportProps) => {
const [tabNumber, setTabNumber] = useState(0)

const handleTabChange = (event: React.SyntheticEvent, newValue: number) => {
setTabNumber(newValue)
}

const groupedFireZoneUnits = useFireCentreDetails(selectedFireCenter)
const fireZoneUnitDetails = groupedFireZoneUnits.find(
zone => zone.fire_shape_id === selectedFireZoneUnit?.fire_shape_id
)

return (
<div data-testid="advisory-report">
<InfoAccordion
defaultExpanded={true}
title={'Advisory Report'}
accordionDetailBackgroundColour={INFO_PANEL_CONTENT_BACKGROUND}
showAdvisoryStatusBar={true}
advisoryStatus={calculateStatusText(fireZoneUnitDetails?.fireShapeDetails || [], advisoryThreshold)}
>
<Grid container justifyContent="center">
<Grid item sx={{ width: '90%' }}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ const FireZoneUnitTabs = ({
key={key}
data-testid={`zone-${key}-tab`}
sx={{
backgroundColor: calculateStatusColour(zone.fireShapeDetails, advisoryThreshold, '#DCDCDC'),
backgroundColor: calculateStatusColour(zone.fireShapeDetails, advisoryThreshold, '#FFFFFF'),
minWidth: 'auto',
marginTop: theme.spacing(2),
fontWeight: 'bold',
Expand Down
80 changes: 64 additions & 16 deletions web/src/features/fba/components/infoPanel/InfoAccordion.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,51 @@
import React from 'react'

import { Accordion, AccordionDetails, AccordionSummary, Typography } from '@mui/material'
import { Accordion, AccordionDetails, AccordionSummary, Box, Typography } from '@mui/material'
import { styled, useTheme } from '@mui/material/styles'
import ExpandMoreIcon from '@mui/icons-material/ExpandMore'
import { INFO_PANEL_HEADER_BACKGROUND } from 'app/theme'
import { INFO_PANEL_CONTENT_BACKGROUND, INFO_PANEL_HEADER_BACKGROUND } from 'app/theme'
import { AdvisoryStatus } from '@/utils/constants'
import { ADVISORY_ORANGE_FILL, ADVISORY_RED_LINE } from '@/features/fba/components/map/featureStylers'

const getAdvisoryBarColour = (advisoryStatus: AdvisoryStatus | undefined) => {
switch (advisoryStatus) {
case AdvisoryStatus.WARNING:
return ADVISORY_RED_LINE
case AdvisoryStatus.ADVISORY:
return ADVISORY_ORANGE_FILL
default:
return INFO_PANEL_CONTENT_BACKGROUND
}
}
interface AdvisoryStatusBarProps {
advisoryStatus: AdvisoryStatus | undefined
}

const AdvisoryStatusBar = ({ advisoryStatus }: AdvisoryStatusBarProps) => {
const barColour = getAdvisoryBarColour(advisoryStatus)

const advisoryBackground = advisoryStatus
? `repeating-linear-gradient(135deg, ${barColour}, ${barColour} 40px, white 40px, white 70px)`
: barColour

return (
<Box
data-testid="advisory-status-bar"
sx={{
height: '10px',
background: advisoryBackground
}}
/>
)
}

interface InfoAccordionProps {
accordionDetailBackgroundColour?: string
children: React.ReactNode
defaultExpanded: boolean
title: string
showAdvisoryStatusBar?: boolean
advisoryStatus?: AdvisoryStatus
}

const StyledAccordionSummary = styled(AccordionSummary)(() => ({
Expand All @@ -20,24 +56,36 @@ const StyledAccordionSummary = styled(AccordionSummary)(() => ({
}))

// A component for rendering the provided title and content in an accordion format in the info panel.
const InfoAccordion = ({ accordionDetailBackgroundColour, children, defaultExpanded, title }: InfoAccordionProps) => {
const InfoAccordion = ({
accordionDetailBackgroundColour,
children,
defaultExpanded,
title,
showAdvisoryStatusBar = false,
advisoryStatus
}: InfoAccordionProps) => {
const theme = useTheme()

return (
<Accordion data-testid="info-accordion" disableGutters defaultExpanded={defaultExpanded} elevation={0}>
<StyledAccordionSummary expandIcon={<ExpandMoreIcon />}>
<Typography
data-testid="info-accordion-title"
sx={{
color: theme.palette.primary.main,
fontWeight: 'bold',
paddingLeft: '1.25rem'
}}
variant="h6"
>
{title}
</Typography>
</StyledAccordionSummary>
<Box>
<StyledAccordionSummary expandIcon={<ExpandMoreIcon />}>
<Typography
data-testid="info-accordion-title"
sx={{
color: theme.palette.primary.main,
fontWeight: 'bold',
paddingLeft: '1.25rem'
}}
variant="h6"
>
{title}
</Typography>
</StyledAccordionSummary>
{showAdvisoryStatusBar && (
<AdvisoryStatusBar data-testid="advisory-status-bar" advisoryStatus={advisoryStatus} />
)}
</Box>
<AccordionDetails
data-testid="info-accordion-details"
sx={{
Expand Down
57 changes: 56 additions & 1 deletion web/src/features/fba/components/infoPanel/infoAccordion.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@

import InfoAccordion from 'features/fba/components/infoPanel/InfoAccordion'
import { render } from '@testing-library/react'
import { AdvisoryStatus } from '@/utils/constants'
import { ADVISORY_ORANGE_FILL, ADVISORY_RED_LINE } from '@/features/fba/components/map/featureStylers'
import { INFO_PANEL_CONTENT_BACKGROUND } from '@/app/theme'

describe('InfoAccordion', () => {
it('should render', () => {
Expand Down Expand Up @@ -58,4 +60,57 @@ describe('InfoAccordion', () => {
const fizzDiv = getByTestId('fizz')
expect(fizzDiv).not.toBeVisible()
})
it('should render a red advisory status bar if provided a Warning status', () => {
const { getByTestId } = render(
<InfoAccordion
defaultExpanded={true}
title="foo"
showAdvisoryStatusBar={true}
advisoryStatus={AdvisoryStatus.WARNING}
>
<div data-testid="fizz">fizz</div>
</InfoAccordion>
)
const statusBar = getByTestId('advisory-status-bar')
expect(statusBar).toBeVisible()
expect(statusBar).toHaveStyle(`
background: repeating-linear-gradient(135deg, ${ADVISORY_RED_LINE} , ${ADVISORY_RED_LINE} 40px, white 40px, white 70px)
`)
})
it('should render an orange advisory status bar if provided an Advisory status', () => {
const { getByTestId } = render(
<InfoAccordion
defaultExpanded={true}
title="foo"
showAdvisoryStatusBar={true}
advisoryStatus={AdvisoryStatus.ADVISORY}
>
<div data-testid="fizz">fizz</div>
</InfoAccordion>
)
const statusBar = getByTestId('advisory-status-bar')
expect(statusBar).toBeVisible()
expect(statusBar).toHaveStyle(`
background: repeating-linear-gradient(135deg, ${ADVISORY_ORANGE_FILL} , ${ADVISORY_ORANGE_FILL} 40px, white 40px, white 70px)
`)
})
it('should render a grey advisory status bar if no status is provided or the status is undefined', () => {
const { queryByTestId } = render(
<InfoAccordion defaultExpanded={true} title="foo" showAdvisoryStatusBar={true} advisoryStatus={undefined}>
<div data-testid="fizz">fizz</div>
</InfoAccordion>
)
const statusBar = queryByTestId('advisory-status-bar')
expect(statusBar).toBeVisible()
expect(statusBar).toHaveStyle(`background: ${INFO_PANEL_CONTENT_BACKGROUND}`)
})
it('should not render an advisory status bar if showAdvisoryStatusBar is not set to true', () => {
const { queryByTestId } = render(
<InfoAccordion defaultExpanded={true} title="foo">
<div data-testid="fizz">fizz</div>
</InfoAccordion>
)
const statusBar = queryByTestId('advisory-status-bar')
expect(statusBar).not.toBeInTheDocument()
})
})
12 changes: 8 additions & 4 deletions web/src/features/fba/components/map/featureStylers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ const EMPTY_FILL = 'rgba(0, 0, 0, 0.0)'
export const ADVISORY_ORANGE_FILL = 'rgba(255, 147, 38, 0.4)'
export const ADVISORY_RED_FILL = 'rgba(128, 0, 0, 0.4)'

export const ADVISORY_RED_LINE = 'rgba(238, 0, 0, 1)'
export const ADVISORY_ORANGE_LINE = 'rgba(219, 135, 1, 1)'
const ADVISORY_GREY_LINE = 'rgba(127, 127, 127, 1)'

export const HFI_ADVISORY = 'rgba(255, 128, 0, 0.4)'
export const HFI_WARNING = 'rgba(255, 0, 0, 0.4)'

Expand Down Expand Up @@ -131,11 +135,11 @@ const getFireShapeStatus = (advisoryThreshold: number, fireShapeArea?: FireShape
const getFireShapeStrokeColor = (fireShapeStatus: FireShapeStatus) => {
switch (fireShapeStatus) {
case FireShapeStatus.ADVISORY:
return '#db8701'
return ADVISORY_ORANGE_LINE
case FireShapeStatus.WARNING:
return [227, 0, 1, 0.99]
return ADVISORY_RED_LINE
default:
return '#7f7f7f'
return ADVISORY_GREY_LINE
}
}

Expand Down Expand Up @@ -164,7 +168,7 @@ const getFireZoneUnitLabel = (feature: RenderFeature | ol.Feature<Geometry>) =>
const index = fireZoneUnit.indexOf('(')
const prefix = fireZoneUnit.substring(0, index).trim()
const suffix = fireZoneUnit.substring(index)
fireZoneUnit = `${prefix}\n${suffix}`
fireZoneUnit = `${prefix}\n${suffix}`
}

return `${fireZoneId}-${fireZoneUnit}`
Expand Down
Loading