From 777966d21d6399cecd2a346b35922860f21f0567 Mon Sep 17 00:00:00 2001 From: Marine Heckler Date: Tue, 19 Nov 2024 12:25:23 +0100 Subject: [PATCH] =?UTF-8?q?Export=20group=C3=A9=20des=20fiches=20actions?= =?UTF-8?q?=20au=20format=20pdf?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExportFicheActionButton.tsx | 16 +- .../ExportFicheActionGroupeesButton.tsx | 78 ++++++++ .../FicheActionPdf/Acteurs.tsx | 0 .../FicheActionPdf/ActionsLiees.tsx | 0 .../FicheActionPdf/Budget.tsx | 0 .../FicheActionPdf/Chemins.tsx | 2 +- .../FicheActionPdf/CreationFiche.tsx | 0 .../FicheActionPdf/Description.tsx | 0 .../FicheActionPdf/Documents.tsx | 4 +- .../FicheActionPdf/FicheActionPdf.tsx | 2 +- .../FicheActionPdf/FichesLiees.tsx | 4 +- .../FicheActionPdf/Indicateurs.tsx | 0 .../FicheActionPdf/Notes.tsx | 0 .../FicheActionPdf/NotesDeSuivi.tsx | 27 ++- .../FicheActionPdf/Pilotes.tsx | 2 +- .../FicheActionPdf/Planning.tsx | 0 .../FicheAction/Carte/FicheActionCard.tsx | 23 ++- .../MenuDescription.tsx | 2 +- .../FichesActionListe.tsx | 166 ++++++++++++++---- .../ToutesLesFichesAction.tsx | 6 +- .../src/ui/export-pdf/DocumentToExport.tsx | 77 ++++---- .../src/ui/export-pdf/ExportPDFButton.tsx | 34 +++- .../ui/export-pdf/assets/icons/EditIcon.tsx | 10 ++ .../src/ui/export-pdf/assets/icons/index.ts | 1 + .../src/ui/export-pdf/styles.ts | 6 +- .../src/components/tracking/trackingPlan.ts | 9 + packages/ui/src/design-system/Alert/Alert.tsx | 26 ++- .../src/design-system/Button/ButtonMenu.tsx | 2 +- packages/ui/src/design-system/Button/types.ts | 2 - 29 files changed, 370 insertions(+), 129 deletions(-) rename app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/{FicheAction/FicheActionDescription => ExportPdf}/ExportFicheActionButton.tsx (80%) create mode 100644 app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/ExportFicheActionGroupeesButton.tsx rename app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/{FicheAction => ExportPdf}/FicheActionPdf/Acteurs.tsx (100%) rename app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/{FicheAction => ExportPdf}/FicheActionPdf/ActionsLiees.tsx (100%) rename app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/{FicheAction => ExportPdf}/FicheActionPdf/Budget.tsx (100%) rename app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/{FicheAction => ExportPdf}/FicheActionPdf/Chemins.tsx (95%) rename app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/{FicheAction => ExportPdf}/FicheActionPdf/CreationFiche.tsx (100%) rename app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/{FicheAction => ExportPdf}/FicheActionPdf/Description.tsx (100%) rename app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/{FicheAction => ExportPdf}/FicheActionPdf/Documents.tsx (94%) rename app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/{FicheAction => ExportPdf}/FicheActionPdf/FicheActionPdf.tsx (97%) rename app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/{FicheAction => ExportPdf}/FicheActionPdf/FichesLiees.tsx (97%) rename app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/{FicheAction => ExportPdf}/FicheActionPdf/Indicateurs.tsx (100%) rename app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/{FicheAction => ExportPdf}/FicheActionPdf/Notes.tsx (100%) rename app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/{FicheAction => ExportPdf}/FicheActionPdf/NotesDeSuivi.tsx (64%) rename app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/{FicheAction => ExportPdf}/FicheActionPdf/Pilotes.tsx (93%) rename app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/{FicheAction => ExportPdf}/FicheActionPdf/Planning.tsx (100%) create mode 100644 app.territoiresentransitions.react/src/ui/export-pdf/assets/icons/EditIcon.tsx diff --git a/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionDescription/ExportFicheActionButton.tsx b/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/ExportFicheActionButton.tsx similarity index 80% rename from app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionDescription/ExportFicheActionButton.tsx rename to app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/ExportFicheActionButton.tsx index 6f819b5eb6..5616e1d561 100644 --- a/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionDescription/ExportFicheActionButton.tsx +++ b/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/ExportFicheActionButton.tsx @@ -1,20 +1,20 @@ import { createElement, useEffect, useState } from 'react'; import { FicheAction } from '@tet/api/plan-actions'; -import { useFicheActionChemins } from '../../PlanAction/data/usePlanActionChemin'; -import { useIndicateurDefinitions } from '../../../Indicateurs/Indicateur/useIndicateurDefinition'; -import { useFichesActionLiees } from '../data/useFichesActionLiees'; -import { useActionListe } from '../data/options/useActionListe'; -import { useAnnexesFicheActionInfos } from '../data/useAnnexesFicheActionInfos'; -import { useFicheActionNotesSuivi } from '../data/useFicheActionNotesSuivi'; +import { useFicheActionChemins } from '../PlanAction/data/usePlanActionChemin'; +import { useIndicateurDefinitions } from '../../Indicateurs/Indicateur/useIndicateurDefinition'; +import { useFichesActionLiees } from '../FicheAction/data/useFichesActionLiees'; +import { useActionListe } from '../FicheAction/data/options/useActionListe'; +import { useAnnexesFicheActionInfos } from '../FicheAction/data/useAnnexesFicheActionInfos'; +import { useFicheActionNotesSuivi } from '../FicheAction/data/useFicheActionNotesSuivi'; import ExportPDFButton from 'ui/export-pdf/ExportPDFButton'; -import FicheActionPdf from '../FicheActionPdf/FicheActionPdf'; +import FicheActionPdf from './FicheActionPdf/FicheActionPdf'; type FicheActionPdfContentProps = { fiche: FicheAction; generateContent: (content: JSX.Element) => void; }; -const FicheActionPdfContent = ({ +export const FicheActionPdfContent = ({ fiche, generateContent, }: FicheActionPdfContentProps) => { diff --git a/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/ExportFicheActionGroupeesButton.tsx b/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/ExportFicheActionGroupeesButton.tsx new file mode 100644 index 0000000000..cbc88e807c --- /dev/null +++ b/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/ExportFicheActionGroupeesButton.tsx @@ -0,0 +1,78 @@ +import { useEffect, useState } from 'react'; +import ExportPDFButton from 'ui/export-pdf/ExportPDFButton'; +import { useCurrentCollectivite } from 'core-logic/hooks/useCurrentCollectivite'; +import { useFicheAction } from '../FicheAction/data/useFicheAction'; +import { FicheActionPdfContent } from './ExportFicheActionButton'; +import { useEventTracker } from '@tet/ui'; + +type FicheActionPdfWrapperProps = { + ficheId: number; + generateContent: (content: JSX.Element) => void; +}; + +const FicheActionPdfWrapper = ({ + ficheId, + generateContent, +}: FicheActionPdfWrapperProps) => { + const { data: fiche } = useFicheAction(ficheId.toString()); + + return ( + fiche && ( + + ) + ); +}; + +const ExportFicheActionGroupeesButton = ({ + fichesIds, +}: { + fichesIds: number[]; +}) => { + const collectivite = useCurrentCollectivite()!; + const tracker = useEventTracker('app/actions-groupees-fiches-action'); + + const [isDataRequested, setIsDataRequested] = useState(false); + const [content, setContent] = useState(undefined); + + const fileName = `fiches-actions-${collectivite.collectivite_id}`; + + useEffect(() => { + if (content?.length === fichesIds.length) { + setIsDataRequested(false); + } + }, [content?.length, fichesIds.length]); + + useEffect(() => setContent(undefined), [isDataRequested]); + + return ( + <> + setIsDataRequested(true)} + icon="file-pdf-line" + variant="outlined" + onClick={() => + tracker('export_PDF_telechargement_groupe', { + collectivite_id: collectivite.collectivite_id, + }) + } + > + Exporter au format PDF + + + {isDataRequested && + fichesIds.map((id) => ( + { + setContent((prevState) => [...(prevState ?? []), newContent]); + }} + /> + ))} + + ); +}; + +export default ExportFicheActionGroupeesButton; diff --git a/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/Acteurs.tsx b/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/Acteurs.tsx similarity index 100% rename from app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/Acteurs.tsx rename to app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/Acteurs.tsx diff --git a/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/ActionsLiees.tsx b/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/ActionsLiees.tsx similarity index 100% rename from app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/ActionsLiees.tsx rename to app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/ActionsLiees.tsx diff --git a/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/Budget.tsx b/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/Budget.tsx similarity index 100% rename from app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/Budget.tsx rename to app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/Budget.tsx diff --git a/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/Chemins.tsx b/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/Chemins.tsx similarity index 95% rename from app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/Chemins.tsx rename to app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/Chemins.tsx index 748267f453..135c32b5fb 100644 --- a/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/Chemins.tsx +++ b/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/Chemins.tsx @@ -2,7 +2,7 @@ import { preset } from '@tet/ui'; import { TAxeRow } from 'types/alias'; import { Paragraph, Stack } from 'ui/export-pdf/components'; import { ArrowRightIcon } from 'ui/export-pdf/assets/icons'; -import { generateTitle } from '../data/utils'; +import { generateTitle } from '../../FicheAction/data/utils'; const { colors } = preset.theme.extend; diff --git a/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/CreationFiche.tsx b/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/CreationFiche.tsx similarity index 100% rename from app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/CreationFiche.tsx rename to app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/CreationFiche.tsx diff --git a/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/Description.tsx b/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/Description.tsx similarity index 100% rename from app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/Description.tsx rename to app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/Description.tsx diff --git a/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/Documents.tsx b/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/Documents.tsx similarity index 94% rename from app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/Documents.tsx rename to app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/Documents.tsx index 36b6160de5..da25c58c91 100644 --- a/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/Documents.tsx +++ b/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/Documents.tsx @@ -9,8 +9,8 @@ import { } from 'ui/export-pdf/components'; import { DiscussIcon, FileIcon, LinkIcon } from 'ui/export-pdf/assets/icons'; import { getAuthorAndDate } from 'ui/shared/preuves/Bibliotheque/utils'; -import { AnnexeInfo } from '../data/useAnnexesFicheActionInfos'; -import { generateTitle } from '../data/utils'; +import { AnnexeInfo } from '../../FicheAction/data/useAnnexesFicheActionInfos'; +import { generateTitle } from '../../FicheAction/data/utils'; const { colors } = preset.theme.extend; diff --git a/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/FicheActionPdf.tsx b/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/FicheActionPdf.tsx similarity index 97% rename from app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/FicheActionPdf.tsx rename to app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/FicheActionPdf.tsx index 1c8f22e4e1..27590459a6 100644 --- a/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/FicheActionPdf.tsx +++ b/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/FicheActionPdf.tsx @@ -5,7 +5,7 @@ import { } from '@tet/api/plan-actions'; import { TActionStatutsRow, TAxeRow } from 'types/alias'; import { IndicateurDefinition } from '@tet/api/indicateurs/domain'; -import { AnnexeInfo } from '../data/useAnnexesFicheActionInfos'; +import { AnnexeInfo } from '../../FicheAction/data/useAnnexesFicheActionInfos'; import { Divider, Stack, Title } from 'ui/export-pdf/components'; import Acteurs from './Acteurs'; diff --git a/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/FichesLiees.tsx b/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/FichesLiees.tsx similarity index 97% rename from app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/FichesLiees.tsx rename to app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/FichesLiees.tsx index ca4b9ea82b..85f5602a08 100644 --- a/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/FichesLiees.tsx +++ b/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/FichesLiees.tsx @@ -18,7 +18,7 @@ import { LoopLeftIcon, UserIcon, } from 'ui/export-pdf/assets/icons'; -import { generateTitle } from '../data/utils'; +import { generateTitle } from '../../FicheAction/data/utils'; const { colors } = preset.theme.extend; @@ -80,7 +80,7 @@ const FicheLieeCard = ({ ficheLiee }: FicheLieeCardProps) => { {/* Pilotes et date de fin prévisionnelle */} {(hasPilotes || hasDateDeFin || ameliorationContinue) && ( - + {/* Personnes pilote */} {hasPilotes && ( diff --git a/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/Indicateurs.tsx b/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/Indicateurs.tsx similarity index 100% rename from app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/Indicateurs.tsx rename to app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/Indicateurs.tsx diff --git a/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/Notes.tsx b/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/Notes.tsx similarity index 100% rename from app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/Notes.tsx rename to app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/Notes.tsx diff --git a/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/NotesDeSuivi.tsx b/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/NotesDeSuivi.tsx similarity index 64% rename from app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/NotesDeSuivi.tsx rename to app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/NotesDeSuivi.tsx index c67ed083aa..4d94900396 100644 --- a/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/NotesDeSuivi.tsx +++ b/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/NotesDeSuivi.tsx @@ -1,6 +1,10 @@ +import { format } from 'date-fns'; import { FicheActionNote } from '@tet/api/plan-actions'; +import { preset } from '@tet/ui'; import { Card, Paragraph, Stack, Title } from 'ui/export-pdf/components'; -import { format } from 'date-fns'; +import { EditIcon, UserIcon } from 'ui/export-pdf/assets/icons'; + +const { colors } = preset.theme.extend; type NotesDeSuiviCardProps = { noteSuivi: FicheActionNote; @@ -22,20 +26,25 @@ const NotesDeSuiviCard = ({ noteSuivi }: NotesDeSuiviCardProps) => { {new Date(dateNote).getFullYear()} {/* Contenu */} - - {note} - + {note} {/* Créée par... / modifiée par... */} - - Créée le {format(new Date(createdAt), 'dd/MM/yyyy')} par {createdBy} + + + + Créée le {format(new Date(createdAt), 'dd/MM/yyyy')} par {createdBy} + {modifiedAt !== createdAt && ( <> - | Modifiée le {format(new Date(modifiedAt), 'dd/MM/yyyy')} par{' '} - {modifiedBy} + | + + + Modifiée le {format(new Date(modifiedAt), 'dd/MM/yyyy')} par{' '} + {modifiedBy} + )} - + ); diff --git a/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/Pilotes.tsx b/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/Pilotes.tsx similarity index 93% rename from app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/Pilotes.tsx rename to app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/Pilotes.tsx index 20e0b29112..f1ed525c97 100644 --- a/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/Pilotes.tsx +++ b/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/Pilotes.tsx @@ -7,7 +7,7 @@ const Pilotes = ({ fiche }: FicheActionPdfProps) => { return ( - + Personnes pilotes diff --git a/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/Planning.tsx b/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/Planning.tsx similarity index 100% rename from app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionPdf/Planning.tsx rename to app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ExportPdf/FicheActionPdf/Planning.tsx diff --git a/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/Carte/FicheActionCard.tsx b/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/Carte/FicheActionCard.tsx index ce8a6dc2bf..e1b92ad805 100644 --- a/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/Carte/FicheActionCard.tsx +++ b/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/Carte/FicheActionCard.tsx @@ -1,5 +1,5 @@ import { FicheResume } from '@tet/api/plan-actions/domain'; -import { Button, Card, Notification, Tooltip } from '@tet/ui'; +import { Button, Card, Checkbox, Notification, Tooltip } from '@tet/ui'; import classNames from 'classnames'; import { useCurrentCollectivite } from 'core-logic/hooks/useCurrentCollectivite'; import { useState } from 'react'; @@ -24,8 +24,12 @@ type FicheActionCardProps = { /** Pour invalider la liste des fiches d'un axe à la suppression de la fiche */ axeIdToInvalidate?: number; editKeysToInvalidate?: QueryKey[]; + /** Etat sélectionné ou non de la fiche */ + isSelected?: boolean; /** Dissociation de la fiche action */ onUnlink?: () => void; + /** Sélection de la fiche action */ + onSelect?: (isSelected: boolean) => void; }; const FicheActionCard = ({ @@ -35,7 +39,9 @@ const FicheActionCard = ({ isEditable = false, axeIdToInvalidate, editKeysToInvalidate, + isSelected = false, onUnlink, + onSelect, }: FicheActionCardProps) => { const collectivite = useCurrentCollectivite(); @@ -60,7 +66,7 @@ const FicheActionCard = ({ onClick={onUnlink} /> )} - {isEditable && ( + {isEditable && !onSelect && ( <> <> {isEditOpen && ( @@ -117,8 +123,10 @@ const FicheActionCard = ({ 'hover:border-primary-3 hover:!bg-primary-1': !isNotClickable, } )} - href={link} + href={onSelect ? undefined : link} + onClick={onSelect ? () => onSelect(!isSelected) : undefined} disabled={isNotClickable} + isSelected={isSelected} external={openInNewTab} header={ // Badges priorité et statut de la fiche @@ -171,9 +179,12 @@ const FicheActionCard = ({ } > {/* Titre de la fiche action */} - <span className="text-base font-bold text-primary-9"> - {generateTitle(ficheAction.titre)} - </span> + <div className="flex min-w-min"> + {onSelect && <Checkbox checked={isSelected} />} + <span className="text-base font-bold text-primary-9"> + {generateTitle(ficheAction.titre)} + </span> + </div> {/* Plans d'action dans lesquels sont la fiche */} <span title="Emplacements" className="text-sm font-medium"> diff --git a/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionDescription/MenuDescription.tsx b/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionDescription/MenuDescription.tsx index db663f6a4b..50bec80988 100644 --- a/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionDescription/MenuDescription.tsx +++ b/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/FicheAction/FicheActionDescription/MenuDescription.tsx @@ -3,7 +3,7 @@ import { FicheAction } from '@tet/api/plan-actions'; import ModaleDescription from './ModaleDescription'; import ModaleEmplacement from './EmplacementFiche/ModaleEmplacement'; import ModaleSuppression from './ModaleSuppression'; -import ExportFicheActionButton from './ExportFicheActionButton'; +import ExportFicheActionButton from '../../ExportPdf/ExportFicheActionButton'; type MenuDescriptionProps = { isReadonly: boolean; diff --git a/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ToutesLesFichesAction/FichesActionListe.tsx b/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ToutesLesFichesAction/FichesActionListe.tsx index a214092f03..1a79d9bf71 100644 --- a/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ToutesLesFichesAction/FichesActionListe.tsx +++ b/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ToutesLesFichesAction/FichesActionListe.tsx @@ -1,27 +1,29 @@ +import classNames from 'classnames'; import { useEffect, useState } from 'react'; -import { Button, Input, Pagination, Select } from '@tet/ui'; import { FetchOptions, Filtre, SortFichesAction, SortFichesActionValue, } from '@tet/api/plan-actions/fiche-resumes.list/domain/fetch-options.schema'; +import { Alert, Button, Checkbox, Input, Pagination, Select } from '@tet/ui'; import { OpenState } from '@tet/ui/utils/types'; -import SpinnerLoader from 'ui/shared/SpinnerLoader'; -import PictoExpert from 'ui/pictogrammes/PictoExpert'; import FicheActionCard from 'app/pages/collectivite/PlansActions/FicheAction/Carte/FicheActionCard'; +import PictoExpert from 'ui/pictogrammes/PictoExpert'; +import SpinnerLoader from 'ui/shared/SpinnerLoader'; import { useFicheResumesFetch } from 'app/pages/collectivite/PlansActions/FicheAction/data/useFicheResumesFetch'; -import { useCollectiviteId } from 'core-logic/hooks/params'; import { makeCollectiviteFicheNonClasseeUrl, makeCollectivitePlanActionFicheUrl, } from 'app/paths'; +import { useCollectiviteId } from 'core-logic/hooks/params'; import FilterBadges, { CustomFilterBadges, useFiltersToBadges, } from 'ui/shared/filters/filter-badges'; +import ExportFicheActionGroupeesButton from '../ExportPdf/ExportFicheActionGroupeesButton'; type sortByOptionsType = SortFichesAction & { label: string; @@ -59,6 +61,7 @@ type Props = { resetFilters?: () => void; maxNbOfCards?: number; sortSettings?: SortFicheActionSettings; + enableGroupedActions?: boolean; }; /** Liste de fiches action avec tri et options de fitlre */ @@ -71,10 +74,13 @@ const FichesActionListe = ({ resetFilters, settings, maxNbOfCards = 15, + enableGroupedActions = false, }: Props) => { const collectiviteId = useCollectiviteId(); const [isSettingsOpen, setIsSettingsOpen] = useState(false); + const [isGroupedActionsOn, setIsGroupedActionsOn] = useState(false); + const [selectedIds, setSelectedIds] = useState<number[]>([]); /** Tri sélectionné */ const [sort, setSort] = useState( @@ -126,6 +132,15 @@ const FichesActionListe = ({ options: ficheResumesOptions, }); + /** Gère les ids sélectionnés pour les actions groupées */ + const handleSelectId = (id: number) => { + if (selectedIds.includes(id)) { + setSelectedIds(selectedIds.filter((s) => s !== id)); + } else { + setSelectedIds([...selectedIds, id]); + } + }; + useEffect(() => { setCurrentPage(1); }, [filtres]); @@ -143,40 +158,93 @@ const FichesActionListe = ({ return ( <> - <div className="flex items-center gap-8 py-6 border-y border-primary-3"> - {/** Tri */} - <div className="w-64"> - <Select - options={sortOptions} - onChange={(value) => - value && setSort(sortByOptions.find((o) => o.field === value)!) - } - values={sort.field} - customItem={(v) => <span className="text-grey-8">{v.label}</span>} - disabled={sortOptions.length === 1} - small - /> + <div className="relative"> + <div className="relative z-[1] bg-grey-2 flex max-xl:flex-col justify-between xl:items-center gap-4 py-6 border-y border-primary-3"> + <div className="flex max-md:flex-col gap-x-8 gap-y-4 md:items-center"> + {/** Tri */} + <div className="w-full md:w-64"> + <Select + options={sortOptions} + onChange={(value) => + value && + setSort(sortByOptions.find((o) => o.field === value)!) + } + values={sort.field} + customItem={(v) => ( + <span className="text-grey-8">{v.label}</span> + )} + disabled={sortOptions.length === 1} + small + /> + </div> + + <div className="flex gap-x-8 gap-y-4 max-md:order-first"> + {/** Nombre total de résultats */} + <span className="shrink-0 text-grey-7"> + {isLoading ? '--' : countTotal} + {` `} + {`action`} + {countTotal > 1 ? 's' : ''} + </span> + + {/* Mode actions groupées */} + {enableGroupedActions && ( + <Checkbox + label="Appliquer des actions groupées" + variant="switch" + labelClassname="font-normal !text-grey-7" + checked={isGroupedActionsOn} + onChange={(evt) => { + if (isGroupedActionsOn) setSelectedIds([]); + setIsGroupedActionsOn(evt.currentTarget.checked); + }} + disabled={isLoading} + /> + )} + </div> + </div> + + <div className="flex gap-x-8 gap-y-4"> + {/** Champ de recherche */} + <Input + type="search" + onChange={(e) => setSearch(e.target.value)} + onSearch={(v) => setDebouncedSearch(v)} + value={search} + containerClassname="w-full xl:w-96" + placeholder="Rechercher par nom ou description" + displaySize="sm" + /> + {/** Bouton d'édition des filtres (une modale avec bouton ou un ButtonMenu) */} + {settings({ isOpen: isSettingsOpen, setIsOpen: setIsSettingsOpen })} + </div> </div> - {/** Nombre total de résultats */} - <span className="shrink-0 text-grey-7"> - {isLoading ? '--' : countTotal} - {` `} - {`action`} - {countTotal > 1 ? 's' : ''} - </span> - {/** Champ de recherche */} - <Input - type="search" - onChange={(e) => setSearch(e.target.value)} - onSearch={(v) => setDebouncedSearch(v)} - value={search} - containerClassname="ml-auto w-full md:w-96" - placeholder="Rechercher par nom ou description" - displaySize="sm" - /> - {/** Bouton d'édition des filtres (une modale avec bouton ou un ButtonMenu) */} - {settings({ isOpen: isSettingsOpen, setIsOpen: setIsSettingsOpen })} + + {/* Apperçu du nombre de fiches sélectionnées */} + {enableGroupedActions && ( + <div + className={classNames( + 'relative flex justify-between py-5 border-b border-primary-3 transition-all duration-500', + { + '-translate-y-full -mb-16': !isGroupedActionsOn, + 'translate-y-0 mb-0': isGroupedActionsOn, + } + )} + > + <div className="text-grey-7 font-medium ml-auto"> + <span className="text-primary-9">{`${ + (selectedIds ?? []).length + } action${ + (selectedIds ?? []).length > 1 ? 's' : '' + } sélectionnée${ + (selectedIds ?? []).length > 1 ? 's' : '' + }`}</span> + {` / ${countTotal} action${countTotal > 1 ? 's' : ''}`} + </div> + </div> + )} </div> + {/** Liste des filtres appliqués */} {!!filterBadges?.length && ( <FilterBadges badges={filterBadges} resetFilters={resetFilters} /> @@ -208,12 +276,18 @@ const FichesActionListe = ({ /** Liste des fiches actions */ // besoin de cette div car `grid` semble rentrer en conflit avec le container `flex` sur Safari <div> - <div className="grid grid-cols-2 2xl:grid-cols-3 gap-4"> + <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4"> {data?.data?.map((fiche) => ( <FicheActionCard key={fiche.id} ficheAction={fiche} isEditable + onSelect={ + isGroupedActionsOn + ? () => handleSelectId(fiche.id) + : undefined + } + isSelected={selectedIds?.includes(fiche.id)} editKeysToInvalidate={[ [ 'fiches_resume_collectivite', @@ -247,6 +321,24 @@ const FichesActionListe = ({ </div> </div> )} + + <Alert + className={classNames( + 'absolute left-0 bottom-0 border-t border-t-info-1 pt-2 pb-4 transition-all duration-500', + { + 'opacity-100 z-50': isGroupedActionsOn && selectedIds.length > 1, + 'opacity-0 -z-10': selectedIds.length <= 1, + } + )} + title="Appliquer une action groupée" + description={ + <div className="flex gap-2"> + <ExportFicheActionGroupeesButton fichesIds={selectedIds} /> + </div> + } + fullPageWidth + noIcon + /> </> ); }; diff --git a/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ToutesLesFichesAction/ToutesLesFichesAction.tsx b/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ToutesLesFichesAction/ToutesLesFichesAction.tsx index 03aedb6a4e..f7ffa42c8e 100644 --- a/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ToutesLesFichesAction/ToutesLesFichesAction.tsx +++ b/app.territoiresentransitions.react/src/app/pages/collectivite/PlansActions/ToutesLesFichesAction/ToutesLesFichesAction.tsx @@ -1,6 +1,5 @@ import { Filtre } from '@tet/api/plan-actions/fiche-resumes.list/domain/fetch-options.schema'; import { useCreateFicheAction } from '@tet/app/pages/collectivite/PlansActions/FicheAction/data/useCreateFicheAction'; -import { useCreateFicheResume } from '@tet/app/pages/collectivite/PlansActions/FicheAction/data/useCreateFicheResume'; import { Button, ButtonMenu } from '@tet/ui'; import { OpenState } from '@tet/ui/utils/types'; import FichesActionListe from 'app/pages/collectivite/PlansActions/ToutesLesFichesAction/FichesActionListe'; @@ -91,8 +90,8 @@ const ToutesLesFichesAction = () => { return ( <div className="min-h-[44rem] flex flex-col gap-8"> - <div className="flex items-end"> - <h2 className="mb-0 mr-auto">Toutes les actions</h2> + <div className="flex justify-between max-sm:flex-col gap-y-4"> + <h2 className="mb-0">Toutes les actions</h2> {!isReadonly && ( <Button size="sm" onClick={() => createFicheAction()}> Créer une fiche d’action @@ -119,6 +118,7 @@ const ToutesLesFichesAction = () => { /> </ButtonMenu> )} + enableGroupedActions={!isReadonly} /> </div> ); diff --git a/app.territoiresentransitions.react/src/ui/export-pdf/DocumentToExport.tsx b/app.territoiresentransitions.react/src/ui/export-pdf/DocumentToExport.tsx index 7f73c633a4..dc0e27051c 100644 --- a/app.territoiresentransitions.react/src/ui/export-pdf/DocumentToExport.tsx +++ b/app.territoiresentransitions.react/src/ui/export-pdf/DocumentToExport.tsx @@ -2,43 +2,56 @@ import { Document, Image, Page, Text, View } from '@react-pdf/renderer'; import { styles } from './styles'; type DocumentToExportProps = { - content: JSX.Element; + content: JSX.Element | JSX.Element[]; }; +const Header = () => ( + <View fixed style={styles.header}> + {/* Logos */} + <Image src="/repFrancaiseLogo.png" style={styles.logo} /> + <Image src="/ademeLogo.png" style={styles.logo} /> + + {/* Titles */} + <View style={styles.titlesBlock}> + <Text style={styles.title}>Territoires en transitions</Text> + <Text style={styles.subtitle}> + Accompagner la transition écologique des collectivités + </Text> + </View> + + {/* Pagination */} + <View style={styles.pagination}> + <Text + render={({ pageNumber, totalPages }) => + `Page ${pageNumber}/${totalPages}` + } + /> + </View> + </View> +); + const DocumentToExport = ({ content }: DocumentToExportProps) => { return ( <Document> - <Page size="A4" style={styles.page}> - {/* Header */} - <View fixed style={styles.header}> - {/* Logos */} - <Image src="/repFrancaiseLogo.png" style={styles.logo} /> - <Image src="/ademeLogo.png" style={styles.logo} /> - - {/* Titles */} - <View style={styles.titlesBlock}> - <Text style={styles.title}>Territoires en transitions</Text> - <Text style={styles.subtitle}> - Accompagner la transition écologique des collectivités - </Text> - </View> - - {/* Pagination */} - <View style={styles.pagination}> - <Text - render={({ pageNumber, totalPages }) => - `Page ${pageNumber}/${totalPages}` - } - /> - </View> - </View> - - {/* Body */} - <View style={styles.body}>{content}</View> - - {/* Footer */} - <View fixed style={styles.footer} /> - </Page> + {Array.isArray(content) ? ( + content.map((c, index) => ( + <Page key={index} size="A4" style={styles.page}> + {/* Header */} + <Header /> + + {/* Body */} + <View style={styles.body}>{c}</View> + </Page> + )) + ) : ( + <Page size="A4" style={styles.page}> + {/* Header */} + <Header /> + + {/* Body */} + <View style={styles.body}>{content}</View> + </Page> + )} </Document> ); }; diff --git a/app.territoiresentransitions.react/src/ui/export-pdf/ExportPDFButton.tsx b/app.territoiresentransitions.react/src/ui/export-pdf/ExportPDFButton.tsx index 2154fefa1f..8cafc0a7f4 100644 --- a/app.territoiresentransitions.react/src/ui/export-pdf/ExportPDFButton.tsx +++ b/app.territoiresentransitions.react/src/ui/export-pdf/ExportPDFButton.tsx @@ -1,24 +1,36 @@ import { useEffect, useState } from 'react'; import { usePDF } from '@react-pdf/renderer'; -import { Button } from '@tet/ui'; +import { Button, ButtonProps } from '@tet/ui'; import { saveBlob } from '../shared/preuves/Bibliotheque/saveBlob'; import DocumentToExport from './DocumentToExport'; const TEST_MODE = false; -export type ExportPDFButtonType = { +export type ExportPDFButtonType = Pick< + ButtonProps, + 'children' | 'title' | 'variant' | 'size' | 'icon' | 'iconPosition' +> & { /** Content of the pdf - Content shouldn't be undefined if requestData isn't used */ - content: JSX.Element | undefined; + content: JSX.Element | JSX.Element[] | undefined; /** Name of the generated pdf */ fileName: string; /** Allows to request data to the parent component when the user requests a download */ requestData?: () => void; + /** Action supplémentaire au click */ + onClick?: () => void; }; const ExportPDFButton = ({ content, fileName, + children, + title = 'Exporter en PDF', + variant = 'white', + size = 'xs', + icon = 'download-fill', + iconPosition = 'left', requestData, + onClick, }: ExportPDFButtonType) => { const [instance, updateInstance] = usePDF({ document: undefined }); const [isDownloadRequested, setIsDownloadRequested] = useState(false); @@ -29,7 +41,11 @@ const ExportPDFButton = ({ }; useEffect(() => { - if (content && !!requestData) { + if ( + content && + ((Array.isArray(content) && content.length) || !Array.isArray(content)) && + !!requestData + ) { updateInstance(<DocumentToExport content={content} />); } }, [content]); @@ -47,18 +63,18 @@ const ExportPDFButton = ({ return ( <Button - icon="download-fill" - title="Exporter en PDF" - variant="white" - size="xs" loading={instance.loading} disabled={!requestData && !content} onClick={() => { handleDownloadRequest(); if (!requestData && content) updateInstance(<DocumentToExport content={content} />); + onClick?.(); }} - /> + {...{ title, variant, size, icon, iconPosition }} + > + {children} + </Button> ); }; diff --git a/app.territoiresentransitions.react/src/ui/export-pdf/assets/icons/EditIcon.tsx b/app.territoiresentransitions.react/src/ui/export-pdf/assets/icons/EditIcon.tsx new file mode 100644 index 0000000000..f09e12d961 --- /dev/null +++ b/app.territoiresentransitions.react/src/ui/export-pdf/assets/icons/EditIcon.tsx @@ -0,0 +1,10 @@ +import { Icon, IconProps } from './Icon'; + +export const EditIcon = ({ ...props }: Omit<IconProps, 'path'>) => { + return ( + <Icon + path="M6.41421 15.89L16.5563 5.74785L15.1421 4.33363L5 14.4758V15.89H6.41421ZM7.24264 17.89H3V13.6473L14.435 2.21231C14.8256 1.82179 15.4587 1.82179 15.8492 2.21231L18.6777 5.04074C19.0682 5.43126 19.0682 6.06443 18.6777 6.45495L7.24264 17.89ZM3 19.89H21V21.89H3V19.89Z" + {...props} + /> + ); +}; diff --git a/app.territoiresentransitions.react/src/ui/export-pdf/assets/icons/index.ts b/app.territoiresentransitions.react/src/ui/export-pdf/assets/icons/index.ts index b370b75f8e..04208ece1c 100644 --- a/app.territoiresentransitions.react/src/ui/export-pdf/assets/icons/index.ts +++ b/app.territoiresentransitions.react/src/ui/export-pdf/assets/icons/index.ts @@ -1,6 +1,7 @@ export * from './ArrowRightIcon'; export * from './CalendarIcon'; export * from './DiscussIcon'; +export * from './EditIcon'; export * from './FileIcon'; export * from './Icon'; export * from './LinkIcon'; diff --git a/app.territoiresentransitions.react/src/ui/export-pdf/styles.ts b/app.territoiresentransitions.react/src/ui/export-pdf/styles.ts index d8aed73724..d616181e61 100644 --- a/app.territoiresentransitions.react/src/ui/export-pdf/styles.ts +++ b/app.territoiresentransitions.react/src/ui/export-pdf/styles.ts @@ -32,6 +32,7 @@ Font.register({ export const styles = StyleSheet.create({ page: { fontFamily: 'Marianne', + paddingBottom: '25pt', }, // Header @@ -75,9 +76,4 @@ export const styles = StyleSheet.create({ padding: '0pt 25pt', fontFamily: 'Marianne', }, - - // Footer - footer: { - paddingTop: '25pt', - }, }); diff --git a/packages/ui/src/components/tracking/trackingPlan.ts b/packages/ui/src/components/tracking/trackingPlan.ts index fdea84a407..f6fbaac80d 100644 --- a/packages/ui/src/components/tracking/trackingPlan.ts +++ b/packages/ui/src/components/tracking/trackingPlan.ts @@ -221,6 +221,15 @@ export interface TrackingPlan extends Record<never, Page> { }; }; + /** Actions groupées sur les fiches actions */ + 'app/actions-groupees-fiches-action': { + properties: { collectivite_id: number }; + onglets: never; + events: { + export_PDF_telechargement_groupe: {}; + }; + }; + /** Page "créer un plan" */ 'app/creer-plan': { properties: { collectivite_id: number }; diff --git a/packages/ui/src/design-system/Alert/Alert.tsx b/packages/ui/src/design-system/Alert/Alert.tsx index aa4bbeed06..4bd98f25ee 100644 --- a/packages/ui/src/design-system/Alert/Alert.tsx +++ b/packages/ui/src/design-system/Alert/Alert.tsx @@ -14,6 +14,8 @@ type AlertProps = { state?: AlertState; /** Remplace l'icône par défaut */ customIcon?: IconValue; + /** Supprime l'icône */ + noIcon?: boolean; /** Initialisation de l'état open */ isOpen?: boolean; /** Gestion de l'affichage pour les alertes sur toute la largeur de page */ @@ -36,6 +38,7 @@ export const Alert = ({ footer, state = 'info', customIcon, + noIcon = false, isOpen = true, fullPageWidth = false, rounded = false, @@ -68,10 +71,12 @@ export const Alert = ({ )} > {/* Icône à gauche du bloc */} - <Icon - icon={customIcon ? customIcon : stateToIcon[state]} - className={classNames('mt-0.5', styles.text)} - /> + {!noIcon && ( + <Icon + icon={customIcon ? customIcon : stateToIcon[state]} + className={classNames('mt-0.5', styles.text)} + /> + )} {/* Titre et texte additionnel */} <div className="flex flex-col gap-3 justify-center"> @@ -80,11 +85,14 @@ export const Alert = ({ {title} </div> )} - {!!description && ( - <div className="text-sm [&_*]:text-sm font-medium text-grey-9 [&_*]:text-grey-9 [&>*]:last:mb-0 flex flex-col gap-3"> - {description} - </div> - )} + {!!description && + (typeof description === 'string' ? ( + <div className="text-sm [&_*]:text-sm font-medium text-grey-9 [&_*]:text-grey-9 [&>*]:last:mb-0 flex flex-col gap-3"> + {description} + </div> + ) : ( + description + ))} {!!footer && footer} </div> diff --git a/packages/ui/src/design-system/Button/ButtonMenu.tsx b/packages/ui/src/design-system/Button/ButtonMenu.tsx index 95515680f4..cb0f09c2bf 100644 --- a/packages/ui/src/design-system/Button/ButtonMenu.tsx +++ b/packages/ui/src/design-system/Button/ButtonMenu.tsx @@ -108,7 +108,7 @@ export const ButtonMenu = ({ maxHeight: maxHeight - 16, }, className: - 'relative overflow-y-auto bg-white rounded-b-lg border border-grey-4 rounded-lg shadow-card', + 'relative z-[1] overflow-y-auto bg-white rounded-b-lg border border-grey-4 rounded-lg shadow-card', })} > {children} diff --git a/packages/ui/src/design-system/Button/types.ts b/packages/ui/src/design-system/Button/types.ts index a982ff3d35..2c2360029d 100644 --- a/packages/ui/src/design-system/Button/types.ts +++ b/packages/ui/src/design-system/Button/types.ts @@ -36,8 +36,6 @@ export type ButtonContentProps = { type BaseButtonProps = { /** Position de l'icône dans le bouton */ iconPosition?: IconPosition; - /** Affiche un loader à la place de l'icône */ - loading?: boolean; /** Lien externe */ external?: boolean; /** Donné par le dropdownfloater si utilisé pour afficher un élément floating-ui */