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

feat: show DGFIP address on owner edition modals #1001

Merged
merged 12 commits into from
Nov 22, 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
2 changes: 2 additions & 0 deletions frontend/src/colors.scss
Original file line number Diff line number Diff line change
Expand Up @@ -314,4 +314,6 @@
--beige-gris-galet-moon-125: #2e2924;
--beige-gris-galet-moon-100: #28231f;
--beige-gris-galet-moon-75: #211d19;


}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { fr } from '@codegouvfr/react-dsfr';
import Input, { InputProps } from '@codegouvfr/react-dsfr/Input';
import Autocomplete from '@mui/material/Autocomplete';
import Typography from '@mui/material/Typography';
import Grid from '@mui/material/Unstable_Grid2';
import { useDebounce, useList, usePreviousDistinct } from 'react-use';
import type { MarkOptional } from 'ts-essentials';
Expand Down Expand Up @@ -86,17 +85,6 @@ function AddressSearchableSelectNext(props: Props) {
justifyContent="space-between"
sm
>
<Typography component="span">
Adresse (source : 
<a
href="https://adresse.data.gouv.fr/base-adresse-nationale#4.4/46.9/1.7"
rel="noreferrer"
target="_blank"
>
Base Adresse Nationale
</a>
)
</Typography>
<a
className={fr.cx('fr-link--sm')}
href="https://zerologementvacant.crisp.help/fr/article/comment-choisir-entre-ladresse-ban-et-ladresse-lovac-1ivvuep/?bust=1705403706774"
Expand All @@ -107,7 +95,7 @@ function AddressSearchableSelectNext(props: Props) {
</a>
</Grid>
}
hintText="Commencez à taper votre recherche dans le champ de saisi et choisissez une des options proposées dans la liste (exemple : 72 rue de Varenne, Paris)"
hintText="Cette adresse est la plus proche identifiée dans la Base Adresse Nationale. Ce format est recommandé pour vos courriers. Pour modifier l'adresse, commencez à saisir votre recherche et choisissez une des options dans la liste."
nativeInputProps={{
type: 'search',
placeholder: 'Rechercher une adresse',
Expand Down
8 changes: 5 additions & 3 deletions frontend/src/components/HousingList/HousingList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,11 @@ const HousingList = ({
name: 'address',
headerRender: () => getSortButton('rawAddress', 'Adresse du logement'),
render: ({ id, rawAddress }: Housing) => (
<AppLink className="capitalize" isSimple to={`/logements/${id}`}>
{rawAddress.map((line) => capitalize(line)).join('\n')}
</AppLink>
<>
<AppLink className="capitalize" isSimple to={`/logements/${id}`}>
{rawAddress.map((line) => capitalize(line)).join('\n')}
</AppLink>
</>
)
};

Expand Down
123 changes: 12 additions & 111 deletions frontend/src/components/OwnerAddressEdition/OwnerAddressEdition.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import Button from '@codegouvfr/react-dsfr/Button';
import ButtonsGroup from '@codegouvfr/react-dsfr/ButtonsGroup';
import Typography from '@mui/material/Typography';
import { useState } from 'react';

import { Text } from '../_dsfr';
import { Address, isBanEligible } from '../../models/Address';
import { AddressSearchResult } from '../../services/address.service';
import AddressSearchableSelectNext from '../AddressSearchableSelect/AddressSearchableSelectNext';
import CallOut from '@codegouvfr/react-dsfr/CallOut';

interface Props {
banAddress?: Address;
Expand All @@ -15,66 +12,15 @@ interface Props {
help?: boolean;
rawAddress: string[];
onSelectAddress(address: AddressSearchResult | null): void;
warningVisible: boolean;
setWarningVisible: (visible: boolean) => void;
}

function OwnerAddressEdition(props: Props) {
const [searchAddressFromLovac, setSearchAddressFromLovac] = useState(false);
const [previousAddress, setPreviousAddress] = useState<AddressSearchResult>();

const [inputValue, setInputValue] = useState('');
const [open, setOpen] = useState(false);

if (searchAddressFromLovac) {
return (
<>
<AddressSearchableSelectNext
className="fr-mb-2w"
disabled={props.disabled}
value={props.banAddress ?? null}
inputValue={inputValue}
open={open}
onChange={(address) => {
props.onSelectAddress(
address
? {
...address,
banId: address.banId ?? '',
latitude: address.latitude ?? 0,
longitude: address.longitude ?? 0,
// Consider that the user has validated the address
score: 1
}
: null
);
}}
onInputChange={setInputValue}
onOpen={() => setOpen(true)}
onClose={() => setOpen(false)}
stateRelatedMessage={props.errorMessage}
/>
{previousAddress && (
<div className="fr-p-2w fr-mb-2w bg-bf975">
<Typography mb={2}>Adresse précédente :</Typography>
<Typography mb={2} sx={{ fontWeight: 900 }}>
{previousAddress.label}
</Typography>
<div className="align-right">
<Button
priority="secondary"
onClick={() => {
setSearchAddressFromLovac(false);
props.onSelectAddress(previousAddress);
}}
>
Appliquer
</Button>
</div>
</div>
)}
</>
);
}

return (
<>
<AddressSearchableSelectNext
Expand All @@ -101,60 +47,15 @@ function OwnerAddressEdition(props: Props) {
onOpen={() => setOpen(true)}
onClose={() => setOpen(false)}
/>
{props.banAddress && !isBanEligible(props.banAddress) && (
<div className="fr-mt-3w fr-p-2w bg-bf975">
<Text size="md" className="color-info-425 weight-900">
Amélioration possible
</Text>
<Typography mb={2}>
L’adresse issue de la <u>Base Adresse Nationale</u>, indiquée dans
le champ Adresse ci-dessus, semble différente de l’adresse issue de
la <u>DGFIP</u> : <b>{props.rawAddress.join(' ')}</b>
</Typography>
<Typography mb={2}>
Modifier le champ Adresse à partir de l’adresse DGFIP ?
</Typography>
<ButtonsGroup
buttons={[
{
children: 'Oui',
priority: 'secondary',
onClick: () => {
if (props.banAddress) {
setPreviousAddress({
...props.banAddress,
banId: props.banAddress.banId ?? '',
latitude: props.banAddress.latitude ?? 0,
longitude: props.banAddress.longitude ?? 0,
score: props.banAddress.score ?? Number.NaN
});
}
setInputValue(props.rawAddress.join(' '));
setSearchAddressFromLovac(true);
setOpen(true);
}
},
{
children: 'Non',
priority: 'secondary',
onClick: () => {
if (props.banAddress) {
props.onSelectAddress({
...props.banAddress,
banId: props.banAddress.banId ?? '',
latitude: props.banAddress.latitude ?? 0,
longitude: props.banAddress.longitude ?? 0,
// Consider that the user has validated the address
score: 1
});
}
}
}
]}
alignment="left"
inlineLayoutWhen="sm and up"
></ButtonsGroup>
</div>
{props.warningVisible && !isBanEligible(props.banAddress) && (
<CallOut
className="fr-mt-3w"
buttonProps={{
children: 'Ignorer',
onClick: () => {props.setWarningVisible(false);},
}}>
L’adresse de la Base Adresse Nationale diffère de celle de la DGFIP. Veuillez vérifier attentivement ces informations ou ignorez l’alerte.
</CallOut>
)}
</>
);
Expand Down
35 changes: 21 additions & 14 deletions frontend/src/components/OwnerCard/OwnerCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,6 @@ function OwnerCard(props: OwnerCardProps) {
const archivedOwners =
props.coOwners?.filter((owner) => owner.rank <= 0) ?? [];

const address: ReadonlyArray<ReactNode> = (
props.owner.banAddress
? formatAddress(props.owner.banAddress)
: props.owner.rawAddress
).map((line: string) => <Typography key={line}>{line}</Typography>);

return (
<Paper component="article" elevation={0} sx={{ padding: 3 }}>
<Grid component="header" container sx={{ mb: 1 }}>
Expand Down Expand Up @@ -64,6 +58,22 @@ function OwnerCard(props: OwnerCardProps) {
</Grid>
) : null}

<Grid xs={12}>
<LabelNext component="h3">
<span
className={fr.cx(
'fr-icon-bank-line',
'fr-icon--sm',
'fr-mr-1w'
)}
aria-hidden={true}
/>
Adresse fiscale (source: DGFIP)
</LabelNext>
<Typography color={fr.colors.decisions.text.default.grey.default}>{props.owner.rawAddress ? props.owner.rawAddress.join(' ') : 'Inconnue'}</Typography>
</Grid>


<Grid xs={12}>
<LabelNext component="h3">
<span
Expand All @@ -74,27 +84,24 @@ function OwnerCard(props: OwnerCardProps) {
)}
aria-hidden={true}
/>
Adresse postale
Adresse postale (source: Base Adresse Nationale)
</LabelNext>
<Typography>{address}</Typography>
<Typography>{props.owner.banAddress ? formatAddress(props.owner.banAddress).join(' ') : 'Inconnue'}</Typography>
</Grid>


{!isBanEligible(props.owner.banAddress) && (
<Grid xs={12}>
<Alert
severity="info"
classes={{ title: fr.cx('fr-mb-2w') }}
title="Adresse à vérifier"
as="h3"
description={
<>
<Typography>
Cette adresse issue de la BAN est différente de l’adresse
fiscale.
L’adresse Base Adresse Nationale ne correspond pas à celle de la DGFIP.
</Typography>
<Typography>
Cliquez sur “Modifier” pour valider l’adresse que vous
souhaitez utiliser.
Nous vous recommandons de vérifier en cliquant sur &quot;Modifier&quot;.
</Typography>
</>
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { fr } from '@codegouvfr/react-dsfr';
import Button from '@codegouvfr/react-dsfr/Button';
import { FormEvent, useState } from 'react';
import { object, string } from 'yup';
Expand All @@ -10,6 +11,7 @@ import { Owner } from '../../models/Owner';
import { banAddressValidator, useForm } from '../../hooks/useForm';
import { useUpdateOwnerMutation } from '../../services/owner.service';
import { useNotification } from '../../hooks/useNotification';
import { Grid, Typography } from '@mui/material';

interface Props {
className?: string;
Expand All @@ -19,24 +21,24 @@ interface Props {
function OwnerEditionSideMenu(props: Props) {
const { active, setActive, toggle } = useToggle();

const storedWarningVisible = localStorage.getItem('OwnerEdition.warningVisible');
const [warningVisible, setWarningVisible] = useState(storedWarningVisible === null || storedWarningVisible === 'true');

const shape = {
fullName: string().optional(),
address: banAddressValidator.optional(),
additionalAddress: string().optional().nullable()
};
type FormShape = typeof shape;
const schema = object(shape);

const [fullName, setFullName] = useState(props.owner.fullName);
const [address, setAddress] = useState(props.owner.banAddress);
const [additionalAddress, setAdditionalAddress] = useState(
props.owner.additionalAddress ?? ''
);
const formId = 'owner-edition-form';
const form = useForm(schema, {
address,
additionalAddress,
fullName
additionalAddress
});

function open(): void {
Expand All @@ -50,11 +52,11 @@ function OwnerEditionSideMenu(props: Props) {
const [updateOwner, mutation] = useUpdateOwnerMutation();

async function save(event: FormEvent): Promise<void> {
localStorage.setItem('OwnerEdition.warningVisible', warningVisible.toString());
event.preventDefault();
await form.validate(async () => {
await updateOwner({
...props.owner,
fullName,
banAddress: address,
additionalAddress
}).unwrap();
Expand Down Expand Up @@ -97,20 +99,43 @@ function OwnerEditionSideMenu(props: Props) {
title="Modifier les informations du propriétaire"
content={
<form id={formId} className="fr-px-6w">
<AppTextInput<FormShape>
inputForm={form}
inputKey="fullName"
label="Nom prénom"
value={fullName}
onChange={(e) => setFullName(e.target.value)}
/>
<section className="fr-mb-3w">
<Grid container>
<Typography component="h3" color={fr.colors.decisions.text.active.grey.default}>
<span
className={fr.cx(
'fr-icon-bank-line',
'fr-icon--sm',
'fr-mr-1w'
)}
aria-hidden={true}
/>
Adresse fiscale (source: DGFIP)
</Typography>
<Grid>
<span className='fr-hint-text'>Cette adresse est issue du fichier LOVAC, récupérée via le fichier 1767BIS-COM. Celle-ci n’est pas modifiable.</span>
<Typography color={fr.colors.decisions.text.default.grey.default}>{props.owner.rawAddress ? props.owner.rawAddress.join(' ') : 'Inconnue'}</Typography>
</Grid>
</Grid>
<section className="fr-mb-3w fr-mt-3w">
<Typography component="h3" color={fr.colors.decisions.text.active.grey.default}>
<span
className={fr.cx(
'fr-icon-home-4-line',
'fr-icon--sm',
'fr-mr-1w'
)}
aria-hidden={true}
/>
Adresse postale (source: Base Adresse Nationale)
</Typography>
<OwnerAddressEdition
banAddress={address}
errorMessage={form.message('address')}
help={false}
rawAddress={props.owner.rawAddress}
onSelectAddress={(value) => setAddress(value ?? undefined)}
warningVisible={warningVisible}
setWarningVisible={setWarningVisible}
/>
</section>
<AppTextInput<FormShape>
Expand Down
Loading
Loading