Skip to content

Commit

Permalink
feat: signalement V1 (#919)
Browse files Browse the repository at this point in the history
* feat: signalement v1

* fix: no white list if the env var is undefined

* fix: request signalements context ignored instead of expired

* feat: retour atelier signalement Thumeries

* fix product tour

* fix: product tour

* fix: wrong fly to for creations

* fix: infinite loop on create adresse

* fix: add hook for map loaded

* review: add cadastre colors to const
  • Loading branch information
MaGOs92 authored Jan 2, 2025
1 parent 9611cd2 commit 0639832
Show file tree
Hide file tree
Showing 112 changed files with 4,788 additions and 1,571 deletions.
2 changes: 1 addition & 1 deletion .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ NEXT_PUBLIC_MATOMO_SITE_ID=
NEXT_PUBLIC_MATOMO_TRACKER_URL=https://stats.beta.gouv.fr/
NEXT_PUBLIC_BAL_ADMIN_URL=
NEXT_PUBLIC_API_SIGNALEMENT=
PORT=3000
PORT=3000
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ Elles peuvent être définies classiquement ou en créant un fichier `.env` sur
| `NEXT_PUBLIC_PEERTUBE` | URL du peertube |
| `NEXT_PUBLIC_MATOMO_TRACKER_URL` | URL du matomo |
| `NEXT_PUBLIC_MATOMO_SITE_ID` | Id du site sur matomo |
| `NEXT_PUBLIC_API_SIGNALEMENT` | URL de l'API signalement |
| `NEXT_PUBLIC_BAL_ADMIN_URL` | URL de base de bal admin |
| `PORT` | Port de l'application |

Expand Down
29 changes: 6 additions & 23 deletions components/bal/address-preview.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,14 @@
import { Pane, Text } from "evergreen-ui";

import { computeCompletNumero } from "@/lib/utils/numero";
import { CommuneType } from "@/types/commune";

const getAddressPreview = (numero, suffixe, toponyme, voie, commune) => {
const completNumero = computeCompletNumero(numero, suffixe) || "";
if (toponyme) {
return `${completNumero} ${voie}, ${toponyme} - ${commune.nom} (${commune.code})`;
}

if (voie) {
return `${completNumero} ${voie} - ${commune.nom} (${commune.code})`;
}

if (!voie && !toponyme) {
return `${completNumero} - ${commune.nom} (${commune.code})`;
}

return `${completNumero} ${voie} - ${commune.nom} (${commune.code})`;
};
import { getAddressPreview } from "@/lib/utils/address";

interface AddressPreviewProps {
numero: string | number;
suffixe?: string;
selectedNomToponyme: string;
voie: string;
commune: CommuneType;
selectedNomToponyme?: string;
voie?: string;
commune?: CommuneType;
}

function AddressPreview({
Expand All @@ -38,9 +21,9 @@ function AddressPreview({
const address = getAddressPreview(
numero,
suffixe,
commune,
selectedNomToponyme,
voie,
commune
voie
);

return (
Expand Down
13 changes: 10 additions & 3 deletions components/bal/commune-tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,20 @@ interface CommuneTabProps {
function CommuneTab({ commune, openRecoveryDialog }: CommuneTabProps) {
const { baseLocale } = useContext(BalDataContext);
const { token } = useContext(TokenContext);
const { signalements } = useContext(SignalementContext);
const { pendingSignalementsCount, archivedSignalementsCount } =
useContext(SignalementContext);

return (
<Pane overflowY="auto">
{!token && <ReadOnlyInfos openRecoveryDialog={openRecoveryDialog} />}
{signalements.length > 0 && (
<SignalementsInfos balId={baseLocale.id} signalements={signalements} />
{(pendingSignalementsCount > 0 || archivedSignalementsCount > 0) && (
<SignalementsInfos
balId={baseLocale.id}
signalementCounts={{
pending: pendingSignalementsCount,
archived: archivedSignalementsCount,
}}
/>
)}
{token && baseLocale.status !== BaseLocale.status.DEMO && (
<HabilitationInfos commune={commune} />
Expand Down
5 changes: 2 additions & 3 deletions components/bal/habilitation-infos.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,8 @@ function HabilitationInfos({ commune }: HabilitationInfosProps) {
}
>
<Text marginTop={5} is="p">
Cette Base Adresse Locale détient une habilitation permettant
d&apos;alimenter la Base Adresse Nationale pour la commune de{" "}
{commune.nom}. Cette habilitation est valide jusqu&apos;au{" "}
Toutes les modifications remonteront automatiquement dans la Base
Adresse Nationale jusqu&apos;au{" "}
<b>{format(new Date(habilitation.expiresAt), "dd/MM/yyyy")}</b>.
</Text>
</Alert>
Expand Down
6 changes: 3 additions & 3 deletions components/bal/numero-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ function NumeroEditor({
refreshBALSync,
reloadVoies,
} = useContext(BalDataContext);
const { selectedParcelles } = useContext(ParcellesContext);
const { highlightedParcelles } = useContext(ParcellesContext);
const { markers, suggestedNumero, setCompleteNumero } =
useContext(MarkersContext);
const { reloadTiles } = useContext(MapContext);
Expand Down Expand Up @@ -116,7 +116,7 @@ function NumeroEditor({
numero: Number(numero),
suffixe: suffixe?.length > 0 ? suffixe.toLowerCase().trim() : null,
comment: comment.length > 0 ? comment : null,
parcelles: selectedParcelles,
parcelles: highlightedParcelles,
certifie: certifie ?? (initialValue?.certifie || false),
};

Expand All @@ -143,7 +143,7 @@ function NumeroEditor({
certifie,
toponymeId,
comment,
selectedParcelles,
highlightedParcelles,
]);

const onFormSubmit = useCallback(
Expand Down
12 changes: 6 additions & 6 deletions components/bal/numero-editor/select-parcelles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ function SelectParcelles({
const { isCadastreDisplayed, setIsCadastreDisplayed } =
useContext(MapContext);
const {
selectedParcelles,
setSelectedParcelles,
highlightedParcelles,
setHighlightedParcelles,
setIsParcelleSelectionEnabled,
hoveredParcelle,
handleHoveredParcelle,
Expand All @@ -36,23 +36,23 @@ function SelectParcelles({
const addressType = isToponyme ? "toponyme" : "numéro";

useEffect(() => {
setSelectedParcelles(initialParcelles);
setHighlightedParcelles(initialParcelles);
setIsParcelleSelectionEnabled(true);

return () => {
setIsParcelleSelectionEnabled(false);
};
}, []);
}, [setHighlightedParcelles, setIsParcelleSelectionEnabled]);

Check warning on line 45 in components/bal/numero-editor/select-parcelles.tsx

View workflow job for this annotation

GitHub Actions / build (22.x)

React Hook useEffect has a missing dependency: 'initialParcelles'. Either include it or remove the dependency array

return (
<Pane display="flex" flexDirection="column">
<InputLabel
title="Parcelles cadastre"
help={`Depuis la carte, cliquez sur les parcelles que vous souhaitez ajouter au ${addressType}. En précisant les parcelles associées à cette adresse, vous accélérez sa réutilisation par de nombreux services, DDFiP, opérateurs de courrier, de fibre et de GPS.`}
/>
{selectedParcelles.length > 0 ? (
{highlightedParcelles.length > 0 ? (
<Pane display="grid" gridTemplateColumns="1fr 1fr 1fr">
{selectedParcelles.map((parcelle) => {
{highlightedParcelles.map((parcelle) => {
const isHovered = parcelle === hoveredParcelle?.id;

return (
Expand Down
61 changes: 47 additions & 14 deletions components/bal/signalement-infos.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,58 @@
import React from "react";
import NextLink from "next/link";
import { Pane, Text, Heading, Link } from "evergreen-ui";
import { Signalement } from "@/lib/openapi-signalement";
import { Pane, Heading, Button, Alert } from "evergreen-ui";
import { useRouter } from "next/navigation";

interface SignalementInfosProps {
balId: string;
signalements: Signalement[];
signalementCounts: {
pending: number;
archived: number;
};
}

function SignalementInfos({ balId, signalements }: SignalementInfosProps) {
function SignalementInfos({ balId, signalementCounts }: SignalementInfosProps) {
const router = useRouter();
const onClick = () => {
router.push(`/bal/${balId}/signalements`);
};

const signalementBtn = (
<Button
type="button"
onClick={onClick}
width="fit-content"
alignSelf="center"
appearance="primary"
>
Consulter les signalements
</Button>
);

return (
<Pane backgroundColor="white" padding={8} borderRadius={10} margin={8}>
<Pane
display="flex"
flexDirection="column"
backgroundColor="white"
padding={8}
borderRadius={10}
margin={8}
>
<Heading marginBottom={15}>Signalements</Heading>
<Text marginTop={5} is="p">
Vous avez <b>{signalements.length}</b>{" "}
{signalements.length > 1 ? "signalements" : "signalement"} en attente de
traitement.
</Text>
<Link is={NextLink} href={`/bal/${balId}/signalements`}>
Consulter les signalements
</Link>
{signalementCounts.pending > 0 ? (
<Alert
intent="info"
title={
<Pane fontWeight="normal">
Vous avez reçu <b>{signalementCounts.pending}</b>{" "}
{signalementCounts.pending > 1 ? "propositions" : "proposition"}.
</Pane>
}
>
<Pane marginTop="1rem">{signalementBtn}</Pane>
</Alert>
) : (
<Pane>{signalementBtn}</Pane>
)}
</Pane>
);
}
Expand Down
6 changes: 3 additions & 3 deletions components/bal/toponyme-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ function ToponymeEditor({
reloadNumeros,
} = useContext(BalDataContext);
const { markers } = useContext(MarkersContext);
const { selectedParcelles } = useContext(ParcellesContext);
const { highlightedParcelles } = useContext(ParcellesContext);
const [ref, setIsFocus] = useFocus(true);

const updateNumerosToponyme = useCallback(
Expand Down Expand Up @@ -89,7 +89,7 @@ function ToponymeEditor({
nom,
nomAlt: Object.keys(nomAlt).length > 0 ? nomAlt : null,
positions: [],
parcelles: selectedParcelles,
parcelles: highlightedParcelles,
};

if (markers) {
Expand Down Expand Up @@ -163,7 +163,7 @@ function ToponymeEditor({
nom,
nomAlt,
markers,
selectedParcelles,
highlightedParcelles,
setToponyme,
closeForm,
refreshBALSync,
Expand Down
16 changes: 16 additions & 0 deletions components/base-locale-card/base-locale-card-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ interface BaseLocaleCardContentProps {
onRemove?: (e: any) => void;
onHide?: (e: any) => void;
isShownHabilitationStatus?: boolean;
pendingSignalementsCount?: number;
}

function BaseLocaleCardContent({
Expand All @@ -50,6 +51,7 @@ function BaseLocaleCardContent({
onSelect,
onRemove,
onHide,
pendingSignalementsCount,
}: BaseLocaleCardContentProps) {
const { status, createdAt, emails } = baseLocale;
const { isMobile } = useContext(LayoutContext);
Expand Down Expand Up @@ -120,6 +122,20 @@ function BaseLocaleCardContent({
</Pane>
)}

{Boolean(pendingSignalementsCount) && (
<Pane
flex={1}
textAlign="center"
margin="auto"
{...(isMobile && { marginBottom: 10 })}
>
<Text display="block">Signalements</Text>
<Text fontWeight="bold" whiteSpace="nowrap">
{pendingSignalementsCount}
</Text>
</Pane>
)}

{commune && (
<Pane
flex={1}
Expand Down
21 changes: 21 additions & 0 deletions components/base-locale-card/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@ import { ApiGeoService } from "@/lib/geo-api";
import StatusBadge from "@/components/status-badge";
import BaseLocaleCardContent from "@/components/base-locale-card/base-locale-card-content";
import {
BaseLocale,
ExtendedBaseLocaleDTO,
HabilitationDTO,
HabilitationService,
OpenAPI,
} from "@/lib/openapi-api-bal";
import { CommuneApiGeoType } from "@/lib/geo-api/type";
import { Signalement, SignalementsService } from "@/lib/openapi-signalement";
import { canFetchSignalements } from "@/lib/utils/signalement";

const ADRESSE_URL =
process.env.NEXT_PUBLIC_ADRESSE_URL || "https://adresse.data.gouv.fr";
Expand Down Expand Up @@ -52,6 +55,8 @@ function BaseLocaleCard({
const [habilitation, setHabilitation] = useState<HabilitationDTO | null>(
null
);
const [pendingSignalementsCount, setPendingSignalementsCount] =
useState<number>();
const [isHabilitationValid, setIsHabilitationValid] =
useState<boolean>(false);
const [isOpen, setIsOpen] = useState(isAdmin ? isDefaultOpen : false);
Expand Down Expand Up @@ -100,11 +105,26 @@ function BaseLocaleCard({
Object.assign(OpenAPI, { TOKEN: null });
};

const fetchPendingSignalementsCount = async () => {
const paginatedSignalements = await SignalementsService.getSignalements(
1,
undefined,
[Signalement.status.PENDING],
undefined,
undefined,
[baseLocale.commune]
);
setPendingSignalementsCount(paginatedSignalements.total);
};

void fetchCommune();

if (!baseLocale.token) {
void fetchHabilitationIsValid();
} else {
if (canFetchSignalements(baseLocale, baseLocale.token)) {
void fetchPendingSignalementsCount();
}
void fetchHabilitation();
}
}, [baseLocale]);
Expand Down Expand Up @@ -181,6 +201,7 @@ function BaseLocaleCard({
onSelect={onSelect}
onRemove={onRemove}
onHide={onHide}
pendingSignalementsCount={pendingSignalementsCount}
/>
)}
</Card>
Expand Down
8 changes: 5 additions & 3 deletions components/bases-locales-list/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ interface BasesLocalesListProps {
basesLocales: ExtendedBaseLocaleDTO[];
}

const fuseOptions = {
keys: ["nom", "commune"],
};

function BasesLocalesList({ basesLocales }: BasesLocalesListProps) {
const { removeBAL, getHiddenBal, addHiddenBal } =
useContext(LocalStorageContext);
Expand All @@ -33,9 +37,7 @@ function BasesLocalesList({ basesLocales }: BasesLocalesListProps) {
Router.push(`/bal/${bal.id}`);
};

const [filtered, onFilter] = useFuse(basesLocales, 200, {
keys: ["nom", "commune"],
});
const [filtered, onFilter] = useFuse(basesLocales, 200, fuseOptions);

const onRemove = useCallback(async () => {
await removeBAL(toRemove);
Expand Down
Loading

0 comments on commit 0639832

Please sign in to comment.