From 7b925d1612b933131c910e98550c17cc5e9e66ff Mon Sep 17 00:00:00 2001 From: Xavier Jp Date: Wed, 15 May 2024 17:32:39 +0200 Subject: [PATCH] Revert "Revert "Move association and protected certificat to server component"" (#1054) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Revert "Revert "Move association and protected certificat to server component…" This reverts commit 7ad8552c1ad3373273ba749eb4cc9277f64a283c. * fix: notFoundInfo null should not display section Loader appears sooner. fix #1057 * fix: hide association & RNE for bots fix #1056 * fix: add no certificat found explanation when no certificats are found --------- Co-authored-by: Johan Girod --- .../dirigeants/[slug]/page.tsx | 11 +- .../_component/sections/mandataires-rcs.tsx | 1 + .../entreprise/[slug]/page.tsx | 29 ++--- .../justificatif/[slug]/page.tsx | 16 +-- .../_components/protected-certificats.tsx | 57 ++++++++++ .../labels-certificats/[slug]/page.tsx | 51 +++------ .../data-fetching/association/[slug]/route.ts | 31 ------ clients/routes.ts | 1 - .../association-adress.tsx | 7 +- components/association-section/index.tsx | 101 ++++++++---------- .../protected-certificats.tsx | 18 ++-- .../certifications/opqibi-section.tsx | 10 +- .../certifications/qualibat-section.tsx | 10 +- .../certifications/qualifelec-section.tsx | 17 ++- components/page-loader/index.tsx | 11 +- components/page-loader/style.module.css | 16 +++ components/section/data-section/index.tsx | 18 ++-- components/section/data-section/loader.tsx | 13 +-- components/section/data-section/server.tsx | 40 +++++-- .../section/data-section/style.module.css | 5 + components/unite-legale-section/index.tsx | 25 +++-- hooks/fetch/association.ts | 35 ------ models/espace-agent/certificats/index.ts | 35 ------ models/espace-agent/certificats/opqibi.ts | 7 +- models/espace-agent/certificats/qualibat.ts | 5 +- models/espace-agent/certificats/qualifelec.ts | 5 +- 26 files changed, 262 insertions(+), 313 deletions(-) create mode 100644 app/(header-default)/labels-certificats/[slug]/_components/protected-certificats.tsx delete mode 100644 app/api/data-fetching/association/[slug]/route.ts create mode 100644 components/page-loader/style.module.css create mode 100644 components/section/data-section/style.module.css delete mode 100644 hooks/fetch/association.ts delete mode 100644 models/espace-agent/certificats/index.ts diff --git a/app/(header-default)/dirigeants/[slug]/page.tsx b/app/(header-default)/dirigeants/[slug]/page.tsx index 82b15e0a5..2393a9dca 100644 --- a/app/(header-default)/dirigeants/[slug]/page.tsx +++ b/app/(header-default)/dirigeants/[slug]/page.tsx @@ -58,9 +58,14 @@ const DirigeantsPage = async (props: AppRouterProps) => { {servicePublic ? ( ) : ( - }> - - + !isBot && ( + }> + + + ) )} diff --git a/app/(header-default)/dirigeants/_component/sections/mandataires-rcs.tsx b/app/(header-default)/dirigeants/_component/sections/mandataires-rcs.tsx index 7014e6695..0c0831d23 100644 --- a/app/(header-default)/dirigeants/_component/sections/mandataires-rcs.tsx +++ b/app/(header-default)/dirigeants/_component/sections/mandataires-rcs.tsx @@ -35,6 +35,7 @@ async function MandatairesRCSSection({ id="rne-dirigeants" title="Dirigeant(s)" isProtected + notFoundInfo={null} sources={[EAdministration.INFOGREFFE]} data={mandatairesRCS} > diff --git a/app/(header-default)/entreprise/[slug]/page.tsx b/app/(header-default)/entreprise/[slug]/page.tsx index 9d3570618..e0e88a63a 100644 --- a/app/(header-default)/entreprise/[slug]/page.tsx +++ b/app/(header-default)/entreprise/[slug]/page.tsx @@ -17,7 +17,6 @@ import UsefulShortcuts from '#components/useful-shortcuts'; import { isAPINotResponding } from '#models/api-not-responding'; import { estNonDiffusible } from '#models/core/statut-diffusion'; import { isAssociation, isCollectiviteTerritoriale } from '#models/core/types'; -import { getProtectedCertificats } from '#models/espace-agent/certificats'; import { getImmatriculationEORI } from '#models/espace-agent/immatriculation-eori'; import { getServicePublicByUniteLegale } from '#models/service-public'; import { EScope, hasRights } from '#models/user/rights'; @@ -56,18 +55,14 @@ export default async function UniteLegalePage(props: AppRouterProps) { const session = await getSession(); const uniteLegale = await cachedGetUniteLegale(slug, isBot, page); - const [servicePublic, immatriculationEORI, privateCertificats] = - await Promise.all([ - getServicePublicByUniteLegale(uniteLegale, { - isBot, - }), - hasRights(session, EScope.eori) - ? getImmatriculationEORI(uniteLegale.siege.siret, session?.user) - : null, - hasRights(session, EScope.protectedCertificats) - ? getProtectedCertificats(uniteLegale, session?.user) - : null, - ]); + const [servicePublic, immatriculationEORI] = await Promise.all([ + getServicePublicByUniteLegale(uniteLegale, { + isBot, + }), + hasRights(session, EScope.eori) + ? getImmatriculationEORI(uniteLegale.siege.siret, session?.user) + : null, + ]); return ( <> @@ -84,11 +79,7 @@ export default async function UniteLegalePage(props: AppRouterProps) { ) : ( <> - + {hasRights(session, EScope.isAgent) && ( )} - {isAssociation(uniteLegale) && ( + {!isBot && isAssociation(uniteLegale) && ( )} diff --git a/app/(header-default)/justificatif/[slug]/page.tsx b/app/(header-default)/justificatif/[slug]/page.tsx index 52f79106f..8cfd6ef13 100644 --- a/app/(header-default)/justificatif/[slug]/page.tsx +++ b/app/(header-default)/justificatif/[slug]/page.tsx @@ -49,13 +49,15 @@ const JustificatifPage = async (props: AppRouterProps) => { ficheType={FICHE.JUSTIFICATIFS} session={session} /> - }> - - + {!isBot && ( + }> + + + )} ); diff --git a/app/(header-default)/labels-certificats/[slug]/_components/protected-certificats.tsx b/app/(header-default)/labels-certificats/[slug]/_components/protected-certificats.tsx new file mode 100644 index 000000000..af75940df --- /dev/null +++ b/app/(header-default)/labels-certificats/[slug]/_components/protected-certificats.tsx @@ -0,0 +1,57 @@ +import { Suspense } from 'react'; +import { OpqibiSection } from '#components/espace-agent-components/certifications/opqibi-section'; +import { QualibatSection } from '#components/espace-agent-components/certifications/qualibat-section'; +import { QualifelecSection } from '#components/espace-agent-components/certifications/qualifelec-section'; +import { + IAPINotRespondingError, + isAPINotResponding, +} from '#models/api-not-responding'; +import { IUniteLegale } from '#models/core/types'; +import { getOpqibi } from '#models/espace-agent/certificats/opqibi'; +import { getQualibat } from '#models/espace-agent/certificats/qualibat'; +import { getQualifelec } from '#models/espace-agent/certificats/qualifelec'; +import { ISession } from '#models/user/session'; + +type IProps = { + uniteLegale: IUniteLegale; + session: ISession | null; + hasOtherCertificates: boolean; +}; + +export async function ProtectedCertificats({ + uniteLegale, + session, + hasOtherCertificates, +}: IProps) { + const opqibi = getOpqibi(uniteLegale.siren, session?.user?.siret); + const qualifelec = getQualifelec( + uniteLegale.siege.siret, + session?.user?.siret + ); + const qualibat = getQualibat(uniteLegale.siege.siret, session?.user?.siret); + + return ( + <> + {!hasOtherCertificates && ( + + + + )} + + + + + ); +} + +async function NoCertificatsWarning({ + certificats: certificatsPromise, +}: { + certificats: Promise[]; +}) { + const certificats = await Promise.all(certificatsPromise); + if (certificats.every((certificat) => isAPINotResponding(certificat))) { + return

Aucun certificat n’a été trouvé pour cette entreprise.

; + } + return null; +} diff --git a/app/(header-default)/labels-certificats/[slug]/page.tsx b/app/(header-default)/labels-certificats/[slug]/page.tsx index e3fc25eb2..e5c3551a6 100644 --- a/app/(header-default)/labels-certificats/[slug]/page.tsx +++ b/app/(header-default)/labels-certificats/[slug]/page.tsx @@ -4,9 +4,6 @@ import { checkHasLabelsAndCertificates, checkHasQuality, } from '#components/badges-section/labels-and-certificates'; -import { OpqibiSection } from '#components/espace-agent-components/certifications/opqibi-section'; -import { QualibatSection } from '#components/espace-agent-components/certifications/qualibat-section'; -import { QualifelecSection } from '#components/espace-agent-components/certifications/qualifelec-section'; import { CertificationsBioSection } from '#components/labels-and-certificates/bio'; import { EgaproSection } from '#components/labels-and-certificates/egapro'; import { CertificationsEntrepreneurSpectaclesSection } from '#components/labels-and-certificates/entrepreneur-spectacles'; @@ -18,10 +15,6 @@ import { CertificationSocieteMission } from '#components/labels-and-certificates import Title from '#components/title-section'; import { FICHE } from '#components/title-section/tabs'; import { getCertificationsFromSlug } from '#models/certifications'; -import { - getProtectedCertificats, - hasProtectedCertificatsEntreprise, -} from '#models/espace-agent/certificats'; import { EScope, hasRights } from '#models/user/rights'; import { uniteLegalePageDescription, @@ -32,6 +25,7 @@ import extractParamsAppRouter, { AppRouterProps, } from '#utils/server-side-helper/app/extract-params'; import getSession from '#utils/server-side-helper/app/get-session'; +import { ProtectedCertificats } from './_components/protected-certificats'; export const generateMetadata = async ( props: AppRouterProps @@ -70,23 +64,15 @@ const LabelsAndCertificatsPage = async (props: AppRouterProps) => { estEntrepriseInclusive, } = uniteLegale.complements; - const [ - { - rge, - entrepreneurSpectacles, - egapro, - bio, - organismesDeFormation, - ess, - entrepriseInclusive, - }, - protectedCertificats, - ] = await Promise.all([ - getCertificationsFromSlug(uniteLegale), - hasRights(session, EScope.protectedCertificats) - ? getProtectedCertificats(uniteLegale, session?.user) - : null, - ]); + const { + rge, + entrepreneurSpectacles, + egapro, + bio, + organismesDeFormation, + ess, + entrepriseInclusive, + } = await getCertificationsFromSlug(uniteLegale); return ( <> @@ -97,8 +83,7 @@ const LabelsAndCertificatsPage = async (props: AppRouterProps) => { session={session} /> {!checkHasLabelsAndCertificates(uniteLegale) && - (!protectedCertificats || - !hasProtectedCertificatsEntreprise(protectedCertificats)) && ( + !hasRights(session, EScope.protectedCertificats) && (

Cette structure ne possède aucun label ou certificat.

)} {estEss && } @@ -131,14 +116,12 @@ const LabelsAndCertificatsPage = async (props: AppRouterProps) => { {estBio && ( )} - {protectedCertificats && ( - - )} - {protectedCertificats && ( - - )} - {protectedCertificats && ( - + {hasRights(session, EScope.protectedCertificats) && ( + )} diff --git a/app/api/data-fetching/association/[slug]/route.ts b/app/api/data-fetching/association/[slug]/route.ts deleted file mode 100644 index dcbd6c2d1..000000000 --- a/app/api/data-fetching/association/[slug]/route.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { EAdministration } from '#models/administrations/EAdministration'; -import { getAssociationFromSlug } from '#models/association'; -import { FetchRessourceException } from '#models/exceptions'; -import logErrorInSentry from '#utils/sentry'; -import { withIgnoreBot } from '#utils/server-side-helper/app/with-anti-bot'; - -export const GET = withIgnoreBot(async function ( - _request: Request, - { params }: { params: { slug: string } } -) { - const slug = params.slug; - try { - const immatriculation = await getAssociationFromSlug(slug as string); - return Response.json(immatriculation, { status: 200 }); - } catch (e: any) { - const message = 'Failed to fetch Association'; - - logErrorInSentry( - new FetchRessourceException({ - cause: e, - ressource: 'Association', - administration: EAdministration.MI, - message, - context: { - slug: slug as string, - }, - }) - ); - return Response.json({ message }, { status: e.status || 500 }); - } -}); diff --git a/clients/routes.ts b/clients/routes.ts index c9e2528d7..68218d861 100644 --- a/clients/routes.ts +++ b/clients/routes.ts @@ -1,6 +1,5 @@ const routes = { api: { - association: '/api/data-fetching/association', rne: { documents: { list: '/api/data-fetching/espace-agent/documents/', diff --git a/components-ui/alerts-with-explanations/association-adress.tsx b/components-ui/alerts-with-explanations/association-adress.tsx index e74a36d1c..d44884245 100644 --- a/components-ui/alerts-with-explanations/association-adress.tsx +++ b/components-ui/alerts-with-explanations/association-adress.tsx @@ -10,15 +10,14 @@ import { getPersonnalDataAssociation, } from '#models/core/statut-diffusion'; import { IAssociation } from '#models/core/types'; -import useSession from 'hooks/use-session'; +import { ISession } from '#models/user/session'; import { Warning } from '../alerts'; const AssociationAdressAlert: React.FC<{ uniteLegale: IAssociation; association: IDataAssociation | IAPINotRespondingError | null; -}> = ({ uniteLegale, association }) => { - const session = useSession(); - + session: ISession | null; +}> = ({ uniteLegale, association, session }) => { if (!association || isAPINotResponding(association)) { return null; } diff --git a/components/association-section/index.tsx b/components/association-section/index.tsx index 0084b471a..0fc443e0d 100644 --- a/components/association-section/index.tsx +++ b/components/association-section/index.tsx @@ -1,19 +1,16 @@ -'use client'; - import AssociationAdressAlert from '#components-ui/alerts-with-explanations/association-adress'; import { HorizontalSeparator } from '#components-ui/horizontal-separator'; import BreakPageForPrint from '#components-ui/print-break-page'; import { Tag } from '#components-ui/tag'; -import { Section } from '#components/section'; -import { AsyncDataSectionClient } from '#components/section/data-section/client'; +import { AsyncDataSectionServer } from '#components/section/data-section/server'; import { TwoColumnTable } from '#components/table/simple'; import { EAdministration } from '#models/administrations/EAdministration'; +import { getAssociationFromSlug } from '#models/association'; import { IDataAssociation } from '#models/association/types'; import { getPersonnalDataAssociation } from '#models/core/statut-diffusion'; import { IAssociation, IUniteLegale } from '#models/core/types'; import { ISession } from '#models/user/session'; import { IdRna, formatDate, formatIntFr } from '#utils/helpers'; -import { useFetchAssociation } from 'hooks/fetch/association'; import { AssociationNotFound } from './association-not-found'; const getTableData = ( @@ -133,66 +130,58 @@ const AssociationSection = ({ }) => { const { idAssociation = '' } = uniteLegale.association; - const association = useFetchAssociation(uniteLegale.siren); - - if (!association) { - // Data can be null if the natureJuridique is an association, - // but no idAssociation is provided by Insee API call. - return ( -
- ; -
- ); - } + const association = getAssociationFromSlug(uniteLegale.siren); return ( <> - } > - {(association) => ( - <> - -

- Cette structure est inscrite au{' '} - Répertoire National des Associations (RNA), avec - les informations suivantes : -

- + !association ? ( + + ) : ( + <> + +

+ Cette structure est inscrite au{' '} + Répertoire National des Associations (RNA), + avec les informations suivantes : +

+ + {idAssociation && ( + <> +
+ Retrouvez plus d'informations (comptes, effectifs et + documents administratifs) sur la{' '} + + fiche data-asso de cette association + + . + )} - /> - {idAssociation && ( - <> -
- Retrouvez plus d'informations (comptes, effectifs et - documents administratifs) sur la{' '} - - fiche data-asso de cette association - - . - - )} - - )} -
+ + ) + } + diff --git a/components/badges-section/labels-and-certificates/protected-certificats.tsx b/components/badges-section/labels-and-certificates/protected-certificats.tsx index 2ba0b2972..6d2a38bdc 100644 --- a/components/badges-section/labels-and-certificates/protected-certificats.tsx +++ b/components/badges-section/labels-and-certificates/protected-certificats.tsx @@ -1,18 +1,22 @@ import { Icon } from '#components-ui/icon/wrapper'; import { isAPINotResponding } from '#models/api-not-responding'; import constants from '#models/constants'; -import { IProtectedCertificatsEntreprise } from '#models/espace-agent/certificats'; +import { getOpqibi } from '#models/espace-agent/certificats/opqibi'; +import { getQualibat } from '#models/espace-agent/certificats/qualibat'; +import { getQualifelec } from '#models/espace-agent/certificats/qualifelec'; +import { ISession } from '#models/user/session'; import { IUniteLegale } from '../../../models/core/types'; import { LabelWithLinkToSection } from './label-with-link-to-section'; export const ProtectedCertificatesBadgesSection: React.FC<{ uniteLegale: IUniteLegale; - protectedCertificats: IProtectedCertificatsEntreprise | null; -}> = ({ uniteLegale, protectedCertificats }) => { - if (!protectedCertificats) { - return null; - } - const { opqibi, qualibat, qualifelec } = protectedCertificats; + session: ISession | null; +}> = async ({ uniteLegale, session }) => { + const [opqibi, qualifelec, qualibat] = await Promise.all([ + getOpqibi(uniteLegale.siren, session?.user?.siret), + getQualifelec(uniteLegale.siege.siret, session?.user?.siret), + getQualibat(uniteLegale.siege.siret, session?.user?.siret), + ]); if ( isAPINotResponding(opqibi) && diff --git a/components/espace-agent-components/certifications/opqibi-section.tsx b/components/espace-agent-components/certifications/opqibi-section.tsx index 1cbb428bb..9da630c8f 100644 --- a/components/espace-agent-components/certifications/opqibi-section.tsx +++ b/components/espace-agent-components/certifications/opqibi-section.tsx @@ -1,7 +1,5 @@ -'use client'; - import FAQLink from '#components-ui/faq-link'; -import { DataSection } from '#components/section/data-section'; +import { AsyncDataSectionServer } from '#components/section/data-section/server'; import { TwoColumnTable } from '#components/table/simple'; import { EAdministration } from '#models/administrations/EAdministration'; import { IAPINotRespondingError } from '#models/api-not-responding'; @@ -9,10 +7,10 @@ import { IOpqibi } from '#models/espace-agent/certificats/opqibi'; import { formatDateLong } from '#utils/helpers'; export const OpqibiSection: React.FC<{ - opqibi: IOpqibi | IAPINotRespondingError; + opqibi: Promise; }> = ({ opqibi }) => { return ( - )} - + ); }; diff --git a/components/espace-agent-components/certifications/qualibat-section.tsx b/components/espace-agent-components/certifications/qualibat-section.tsx index 872322562..1e52facae 100644 --- a/components/espace-agent-components/certifications/qualibat-section.tsx +++ b/components/espace-agent-components/certifications/qualibat-section.tsx @@ -1,7 +1,5 @@ -'use client'; - import ButtonLink from '#components-ui/button'; -import { DataSection } from '#components/section/data-section'; +import { AsyncDataSectionServer } from '#components/section/data-section/server'; import { TwoColumnTable } from '#components/table/simple'; import { EAdministration } from '#models/administrations/EAdministration'; import { IAPINotRespondingError } from '#models/api-not-responding'; @@ -9,10 +7,10 @@ import { IQualibat } from '#models/espace-agent/certificats/qualibat'; import { formatDateLong } from '#utils/helpers'; export const QualibatSection: React.FC<{ - qualibat: IQualibat | IAPINotRespondingError; + qualibat: Promise; }> = ({ qualibat }) => { return ( - )} - + ); }; diff --git a/components/espace-agent-components/certifications/qualifelec-section.tsx b/components/espace-agent-components/certifications/qualifelec-section.tsx index 9f9a24b06..861df5973 100644 --- a/components/espace-agent-components/certifications/qualifelec-section.tsx +++ b/components/espace-agent-components/certifications/qualifelec-section.tsx @@ -1,18 +1,17 @@ -'use client'; - import ButtonLink from '#components-ui/button'; -import { DataSection } from '#components/section/data-section'; +import { AsyncDataSectionServer } from '#components/section/data-section/server'; import { FullTable } from '#components/table/full'; import { EAdministration } from '#models/administrations/EAdministration'; import { IAPINotRespondingError } from '#models/api-not-responding'; import { IQualifelec } from '#models/espace-agent/certificats/qualifelec'; import { formatDate, formatDateLong } from '#utils/helpers'; -export const QualifelecSection: React.FC<{ - qualifelec: IQualifelec | IAPINotRespondingError; -}> = ({ qualifelec }) => { +type IProps = { + qualifelec: Promise; +}; +export async function QualifelecSection({ qualifelec }: IProps) { return ( - )} - + ); -}; +} diff --git a/components/page-loader/index.tsx b/components/page-loader/index.tsx index b63c5b0db..bb511b1da 100644 --- a/components/page-loader/index.tsx +++ b/components/page-loader/index.tsx @@ -1,17 +1,12 @@ 'use client'; import { Loader } from '#components-ui/loader'; -import { useTimeout } from 'hooks'; +import style from './style.module.css'; export function PageLoader() { - const before100ms = !useTimeout(100); - if (before100ms) { - return
; - } - return ( - <> +
Chargement des données en cours - +
); } diff --git a/components/page-loader/style.module.css b/components/page-loader/style.module.css new file mode 100644 index 000000000..9e8201e5e --- /dev/null +++ b/components/page-loader/style.module.css @@ -0,0 +1,16 @@ +.loader { + min-height: 500px; + opacity: 0; + /* animate after 500ms during 200ms */ + animation: fadeIn 200ms 300ms forwards; +} + +@keyframes fadeIn { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} \ No newline at end of file diff --git a/components/section/data-section/index.tsx b/components/section/data-section/index.tsx index ac877818a..df270b58f 100644 --- a/components/section/data-section/index.tsx +++ b/components/section/data-section/index.tsx @@ -1,6 +1,7 @@ /* eslint-disable react/jsx-props-no-spreading */ import { IAPILoading } from '#models/api-loading'; +import { isAPI404 } from '#models/api-not-responding'; import { ISectionProps, Section } from '..'; import { DataSectionContent, IDataSectionContentProps } from './content'; @@ -21,15 +22,7 @@ export function DataSection>({ ...props }: IDataSectionProps) { //@ts-ignore - const dataSectionContent = ( - - ); - if (!dataSectionContent) { + if (notFoundInfo === null && isAPI404(data)) { return null; } //@ts-ignore @@ -37,7 +30,12 @@ export function DataSection>({ return (
- {dataSectionContent} +
); } diff --git a/components/section/data-section/loader.tsx b/components/section/data-section/loader.tsx index f4a574ee7..08644c183 100644 --- a/components/section/data-section/loader.tsx +++ b/components/section/data-section/loader.tsx @@ -6,24 +6,20 @@ import { Loader } from '#components-ui/loader'; import { administrationsMetaData } from '#models/administrations'; import { useTimeout } from 'hooks/use-timeout'; import { ISectionProps } from '..'; +import style from './style.module.css'; export function DataSectionLoader({ sources, }: { sources: ISectionProps['sources']; }) { - const before100ms = !useTimeout(100); const after5s = useTimeout(5000); - if (before100ms) { - return
; - } - const dataSources = Array.from(new Set(sources || [])).map( (key) => administrationsMetaData[key] ); return ( - <> +
{after5s && ( @@ -33,7 +29,6 @@ export function DataSectionLoader({ semble occupé en ce moment. Le téléchargement des informations peut prendre du temps (10s à 20s). -
)} @@ -48,7 +43,7 @@ export function DataSectionLoader({

) : ( <> - Nous récupérons les informations dans les bases de données : +

Nous récupérons les informations dans les bases de données :

    {dataSources.map((d) => (
  • {d.long}
  • @@ -57,6 +52,6 @@ export function DataSectionLoader({ )} - +
); } diff --git a/components/section/data-section/server.tsx b/components/section/data-section/server.tsx index 0b837ef20..34172a69a 100644 --- a/components/section/data-section/server.tsx +++ b/components/section/data-section/server.tsx @@ -1,16 +1,17 @@ /* eslint-disable react/jsx-props-no-spreading */ import { Suspense } from 'react'; -import FadeIn from '#components-ui/animation/fade-in'; +import { FadeIn } from '#components-ui/animation/fade-in'; import { HeightTransition } from '#components-ui/animation/height-transition'; -import { IAPINotRespondingError } from '#models/api-not-responding'; +import { IAPINotRespondingError, isAPI404 } from '#models/api-not-responding'; +import { DataSection } from '.'; import { ISectionProps, Section } from '..'; import { DataSectionContent } from './content'; import { DataSectionLoader } from './loader'; interface IDataSectionServerProps extends ISectionProps { data: Promise; - notFoundInfo?: NonNullable; + notFoundInfo?: React.ReactNode; additionalInfoOnError?: React.ReactNode; children: (data: T) => JSX.Element; } @@ -19,9 +20,7 @@ export function AsyncDataSectionServer(props: IDataSectionServerProps) { if (props.notFoundInfo === null) { return ( - - - + ); } @@ -30,9 +29,7 @@ export function AsyncDataSectionServer(props: IDataSectionServerProps) {
}> - - - +
@@ -44,7 +41,30 @@ async function DataSectionContentServerAsync({ ...props }: IDataSectionServerProps) { const data = await promiseData; - return ; + return ( + + {' '} + + ); } /* eslint-enable react/jsx-props-no-spreading */ + +async function DataSectionServerAsync({ + data: promiseData, + ...props +}: IDataSectionServerProps) { + const data = await promiseData; + + if (isAPI404(data as IAPINotRespondingError)) { + return null; + } + return ( + + + {/* eslint-disable-next-line react/jsx-props-no-spreading */} + + + + ); +} diff --git a/components/section/data-section/style.module.css b/components/section/data-section/style.module.css new file mode 100644 index 000000000..dfa209f60 --- /dev/null +++ b/components/section/data-section/style.module.css @@ -0,0 +1,5 @@ +.loader { + /* Composes loader from page-loader */ + composes: loader from 'components/page-loader/style.module.css'; + min-height: 0px; +} \ No newline at end of file diff --git a/components/unite-legale-section/index.tsx b/components/unite-legale-section/index.tsx index d9b233f97..592644b59 100644 --- a/components/unite-legale-section/index.tsx +++ b/components/unite-legale-section/index.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { Suspense } from 'react'; import FAQLink from '#components-ui/faq-link'; import { HorizontalSeparator } from '#components-ui/horizontal-separator'; import { ConventionCollectivesBadgesSection } from '#components/badges-section/convention-collectives'; @@ -19,10 +19,7 @@ import { isAssociation, isServicePublic, } from '#models/core/types'; -import { - IProtectedCertificatsEntreprise, - hasProtectedCertificatsEntreprise, -} from '#models/espace-agent/certificats'; +import { EScope, hasRights } from '#models/user/rights'; import { ISession } from '#models/user/session'; import { formatDate, formatIntFr, formatSiret } from '#utils/helpers'; import { libelleCategorieEntreprise } from '#utils/helpers/formatting/categories-entreprise'; @@ -36,13 +33,11 @@ import { const UniteLegaleSection: React.FC<{ uniteLegale: IUniteLegale; - protectedCertificats: IProtectedCertificatsEntreprise | null; session: ISession | null; -}> = ({ uniteLegale, session, protectedCertificats }) => { +}> = ({ uniteLegale, session }) => { const hasLabelsAndCertificates = checkHasLabelsAndCertificates(uniteLegale) || - (protectedCertificats && - hasProtectedCertificatsEntreprise(protectedCertificats)); + hasRights(session, EScope.protectedCertificats); const conventionsCollectives = Object.keys( uniteLegale.conventionsCollectives || {} ); @@ -126,10 +121,14 @@ const UniteLegaleSection: React.FC<{ }abels et certificats`, <> - + {hasRights(session, EScope.protectedCertificats) && ( + + + + )} , ], ] diff --git a/hooks/fetch/association.ts b/hooks/fetch/association.ts deleted file mode 100644 index 948fd3e81..000000000 --- a/hooks/fetch/association.ts +++ /dev/null @@ -1,35 +0,0 @@ -import routes from '#clients/routes'; -import { EAdministration } from '#models/administrations/EAdministration'; -import { IDataAssociation } from '#models/association/types'; -import { FetchRessourceException } from '#models/exceptions'; -import { Siren } from '#utils/helpers'; -import { httpGet } from '#utils/network'; -import logErrorInSentry from '#utils/sentry'; -import { useFetchData } from './use-fetch-data'; - -export function useFetchAssociation(siren: Siren) { - return useFetchData( - { - fetchData: () => - httpGet(routes.api.association + '/' + siren), - administration: EAdministration.DJEPVA, - logError: (e: any) => { - if (e.status) { - // We already log error server side - return; - } - logErrorInSentry( - new FetchRessourceException({ - ressource: 'Association', - administration: EAdministration.DJEPVA, - cause: e, - context: { - siren, - }, - }) - ); - }, - }, - [siren] - ); -} diff --git a/models/espace-agent/certificats/index.ts b/models/espace-agent/certificats/index.ts deleted file mode 100644 index f9eb1b69e..000000000 --- a/models/espace-agent/certificats/index.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { - IAPINotRespondingError, - isAPINotResponding, -} from '#models/api-not-responding'; -import { IUniteLegale } from '#models/core/types'; -import { ISession } from '#models/user/session'; -import { IOpqibi, getOpqibi } from './opqibi'; -import { IQualibat, getQualibat } from './qualibat'; -import { IQualifelec, getQualifelec } from './qualifelec'; - -export type IProtectedCertificatsEntreprise = { - qualifelec: IQualifelec | IAPINotRespondingError; - qualibat: IQualibat | IAPINotRespondingError; - opqibi: IOpqibi | IAPINotRespondingError; -}; - -export async function getProtectedCertificats( - uniteLegale: IUniteLegale, - user: ISession['user'] | null -): Promise { - const [qualifelec, qualibat, opqibi] = await Promise.all([ - getQualifelec(uniteLegale.siege.siret, user), - getQualibat(uniteLegale.siege.siret, user), - getOpqibi(uniteLegale.siren, user), - ]); - return { qualifelec, qualibat, opqibi }; -} - -export function hasProtectedCertificatsEntreprise( - privateCertificats: IProtectedCertificatsEntreprise -): boolean { - return Object.values(privateCertificats).some( - (certificat) => !isAPINotResponding(certificat) - ); -} diff --git a/models/espace-agent/certificats/opqibi.ts b/models/espace-agent/certificats/opqibi.ts index b7ef530d0..79457c883 100644 --- a/models/espace-agent/certificats/opqibi.ts +++ b/models/espace-agent/certificats/opqibi.ts @@ -1,7 +1,6 @@ import { clientApiEntrepriseOpqibi } from '#clients/api-entreprise/opqibi'; import { IAPINotRespondingError } from '#models/api-not-responding'; -import { ISession } from '#models/user/session'; -import { Siren } from '#utils/helpers'; +import { Siren, Siret } from '#utils/helpers'; import { handleApiEntrepriseError } from '../utils'; type Qualification = { nom: string; @@ -23,9 +22,9 @@ export type IOpqibi = { export const getOpqibi = async ( siren: Siren, - user: ISession['user'] | null + recipientSiret: Siret | undefined ): Promise => { - return clientApiEntrepriseOpqibi(siren, user?.siret).catch((error) => + return clientApiEntrepriseOpqibi(siren, recipientSiret).catch((error) => handleApiEntrepriseError(error, { siren }) ); }; diff --git a/models/espace-agent/certificats/qualibat.ts b/models/espace-agent/certificats/qualibat.ts index d0dd9c1d1..79620e5ae 100644 --- a/models/espace-agent/certificats/qualibat.ts +++ b/models/espace-agent/certificats/qualibat.ts @@ -1,6 +1,5 @@ import { clientApiEntrepriseQualibat } from '#clients/api-entreprise/qualibat'; import { IAPINotRespondingError } from '#models/api-not-responding'; -import { ISession } from '#models/user/session'; import { Siret } from '#utils/helpers'; import { handleApiEntrepriseError } from '../utils'; export type IQualibat = { @@ -27,9 +26,9 @@ export type IQualibat = { export const getQualibat = async ( siret: Siret, - user: ISession['user'] | null + recipientSiret: Siret | undefined ): Promise => { - return clientApiEntrepriseQualibat(siret, user?.siret).catch((error) => + return clientApiEntrepriseQualibat(siret, recipientSiret).catch((error) => handleApiEntrepriseError(error, { siret }) ); }; diff --git a/models/espace-agent/certificats/qualifelec.ts b/models/espace-agent/certificats/qualifelec.ts index cc3d75532..1c6bd5bd9 100644 --- a/models/espace-agent/certificats/qualifelec.ts +++ b/models/espace-agent/certificats/qualifelec.ts @@ -1,6 +1,5 @@ import { clientApiEntrepriseQualifelec } from '#clients/api-entreprise/qualifelec'; import { IAPINotRespondingError } from '#models/api-not-responding'; -import { ISession } from '#models/user/session'; import { Siret } from '#utils/helpers'; import { handleApiEntrepriseError } from '../utils'; export type IQualifelec = Array<{ @@ -43,9 +42,9 @@ export type IQualifelec = Array<{ }>; export const getQualifelec = async ( siret: Siret, - user: ISession['user'] | null + recipientSiret: Siret | undefined ): Promise => { - return clientApiEntrepriseQualifelec(siret, user?.siret).catch((error) => + return clientApiEntrepriseQualifelec(siret, recipientSiret).catch((error) => handleApiEntrepriseError(error, { siret }) ); };