diff --git a/src/client/src/components/App/Layout.js b/src/client/src/components/App/Layout.js index 1f07089b..2994046a 100644 --- a/src/client/src/components/App/Layout.js +++ b/src/client/src/components/App/Layout.js @@ -13,12 +13,12 @@ const Layout = ({ hasSharedButton = false, children, displayMessage = false, + isNotFound = false, }) => { const isActiveMaintenanceMode = Config.get("maintenanceMode"); - return ( <> - {hasLandingHeader ? ( + {!isNotFound && hasLandingHeader ? (
) : ( <> @@ -42,6 +42,7 @@ Layout.propTypes = { displayMessage: PropTypes.bool, hasLandingHeader: PropTypes.bool, hasSharedButton: PropTypes.bool, + isNotFound: PropTypes.bool, }; export default Layout; diff --git a/src/client/src/components/App/app.scss b/src/client/src/components/App/app.scss index b28ccc34..67877360 100644 --- a/src/client/src/components/App/app.scss +++ b/src/client/src/components/App/app.scss @@ -67,6 +67,10 @@ a { &--nowrap a { white-space: nowrap; } + &--sm-cell { + font-size: 0.5rem !important; + align-items: center !important; + } } } diff --git a/src/client/src/components/DataSheets/NotFound/NotFound.jsx b/src/client/src/components/DataSheets/NotFound/NotFound.jsx new file mode 100644 index 00000000..087d07ad --- /dev/null +++ b/src/client/src/components/DataSheets/NotFound/NotFound.jsx @@ -0,0 +1,17 @@ +import "./notFound.scss"; + +import React from "react"; + +const NotFound = () => { + return ( +
+
+
+
0 entreprise correspond à votre requête
+
+
+
+ ); +}; + +export default NotFound; diff --git a/src/client/src/components/DataSheets/NotFound/notFound.scss b/src/client/src/components/DataSheets/NotFound/notFound.scss new file mode 100644 index 00000000..036ae221 --- /dev/null +++ b/src/client/src/components/DataSheets/NotFound/notFound.scss @@ -0,0 +1,7 @@ +.notFound { + display: flex; + justify-content: center; + align-items: center; + font-size: 22px; + font-weight: bold; +} diff --git a/src/client/src/components/DataSheets/Sections/Establishment/MarchesPublic/MarchesPublic.jsx b/src/client/src/components/DataSheets/Sections/Establishment/MarchesPublic/MarchesPublic.jsx index 871f47f1..ed2a0c8a 100644 --- a/src/client/src/components/DataSheets/Sections/Establishment/MarchesPublic/MarchesPublic.jsx +++ b/src/client/src/components/DataSheets/Sections/Establishment/MarchesPublic/MarchesPublic.jsx @@ -6,18 +6,22 @@ import { formatSiret } from "../../../../../helpers/utils/format.js"; import { convertirMoisEnAnnees } from "../../../../../helpers/utils/utils.js"; import { formatChiffre } from "../../../../../utils/donnees-ecofi/donnees-ecofi.js"; import { formatUpperCase } from "../../../../../utils/entreprise/entreprise.js"; +import { getCity } from "../../../../../utils/establishment/establishment"; +import LoadableContent from "../../../../shared/LoadableContent/LoadableContent.js"; import Value from "../../../../shared/Value/index.js"; import BlocTitle from "../../SharedComponents/BlocTitle/BlocTitle.jsx"; import NonBorderedTable from "../../SharedComponents/NonBorderedTable/NonBorderedTable.js"; import SeeDetailsLink from "../../SharedComponents/SeeDetailsLink/SeeDetailsLink.js"; import Subcategory from "../../SharedComponents/Subcategory/index.js"; -import { useMarchesPublic } from "./marchesPublic.gql.js"; +import { useMarchesPublicWithEtablissements } from "./marchesPublic.gql.js"; const MarchesPublic = ({ siret }) => { - const { loading, data, error } = useMarchesPublic(siret); + const { enrichedMarches, loading, error } = + useMarchesPublicWithEtablissements(siret); + const [accordionOpen, setAccordionOpen] = useState(true); - if (loading || error || !siret) { + if (error || !siret) { return null; } @@ -40,72 +44,86 @@ const MarchesPublic = ({ siret }) => { sourceDate={null} /> -
- {data?.marches?.length > 0 && ( - 10} - > - - - Acheteur - Objet - CPV - Procédure - Montant - Notifié le - Durée - - - - {data?.marches?.map( - ({ - acheteur_id, - objet, - cpv_libelle, - procedure, - montant, - dateNotification, - dureeMois, - }) => ( - - - - + +
+ {enrichedMarches?.length > 0 && ( + 10} + > + + + Acheteur + Objet + CPV + Procédure + Montant + Notifié le + Durée + + + + {enrichedMarches?.map((marche) => { + const adresse = getCity(marche?.etablissement); - - - - - - - - - - - - - - - - - - - - ) - )} - - - )} -
- {data?.marches?.length === 0 && ( -
- {"Aucun appel d'offres connu"} + return ( + + + + + {/* + {" "} + + */} + + + + + + + + + + + + + + + + + + + + + ); + })} + + + )}
- )} + {enrichedMarches?.length === 0 && ( +
+ {"Aucun appel d'offres connu"} +
+ )} +
)} diff --git a/src/client/src/components/DataSheets/Sections/Establishment/MarchesPublic/marchesPublic.gql.js b/src/client/src/components/DataSheets/Sections/Establishment/MarchesPublic/marchesPublic.gql.js index 0719d4fd..23ffc527 100644 --- a/src/client/src/components/DataSheets/Sections/Establishment/MarchesPublic/marchesPublic.gql.js +++ b/src/client/src/components/DataSheets/Sections/Establishment/MarchesPublic/marchesPublic.gql.js @@ -1,25 +1,93 @@ -import { gql, useQuery } from "@apollo/client"; +import { gql, useApolloClient, useQuery } from "@apollo/client"; +import { useEffect, useState } from "react"; import { BCE_CLIENT } from "../../../../../services/GraphQL/GraphQL"; const marchesPublicQuery = gql` query getMarchesPublic($siret: String!) { - marches: fce_marches_valides(where: { siret: { _eq: $siret } }) { + marches: fce_marches_valides( + where: { siret: { _eq: $siret } } + order_by: { dateNotification: desc } + ) { acheteur_id - codeCPV - cpv_libelle dateNotification dureeMois montant objet procedure - sousTraitanceDeclaree } } `; -export const useMarchesPublic = (siret) => - useQuery(marchesPublicQuery, { +const etablissementQuery = gql` + query getEtablissement($acheteurId: String!) { + etablissement: fce_etablissements(where: { siret: { _eq: $acheteurId } }) { + siret + etb_raisonsociale + codepostaletablissement + numerovoieetablissement + indicerepetitionetablissement + typevoieetablissement + complementadresseetablissement + libellevoieetablissement + libellecommuneetablissement + codecommune2etablissement + codecommuneetablissement + libellepaysetrangeretablissement + } + } +`; + +export const useMarchesPublicWithEtablissements = (siret) => { + const client = useApolloClient(); // Accéder à l'instance du client Apollo + const { + data: marcheData, + loading: marcheLoading, + error: marcheError, + } = useQuery(marchesPublicQuery, { context: { clientName: BCE_CLIENT }, variables: { siret }, }); + + const [enrichedMarches, setEnrichedMarches] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + if (marcheData && marcheData.marches.length > 0) { + const fetchEtablissements = async () => { + try { + setLoading(true); + const results = await Promise.all( + marcheData.marches.map(async (marche) => { + const { data: etablissementData } = await client.query({ + context: { clientName: BCE_CLIENT }, + query: etablissementQuery, + variables: { acheteurId: marche.acheteur_id }, + }); + return { + ...marche, + etablissement: etablissementData.etablissement[0], + }; + }) + ); + setEnrichedMarches(results); + setLoading(false); + } catch (e) { + setError(e); + setLoading(false); + } + }; + + fetchEtablissements(); + } else { + setLoading(false); + } + }, [marcheData, client]); // Ajoutez 'client' comme dépendance + + return { + enrichedMarches, + error: marcheError || error, + loading: marcheLoading || loading, + }; +}; diff --git a/src/client/src/components/DataSheets/Sections/SharedComponents/SeeDetailsLink/SeeDetailsLink.js b/src/client/src/components/DataSheets/Sections/SharedComponents/SeeDetailsLink/SeeDetailsLink.js index 5b0b5c94..e17a7ec1 100644 --- a/src/client/src/components/DataSheets/Sections/SharedComponents/SeeDetailsLink/SeeDetailsLink.js +++ b/src/client/src/components/DataSheets/Sections/SharedComponents/SeeDetailsLink/SeeDetailsLink.js @@ -4,27 +4,44 @@ import PropTypes from "prop-types"; import React from "react"; import { HashLink as Link } from "react-router-hash-link"; +import BuildingIcon from "../../../../shared/Icons/BuildingIcon.jsx"; + const scrollWithOffset = (el) => { const yCoordinate = el.getBoundingClientRect().top + window.pageYOffset; const yOffset = -60; window.scrollTo({ behavior: "smooth", top: yCoordinate + yOffset }); }; -const SeeDetailsLink = ({ link, text = "Voir la fiche établissement" }) => { +const SeeDetailsLink = ({ + link, + text = "Voir la fiche établissement", + description, + className, +}) => { return (
scrollWithOffset(el)} > {text} + {description && ( +
+ + + {" "} + {description} +
+ )}
); }; SeeDetailsLink.propTypes = { + className: PropTypes.string, + description: PropTypes.string, link: PropTypes.string.isRequired, text: PropTypes.string, }; diff --git a/src/client/src/components/DataSheets/Sections/SharedComponents/SeeDetailsLink/seeDetailsLink.scss b/src/client/src/components/DataSheets/Sections/SharedComponents/SeeDetailsLink/seeDetailsLink.scss index ab35c15f..9fda80d3 100644 --- a/src/client/src/components/DataSheets/Sections/SharedComponents/SeeDetailsLink/seeDetailsLink.scss +++ b/src/client/src/components/DataSheets/Sections/SharedComponents/SeeDetailsLink/seeDetailsLink.scss @@ -6,6 +6,9 @@ &__link { font-size: 0.9rem; + &.list { + display: flex; + } } &__icon { @@ -18,6 +21,11 @@ font-weight: 400; line-height: 1.5rem; color: $title-grey; + &-text { + display: flex; + align-items: center; + text-transform: capitalize; + } a { color: $dark-blue !important; diff --git a/src/client/src/services/PrivateRoute/CustomLayout.jsx b/src/client/src/services/PrivateRoute/CustomLayout.jsx index 7086f409..c1d43429 100644 --- a/src/client/src/services/PrivateRoute/CustomLayout.jsx +++ b/src/client/src/services/PrivateRoute/CustomLayout.jsx @@ -1,6 +1,7 @@ import PropTypes from "prop-types"; import React from "react"; +import NotFound from "../../components/DataSheets/NotFound/NotFound.jsx"; import { EstablishmentProvider } from "../../components/DataSheets/Sections/SharedComponents/EstablishmentContext.jsx"; import SubHeader from "../../components/DataSheets/Sections/SharedComponents/SubHeader/SubHeader.jsx"; import Sidebar from "../../components/DataSheets/Sidebar/Sidebar"; @@ -13,6 +14,7 @@ const CustomLayout = ({ siren, siret, children, + isNotFound = false, }) => { const [isOpenUserFeedback, setIsOpenUserFeedback] = React.useState(false); @@ -22,6 +24,7 @@ const CustomLayout = ({ const openUserFeedback = () => { setIsOpenUserFeedback(true); }; + if (isNotFound) return ; return ( <> @@ -61,6 +64,7 @@ CustomLayout.propTypes = { isEntrepriseDisplayed: PropTypes.bool.isRequired, isEstablishmentDisplayed: PropTypes.bool.isRequired, isEstablishmentsDisplayed: PropTypes.bool.isRequired, + isNotFound: PropTypes.bool, siren: PropTypes.string.isRequired, siret: PropTypes.string, }; diff --git a/src/client/src/services/PrivateRoute/PrivateRoute.js b/src/client/src/services/PrivateRoute/PrivateRoute.js index fc9fb19e..d009d6fc 100644 --- a/src/client/src/services/PrivateRoute/PrivateRoute.js +++ b/src/client/src/services/PrivateRoute/PrivateRoute.js @@ -1,10 +1,11 @@ import PropTypes from "prop-types"; -import React from "react"; +import React, { useEffect } from "react"; import { Redirect, Route, useHistory } from "react-router-dom"; import Layout from "../../components/App/Layout"; import { getSirenFromSiret } from "../../utils/establishment/establishment"; import Auth from "../Auth"; +import { useElasticQuery } from "../Elastic/elastic.js"; import CustomLayout from "./CustomLayout.jsx"; const PrivateRoute = ({ @@ -43,13 +44,22 @@ const PrivateRoute = ({ const { auth, redirect } = checkAuthorization(); const siret = rest?.computedMatch?.params?.siret; const siren = rest?.computedMatch?.params?.siren || getSirenFromSiret(siret); + const { data, error, loading, makeQuery } = useElasticQuery(); + useEffect(() => { + makeQuery(siret || siren, { + page: { current: 0, size: 10 }, + params: null, + }); + }, [siren, makeQuery]); + const isNotFound = + !loading && (error || !data?.results || data.results.length === 0); return ( auth ? ( - + {isEstablishmentDisplayed || isEntrepriseDisplayed || isEstablishmentsDisplayed ? ( @@ -57,10 +67,11 @@ const PrivateRoute = ({ isEstablishmentDisplayed={isEstablishmentDisplayed} isEntrepriseDisplayed={isEntrepriseDisplayed} isEstablishmentsDisplayed={isEstablishmentsDisplayed} + isNotFound={isNotFound} siren={siren} siret={siret} > - + {!isNotFound && } ) : (