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 8 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
16 changes: 15 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,31 @@ 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}
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
70 changes: 54 additions & 16 deletions web/src/features/fba/components/infoPanel/InfoAccordion.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,42 @@
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) => {
switch (advisoryStatus) {
case AdvisoryStatus.WARNING:
return ADVISORY_RED_LINE
case AdvisoryStatus.ADVISORY:
return ADVISORY_ORANGE_FILL
default:
return INFO_PANEL_CONTENT_BACKGROUND
}
}
interface AdvisoryStatusBarProps {
barColour: string
}

const AdvisoryStatusBar = ({ barColour }: AdvisoryStatusBarProps) => (
<Box
data-testid="advisory-status-bar"
sx={{
height: '10px',
background: `repeating-linear-gradient(135deg, ${barColour}, ${barColour} 40px, white 40px, white 70px)`
}}
/>
)

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

const StyledAccordionSummary = styled(AccordionSummary)(() => ({
Expand All @@ -20,24 +47,35 @@ 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,
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>
{advisoryStatus && (
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a fan of the way the UI 'jumps' when switching between a fire zone unit that has an advisory/warning and one that doesn't. What do you think about removing this check for advisoryStatus and having the AdvisoryStatusBar display with the default background when there is no advisory status?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, can do something that. Will need to sort out some different styling logic in that case, otherwise every drop down will have a grey/white hash bar

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, definitely don't want a grey/white hashbar anywhere. I'm thinking just a solid bar all the time when there is no advisoryStatus.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 0b29a3b. Added showAdvisoryStatusBar so we don't also get an extra 10px grey bar on the stats dropdown, thoughts?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great!

<AdvisoryStatusBar data-testid="advisory-status-bar" barColour={getAdvisoryBarColour(advisoryStatus)} />
)}
</Box>
<AccordionDetails
data-testid="info-accordion-details"
sx={{
Expand Down
36 changes: 35 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,7 @@

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'

describe('InfoAccordion', () => {
it('should render', () => {
Expand Down Expand Up @@ -58,4 +59,37 @@ 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" 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" 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 not render an advisory status bar if no status is provided or the status is undefined', () => {
const { queryByTestId } = render(
<InfoAccordion defaultExpanded={true} title="foo" advisoryStatus={undefined}>
<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