Skip to content

Commit

Permalink
Procuration - improve status filter (#3029)
Browse files Browse the repository at this point in the history
* Procuration - improve status filter

* Fix review
  • Loading branch information
ottaviano committed Jun 19, 2024
1 parent 8dbe0f6 commit acba132
Show file tree
Hide file tree
Showing 9 changed files with 113 additions and 97 deletions.
9 changes: 9 additions & 0 deletions src/api/Procuration/procuration.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export interface ProcurationProxyDetailModel extends EmailPhoneModel {
first_names: string
last_name: string
uuid: string
status: ProcurationStatusEnum
id: string
vote_place_name: string
vote_zone: VoteZoneModel
Expand Down Expand Up @@ -111,6 +112,14 @@ export enum ProcurationStatusEnum {
DUPLICATE = 'duplicate',
}

export const PROCURATION_STATUS_LABELS = {
[ProcurationStatusEnum.PENDING]: 'En attente',
[ProcurationStatusEnum.DUPLICATE]: 'Doublon',
[ProcurationStatusEnum.EXCLUDED]: 'Exclu',
[ProcurationStatusEnum.MANUAL]: 'Traité',
[ProcurationStatusEnum.COMPLETED]: 'Traité',
}

export interface AvailableProxyModel extends ProcurationModel {
slots?: number
requests?: ProcurationModel[]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { fireEvent, render } from '@testing-library/react'
import { faker } from '@faker-js/faker'
import { beforeAll, expect, vitest } from 'vitest'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { ProcurationStatusEnum } from '~/api/Procuration/procuration.model'

describe('Mandate person card', () => {
beforeAll(() => {
Expand All @@ -17,6 +18,7 @@ describe('Mandate person card', () => {
avatarUrl: faker.image.url(),
extraInfos: [],
firstName: faker.person.firstName(),
status: ProcurationStatusEnum.PENDING,
id: faker.string.uuid(),
lastName: faker.person.lastName(),
location: faker.person.jobArea(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ import {
MandatePersonCardStateExclude,
} from '~/components/Procurations/Components/MandantTab/Components/MandatePersonCard/Components/MandatePersonCardStateActions'
import MandatePersonCardButtonGroup from '~/components/Procurations/Components/MandantTab/Components/MandatePersonCard/Components/MandatePersonCardButtonGroup'
import { SlotModel } from '~/api/Procuration/procuration.model'
import { PROCURATION_STATUS_LABELS, ProcurationStatusEnum, SlotModel } from '~/api/Procuration/procuration.model'
import { getFormattedDate } from '~/utils/date'

export interface MandatePersonCardProps {
firstName: string
lastName: string
status: string
avatarUrl?: string
tags: LabelTypeModel[]
peopleInSameVotePlace?: number
Expand Down Expand Up @@ -79,11 +80,21 @@ export default function MandatePersonCard(props: MandatePersonCardProps) {
MandatePersonCardType.MATCH_MANDANT,
MandatePersonCardType.FIND,
MandatePersonCardType.MATCHED_MANDANT,
].includes(props.type) && <MandateTag done={props.type === MandatePersonCardType.MATCHED_MANDANT} />}
].includes(props.type) &&
((props.status !== ProcurationStatusEnum.PENDING && (
<>
<MandateTag status={'Mandant'} />
<MandateTag status={props.status} />
</>
)) || <MandateTag status={'Mandant'} />)}

{[MandatePersonCardType.MATCH_PROXY, MandatePersonCardType.MATCHED_PROXY].includes(props.type) && (
<ProxyTag done={props.type === MandatePersonCardType.MATCHED_PROXY} />
)}
{[MandatePersonCardType.MATCH_PROXY, MandatePersonCardType.MATCHED_PROXY].includes(props.type) &&
((props.status !== ProcurationStatusEnum.PENDING && (
<>
<ProxyTag status={'Mandataire'} />
<ProxyTag status={props.status} />
</>
)) || <ProxyTag status={'Mandataire'} />)}

{props.tags.map(tag => (
<UIChip
Expand Down Expand Up @@ -249,19 +260,19 @@ const ExpandButton = ({ onExpand }: { onExpand?: () => void }) => (
</Grid>
)

const MandateTag = ({ done }: { done?: boolean }) => (
const MandateTag = ({ status }: { status: string }) => (
<UIChip
label={done ? 'Mandant traité' : 'Mandant'}
label={PROCURATION_STATUS_LABELS[status] ?? status}
labelStyle={{ fontSize: '14px', fontWeight: fontWeight.medium }}
color={'white'}
variant={'contained'}
bgcolor={'#00B8D9'}
/>
)

const ProxyTag = ({ done }: { done?: boolean }) => (
const ProxyTag = ({ status }: { status: string }) => (
<UIChip
label={done ? 'Mandataire traité' : 'Mandataire'}
label={PROCURATION_STATUS_LABELS[status] ?? status}
labelStyle={{ fontSize: '14px', fontWeight: fontWeight.medium }}
color={'white'}
variant={'contained'}
Expand Down
20 changes: 17 additions & 3 deletions src/components/Procurations/Components/MandantTab/MandantTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,30 @@ interface Props {
done?: boolean
}

interface IFilters {
status: ProcurationStatusEnum[]
search?: string
}

export default function MandantTab({ done = false }: Props) {
const [expended, setExpended] = useState<Record<string, boolean>>({})
const [customFilters, setCustomFilers] = useState<Record<string, string>>({})
const [customFilters, setCustomFilers] = useState<IFilters>({
status: done
? [
ProcurationStatusEnum.COMPLETED,
ProcurationStatusEnum.DUPLICATE,
ProcurationStatusEnum.EXCLUDED,
ProcurationStatusEnum.MANUAL,
]
: [ProcurationStatusEnum.PENDING],
})
const debouncedFilters = useDebounce(customFilters, 400)

const { aggregate, total, isFetchingPreviousPage, isFetchingNextPage, hasNextPage, fetchNextPage, isInitialLoading } =
useProcurationRequestList({
order: {
createdAt: 'asc',
},
status: done ? ProcurationStatusEnum.COMPLETED : ProcurationStatusEnum.PENDING,
...debouncedFilters,
})

Expand Down Expand Up @@ -97,7 +110,7 @@ export default function MandantTab({ done = false }: Props) {
<Grid item xs sx={{ mb: MuiSpacing.normal }}>
<MandateFilters
onFilter={setCustomFilers}
status={done ? ProcurationStatusEnum.COMPLETED : ProcurationStatusEnum.PENDING}
status={debouncedFilters.status}
onToggleMore={onToggleMore}
advanced={done}
isRequest
Expand Down Expand Up @@ -193,6 +206,7 @@ const MandateItemComponent = ({
<MandatePersonCard
hideActions={done}
uuid={item.uuid}
status={item.status}
firstName={item.first_names}
lastName={item.last_name}
votePlace={item.vote_place_name}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,23 @@
import { Button, FormControl, Grid, InputLabel, MenuItem, Select, TextField, Typography } from '@mui/material'
import { Button, FormControl, Grid, InputLabel, MenuItem, Select, TextField } from '@mui/material'
import { grey } from '~/theme/palette'
import Iconify from '~/mui/iconify'
import { Controller, useForm } from 'react-hook-form'
import { MuiSpacing } from '~/theme/spacing'
import ModalBase from '~/components/ModalBase/ModalBase'
import { memo, useCallback, useState } from 'react'
import { ProcurationStatusEnum } from '~/api/Procuration/procuration.model'
import { fontWeight } from '~/theme/typography'

interface MandateFiltersProps {
onFilter: (data: Record<string, string>) => void
onFilter: (data: { status: ProcurationStatusEnum[]; search: string }) => void
onToggleMore: (newValue: boolean) => void
status: ProcurationStatusEnum[]
isRequest?: boolean
advanced?: boolean
status?: ProcurationStatusEnum
}

function MandateFilters({
onFilter,
onToggleMore,
status = ProcurationStatusEnum.PENDING,
status,
isRequest = false,
advanced = false,
}: Readonly<MandateFiltersProps>) {
Expand All @@ -29,85 +27,40 @@ function MandateFilters({
search: '',
},
})
const [showModal, setShowModal] = useState(false)
const [moreState, setMoreState] = useState(false)

const toggleModal = useCallback(() => setShowModal(v => !v), [])

const filterThenClose = useCallback(() => {
handleSubmit(onFilter)()
setShowModal(false)
}, [handleSubmit, onFilter])

const onToggleClick = useCallback(() => {
onToggleMore(!moreState)
setMoreState(v => !v)
}, [moreState, onToggleMore])

const registeredSearch = register('search')
const demandStateOptions = isRequest ? requestStatuses : defaultStatuses
const onSubmit = handleSubmit(onFilter)

return (
<form onSubmit={handleSubmit(onFilter)}>
<form onSubmit={onSubmit}>
<Grid container spacing={MuiSpacing.normal}>
<Grid item xs={12} sm={12} md={12} lg={6}>
<Grid item xs={12} sm={12} md={12} lg={4}>
<TextField
fullWidth
variant="outlined"
placeholder="Rechercher par prénom, nom, commune"
placeholder="Prénom, nom, commune, bureau de vote"
size="small"
label="Rechercher"
InputProps={{
startAdornment: <Iconify icon="eva:search-fill" color={grey[500]} sx={{ mr: 1 }} />,
}}
{...register('search')}
onChange={ev => {
onFilter({ search: ev.target.value })
registeredSearch.onChange(ev)
onSubmit()
}}
/>
</Grid>
<Grid item xs={12} sm={12} md={12} lg container spacing={MuiSpacing.normal}>
{advanced && (
<Grid item xs={6} lg={4}>
<Button variant="outlined" onClick={toggleModal} fullWidth>
Filtres
</Button>
</Grid>
)}
<Grid item xs={6} lg={8}>
<Button
variant="outlined"
onClick={onToggleClick}
fullWidth
startIcon={
<Iconify
icon={moreState ? 'eva:arrow-ios-upward-fill' : 'eva:arrow-ios-downward-fill'}
sx={{ mr: 1 }}
/>
}
>
{!moreState ? 'Ouvrir tous les volets' : 'Fermer tous les volets'}
</Button>
</Grid>
</Grid>
</Grid>

{showModal && (
<ModalBase pageOnMobile>
<Grid container spacing={MuiSpacing.normal}>
<Grid item sx={{ display: { xs: 'block', sm: 'none' } }}>
<Button startIcon={<Iconify icon="eva:arrow-ios-back-fill" />} onClick={toggleModal}>
Retour
</Button>
</Grid>

<Grid item xs>
<Typography fontSize={14} fontWeight={fontWeight.medium}>
Statut
</Typography>
</Grid>

<Grid item xs={12}>
<Grid item xs={6} lg={6}>
<FormControl fullWidth>
<InputLabel id="statuts-label" sx={{ bgcolor: 'white', px: MuiSpacing.smaller }}>
Statut
Expand All @@ -116,8 +69,17 @@ function MandateFilters({
name="status"
control={control}
render={({ field: { onChange, value } }) => (
<Select fullWidth labelId="statuts-label" onChange={onChange} value={value}>
<MenuItem value={undefined}>Tous</MenuItem>
<Select
fullWidth
size="small"
labelId="statuts-label"
onChange={ev => {
onChange(ev)
onSubmit()
}}
value={value}
multiple={true}
>
{demandStateOptions.map(el => (
<MenuItem key={el.label} value={el.value}>
{el.label}
Expand All @@ -128,22 +90,24 @@ function MandateFilters({
/>
</FormControl>
</Grid>

<Grid item xs={12} container spacing={MuiSpacing.small} justifyContent="flex-end">
<Grid item>
<Button onClick={toggleModal} fullWidth>
Annuler
</Button>
</Grid>
<Grid item>
<Button variant="contained" onClick={filterThenClose} fullWidth>
Filtrer
</Button>
</Grid>
</Grid>
)}
<Grid item xs={6} lg={6}>
<Button
variant="outlined"
onClick={onToggleClick}
fullWidth
startIcon={
<Iconify
icon={moreState ? 'eva:arrow-ios-upward-fill' : 'eva:arrow-ios-downward-fill'}
sx={{ mr: 1 }}
/>
}
>
{!moreState ? 'Ouvrir tous les volets' : 'Fermer tous les volets'}
</Button>
</Grid>
</ModalBase>
)}
</Grid>
</Grid>
</form>
)
}
Expand All @@ -153,16 +117,16 @@ const defaultStatuses: { label: string; value: ProcurationStatusEnum }[] = [
value: ProcurationStatusEnum.COMPLETED,
label: 'Terminé',
},
{
value: ProcurationStatusEnum.EXCLUDED,
label: 'Exclus',
},
{
value: ProcurationStatusEnum.DUPLICATE,
label: 'Doublon',
},
]

const requestStatuses = [
...defaultStatuses,
{ value: ProcurationStatusEnum.EXCLUDED, label: 'Exclus' },
{ value: ProcurationStatusEnum.MANUAL, label: 'Manuel' },
]
const requestStatuses = [...defaultStatuses, { value: ProcurationStatusEnum.MANUAL, label: 'Manuel' }]

export default memo(MandateFilters)
Loading

0 comments on commit acba132

Please sign in to comment.