Skip to content

Commit

Permalink
feat(procu): add manual processing by slot (#3028)
Browse files Browse the repository at this point in the history
  • Loading branch information
OverGlass committed Jun 19, 2024
1 parent 74af1b9 commit 8dbe0f6
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 50 deletions.
21 changes: 21 additions & 0 deletions src/api/Procuration/Hooks/useProcurationProxySlotState.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { useErrorHandler } from '~/components/shared/error/hooks'
import { ProcurationService, ProcurationServiceKey } from '../procuration.service'
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { addBreadcrumb } from '@sentry/react'

export default function useProcurationProxySlotState() {
const { handleError } = useErrorHandler()
const client = useQueryClient()

return useMutation({
mutationFn: ProcurationService.updateProxySlot,
onSettled: () =>
client.invalidateQueries({
queryKey: [ProcurationServiceKey.availableProxies],
}),
onError: (error: Error) => {
addBreadcrumb({ message: 'Error while matching procuration' })
handleError(error)
},
})
}
21 changes: 21 additions & 0 deletions src/api/Procuration/Hooks/useProcurationRequestSlotState.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { useErrorHandler } from '~/components/shared/error/hooks'
import { ProcurationService, ProcurationServiceKey } from '../procuration.service'
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { addBreadcrumb } from '@sentry/react'

export default function useProcurationRequestSlotState() {
const { handleError } = useErrorHandler()
const client = useQueryClient()

return useMutation({
mutationFn: ProcurationService.updateRequestSlot,
onSettled: () =>
client.invalidateQueries({
queryKey: [ProcurationServiceKey.request],
}),
onError: (error: Error) => {
addBreadcrumb({ message: 'Error while matching procuration' })
handleError(error)
},
})
}
1 change: 1 addition & 0 deletions src/api/Procuration/procuration.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export interface SlotModel {
uuid: string
created_at: string
round: RoundModel
manual: boolean
request: null | ProcurationProxyDetailModel
proxy: null | ProcurationProxyDetailModel
}
Expand Down
7 changes: 7 additions & 0 deletions src/api/Procuration/procuration.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export const ProcurationServiceKey = {

const base = 'v3/procuration/requests'
const proxyBase = 'v3/procuration/proxies'
const slotBase = 'v3/procuration/request_slots'
const proxySlotBase = 'v3/procuration/proxy_slots'

export const ProcurationService = {
listRequests: ({ params, signal }: PaginatedApiQueryBaseModel): Promise<PaginatedDataModel<ProcurationModel>> =>
Expand Down Expand Up @@ -51,6 +53,11 @@ export const ProcurationService = {
}),
update: ({ uuid, status }: { uuid: string; status: ProcurationStatusEnum }) =>
apiClient.patch(`${base}/${uuid}`, { status }),
updateProxySlot: ({ uuid, payload }: { uuid: string; payload: { manual: boolean } }) =>
apiClient.put(`${proxySlotBase}/${uuid}`, payload),

updateRequestSlot: ({ uuid, payload }: { uuid: string; payload: { manual: boolean } }) =>
apiClient.put(`${slotBase}/${uuid}`, payload),
updateProxy: ({ uuid, status }: { uuid: string; status: ProcurationStatusEnum }) =>
apiClient.patch(`${proxyBase}/${uuid}`, { status }),
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ import {
} from '~/components/Procurations/Components/MandantTab/Components/MandatePersonCard/MandatePersonCard'

export default function MandatePersonCardButtonGroup(
props: { fullWidth?: boolean; extraText?: string } & Omit<MandatePersonCardProps, 'onSelect'> & {
props: { fullWidth?: boolean; extraText?: string; disabled?: boolean } & Omit<MandatePersonCardProps, 'onSelect'> & {
onSelect: () => void
}
) {
switch (props.type) {
case MandatePersonCardType.FIND:
return (
<Button onClick={props.onSelect} variant={'contained'} fullWidth={props.fullWidth}>
<Button onClick={props.onSelect} variant={'contained'} fullWidth={props.fullWidth} disabled={props.disabled}>
Trouver un mandataire {props.extraText}
</Button>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,40 +1,80 @@
import { useCallback, useState } from 'react'
import useProcurationProxyState from '~/api/Procuration/Hooks/useProcurationProxyState'
import useProcurationState from '~/api/Procuration/Hooks/useProcurationState'
import { ProcurationStatusEnum } from '~/api/Procuration/procuration.model'
import { ProcurationStatusEnum, SlotModel } from '~/api/Procuration/procuration.model'
import { Button, Grid } from '@mui/material'
import { MuiSpacing } from '~/theme/spacing'
import ConfirmationModal from '~/ui/Confirmation'
import {
MandatePersonCardProps,
MandatePersonCardType,
} from '~/components/Procurations/Components/MandantTab/Components/MandatePersonCard/MandatePersonCard'
import useProcurationRequestSlotState from '~/api/Procuration/Hooks/useProcurationRequestSlotState'
import useProcurationProxySlotState from '~/api/Procuration/Hooks/useProcurationProxySlotState'

export default function MandatePersonCardStateActions(props: MandatePersonCardProps) {
const [shouldConfirmExclude, setShouldConfirmExclude] = useState(false)
export function MandatePersonCardStateManual({
currentSlot,
...props
}: MandatePersonCardProps & { currentSlot: Omit<SlotModel, 'proxy'> }) {
const [shouldConfirmManual, setShouldConfirmManual] = useState(false)

const isProxy = [MandatePersonCardType.MATCH_PROXY, MandatePersonCardType.MATCHED_PROXY].includes(props.type)
const { mutateAsync, isLoading } = isProxy ? useProcurationProxyState() : useProcurationState()
const { mutateAsync, isLoading } = isProxy ? useProcurationProxySlotState() : useProcurationRequestSlotState()

const onManual = useCallback(() => {
if (!props.uuid) {
if (!currentSlot.uuid) {
return
}

if (shouldConfirmManual) {
mutateAsync({
status: ProcurationStatusEnum.MANUAL,
uuid: props.uuid,
payload: {
manual: !currentSlot.manual,
},
uuid: currentSlot.uuid,
}).then(() => {
setShouldConfirmManual(false)
})
} else {
setShouldConfirmManual(true)
}
}, [mutateAsync, props.uuid, shouldConfirmManual])
}, [mutateAsync, currentSlot.uuid, shouldConfirmManual, currentSlot.manual])
const onCancelManual = useCallback(() => setShouldConfirmManual(false), [])

const modalDescription = currentSlot.manual
? `Êtes-vous sûr de vouloir retirer le traitement manuel du ${currentSlot.round.name} de ${props.firstName} ?`
: `Êtes-vous sûr de vouloir passer en traitement manuel le ${currentSlot.round.name} de ${props.firstName} ?`

return (
<>
{!isProxy && (
<Button
variant={'soft'}
fullWidth
color={currentSlot.manual ? 'warning' : 'inherit'}
disabled={isLoading || shouldConfirmManual}
onClick={onManual}
>
{currentSlot.manual ? 'Retirer le traitement manuel' : 'Traité manuellement'}
</Button>
)}

{shouldConfirmManual && (
<ConfirmationModal
title={'Traitement manuel'}
description={modalDescription}
onConfirm={onManual}
onCancel={onCancelManual}
isLoading={isLoading}
/>
)}
</>
)
}

export function MandatePersonCardStateExclude(props: MandatePersonCardProps) {
const [shouldConfirmExclude, setShouldConfirmExclude] = useState(false)
const isProxy = [MandatePersonCardType.MATCH_PROXY, MandatePersonCardType.MATCHED_PROXY].includes(props.type)
const { mutateAsync, isLoading } = isProxy ? useProcurationProxyState() : useProcurationState()

const onExclude = useCallback(() => {
if (!props.uuid) {
return
Expand All @@ -55,19 +95,10 @@ export default function MandatePersonCardStateActions(props: MandatePersonCardPr

return (
<>
<Grid item container mb={MuiSpacing.normal}>
{!isProxy && (
<Grid item xs={6}>
<Button variant="soft" color="inherit" disabled={isLoading || shouldConfirmManual} onClick={onManual}>
Traité manuellement
</Button>
</Grid>
)}
<Grid item xs={isProxy ? 12 : 6} textAlign="right">
<Button variant="soft" color="error" disabled={isLoading || shouldConfirmExclude} onClick={onExclude}>
Exclure
</Button>
</Grid>
<Grid item textAlign="right">
<Button variant="soft" color="error" disabled={isLoading || shouldConfirmExclude} onClick={onExclude}>
Exclure
</Button>
</Grid>

{shouldConfirmExclude && (
Expand All @@ -80,16 +111,6 @@ export default function MandatePersonCardStateActions(props: MandatePersonCardPr
isLoading={isLoading}
/>
)}

{shouldConfirmManual && (
<ConfirmationModal
title={'Traitement manuel'}
description={`Êtes-vous sûr de vouloir passer en "traité manuellement" ${props.firstName} ?`}
onConfirm={onManual}
onCancel={onCancelManual}
isLoading={isLoading}
/>
)}
</>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ import { grey, success, tagsColor } from '~/theme/palette'
import { MuiSpacing, withBottomSpacing } from '~/theme/spacing'
import { fontWeight } from '~/theme/typography'
import { UIChip } from '~/ui/Card'
import MandatePersonCardStateActions from '~/components/Procurations/Components/MandantTab/Components/MandatePersonCard/Components/MandatePersonCardStateActions'
import {
MandatePersonCardStateManual,
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 { getFormattedDate } from '~/utils/date'
Expand Down Expand Up @@ -67,6 +70,9 @@ export default function MandatePersonCard(props: MandatePersonCardProps) {
<Grid item xs={6} md={8} lg={6}>
<PersonWithAvatar firstName={props.firstName} lastName={props.lastName} src={props.avatarUrl} id={props.id} />
</Grid>
<Grid item xs={6} md={8} lg={6}>
{!props.hideStateActions && <MandatePersonCardStateExclude {...props} />}
</Grid>

<Grid item container gap={0.5} xs={12}>
{[
Expand Down Expand Up @@ -103,20 +109,31 @@ export default function MandatePersonCard(props: MandatePersonCardProps) {
</Typography>
</Grid>

{props.type === MandatePersonCardType.FIND || props.roundId === x.round.uuid ? (
<Grid key={x.uuid} item xs={12} pb={2}>
{x.proxy.length < 1 && (
<>
<MandatePersonCardButtonGroup
fullWidth
{...props}
onSelect={() => props.onSelect?.(x.round.uuid)}
extraText={x.round.name}
/>
</>
)}
<Grid container justifyItems="center">
{props.type === MandatePersonCardType.FIND || props.roundId === x.round.uuid ? (
<>
<Grid item xs={8} pb={2} pr={MuiSpacing.normal}>
{x.proxy.length < 1 && (
<MandatePersonCardButtonGroup
fullWidth
{...props}
disabled={x.manual}
onSelect={() => props.onSelect?.(x.round.uuid)}
extraText={x.round.name}
/>
)}
</Grid>
<Grid item xs={4}>
<MandatePersonCardStateManual {...props} currentSlot={x} />
</Grid>
</>
) : null}
</Grid>
{[MandatePersonCardType.MATCHED_MANDANT].includes(props.type) && x.manual && (
<Grid item xs={12}>
<MandatePersonCardStateManual {...props} currentSlot={x} />
</Grid>
) : null}
)}

{x.proxy !== undefined &&
[MandatePersonCardType.MATCH_PROXY, MandatePersonCardType.MATCHED_PROXY].includes(props.type) && (
Expand Down Expand Up @@ -191,7 +208,6 @@ export default function MandatePersonCard(props: MandatePersonCardProps) {

{props.extraInfos && <Divider sx={withBottomSpacing} />}

{!props.hideStateActions && <MandatePersonCardStateActions {...props} />}
{!props.expended && props.onExpend && <ExpandButton onExpand={() => props.onExpend?.(props.id)} />}

{props.expended && (
Expand Down

0 comments on commit 8dbe0f6

Please sign in to comment.