Skip to content

Commit

Permalink
[Dashboard] Add SelectAll in regulatoryAreas filters
Browse files Browse the repository at this point in the history
  • Loading branch information
claire2212 committed Jan 28, 2025
1 parent 06674c0 commit 85b78f2
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 86 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { CustomPeriodContainer } from '@components/style'
import { getFilteredReportings } from '@features/Dashboard/slice'
import { StyledSelect } from '@features/Reportings/Filters/style'
import { useAppDispatch } from '@hooks/useAppDispatch'
Expand Down Expand Up @@ -92,7 +91,10 @@ export const Filters = forwardRef<HTMLDivElement, ComponentProps<'div'>>(({ ...p
$hasChildren={filteredReportings.length > 1}
$hasPeriodFilter={reportingFilters.dateRange === DateRangeEnum.CUSTOM}
>
<DateAndTypeWrapper $hasChildren={filteredReportings.length > 1}>
<FirstLine
$hasChildren={filteredReportings.length > 1}
$hasPeriodFilter={reportingFilters.dateRange === DateRangeEnum.CUSTOM}
>
<DateRangeSelect
cleanable={false}
isLabelHidden
Expand All @@ -102,6 +104,7 @@ export const Filters = forwardRef<HTMLDivElement, ComponentProps<'div'>>(({ ...p
onChange={setPeriodFilter}
options={dateRangeOptions}
placeholder="Date de signalement depuis"
style={{ width: '160px' }}
value={reportingFilters.dateRange}
/>
<Select
Expand All @@ -112,74 +115,61 @@ export const Filters = forwardRef<HTMLDivElement, ComponentProps<'div'>>(({ ...p
onChange={setTypeFilter}
options={typeOptions}
placeholder="Type de signalement"
style={{ width: '160px' }}
value={reportingFilters.type}
/>
</DateAndTypeWrapper>
<SpecificDateAndStatusWrapper $hasChildren={filteredReportings.length > 0}>
{reportingFilters.dateRange === DateRangeEnum.CUSTOM && (
<CustomPeriodContainer>
<DateRangePicker
key="dateRange"
baseContainer={newWindowContainerRef.current}
defaultValue={reportingFilters.period}
isLabelHidden
isStringDate
label="Période spécifique"
name="dateRange"
onChange={setCustomPeriodFilter}
/>
</CustomPeriodContainer>
)}

<StatusWrapper>
{statusOptions.map(statusOption => (
<Checkbox
key={statusOption.label}
checked={reportingFilters.status.includes(statusOption.value as StatusFilterEnum)}
label={statusOption.label}
name={statusOption.label}
onChange={isChecked => setStatusFilter(statusOption, isChecked)}
/>
))}
</StatusWrapper>
</SpecificDateAndStatusWrapper>

{statusOptions.map(statusOption => (
<StyledCheckbox
key={statusOption.label}
checked={reportingFilters.status.includes(statusOption.value as StatusFilterEnum)}
label={statusOption.label}
name={statusOption.label}
onChange={isChecked => setStatusFilter(statusOption, isChecked)}
/>
))}
</FirstLine>

{reportingFilters.dateRange === DateRangeEnum.CUSTOM && (
<SecondLine $hasChildren={filteredReportings.length > 1}>
<DateRangePicker
key="dateRange"
baseContainer={newWindowContainerRef.current}
defaultValue={reportingFilters.period}
isLabelHidden
isStringDate
label="Période spécifique"
name="dateRange"
onChange={setCustomPeriodFilter}
/>
</SecondLine>
)}
</Wrapper>
)
})

const Wrapper = styled.div<{ $hasChildren: boolean; $hasPeriodFilter: boolean }>`
padding: 16px 24px;
${({ $hasChildren, $hasPeriodFilter }) => $hasPeriodFilter && !$hasChildren && 'padding-bottom: 58px;'}
${({ $hasChildren, $hasPeriodFilter }) => $hasPeriodFilter && !$hasChildren && 'padding-bottom: 84px;'}
${({ $hasChildren }) =>
$hasChildren
? 'display: flex; flex-direction: column; gap: 16px; justify-content: space-between;'
: 'display: flow-root;'}
`
const StatusWrapper = styled.fieldset`
border: none;
display: flex;
gap: 16px;
float: right;
padding-bottom: 16px;
`
const DateAndTypeWrapper = styled.div<{ $hasChildren: boolean }>`
display: flex;
gap: 16px;
${p => !p.$hasChildren && 'position: absolute;'}
z-index: 2;
$hasChildren ? 'display: flex; flex-direction: column; justify-content: space-between;' : 'display: flow-root;'}
`

const SpecificDateAndStatusWrapper = styled.div<{ $hasChildren: boolean }>`
const FirstLine = styled.div<{ $hasChildren: boolean; $hasPeriodFilter: boolean }>`
display: flex;
gap: 16px;
${p => !p.$hasChildren && 'position: relative; top: 40px;'}
flex-wrap: wrap;
gap: 10px;
${p => !p.$hasChildren && 'position: absolute; z-index: 2;'}
${p => !p.$hasChildren && !p.$hasPeriodFilter && 'margin-bottom: 10px;'}
`

> fieldset {
padding-bottom: 0px;
padding-left: 0px;
}
const SecondLine = styled.div<{ $hasChildren: boolean }>`
${p => (p.$hasChildren ? 'margin-top: 10px;' : 'position: absolute; margin-top: 40px; z-index: 1;')}
`

const DateRangeSelect = styled(StyledSelect)`
width: 200px;
`
const StyledCheckbox = styled(Checkbox)`
justify-content: center;
`
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { VigilanceArea } from '@features/VigilanceArea/types'
import { useAppDispatch } from '@hooks/useAppDispatch'
import { useAppSelector } from '@hooks/useAppSelector'
import {
Checkbox,
CheckPicker,
CustomSearch,
getOptionsFromLabelledEnum,
Expand All @@ -22,8 +23,6 @@ type FiltersProps = {
dashboard: DashboardType
}

const ALL_REGULATOY_AREAS = 'ALL_REGULATOY_AREAS'

export function DashboardFilters({ dashboard }: FiltersProps) {
const dispatch = useAppDispatch()
const { extractedArea } = dashboard
Expand All @@ -43,39 +42,43 @@ export function DashboardFilters({ dashboard }: FiltersProps) {
const vigilanceAreaPeriodOptions = getOptionsFromLabelledEnum(VigilanceArea.VigilanceAreaFilterPeriodLabel)

const setFilteredRegulatoryThemes = (value: string[] | undefined) => {
if (filters?.regulatoryThemes?.includes(ALL_REGULATOY_AREAS) && !value?.includes(ALL_REGULATOY_AREAS)) {
dispatch(dashboardFiltersActions.setFilters({ filters: { regulatoryThemes: [] }, id }))
dispatch(dashboardFiltersActions.setFilters({ filters: { regulatoryThemes: value }, id }))
}

return
}
const areAllRegulatoryChecked = useMemo(
() => filters?.regulatoryThemes?.length === regulatoryThemesAsOption?.length,
[filters?.regulatoryThemes, regulatoryThemesAsOption]
)

if (value?.includes('ALL')) {
// Delete one item when 'ALL_REGULATOY_AREAS' is selected
if (
filters?.regulatoryThemes &&
filters?.regulatoryThemes.length > 0 &&
filters?.regulatoryThemes.length > value?.length
) {
const filtersWithoutAll = value?.filter(filter => filter !== ALL_REGULATOY_AREAS)
dispatch(dashboardFiltersActions.setFilters({ filters: { regulatoryThemes: filtersWithoutAll }, id }))

return
}

// Select all
const allRegulatoryAreasIds = regulatoryThemesAsOption.map(regulatory => regulatory.value)
dispatch(
dashboardFiltersActions.setFilters({
filters: { regulatoryThemes: [ALL_REGULATOY_AREAS, ...allRegulatoryAreasIds] },
id
})
)
const indeterminate = useMemo(
() => filters?.regulatoryThemes && filters.regulatoryThemes.length > 0 && !areAllRegulatoryChecked,
[filters?.regulatoryThemes, areAllRegulatoryChecked]
)

const checkAll = () => {
if (areAllRegulatoryChecked) {
dispatch(dashboardFiltersActions.setFilters({ filters: { regulatoryThemes: undefined }, id }))

return
}
const allRegulatoryAreasIds = regulatoryThemesAsOption.map(regulatory => regulatory.value)

dispatch(dashboardFiltersActions.setFilters({ filters: { regulatoryThemes: value }, id }))
dispatch(dashboardFiltersActions.setFilters({ filters: { regulatoryThemes: allRegulatoryAreasIds }, id }))
}
const renderExtraFooter = () => (
<SelectAllRegulatoryAreasContainer>
<Checkbox
checked={areAllRegulatoryChecked}
indeterminate={indeterminate}
inline
label="Tout sélectionner"
name="selectAll"
onChange={checkAll}
>
Check all
</Checkbox>
</SelectAllRegulatoryAreasContainer>
)

const setFilteredAmpTypes = (value: string[] | undefined) => {
dispatch(dashboardFiltersActions.setFilters({ filters: { amps: value }, id }))
Expand All @@ -100,8 +103,9 @@ export function DashboardFilters({ dashboard }: FiltersProps) {
label="Thématique réglementaire"
name="regulatoryThemes"
onChange={setFilteredRegulatoryThemes}
options={[{ label: 'Tout sélectionner', value: ALL_REGULATOY_AREAS }, ...regulatoryThemesAsOption]}
options={regulatoryThemesAsOption}
placeholder="Thématique réglementaire"
renderExtraFooter={renderExtraFooter}
renderValue={() =>
filters?.regulatoryThemes && (
<OptionValue>{`Thématique réglementaire (${filters?.regulatoryThemes.length})`}</OptionValue>
Expand Down Expand Up @@ -167,3 +171,7 @@ const StyledButton = styled.button`
gap: 4px;
text-decoration: underline;
`
const SelectAllRegulatoryAreasContainer = styled.div`
border-top: 1px solid ${p => p.theme.color.lightGray};
padding: 8px;
`
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import { filterReportings } from './filterReportings'

describe('filterReportings', () => {
const today = customDayjs().utc()
const type = ReportingTypeEnum.INFRACTION_SUSPICION

describe('date range', () => {
const type = undefined
const status = [StatusFilterEnum.IN_PROGRESS]
it('should return true when reporting is within the day', async () => {
// Given
Expand Down Expand Up @@ -119,6 +119,7 @@ describe('filterReportings', () => {
})
})
describe('in progress reporting', () => {
const type = undefined
const status = [StatusFilterEnum.IN_PROGRESS]
it('should return true when reporting is in progress and within validity time', async () => {
// Given
Expand All @@ -143,6 +144,7 @@ describe('filterReportings', () => {
})
})
describe('archived reporting', () => {
const type = undefined
const status = [StatusFilterEnum.ARCHIVED]
it('should return true when reporting is archived and within validity time', async () => {
// Given
Expand All @@ -169,6 +171,7 @@ describe('filterReportings', () => {
})

describe('archived and in progress', () => {
const type = undefined
const status = [StatusFilterEnum.ARCHIVED, StatusFilterEnum.IN_PROGRESS]
it('should return true when reporting is archived and in progress', async () => {
// Given
Expand Down Expand Up @@ -204,6 +207,55 @@ describe('filterReportings', () => {
expect(filterReportings(reporting, { dateRange: DateRangeEnum.DAY, status, type })).toEqual(true)
})
})

describe('observation and infraction', () => {
const status = [StatusFilterEnum.ARCHIVED, StatusFilterEnum.IN_PROGRESS]
it('should return true when reporting is an observation', async () => {
// Given
const type = ReportingTypeEnum.OBSERVATION
const reporting: Reporting = aReporting({
createdAt: `${today.format('YYYY-MM-DDTHH:mm')}:00.000Z`,
reportType: ReportingTypeEnum.OBSERVATION
})

// When & then
expect(filterReportings(reporting, { dateRange: DateRangeEnum.DAY, status, type })).toEqual(true)
})
it('should return false when reporting is not observation', async () => {
// Given
const type = ReportingTypeEnum.OBSERVATION
const reporting: Reporting = aReporting({
createdAt: `${today.format('YYYY-MM-DDTHH:mm')}:00.000Z`,
reportType: ReportingTypeEnum.INFRACTION_SUSPICION
})

// When & then
expect(filterReportings(reporting, { dateRange: DateRangeEnum.DAY, status, type })).toEqual(false)
})

it('should return true when reporting is an infraction', async () => {
// Given
const type = ReportingTypeEnum.INFRACTION_SUSPICION
const reporting: Reporting = aReporting({
createdAt: `${today.format('YYYY-MM-DDTHH:mm')}:00.000Z`,
reportType: ReportingTypeEnum.INFRACTION_SUSPICION
})

// When & then
expect(filterReportings(reporting, { dateRange: DateRangeEnum.DAY, status, type })).toEqual(true)
})
it('should return false when reporting is an observation', async () => {
// Given
const type = ReportingTypeEnum.INFRACTION_SUSPICION
const reporting: Reporting = aReporting({
createdAt: `${today.format('YYYY-MM-DDTHH:mm')}:00.000Z`,
reportType: ReportingTypeEnum.OBSERVATION
})

// When & then
expect(filterReportings(reporting, { dateRange: DateRangeEnum.DAY, status, type })).toEqual(false)
})
})
})

const aReporting = (reporting?: Partial<Reporting>) => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export function filterReportings(
}
case DateRangeEnum.YEAR: {
const endOfDay = customDayjs().utc().endOf('day')
const lastThirtyDays = endOfDay.subtract(1, 'year')
const lastThirtyDays = customDayjs().utc().startOf('year').toISOString()

shouldBeFiltered = createdAt.isBetween(endOfDay, lastThirtyDays)
break
Expand Down

0 comments on commit 85b78f2

Please sign in to comment.