diff --git a/.env.default b/.env.default
index f16264b20..85a91a5ce 100644
--- a/.env.default
+++ b/.env.default
@@ -13,7 +13,7 @@ NEXT_PUBLIC_CERTIFICAT_NUMEROTATION_ENABLED=0
ENABLE_HELMET=0
# Internal URL
-NEXT_PUBLIC_URL_CARTOGRAPHY_BAN = '/carte-base-adresse-nationale'
+NEXT_PUBLIC_URL_CARTOGRAPHY_BAN = /carte-base-adresse-nationale
# -----------------------------------------------
# --- Parametres URL Externe autre projet BAN ---
diff --git a/src/app/carte-base-adresse-nationale/components/Aside/Aside.styles.tsx b/src/app/carte-base-adresse-nationale/components/Aside/Aside.styles.tsx
index d9359125c..3bcc24f7c 100644
--- a/src/app/carte-base-adresse-nationale/components/Aside/Aside.styles.tsx
+++ b/src/app/carte-base-adresse-nationale/components/Aside/Aside.styles.tsx
@@ -17,19 +17,26 @@ export const AsideWrapper = styled.div<{
z-index: 9;
overflow-x: hidden;
overflow-y: auto;
+ scroll-behavior: smooth;
scroll-snap-type: y mandatory;
+ scroll-padding-top: 8rem;
+ font-size: 1rem;
pointer-events: none;
+ @media (hover: hover) {
+ &:hover,
+ &:focus-within,
+ &:active {
+ pointer-events: auto;
+ }
+ }
+
&::before {
${({ $isTypeInfo }) => !$isTypeInfo && css`content: ''`};
display: block;
- height: calc(100% - 2.5rem);
+ height: 100%;
scroll-snap-align: start;
transition: height 0.5s ease;
-
- ${({ $isVisible }) => css`
- height: ${$isVisible ? 'calc(100% - 2.5rem)' : '100%'};
- `}
}
.body {
@@ -38,15 +45,21 @@ export const AsideWrapper = styled.div<{
max-height: 100%;
overflow-x: hidden;
overflow-y: auto;
- box-shadow: 0 0 .5rem -0.125rem rgba(0, 0, 0, 0.7);
scroll-snap-align: start;
-
- ${({ $isTypeInfo }) => $isTypeInfo && css`
- display: flex;
- flex-flow: column nowrap;
- justify-content: flex-end;
- align-items: center;
- padding-bottom: 4rem; `
+ scroll-snap-stop: always;
+
+ ${({ $isTypeInfo }) => $isTypeInfo
+ ? css`
+ display: flex;
+ flex-flow: column nowrap;
+ justify-content: flex-end;
+ align-items: center;
+ padding-bottom: 4rem;
+ `
+ : css`
+ background: var(--background-default-grey);
+ box-shadow: 0 0 .5rem -0.125rem rgba(0, 0, 0, 0.7);
+ `
}
}
@@ -58,9 +71,10 @@ export const AsideWrapper = styled.div<{
max-width: calc(25% + 2rem);
overflow: hidden;
transition: transform 0.5s ease;
+ pointer-events: none;
${({ $withTogglerButton }) => $withTogglerButton
- ? css`
+ ? css`
width: calc(400px + 2rem);
max-width: calc(25% + 2rem);
`
@@ -81,22 +95,23 @@ export const AsideWrapper = styled.div<{
.body {
justify-content: flex-start;
height: 100%;
+ padding-bottom: 8rem;
overflow-x: hidden;
overflow-y: auto;
scroll-snap-type: x mandatory;
- ${({ $isTypeInfo }) => $isTypeInfo && css`padding-top: 4rem;`};
+ ${({ $isTypeInfo }) => $isTypeInfo && css`padding-top: 8rem;`};
}
}
`
export const AsideTogglerButtonWrapper = styled.div`
+ height: 0;
+
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
- height: 2.5rem;
- max-height: 2.5rem;
pointer-events: none;
&::after {
@@ -197,6 +212,11 @@ export const AsideWrapperTogglerButton = styled.button.attrs<{ $isOpen: boolean
}
`
+export const AsideBody = styled.div`
+ background: var(--background-default-grey);
+ pointer-events: auto;
+`
+
export const AsideFooter = styled.footer`
position: sticky;
z-index: 1;
diff --git a/src/app/carte-base-adresse-nationale/components/Aside/Aside.tsx b/src/app/carte-base-adresse-nationale/components/Aside/Aside.tsx
index c855d4476..7f8042e91 100644
--- a/src/app/carte-base-adresse-nationale/components/Aside/Aside.tsx
+++ b/src/app/carte-base-adresse-nationale/components/Aside/Aside.tsx
@@ -1,19 +1,45 @@
+import AsideHeader from './AsideHeader'
+
import {
AsideWrapper,
AsideTogglerButtonWrapper,
AsideWrapperTogglerButton,
+ AsideBody,
AsideFooter,
} from './Aside.styles'
-interface AsideProps {
+import type { MapBreadcrumbPath } from '../MapBreadcrumb'
+
+interface AsideDefaultProps {
children: React.ReactNode
+ header?: React.ReactNode
footer?: React.ReactNode
+ path?: MapBreadcrumbPath
+ onClose?: () => void
onClickToggler?: (args: { isOpen: boolean, togglerButtonType: 'horizontal' | 'vertical' }) => void
isOpen?: boolean
isInfo?: boolean
}
-function Aside({ children, footer, onClickToggler, isOpen = true, isInfo }: AsideProps) {
+interface AsideProps extends AsideDefaultProps {
+ header: React.ReactNode
+ isInfo?: false
+}
+interface AsideInfoProps extends AsideDefaultProps {
+ header?: undefined | null
+ isInfo: true
+}
+
+function Aside({
+ children,
+ header,
+ footer,
+ path,
+ onClose,
+ onClickToggler,
+ isOpen = true,
+ isInfo,
+}: AsideProps | AsideInfoProps) {
const withTogglerButton = Boolean(onClickToggler)
return (
@@ -25,18 +51,6 @@ function Aside({ children, footer, onClickToggler, isOpen = true, isInfo }: Asid
>
{withTogglerButton && (
- {
- onClickToggler?.({
- isOpen,
- togglerButtonType: 'vertical',
- })
- }}
- $isOpen={isOpen}
- />
-
{
@@ -50,9 +64,22 @@ function Aside({ children, footer, onClickToggler, isOpen = true, isInfo }: Asid
)}
-
- {children}
+
+
+ {header && (
+
+ {header}
+
+ )}
+ {isInfo
+ ? children
+ : children && (
+
+ {children}
+
+ )}
+
{footer && (
{footer}
diff --git a/src/app/carte-base-adresse-nationale/components/micro-toponym/AsideFooterMicroToponym.styles.tsx b/src/app/carte-base-adresse-nationale/components/Aside/AsideFooter.styles.tsx
similarity index 82%
rename from src/app/carte-base-adresse-nationale/components/micro-toponym/AsideFooterMicroToponym.styles.tsx
rename to src/app/carte-base-adresse-nationale/components/Aside/AsideFooter.styles.tsx
index 9755929e6..5f09b4aa2 100644
--- a/src/app/carte-base-adresse-nationale/components/micro-toponym/AsideFooterMicroToponym.styles.tsx
+++ b/src/app/carte-base-adresse-nationale/components/Aside/AsideFooter.styles.tsx
@@ -2,7 +2,9 @@
import styled from 'styled-components'
-export const AsideFooterWrapper = styled.div``
+export const AsideFooterWrapper = styled.div`
+ font-size: 1rem;
+`
export const ActionWrapper = styled.ul`
display: flex;
diff --git a/src/app/carte-base-adresse-nationale/components/Aside/AsideFooter.tsx b/src/app/carte-base-adresse-nationale/components/Aside/AsideFooter.tsx
new file mode 100644
index 000000000..f79bad597
--- /dev/null
+++ b/src/app/carte-base-adresse-nationale/components/Aside/AsideFooter.tsx
@@ -0,0 +1,47 @@
+import { useMemo } from 'react'
+
+import Button, { ButtonProps } from '@codegouvfr/react-dsfr/Button'
+
+import {
+ AsideFooterWrapper,
+ ActionWrapper,
+ ActionList,
+} from './AsideFooter.styles'
+
+interface AsideFooterAddressProps {
+ children?: React.ReactNode
+ actions?: {
+ label: ButtonProps['children']
+ onClick: ButtonProps['onClick']
+ iconId: ButtonProps['iconId']
+ priority?: ButtonProps['priority']
+ }[]
+}
+
+function AsideFooterDistrict({ children, actions }: AsideFooterAddressProps) {
+ const actionsButtons = useMemo(() => actions?.map(({ label, ...props }, index) => (
+
+
+ {label}
+
+
+ )
+ ), [actions])
+
+ return (
+
+ {children}
+ {actions && actions.length > 0 && (
+
+
+ {actionsButtons}
+
+
+ )}
+
+ )
+}
+
+export default AsideFooterDistrict
diff --git a/src/app/carte-base-adresse-nationale/components/Aside/AsideHeader.styles.tsx b/src/app/carte-base-adresse-nationale/components/Aside/AsideHeader.styles.tsx
new file mode 100644
index 000000000..da301a99e
--- /dev/null
+++ b/src/app/carte-base-adresse-nationale/components/Aside/AsideHeader.styles.tsx
@@ -0,0 +1,73 @@
+'use client'
+
+import styled from 'styled-components'
+
+export const AsideHeader = styled.div`
+ position: absolute;
+ display: flex;
+ flex-direction: column-reverse;
+ overflow: hidden;
+ width: 100%;
+ padding: 0 1rem 1rem;
+ font-size: 1rem;
+ transform: translateY(-100%);
+ scroll-snap-align: start;
+ scroll-snap-stop: always;
+
+ @media (min-width: ${({ theme }) => theme.breakpoints.md}) {
+ position: static;
+ padding: 8rem 1rem 1rem;
+ background: var(--background-default-grey);
+ margin: 0;
+ transform: none;
+ }
+
+ & * {
+ pointer-events: auto;
+ }
+
+ &::after {
+ content: '';
+ position: absolute;
+ z-index: -1;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-image: linear-gradient(0deg, var(--background-default-grey) 0%, rgba(0, 0, 0, 0) 100%);
+ background-repeat: no-repeat;
+ background-size: 100% 100%;
+ background-position: 100% center;
+ pointer-events: auto;
+ transform: translateY(0);
+ transition: transform 0.5s ease;
+
+ @media (min-width: ${({ theme }) => theme.breakpoints.md}) {
+ content: none;
+ }
+ }
+`
+
+export const AsideHeaderContent = styled.div`
+ position: relative;
+ display: flex;
+ justify-content: flex-start;
+ align-items: center;
+ gap: 1.25rem;
+ padding: 1rem;
+ margin-bottom: 1rem;
+ border-bottom: 4px solid var(--border-active-blue-france);
+ background-color: var(--background-default-grey);
+
+ @media (min-width: ${({ theme }) => theme.breakpoints.md}) {
+ padding: 1rem 0;
+ }
+`
+
+export const AsideHeaderCloseButtonWrapper = styled.div`
+ position: absolute;
+ top: 0;
+ right: 0;
+ z-index: 1;
+ pointer-events: auto;
+`
diff --git a/src/app/carte-base-adresse-nationale/components/Aside/AsideHeader.tsx b/src/app/carte-base-adresse-nationale/components/Aside/AsideHeader.tsx
new file mode 100644
index 000000000..d7707fcec
--- /dev/null
+++ b/src/app/carte-base-adresse-nationale/components/Aside/AsideHeader.tsx
@@ -0,0 +1,40 @@
+import Button from '@codegouvfr/react-dsfr/Button'
+
+import MapBreadcrumb from '../MapBreadcrumb'
+import type { MapBreadcrumbPath } from '../MapBreadcrumb'
+
+import {
+ AsideHeader as AsideHeaderStyle,
+ AsideHeaderContent,
+ AsideHeaderCloseButtonWrapper,
+} from './AsideHeader.styles'
+
+interface AsideHeaderProps {
+ path?: MapBreadcrumbPath
+ children?: React.ReactNode
+ onClose?: () => void
+}
+
+function AsideHeader({ path, children, onClose }: AsideHeaderProps) {
+ return (
+
+ {path && }
+
+ {onClose && (
+
+
+
+ )}
+ {children}
+
+
+ )
+}
+
+export default AsideHeader
diff --git a/src/app/carte-base-adresse-nationale/components/DistrictLink/DistrictLink.styles.tsx b/src/app/carte-base-adresse-nationale/components/DistrictLink/DistrictLink.styles.tsx
new file mode 100644
index 000000000..563e8a83e
--- /dev/null
+++ b/src/app/carte-base-adresse-nationale/components/DistrictLink/DistrictLink.styles.tsx
@@ -0,0 +1,49 @@
+'use client'
+
+import styled from 'styled-components'
+import Link from 'next/link'
+
+export const DistrictLinkWrapper = styled.span`
+ position: relative;
+ font-size: 1em;
+ display: inline-flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ align-items: flex-start;
+ line-height: 1.5;
+ text-decoration: none;
+ cursor: pointer;
+`
+
+export const DistrictName = styled.span`
+ font-size: 1em;
+`
+
+export const DistrictLinkLabel = styled(Link).attrs({
+ className: 'fr-link fr-link--icon-right fr-icon-arrow-right-line --force-DSFR-overload',
+})`
+ &[class]:is(.--force-DSFR-overload) {
+ font-size: 1em;
+ line-height: inherit;
+ position: relative;
+ z-index: 2;
+ display: inline-block;
+ overflow: hidden;
+ max-height: 0;
+ opacity: 0;
+ will-change: max-height, opacity;
+ transition: max-height .3s ease,
+ opacity .3s ease;
+
+ ${DistrictLinkWrapper}:hover &,
+ ${DistrictLinkWrapper}:focus-within & {
+ --underline-hover-width: var(--underline-max-width); /* --force-DSFR-hover-link-style */
+ max-height: 2em;
+ opacity: 1;
+ }
+
+ a {
+ font-size: 1em;
+ }
+ }
+`
diff --git a/src/app/carte-base-adresse-nationale/components/DistrictLink/DistrictLink.tsx b/src/app/carte-base-adresse-nationale/components/DistrictLink/DistrictLink.tsx
new file mode 100644
index 000000000..59eb0c031
--- /dev/null
+++ b/src/app/carte-base-adresse-nationale/components/DistrictLink/DistrictLink.tsx
@@ -0,0 +1,36 @@
+import {
+ DistrictLinkWrapper,
+ DistrictName,
+ DistrictLinkLabel,
+} from './DistrictLink.styles'
+
+interface District {
+ nom: string
+ code: string
+}
+
+interface DistrictLinkProps {
+ children?: React.ReactNode
+ district: District
+}
+
+function DistrictLink({ children, district }: DistrictLinkProps) {
+ const href = `./commune/${district.code}`
+ const titleLink = `Voir la page de la commune de ${district.nom} (COG ${district.code})`
+
+ return (
+
+ {children || district.nom}
+
+
+ Voir la page de la commune
+
+
+ )
+}
+
+export default DistrictLink
diff --git a/src/app/carte-base-adresse-nationale/components/DistrictLink/index.ts b/src/app/carte-base-adresse-nationale/components/DistrictLink/index.ts
new file mode 100644
index 000000000..ba9771053
--- /dev/null
+++ b/src/app/carte-base-adresse-nationale/components/DistrictLink/index.ts
@@ -0,0 +1 @@
+export { default } from './DistrictLink'
diff --git a/src/app/carte-base-adresse-nationale/components/LoadingBar/LoadingBar.styles.tsx b/src/app/carte-base-adresse-nationale/components/LoadingBar/LoadingBar.styles.tsx
new file mode 100644
index 000000000..5b7fad8af
--- /dev/null
+++ b/src/app/carte-base-adresse-nationale/components/LoadingBar/LoadingBar.styles.tsx
@@ -0,0 +1,60 @@
+'use client'
+
+import styled, { css, keyframes } from 'styled-components'
+
+const loadingAnimation = keyframes`
+ 0% {
+ background-position: 200% 0;
+ }
+ 100% {
+ background-position: -200% 0;
+ }
+`
+
+export const LoadingBar = styled.div<{ $isLoading: boolean }>`
+ --loading-bar-size: 5px;
+ --loading-bg-color: var(--background-action-high-blue-france);
+ --loading-bg-color-strength: var(--background-default-grey);
+
+ &::before {
+ content: '';
+ position: absolute;
+ z-index: 1;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ height: 100%;
+ background-image: linear-gradient(
+ 90deg,
+ var(--loading-bg-color) 0,
+ var(--loading-bg-color) 18%,
+ var(--loading-bg-color-strength) 20%,
+ var(--loading-bg-color-strength) 50%,
+ var(--loading-bg-color) 52%,
+ var(--loading-bg-color)
+ );
+ background-size: 200% 100%;
+ opacity: 0.6;
+ animation: ${loadingAnimation} 4s infinite;
+ }
+
+ position: absolute;
+ z-index: 100;
+ top: 0;
+ left: 0;
+ width: 0;
+ height: var(--loading-bar-size);
+ background-color: var(--loading-bg-color);
+ transform: translateY(calc(-1 * var(--loading-bar-size)));
+ opacity: 0;
+ transition: transform 0.3s ease,
+ width 1.5s ease,
+ opacity 0.3s ease;
+
+ ${({ $isLoading }) => $isLoading && css`
+ transform: translateY(0);
+ width: 100%;
+ opacity: 0.9;
+ `}
+`
diff --git a/src/app/carte-base-adresse-nationale/components/LoadingBar/index.ts b/src/app/carte-base-adresse-nationale/components/LoadingBar/index.ts
new file mode 100644
index 000000000..5b4784f3e
--- /dev/null
+++ b/src/app/carte-base-adresse-nationale/components/LoadingBar/index.ts
@@ -0,0 +1 @@
+export { LoadingBar as default, LoadingBar } from './LoadingBar.styles'
diff --git a/src/app/carte-base-adresse-nationale/components/MapBreadcrumb/MapBreadcrumb.tsx b/src/app/carte-base-adresse-nationale/components/MapBreadcrumb/MapBreadcrumb.tsx
index 8d3c44033..cc2461ccc 100644
--- a/src/app/carte-base-adresse-nationale/components/MapBreadcrumb/MapBreadcrumb.tsx
+++ b/src/app/carte-base-adresse-nationale/components/MapBreadcrumb/MapBreadcrumb.tsx
@@ -11,9 +11,9 @@ interface MapBreadcrumbPathSegment {
target?: string
}
}
-interface MapBreadcrumbPath extends Array {}
+export interface MapBreadcrumbPath extends Array {}
-interface MapBreadcrumbProps {
+export interface MapBreadcrumbProps {
path: MapBreadcrumbPath
}
diff --git a/src/app/carte-base-adresse-nationale/components/MapBreadcrumb/index.ts b/src/app/carte-base-adresse-nationale/components/MapBreadcrumb/index.ts
index b5342b536..a61a17919 100644
--- a/src/app/carte-base-adresse-nationale/components/MapBreadcrumb/index.ts
+++ b/src/app/carte-base-adresse-nationale/components/MapBreadcrumb/index.ts
@@ -1 +1,2 @@
export { default } from './MapBreadcrumb'
+export type { MapBreadcrumbProps, MapBreadcrumbPath } from './MapBreadcrumb'
diff --git a/src/app/carte-base-adresse-nationale/components/MapDataLoader/MapDataLoader.styles.tsx b/src/app/carte-base-adresse-nationale/components/MapDataLoader/MapDataLoader.styles.tsx
deleted file mode 100644
index c020f9bfc..000000000
--- a/src/app/carte-base-adresse-nationale/components/MapDataLoader/MapDataLoader.styles.tsx
+++ /dev/null
@@ -1,68 +0,0 @@
-'use client'
-
-import styled, { css, keyframes } from 'styled-components'
-
-export const LoaderWrapper = styled.div<{ $isVisible: boolean }>`
- width: 100%;
- max-height: 100%;
- opacity: 1;
- transform: translate(0, 0);
- transition: transform 0.4s ease 0.3s, opacity 0.6s ease 0.3s, max-height 0.3s ease;
-
- ${({ $isVisible }) => $isVisible && css`
- max-height: 0;
- opacity: 0;
- transform: translate(calc(-100% - 2rem), 0);
- transition: transform 0.4s ease, opacity 0.6s ease, max-height 0.3s ease 0.6s;
- `}
-`
-
-export const LoaderDialog = styled.dialog`
- position: relative;
- z-index: 2310;
- display: flex;
- flex-flow: row nowrap;
- justify-content: flex-start;
- align-items: self-start;
- gap: 1rem;
- width: calc(100% - 1rem - 1rem);
- margin: 1rem 1rem 0;
- padding: 1rem;
- border: 0 none;
- border-bottom: 3px solid var(--border-plain-info);
- border-radius: .25rem .25rem 0 0;
- box-shadow: 0 0 10px rgba(0, 0, 0, 0.25);
- pointer-events: auto;
-`
-
-const rotate = keyframes`
- from { transform: rotate(0deg) }
- to { transform: rotate(360deg) }
-`
-
-export const LoaderIconWrapper = styled.div`
- position: relative;
- display: flex;
- justify-content: center;
- align-items: center;
- width: 1.5rem;
- height: 1.5rem;
- opacity: 0;
- transition: opacity 0.25s ease .25s;
-
- &.loading {
- opacity: 1;
- transition: opacity 0.25s ease;
- }
-
- .loader-icon {
- color: var(--text-default-info);
- animation:${rotate} 2s infinite;
- animation-timing-function: cubic-bezier(0.25, 0.5, 0.25, 0.5);
- }
-`
-
-export const LoaderMessage = styled.div`
- flex: 1;
- font-weight: 600;
-`
diff --git a/src/app/carte-base-adresse-nationale/components/MapDataLoader/MapDataLoader.tsx b/src/app/carte-base-adresse-nationale/components/MapDataLoader/MapDataLoader.tsx
deleted file mode 100644
index 6aab940bb..000000000
--- a/src/app/carte-base-adresse-nationale/components/MapDataLoader/MapDataLoader.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import {
- LoaderWrapper,
- LoaderDialog,
- LoaderIconWrapper,
- LoaderMessage,
-} from './MapDataLoader.styles'
-
-interface MapDataLoaderProps {
- children: React.ReactNode
- isLoading: boolean
-}
-
-function MapDataLoader({ children, isLoading }: MapDataLoaderProps) {
- return (
-
-
-
-
-
-
- {children}
-
-
-
- )
-}
-
-export default MapDataLoader
diff --git a/src/app/carte-base-adresse-nationale/components/MapDataLoader/index.ts b/src/app/carte-base-adresse-nationale/components/MapDataLoader/index.ts
deleted file mode 100644
index 8c8aa0584..000000000
--- a/src/app/carte-base-adresse-nationale/components/MapDataLoader/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from './MapDataLoader'
diff --git a/src/app/carte-base-adresse-nationale/components/address/download-certificate.tsx b/src/app/carte-base-adresse-nationale/components/PanelAddress/DownloadCertificate.tsx
similarity index 100%
rename from src/app/carte-base-adresse-nationale/components/address/download-certificate.tsx
rename to src/app/carte-base-adresse-nationale/components/PanelAddress/DownloadCertificate.tsx
diff --git a/src/app/carte-base-adresse-nationale/components/PanelAddress/PanelAddress.styles.tsx b/src/app/carte-base-adresse-nationale/components/PanelAddress/PanelAddress.styles.tsx
new file mode 100644
index 000000000..6eadd9d54
--- /dev/null
+++ b/src/app/carte-base-adresse-nationale/components/PanelAddress/PanelAddress.styles.tsx
@@ -0,0 +1,60 @@
+'use client'
+
+import styled from 'styled-components'
+
+export const AddressDetailsWrapper = styled.ul`
+ padding: 0;
+ margin: 0;
+ font-size: 0.9rem;
+ line-height: 1.5;
+`
+
+const AddressDetailsItemStyle = styled.li`
+ display: flex;
+ flex-direction: row;
+ margin-bottom: 0.2em;
+
+ b {
+ font-weight: normal;
+ font-size: 1.1em;
+ }
+
+ &::before {
+ margin-right: 0.5em;
+ width: 1.25em;
+ height: 1.25em;
+ vertical-align: -0.25rem;
+ }
+`
+
+interface AddressDetailsItemProps extends React.HTMLAttributes {
+ children: React.ReactNode
+}
+
+export const AddressDetailsItem = ({ children, ...props }: AddressDetailsItemProps) => (
+
+
+ {children}
+
+
+)
+
+interface AddressDetailsCertificationProps extends React.HTMLAttributes {
+ children: React.ReactNode
+ isCertified: boolean
+}
+
+export const AddressDetailsCertification = ({ children, isCertified, ...props }: AddressDetailsCertificationProps) => (
+
+
+ {children}
+
+
+)
+
+export const AddressDetailsItemValue = styled.pre`
+ font-size: small;
+ font-weight: 700;
+ margin-bottom: 0.5rem;
+ white-space: pre-line;
+`
diff --git a/src/app/carte-base-adresse-nationale/components/PanelAddress/PanelAddress.tsx b/src/app/carte-base-adresse-nationale/components/PanelAddress/PanelAddress.tsx
new file mode 100644
index 000000000..921bdb991
--- /dev/null
+++ b/src/app/carte-base-adresse-nationale/components/PanelAddress/PanelAddress.tsx
@@ -0,0 +1,105 @@
+import {
+ AddressDetailsItemValue,
+ AddressDetailsWrapper,
+ AddressDetailsItem,
+ AddressDetailsCertification,
+} from './PanelAddress.styles'
+
+import type { TypeAddressExtended } from '../../types/LegacyBan.types'
+
+interface PanelAddressProps {
+ address: TypeAddressExtended
+}
+
+interface Position {
+ position: TypeAddressExtended['position']
+ positionType: TypeAddressExtended['positionType']
+}
+
+function PanelAddress({ address }: PanelAddressProps) {
+ const dateMaj = new Date(address.dateMAJ).toLocaleDateString('fr-FR', {
+ year: 'numeric',
+ month: 'long',
+ day: 'numeric',
+ })
+
+ const isMultiPosition = Number(address.positions?.length) > 1
+ const {
+ mainPosition,
+ secondariesPositions,
+ }: {
+ mainPosition: Position
+ secondariesPositions: Position[]
+ } = isMultiPosition
+ ? address.positions.reduce((acc, entry) => {
+ if (entry.position.coordinates.join('--') === address.position.coordinates.join('--')) {
+ acc.mainPosition = entry
+ }
+ else {
+ acc.secondariesPositions.push(entry)
+ }
+ return acc
+ }, { mainPosition: (null as unknown as Position), secondariesPositions: ([] as Position[]) })
+ : { mainPosition: {
+ position: address.position,
+ positionType: address.positionType,
+ }, secondariesPositions: [] }
+
+ return (
+
+
+ {address.certifie ? `Adresse certifiée` : 'Adresse non certifiée'}
+
+
+
+ Identifiant BAN :
+ {address.banId}
+
+
+
+
+ Clé d’interopérabilité :
+ {address.cleInterop}
+
+
+
+
+ Parcelles cadastrales :
+ {address?.parcelles.join(', ') || 'Non renseignée(s)'}
+
+
+
+ Date de mise à jour :
+ {dateMaj}
+
+
+ Producteur :
+ {address.sourcePosition}
+
+
+ Libellé d’acheminement :
+ {address.libelleAcheminement}
+
+
+ {isMultiPosition ? 'Position Principale' : 'Position'} :
+ Type / {mainPosition.positionType}
+ Coordonnées / {mainPosition.position.coordinates[0]}, {mainPosition.position.coordinates[1]}
+
+ {isMultiPosition && (
+
+ Position Secondaire :
+
+ {secondariesPositions.map((entry, index) => (
+
+ Type / {entry.positionType}
+ Coordonnées / {entry.position.coordinates[0]}, {entry.position.coordinates[1]}
+
+ ))}
+
+
+ )}
+
+ )
+}
+
+export default PanelAddress
diff --git a/src/app/carte-base-adresse-nationale/components/PanelAddress/PanelAddressFooter.styles.tsx b/src/app/carte-base-adresse-nationale/components/PanelAddress/PanelAddressFooter.styles.tsx
new file mode 100644
index 000000000..8d6293814
--- /dev/null
+++ b/src/app/carte-base-adresse-nationale/components/PanelAddress/PanelAddressFooter.styles.tsx
@@ -0,0 +1,31 @@
+'use client'
+
+import styled from 'styled-components'
+
+export const AsideFooterWrapper = styled.div``
+
+export const ActionWrapper = styled.ul`
+ display: flex;
+ flex-direction: column;
+ gap: 0.25rem;
+ margin: 0;
+ padding: 0;
+ list-style: none;
+`
+
+export const ActionList = styled.ul`
+ display: block;
+ padding: 0;
+ margin: 0;
+ list-style: none;
+`
+
+export const ActionMessage = styled.div`
+ font-size: 0.8rem;
+ font-weight: 300;
+ line-height: 1.5;
+ color: var(--text-default-grey);
+ margin: 0.5em 1em;
+ border-left: 1px solid;
+ padding: 0 1em;
+`
diff --git a/src/app/carte-base-adresse-nationale/components/address/AsideFooterAddress.tsx b/src/app/carte-base-adresse-nationale/components/PanelAddress/PanelAddressFooter.tsx
similarity index 92%
rename from src/app/carte-base-adresse-nationale/components/address/AsideFooterAddress.tsx
rename to src/app/carte-base-adresse-nationale/components/PanelAddress/PanelAddressFooter.tsx
index e6ee2209f..83885ec05 100644
--- a/src/app/carte-base-adresse-nationale/components/address/AsideFooterAddress.tsx
+++ b/src/app/carte-base-adresse-nationale/components/PanelAddress/PanelAddressFooter.tsx
@@ -1,17 +1,17 @@
import { useMemo } from 'react'
+import Button from '@codegouvfr/react-dsfr/Button'
import { isNumeroCertifiable } from '@/lib/ban'
-import { useFocusOnMap } from '../ban-map/BanMap.context'
-import Button from '@codegouvfr/react-dsfr/Button'
-
-import DownloadCertificate from './download-certificate'
+import { useFocusOnMap } from '../ban-map/BanMap.context'
+import DownloadCertificate from './DownloadCertificate'
import {
AsideFooterWrapper,
ActionWrapper,
ActionList,
-} from './AsideFooterAddress.styles'
+ ActionMessage,
+} from './PanelAddressFooter.styles'
import type { TypeAddressExtended } from '../../types/LegacyBan.types'
@@ -40,17 +40,17 @@ function AsideFooterAddress({ banItem: address, withCertificate, children }: Asi
{children}
{!withCertificate && (
-
+
Les certifications d’adresses sur la commune de {address.commune.nom} sont
réalisées directement par la mairie.
Contactez-la pour obtenir un certificat d’adressage ou toute autre information.
-
+
)}
{withCertificate && !isCertifiable && (
-
+
Cette adresse ne remplit pas les critères minimums pour obtenir une certification.
Veuillez contacter votre mairie pour obtenir un certificat d’adressage ou toute autre information.
-
+
)}
diff --git a/src/app/carte-base-adresse-nationale/components/PanelAddress/PanelAddressHeader.styles.tsx b/src/app/carte-base-adresse-nationale/components/PanelAddress/PanelAddressHeader.styles.tsx
new file mode 100644
index 000000000..64577e599
--- /dev/null
+++ b/src/app/carte-base-adresse-nationale/components/PanelAddress/PanelAddressHeader.styles.tsx
@@ -0,0 +1,24 @@
+'use client'
+
+import styled, { css } from 'styled-components'
+
+export const AddressLabelWrapper = styled.div`
+ font-size: 1rem;
+`
+
+export const AddressNumber = styled.span`
+ font-size: 1.75em;
+ font-style: italic;
+ line-height: 1;
+ font-weight: 300;
+`
+export const AddressNumberSuffix = styled.span`
+ font-size: 0.75em;
+ vertical-align: top;
+ margin-left: 0.15em;
+`
+
+export const AddressMicroTopoLabel = styled.span<{ $isOnNewLine: boolean }>`
+ font-size: 1em;
+ ${({ $isOnNewLine }) => $isOnNewLine && css`display: block;`}
+`
diff --git a/src/app/carte-base-adresse-nationale/components/PanelAddress/PanelAddressHeader.tsx b/src/app/carte-base-adresse-nationale/components/PanelAddress/PanelAddressHeader.tsx
new file mode 100644
index 000000000..76c7fa47d
--- /dev/null
+++ b/src/app/carte-base-adresse-nationale/components/PanelAddress/PanelAddressHeader.tsx
@@ -0,0 +1,72 @@
+import DistrictLink from '../DistrictLink'
+import formatNumber from '../../tools/formatNumber'
+
+import {
+ PanelDistrictLabelPrefix,
+ PanelDistrictLabel,
+ PanelNumberAndMicroTopoLabel,
+ PanelAddressPostCode,
+ PanelMicroTopoLabelAlt,
+ PanelMicroTopoLabelAltFlag,
+} from '../PanelStyles/PanelStyles'
+
+import {
+ AddressLabelWrapper,
+ AddressNumber,
+ AddressNumberSuffix,
+ AddressMicroTopoLabel,
+} from './PanelAddressHeader.styles'
+
+import type { TypeAddressExtended } from '../../types/LegacyBan.types'
+
+interface AddressCardProps {
+ address: TypeAddressExtended
+}
+
+function AddressCard({ address }: AddressCardProps) {
+ const district = address.commune
+ const microToponym = address.voie
+
+ return (
+ <>
+
+
+ {(address.numero || address.suffixe) && (
+ <>
+
+ {address.numero ? `${address.numero}` : ''}
+ {address.suffixe && {address.suffixe} }
+
+ {' '}
+ >
+ )}
+
+ {microToponym.nomVoie},
+
+
+
+ {microToponym?.nomVoieAlt && Object.entries(microToponym.nomVoieAlt).map(([lang, odonyme]) => (
+
+ {' '}
+ {odonyme}
+
+ ))}
+
+ CP {formatNumber(address.codePostal)}
+
+ {address.nomAncienneCommune && (
+ <>
+ Commune historique de
+ {address.nomAncienneCommune},
+ >
+ )}
+
+ {district.nom} (COG {district.code})
+
+
+
+ >
+ )
+}
+
+export default AddressCard
diff --git a/src/app/carte-base-adresse-nationale/components/PanelAddress/index.ts b/src/app/carte-base-adresse-nationale/components/PanelAddress/index.ts
new file mode 100644
index 000000000..5ddce2ae2
--- /dev/null
+++ b/src/app/carte-base-adresse-nationale/components/PanelAddress/index.ts
@@ -0,0 +1,3 @@
+export { default as PanelAddressHeader } from './PanelAddressHeader'
+export { default, default as PanelAddress } from './PanelAddress'
+export { default as PanelAddressFooter } from './PanelAddressFooter'
diff --git a/src/app/carte-base-adresse-nationale/components/PanelDistrict/PanelDistrict.styles.tsx b/src/app/carte-base-adresse-nationale/components/PanelDistrict/PanelDistrict.styles.tsx
new file mode 100644
index 000000000..8c7d355ce
--- /dev/null
+++ b/src/app/carte-base-adresse-nationale/components/PanelDistrict/PanelDistrict.styles.tsx
@@ -0,0 +1,27 @@
+'use client'
+
+import styled from 'styled-components'
+
+export const DistrictDetailsWrapper = styled.ul`
+ padding: 0;
+ margin: 2rem 0;
+ font-size: 0.9rem;
+ line-height: 1.5;
+`
+
+export const DistrictDetailsItem = styled.li`
+ display: block;
+ margin-bottom: 0.2em;
+
+ b {
+ font-weight: 500;
+ font-size: 1.1em;
+ }
+
+ &::before {
+ width: 1.25em;
+ height: 1.25em;
+ margin-right: 0.5em;
+ vertical-align: -0.25rem;
+ }
+`
diff --git a/src/app/carte-base-adresse-nationale/components/district/DistrictCard.tsx b/src/app/carte-base-adresse-nationale/components/PanelDistrict/PanelDistrict.tsx
similarity index 66%
rename from src/app/carte-base-adresse-nationale/components/district/DistrictCard.tsx
rename to src/app/carte-base-adresse-nationale/components/PanelDistrict/PanelDistrict.tsx
index a6f10e3ab..a58370af2 100644
--- a/src/app/carte-base-adresse-nationale/components/district/DistrictCard.tsx
+++ b/src/app/carte-base-adresse-nationale/components/PanelDistrict/PanelDistrict.tsx
@@ -1,44 +1,21 @@
import Link from 'next/link'
-import Image from 'next/image'
import formatNumber from '../../tools/formatNumber'
+import PanelDistrictMicroToponymList from './PanelDistrictMicroToponymList'
import {
- DistrictHeaderWrapper,
- DistrictLabelWrapper,
- DistrictLabelPrefix,
- DistrictLabel,
- DistrictLabelCode,
- DistrictLogoWrapper,
DistrictDetailsWrapper,
DistrictDetailsItem,
-} from './DistrictCard.styles'
+} from './PanelDistrict.styles'
import type { TypeDistrictExtended } from '../../types/LegacyBan.types'
-interface DistrictCardProps {
+interface PanelDistrictProps {
district: TypeDistrictExtended
- logo?: string
}
-function DistrictCard({ district, logo }: DistrictCardProps) {
+function PanelDistrict({ district }: PanelDistrictProps) {
return (
<>
-
- {logo && (
-
-
-
- )}
-
-
- Commune de
-
- {district.nomCommune}
-
- COG {district.codeCommune}
-
-
-
{formatNumber(district.population)} habitants
@@ -70,8 +47,10 @@ function DistrictCard({ district, logo }: DistrictCardProps) {
+
+
>
)
}
-export default DistrictCard
+export default PanelDistrict
diff --git a/src/app/carte-base-adresse-nationale/components/address/AsideFooterAddress.styles.tsx b/src/app/carte-base-adresse-nationale/components/PanelDistrict/PanelDistrictFooter.styles.tsx
similarity index 100%
rename from src/app/carte-base-adresse-nationale/components/address/AsideFooterAddress.styles.tsx
rename to src/app/carte-base-adresse-nationale/components/PanelDistrict/PanelDistrictFooter.styles.tsx
diff --git a/src/app/carte-base-adresse-nationale/components/district/AsideFooterDistrict.tsx b/src/app/carte-base-adresse-nationale/components/PanelDistrict/PanelDistrictFooter.tsx
similarity index 81%
rename from src/app/carte-base-adresse-nationale/components/district/AsideFooterDistrict.tsx
rename to src/app/carte-base-adresse-nationale/components/PanelDistrict/PanelDistrictFooter.tsx
index 851d4edfe..f71a7be25 100644
--- a/src/app/carte-base-adresse-nationale/components/district/AsideFooterDistrict.tsx
+++ b/src/app/carte-base-adresse-nationale/components/PanelDistrict/PanelDistrictFooter.tsx
@@ -6,17 +6,17 @@ import {
AsideFooterWrapper,
ActionWrapper,
ActionList,
-} from './AsideFooterDistrict.styles'
+} from './PanelDistrictFooter.styles'
import type { TypeDistrictExtended } from '../../types/LegacyBan.types'
-interface AsideFooterAddressProps {
+interface PanelDistrictFooterProps {
banItem: TypeDistrictExtended
withCertificate: boolean
children?: React.ReactNode
}
-function AsideFooterDistrict({ banItem: microToponym, children }: AsideFooterAddressProps) {
+function PanelDistrictFooter({ banItem: microToponym, children }: PanelDistrictFooterProps) {
const focusOnMap = useFocusOnMap(microToponym)
const handleClick = (evt: React.MouseEvent
) => {
@@ -43,4 +43,4 @@ function AsideFooterDistrict({ banItem: microToponym, children }: AsideFooterAdd
)
}
-export default AsideFooterDistrict
+export default PanelDistrictFooter
diff --git a/src/app/carte-base-adresse-nationale/components/PanelDistrict/PanelDistrictHeader.styles.tsx b/src/app/carte-base-adresse-nationale/components/PanelDistrict/PanelDistrictHeader.styles.tsx
new file mode 100644
index 000000000..db37b3670
--- /dev/null
+++ b/src/app/carte-base-adresse-nationale/components/PanelDistrict/PanelDistrictHeader.styles.tsx
@@ -0,0 +1,39 @@
+'use client'
+
+import styled from 'styled-components'
+
+import { mainInfo } from '../PanelStyles/PanelStyles'
+
+export const DistrictHeaderWrapper = styled.div`
+ display: flex;
+ justify-content: flex-start;
+ align-items: flex-start;
+ gap: 1.25rem;
+ font-size: 1rem;
+`
+
+export const DistrictLogoWrapper = styled.div``
+
+export const DistrictLabelWrapper = styled.div``
+
+export const DistrictLabelPrefix = styled.span`
+ display: block;
+ font-size: .8em;
+ font-weight: 300;
+ line-height: 1;
+ margin-bottom: 0.25rem;
+`
+
+export const DistrictLabel = styled.span`
+ ${mainInfo}
+ display: block;
+ margin-bottom: 0.5rem;
+ line-height: 1;
+`
+
+export const DistrictLabelCode = styled.span`
+ display: block;
+ margin-bottom: 0.5rem;
+ font-size: 0.9em;
+ font-weight: 700;
+`
diff --git a/src/app/carte-base-adresse-nationale/components/PanelDistrict/PanelDistrictHeader.tsx b/src/app/carte-base-adresse-nationale/components/PanelDistrict/PanelDistrictHeader.tsx
new file mode 100644
index 000000000..48ff30ee1
--- /dev/null
+++ b/src/app/carte-base-adresse-nationale/components/PanelDistrict/PanelDistrictHeader.tsx
@@ -0,0 +1,47 @@
+import Image from 'next/image'
+
+import DistrictLink from '../DistrictLink'
+
+import {
+ DistrictHeaderWrapper,
+ DistrictLabelWrapper,
+ DistrictLabelPrefix,
+ DistrictLabel,
+ DistrictLabelCode,
+ DistrictLogoWrapper,
+} from './PanelDistrictHeader.styles'
+
+import type { TypeDistrictExtended } from '../../types/LegacyBan.types'
+
+interface PanelDistrictHeaderProps {
+ district: TypeDistrictExtended
+ logo?: string
+}
+
+function PanelDistrictHeader({ district, logo }: PanelDistrictHeaderProps) {
+ const formatedDistrict = {
+ nom: district.nomCommune,
+ code: district.codeCommune,
+ }
+
+ return (
+
+
+ {logo && (
+
+
+
+ )}
+
+ Commune de
+
+ {district.nomCommune}
+
+ COG {district.codeCommune}
+
+
+
+ )
+}
+
+export default PanelDistrictHeader
diff --git a/src/app/carte-base-adresse-nationale/components/district/DistrictMicroToponymList.styles.tsx b/src/app/carte-base-adresse-nationale/components/PanelDistrict/PanelDistrictMicroToponymList.styles.tsx
similarity index 100%
rename from src/app/carte-base-adresse-nationale/components/district/DistrictMicroToponymList.styles.tsx
rename to src/app/carte-base-adresse-nationale/components/PanelDistrict/PanelDistrictMicroToponymList.styles.tsx
diff --git a/src/app/carte-base-adresse-nationale/components/district/DistrictMicroToponymList.tsx b/src/app/carte-base-adresse-nationale/components/PanelDistrict/PanelDistrictMicroToponymList.tsx
similarity index 91%
rename from src/app/carte-base-adresse-nationale/components/district/DistrictMicroToponymList.tsx
rename to src/app/carte-base-adresse-nationale/components/PanelDistrict/PanelDistrictMicroToponymList.tsx
index c79e25397..aae40ee63 100644
--- a/src/app/carte-base-adresse-nationale/components/district/DistrictMicroToponymList.tsx
+++ b/src/app/carte-base-adresse-nationale/components/PanelDistrict/PanelDistrictMicroToponymList.tsx
@@ -3,14 +3,14 @@ import Link from 'next/link'
import { ToggleSwitch } from '@codegouvfr/react-dsfr/ToggleSwitch'
import { Table } from '@codegouvfr/react-dsfr/Table'
-import { DistrictMicroToponymListInfo } from './DistrictMicroToponymList.styles'
+import { DistrictMicroToponymListInfo } from './PanelDistrictMicroToponymList.styles'
import type { TypeDistrictExtended } from '../../types/LegacyBan.types'
import { env } from 'next-runtime-env'
const URL_CARTOGRAPHY_BAN = env('NEXT_PUBLIC_URL_CARTOGRAPHY_BAN')
-interface DistrictMicroToponymListProps {
+interface PanelDistrictMicroToponymListProps {
district: TypeDistrictExtended
}
@@ -22,7 +22,7 @@ const sortMicroToponymes = (
const testMicroTopoWithAddress = ({ nbNumeros }: { nbNumeros: number }) => nbNumeros && nbNumeros > 0
const testMicroTopoWithoutAddress = ({ nbNumeros }: { nbNumeros: number }) => !nbNumeros || nbNumeros === 0
-function DistrictMicroToponymList({ district }: DistrictMicroToponymListProps) {
+function PanelDistrictMicroToponymList({ district }: PanelDistrictMicroToponymListProps) {
const [isMicroTopoWithAddressVisible, setIsMicroTopoWithAddressVisible] = useState(true)
const [isMicroTopoWithoutAddressVisible, setIsMicroTopoWithoutAddressVisible] = useState(true)
@@ -90,4 +90,4 @@ function DistrictMicroToponymList({ district }: DistrictMicroToponymListProps) {
)
}
-export default DistrictMicroToponymList
+export default PanelDistrictMicroToponymList
diff --git a/src/app/carte-base-adresse-nationale/components/PanelDistrict/index.ts b/src/app/carte-base-adresse-nationale/components/PanelDistrict/index.ts
new file mode 100644
index 000000000..6eccf48eb
--- /dev/null
+++ b/src/app/carte-base-adresse-nationale/components/PanelDistrict/index.ts
@@ -0,0 +1,4 @@
+export { default as PanelDistrictHeader } from './PanelDistrictHeader'
+export { default, default as PanelDistrict } from './PanelDistrict'
+export { default as PanelDistrictMicroToponymList } from './PanelDistrictMicroToponymList'
+export { default as PanelDistrictFooter } from './PanelDistrictFooter'
diff --git a/src/app/carte-base-adresse-nationale/components/micro-toponym/MicroToponymCard.styles.tsx b/src/app/carte-base-adresse-nationale/components/PanelMicroToponym/PanelMicroToponym.styles.tsx
similarity index 96%
rename from src/app/carte-base-adresse-nationale/components/micro-toponym/MicroToponymCard.styles.tsx
rename to src/app/carte-base-adresse-nationale/components/PanelMicroToponym/PanelMicroToponym.styles.tsx
index ae58e9c94..0237b7a42 100644
--- a/src/app/carte-base-adresse-nationale/components/micro-toponym/MicroToponymCard.styles.tsx
+++ b/src/app/carte-base-adresse-nationale/components/PanelMicroToponym/PanelMicroToponym.styles.tsx
@@ -14,8 +14,7 @@ export const MicroToponymHeaderWrapper = styled.div`
border-bottom: 4px solid var(--border-active-blue-france);
`
-export const MicroToponymLabelWrapper = styled.div`
-`
+export const MicroToponymLabelWrapper = styled.div``
export const MicroToponymLabel = styled.span`
display: block;
@@ -34,7 +33,6 @@ export const MicroToponymLabelAlt = styled.span`
`
const flagSize = '1.3em'
-
export const MicroToponymLabelFlag = styled(Image).attrs({
width: 24,
height: 24,
diff --git a/src/app/carte-base-adresse-nationale/components/PanelMicroToponym/PanelMicroToponym.tsx b/src/app/carte-base-adresse-nationale/components/PanelMicroToponym/PanelMicroToponym.tsx
new file mode 100644
index 000000000..f7c7f061b
--- /dev/null
+++ b/src/app/carte-base-adresse-nationale/components/PanelMicroToponym/PanelMicroToponym.tsx
@@ -0,0 +1,15 @@
+import PanelMicroToponymAddressList from './PanelMicroToponymAddressList'
+
+import type { TypeMicroToponymExtended } from '../../types/LegacyBan.types'
+
+interface PanelMicroToponymProps {
+ microToponym: TypeMicroToponymExtended
+}
+
+function PanelMicroToponym({ microToponym }: PanelMicroToponymProps) {
+ return (
+
+ )
+}
+
+export default PanelMicroToponym
diff --git a/src/app/carte-base-adresse-nationale/components/micro-toponym/MicroToponymAddressList.styles.tsx b/src/app/carte-base-adresse-nationale/components/PanelMicroToponym/PanelMicroToponymAddressList.styles.tsx
similarity index 90%
rename from src/app/carte-base-adresse-nationale/components/micro-toponym/MicroToponymAddressList.styles.tsx
rename to src/app/carte-base-adresse-nationale/components/PanelMicroToponym/PanelMicroToponymAddressList.styles.tsx
index 97ec41cb4..8410d3e15 100644
--- a/src/app/carte-base-adresse-nationale/components/micro-toponym/MicroToponymAddressList.styles.tsx
+++ b/src/app/carte-base-adresse-nationale/components/PanelMicroToponym/PanelMicroToponymAddressList.styles.tsx
@@ -1,6 +1,7 @@
'use client'
import styled from 'styled-components'
+import Link from 'next/link'
import { Table } from '@codegouvfr/react-dsfr/Table'
export const MicroToponymAddressListInfo = styled.div.attrs({ className: 'ri-information-line' })`
@@ -19,6 +20,16 @@ export const MicroToponymAddressListInfo = styled.div.attrs({ className: 'ri-inf
}
`
+export const MicroToponymAddressLink = styled(Link)`
+ display: inline-flex;
+ gap: 0.25rem;
+
+ span:first-child {
+ min-width: 1.5rem;
+ text-align: right;
+ }
+`
+
export const MicroToponymAddressListTable = styled(Table)`
margin-top: 1.5rem;
@@ -28,7 +39,7 @@ export const MicroToponymAddressListTable = styled(Table)`
}
th:nth-child(2) {
- width: 4rem;
+ width: 5rem;
text-align: center;
}
}
@@ -36,16 +47,6 @@ export const MicroToponymAddressListTable = styled(Table)`
& > table tbody {
td:nth-child(1) {
text-align: left;
-
- a {
- display: inline-flex;
- gap: 0.25rem;
-
- span:first-child {
- min-width: 1.5rem;
- text-align: right;
- }
- }
}
td:nth-child(2) {
diff --git a/src/app/carte-base-adresse-nationale/components/micro-toponym/MicroToponymAddressList.tsx b/src/app/carte-base-adresse-nationale/components/PanelMicroToponym/PanelMicroToponymAddressList.tsx
similarity index 58%
rename from src/app/carte-base-adresse-nationale/components/micro-toponym/MicroToponymAddressList.tsx
rename to src/app/carte-base-adresse-nationale/components/PanelMicroToponym/PanelMicroToponymAddressList.tsx
index 264b60895..0392f8017 100644
--- a/src/app/carte-base-adresse-nationale/components/micro-toponym/MicroToponymAddressList.tsx
+++ b/src/app/carte-base-adresse-nationale/components/PanelMicroToponym/PanelMicroToponymAddressList.tsx
@@ -4,10 +4,12 @@ import { fr } from '@codegouvfr/react-dsfr'
import { ToggleSwitch } from '@codegouvfr/react-dsfr/ToggleSwitch'
import sortAddresses from '../../tools/sortAddresses'
+
import {
MicroToponymAddressListInfo,
MicroToponymAddressListTable,
-} from './MicroToponymAddressList.styles'
+ MicroToponymAddressLink,
+} from './PanelMicroToponymAddressList.styles'
import type { SortAddressesEntry } from '../../tools/sortAddresses'
import type { TypeMicroToponymExtended } from '../../types/LegacyBan.types'
@@ -15,11 +17,11 @@ import { env } from 'next-runtime-env'
const URL_CARTOGRAPHY_BAN = env('NEXT_PUBLIC_URL_CARTOGRAPHY_BAN')
-interface MicroToponymAddressListProps {
+interface PanelMicroToponymAddressListProps {
microToponym: TypeMicroToponymExtended
}
-function MicroToponymAddressList({ microToponym }: MicroToponymAddressListProps) {
+function PanelMicroToponymAddressList({ microToponym }: PanelMicroToponymAddressListProps) {
const [isAddressUncertifiedVisible, setIsAddressUncertifiedVisible] = useState(true)
const [isAddressCertifiedVisible, setIsAddressCertifiedVisible] = useState(true)
const addressesUncertified = useMemo(
@@ -40,11 +42,11 @@ function MicroToponymAddressList({ microToponym }: MicroToponymAddressListProps)
Adresses
- Une adresse certifiée garantit aux utilisateurs de la Base Adresses Natinale que l’adresse est valide et existe bel et bien sur le territoire de la commune et à la position fournie.
+ Une adresse certifiée garantit aux utilisateurs de la Base Adresses Natinale que cette dernière est valide et existe bel et bien sur le territoire de la commune, à la position fournie.
{addressesUncertified.length} Adresses non certifiés>}
+ label={<>{addressesUncertified.length} {addressesUncertified.length > 1 ? 'Adresses non certifiées' : 'Adresse non certifiée'}>}
labelPosition="right"
inputTitle="terms"
showCheckedHint={false}
@@ -53,7 +55,7 @@ function MicroToponymAddressList({ microToponym }: MicroToponymAddressListProps)
/>
{addressesCertified.length} Adresses Certifiés>}
+ label={<>{addressesCertified.length} {addressesCertified.length > 1 ? 'Adresses certifiées' : 'Adresse certifiée'}>}
labelPosition="right"
inputTitle="terms"
showCheckedHint={false}
@@ -63,17 +65,37 @@ function MicroToponymAddressList({ microToponym }: MicroToponymAddressListProps)
N° ({addresses.length} trouvés dans l’odonyme)>,
- 'État',
+ <>N° (
+ <>
+ {addresses.length}{' '}
+ {addresses.length > 1 ? 'trouvés sur l’odonyme' : 'trouvé sur l’odonyme'}
+ >
+ )
+ >,
+ 'Certif.',
]}
data={
addresses.map((address: any) => (
[
-
+
{address.numero}
- {address?.suffixe && {address.suffixe} }
- ,
- address?.certifie ? : '',
+ {address?.suffixe ? {address.suffixe} : {' '} }
+ ,
+ address?.certifie
+ ? (
+
+ )
+ : (
+
+ ),
]
))
}
@@ -84,4 +106,4 @@ function MicroToponymAddressList({ microToponym }: MicroToponymAddressListProps)
)
}
-export default MicroToponymAddressList
+export default PanelMicroToponymAddressList
diff --git a/src/app/carte-base-adresse-nationale/components/district/AsideFooterDistrict.styles.tsx b/src/app/carte-base-adresse-nationale/components/PanelMicroToponym/PanelMicroToponymFooter.styles.tsx
similarity index 100%
rename from src/app/carte-base-adresse-nationale/components/district/AsideFooterDistrict.styles.tsx
rename to src/app/carte-base-adresse-nationale/components/PanelMicroToponym/PanelMicroToponymFooter.styles.tsx
diff --git a/src/app/carte-base-adresse-nationale/components/micro-toponym/AsideFooterMicroToponym.tsx b/src/app/carte-base-adresse-nationale/components/PanelMicroToponym/PanelMicroToponymFooter.tsx
similarity index 80%
rename from src/app/carte-base-adresse-nationale/components/micro-toponym/AsideFooterMicroToponym.tsx
rename to src/app/carte-base-adresse-nationale/components/PanelMicroToponym/PanelMicroToponymFooter.tsx
index ed0294281..194a38812 100644
--- a/src/app/carte-base-adresse-nationale/components/micro-toponym/AsideFooterMicroToponym.tsx
+++ b/src/app/carte-base-adresse-nationale/components/PanelMicroToponym/PanelMicroToponymFooter.tsx
@@ -6,17 +6,17 @@ import {
AsideFooterWrapper,
ActionWrapper,
ActionList,
-} from './AsideFooterMicroToponym.styles'
+} from './PanelMicroToponymFooter.styles'
import type { TypeMicroToponymExtended } from '../../types/LegacyBan.types'
-interface AsideFooterAddressProps {
+interface PanelMicroToponymFooterProps {
banItem: TypeMicroToponymExtended
withCertificate: boolean
children?: React.ReactNode
}
-function AsideFooterMicroToponym({ banItem: microToponym, children }: AsideFooterAddressProps) {
+function PanelMicroToponymFooter({ banItem: microToponym, children }: PanelMicroToponymFooterProps) {
const focusOnMap = useFocusOnMap(microToponym)
const handleClick = (evt: React.MouseEvent) => {
@@ -43,4 +43,4 @@ function AsideFooterMicroToponym({ banItem: microToponym, children }: AsideFoote
)
}
-export default AsideFooterMicroToponym
+export default PanelMicroToponymFooter
diff --git a/src/app/carte-base-adresse-nationale/components/PanelMicroToponym/PanelMicroToponymHeader.styles.tsx b/src/app/carte-base-adresse-nationale/components/PanelMicroToponym/PanelMicroToponymHeader.styles.tsx
new file mode 100644
index 000000000..0551f812f
--- /dev/null
+++ b/src/app/carte-base-adresse-nationale/components/PanelMicroToponym/PanelMicroToponymHeader.styles.tsx
@@ -0,0 +1,7 @@
+'use client'
+
+import styled from 'styled-components'
+
+export const MicroToponymLabelWrapper = styled.div`
+ font-size: 1rem;
+`
diff --git a/src/app/carte-base-adresse-nationale/components/PanelMicroToponym/PanelMicroToponymHeader.tsx b/src/app/carte-base-adresse-nationale/components/PanelMicroToponym/PanelMicroToponymHeader.tsx
new file mode 100644
index 000000000..e479d448a
--- /dev/null
+++ b/src/app/carte-base-adresse-nationale/components/PanelMicroToponym/PanelMicroToponymHeader.tsx
@@ -0,0 +1,43 @@
+import DistrictLink from '../DistrictLink'
+
+import {
+ MicroToponymLabelWrapper,
+} from './PanelMicroToponymHeader.styles'
+
+import {
+ PanelDistrictLabelPrefix,
+ PanelDistrictLabel,
+ PanelNumberAndMicroTopoLabel,
+ PanelMicroTopoLabelAlt,
+ PanelMicroTopoLabelAltFlag,
+} from '../PanelStyles/PanelStyles'
+
+import type { TypeMicroToponymExtended } from '../../types/LegacyBan.types'
+
+interface PanelMicroToponymHeaderProps {
+ microToponym: TypeMicroToponymExtended
+}
+
+function PanelMicroToponymHeader({ microToponym }: PanelMicroToponymHeaderProps) {
+ const district = microToponym.commune
+
+ return (
+ <>
+
+ {microToponym.nomVoie}
+ {microToponym?.nomVoieAlt && Object.entries(microToponym.nomVoieAlt).map(([lang, odonyme]) => (
+
+ {' '}
+ {odonyme}
+
+ ))}
+
+ Commune de
+ {district.nom} (COG {district.code})
+
+
+ >
+ )
+}
+
+export default PanelMicroToponymHeader
diff --git a/src/app/carte-base-adresse-nationale/components/PanelMicroToponym/index.ts b/src/app/carte-base-adresse-nationale/components/PanelMicroToponym/index.ts
new file mode 100644
index 000000000..6b4eef681
--- /dev/null
+++ b/src/app/carte-base-adresse-nationale/components/PanelMicroToponym/index.ts
@@ -0,0 +1,4 @@
+export { default as PanelMicroToponymHeader } from './PanelMicroToponymHeader'
+export { default, default as PanelMicroToponym } from './PanelMicroToponym'
+export { default as PanelMicroToponymAddressList } from './PanelMicroToponymAddressList'
+export { default as PanelMicroToponymFooter } from './PanelMicroToponymFooter'
diff --git a/src/app/carte-base-adresse-nationale/components/PanelStyles/PanelStyles.tsx b/src/app/carte-base-adresse-nationale/components/PanelStyles/PanelStyles.tsx
new file mode 100644
index 000000000..ca6955164
--- /dev/null
+++ b/src/app/carte-base-adresse-nationale/components/PanelStyles/PanelStyles.tsx
@@ -0,0 +1,83 @@
+'use client'
+
+import styled, { css } from 'styled-components'
+import Image from 'next/image'
+
+const flagSize = '1.05em'
+
+export const mainInfo = css`
+ font-size: 2rem;
+ font-weight: 700;
+ line-height: 1.25;
+`
+export const secondaryInfo = css`
+ font-size: 1.25rem;
+ font-weight: 400;
+ line-height: 1.25;
+`
+export const tertiaryInfo = css`
+ font-size: 1rem;
+ font-weight: 300;
+ line-height: 1.5;
+`
+
+// ---------------
+// MAIN INFO -----
+// ---------------
+
+export const PanelNumberAndMicroTopoLabel = styled.span`
+ ${mainInfo}
+ display: block;
+ margin-bottom: 0.5rem;
+`
+
+// -------------------
+// TERTIARY INFO -----
+// -------------------
+
+export const PanelMicroTopoLabelAlt = styled.span`
+ ${tertiaryInfo}
+ display: block;
+`
+
+export const PanelMicroTopoLabelAltFlag = styled(Image).attrs({
+ width: 24,
+ height: 24,
+})`
+ width: ${flagSize};
+ height: ${flagSize};
+ border-radius: 50%;
+ vertical-align: -0.1em;
+ border: 1px solid #fff;
+ box-shadow: 0 0 0.3rem -0.1rem rgba(0, 0, 0, 0.7);
+`
+
+export const PanelAddressPostCode = styled.span`
+ ${tertiaryInfo}
+ display: block;
+`
+
+// --------------------
+// SECONDARY INFO -----
+// --------------------
+
+export const PanelDistrictLabelPrefix = styled.span`
+ ${secondaryInfo}
+ display: block;
+ font-size: .8em;
+ font-weight: 300;
+`
+
+export const PanelDistrictLabel = styled.span<{ $historique?: boolean }>`
+ display: block;
+ ${secondaryInfo}
+ ${({ $historique }) => $historique
+ ? css`
+ ${tertiaryInfo}
+ font-weight: 300;
+ `
+ : css`
+ font-weight: 600;
+ `
+ };
+`
diff --git a/src/app/carte-base-adresse-nationale/components/PanelStyles/index.ts b/src/app/carte-base-adresse-nationale/components/PanelStyles/index.ts
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/app/carte-base-adresse-nationale/components/address/AddressCard.styles.tsx b/src/app/carte-base-adresse-nationale/components/address/AddressCard.styles.tsx
deleted file mode 100644
index 9af1b39a6..000000000
--- a/src/app/carte-base-adresse-nationale/components/address/AddressCard.styles.tsx
+++ /dev/null
@@ -1,113 +0,0 @@
-'use client'
-
-import styled from 'styled-components'
-import Image from 'next/image'
-
-export const AddressHeaderWrapper = styled.div`
- display: flex;
- justify-content: flex-start;
- align-items: center;
- gap: 1.25rem;
- margin-top: 2rem;
- margin-bottom: 2rem;
- padding-bottom: 2rem;
- border-bottom: 4px solid var(--border-active-blue-france);
-`
-
-export const AddressLabelWrapper = styled.div`
- font-size: 1.5rem;
-`
-
-export const AddressPostCode = styled.span`
- display: block;
- font-size: .7em;
- line-height: 1.5;
-`
-
-export const AddressNumberAndMicroTopoLabel = styled.span`
- display: block;
- font-size: 1.5rem;
- font-size: 1em;
- line-height: 1.25;
- font-weight: 700;
- margin-bottom: 0.5rem;
-
-`
-
-export const AddressMicroTopoLabelAlt = styled.span`
- display: block;
- font-size: 0.95rem;
- line-height: 1;
- font-weight: 700;
- margin-bottom: 0.5rem;
-`
-
-export const AddressMicroTopoLabelFlag = styled(Image).attrs({
- width: 24,
- height: 24,
-})`
- width: 1em;
- height: 1em;
- border-radius: 50%;
- vertical-align: -0.1em;
-`
-
-export const AddressDistrictLabelPrefix = styled.span`
- display: block;
- font-size: .6em;
- line-height: 1;
- margin-bottom: 0.25rem;
-`
-
-export const AddressDistrictLabel = styled.span<{ $historique?: boolean }>`
- display: block;
- font-size: 0.7em;
- line-height: 1.25;
- font-weight: ${({ $historique }) => $historique ? '400' : '700'};
- margin-bottom: 0rem;
-`
-
-export const AddressDetailsWrapper = styled.ul`
- padding: 0;
- line-height: 1.5;
- font-size: 0.9rem;
- margin: 2rem 0;
-`
-
-const AddressDetailsItemStyle = styled.li`
- display: flex;
- flex-direction: row;
- margin-bottom: 0.2em;
-
- b {
- font-weight: 500;
- font-weight: normal;
- font-size: 1.1em;
- }
-
- &::before {
- margin-right: 0.5em;
- width: 1.25em;
- height: 1.25em;
- vertical-align: -0.25rem;
- }
-`
-
-interface AddressDetailsItemProps extends React.HTMLAttributes {
- children: React.ReactNode
-}
-
-export const AddressDetailsItem = ({ children, ...props }: AddressDetailsItemProps) => (
-
-
- {children}
-
-
-)
-
-export const AddressDetailsItemValue = styled.pre`
- font-size: small;
- font-weight: 700;
- margin-bottom: 0.5rem;
- white-space: pre-line;
-`
diff --git a/src/app/carte-base-adresse-nationale/components/address/AddressCard.tsx b/src/app/carte-base-adresse-nationale/components/address/AddressCard.tsx
deleted file mode 100644
index 744c813fc..000000000
--- a/src/app/carte-base-adresse-nationale/components/address/AddressCard.tsx
+++ /dev/null
@@ -1,141 +0,0 @@
-import {
- AddressDetailsItemValue,
-
- AddressHeaderWrapper,
-
- AddressLabelWrapper,
- AddressPostCode,
-
- AddressNumberAndMicroTopoLabel,
- AddressMicroTopoLabelAlt,
- AddressMicroTopoLabelFlag,
-
- AddressDistrictLabelPrefix,
- AddressDistrictLabel,
- AddressDetailsWrapper,
- AddressDetailsItem,
-} from './AddressCard.styles'
-import type { TypeAddressExtended } from '../../types/LegacyBan.types'
-
-interface AddressCardProps {
- address: TypeAddressExtended
-}
-
-interface Position {
- position: TypeAddressExtended['position']
- positionType: TypeAddressExtended['positionType']
-}
-
-function AddressCard({ address }: AddressCardProps) {
- const district = address.commune
- const microToponym = address.voie
- const dateMaj = new Date(address.dateMAJ).toLocaleDateString('fr-FR', {
- year: 'numeric',
- month: 'long',
- day: 'numeric',
- })
-
- const isMultiPosition = Number(address.positions?.length) > 1
- const {
- mainPosition,
- secondariesPositions,
- }: {
- mainPosition: Position
- secondariesPositions: Position[]
- } = isMultiPosition
- ? address.positions.reduce((acc, entry) => {
- if (entry.position.coordinates.join('--') === address.position.coordinates.join('--')) {
- acc.mainPosition = entry
- }
- else {
- acc.secondariesPositions.push(entry)
- }
- return acc
- }, { mainPosition: (null as unknown as Position), secondariesPositions: ([] as Position[]) })
- : { mainPosition: {
- position: address.position,
- positionType: address.positionType,
- }, secondariesPositions: [] }
-
- return (
- <>
-
-
-
- {address.numero ? `${address.numero} ` : ''}
- {address.suffixe ? `${address.suffixe} ` : ''}
- {microToponym.nomVoie},
-
- {microToponym?.nomVoieAlt && Object.entries(microToponym.nomVoieAlt).map(([lang, odonyme]) => (
-
- {' '}
- {odonyme}
-
- ))}
- {address.nomAncienneCommune && (
- <>
- Commune historique de
- {address.nomAncienneCommune},
- >
- )}
- CP {address.codePostal},
- {district.nom} (COG {district.code})
-
-
-
-
-
-
- Identifiant BAN :
- {address.banId}
-
-
-
-
- Clé d’interopérabilité :
- {address.cleInterop}
-
-
-
-
- Parcelles cadastrales :
- {address?.parcelles.join(', ') || 'Non renseignée(s)'}
-
-
-
- Date de mise à jour :
- {dateMaj}
-
-
- Producteur :
- {address.sourcePosition}
-
-
-
- Libellé d’acheminement :
- {address.libelleAcheminement}
-
-
- {isMultiPosition ? 'Position Principale' : 'Position'} :
- Type / {mainPosition.positionType}
- Coordonnées / {mainPosition.position.coordinates[0]}, {mainPosition.position.coordinates[1]}
-
- {isMultiPosition && (
-
- Position Secondaire :
-
- {secondariesPositions.map((entry, index) => (
-
- Type / {entry.positionType}
- Coordonnées / {entry.position.coordinates[0]}, {entry.position.coordinates[1]}
-
- ))}
-
-
- )}
-
- >
- )
-}
-
-export default AddressCard
diff --git a/src/app/carte-base-adresse-nationale/components/address/index.ts b/src/app/carte-base-adresse-nationale/components/address/index.ts
deleted file mode 100644
index 8d9ce7891..000000000
--- a/src/app/carte-base-adresse-nationale/components/address/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export { default, default as AddressCard } from './AddressCard'
-export { default as AsideFooterAddress } from './AsideFooterAddress'
diff --git a/src/app/carte-base-adresse-nationale/components/ban-map/BanMap.context.tsx b/src/app/carte-base-adresse-nationale/components/ban-map/BanMap.context.tsx
index 3aee85d4b..b9a9ba11d 100644
--- a/src/app/carte-base-adresse-nationale/components/ban-map/BanMap.context.tsx
+++ b/src/app/carte-base-adresse-nationale/components/ban-map/BanMap.context.tsx
@@ -14,7 +14,7 @@ interface MapItem {
}
const initBanMapConfig = {
- mapStyle: 'ign-vector',
+ mapStyle: 'osm-vector',
displayLandRegister: false,
}
diff --git a/src/app/carte-base-adresse-nationale/components/ban-map/BanMap.tsx b/src/app/carte-base-adresse-nationale/components/ban-map/BanMap.tsx
index b877e905e..0dd1d7214 100644
--- a/src/app/carte-base-adresse-nationale/components/ban-map/BanMap.tsx
+++ b/src/app/carte-base-adresse-nationale/components/ban-map/BanMap.tsx
@@ -5,8 +5,6 @@ import LayerBan from './LayerBan'
import LayerCadastre from './LayerCadastre'
import Popups from './Popups'
-import { ControlGroup } from './BanMap.styles'
-
import type { MapMouseEvent, MapGeoJSONFeature } from 'react-map-gl/maplibre'
import type { PopupFeature } from './Popups'
import type { Address, PopupInfo } from './types'
@@ -146,7 +144,6 @@ function BanMap({ address, onSelect, isCadastreLayersShown }: BanMapProps) {
)}
-
>
diff --git a/src/app/carte-base-adresse-nationale/components/district/DistrictCard.styles.tsx b/src/app/carte-base-adresse-nationale/components/district/DistrictCard.styles.tsx
deleted file mode 100644
index 837f9711e..000000000
--- a/src/app/carte-base-adresse-nationale/components/district/DistrictCard.styles.tsx
+++ /dev/null
@@ -1,66 +0,0 @@
-'use client'
-
-import styled from 'styled-components'
-
-export const DistrictHeaderWrapper = styled.div`
- display: flex;
- justify-content: flex-start;
- align-items: center;
- gap: 1.25rem;
- margin-top: 2rem;
- margin-bottom: 2rem;
- padding-bottom: 1rem;
- border-bottom: 4px solid var(--border-active-blue-france);
-`
-
-export const DistrictLogoWrapper = styled.div`
-`
-
-export const DistrictLabelWrapper = styled.div`
-`
-
-export const DistrictLabelPrefix = styled.span`
- display: block;
- margin-bottom: 0.25rem;
- font-size: 0.8rem;
- line-height: 1;
-`
-
-export const DistrictLabel = styled.span`
- display: block;
- margin-bottom: 0.5rem;
- font-size: 2rem;
- font-weight: 700;
- line-height: 1;
-`
-
-export const DistrictLabelCode = styled.span`
- display: block;
- margin-bottom: 0.5rem;
- font-size: 0.9rem;
- font-weight: 700;
-`
-
-export const DistrictDetailsWrapper = styled.ul`
- padding: 0;
- margin: 2rem 0;
- font-size: 0.9rem;
- line-height: 1.5;
-`
-
-export const DistrictDetailsItem = styled.li`
- display: block;
- margin-bottom: 0.2em;
-
- b {
- font-weight: 500;
- font-size: 1.1em;
- }
-
- &::before {
- width: 1.25em;
- height: 1.25em;
- margin-right: 0.5em;
- vertical-align: -0.25rem;
- }
-`
diff --git a/src/app/carte-base-adresse-nationale/components/district/index.ts b/src/app/carte-base-adresse-nationale/components/district/index.ts
deleted file mode 100644
index 45fa4f9e3..000000000
--- a/src/app/carte-base-adresse-nationale/components/district/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export { default as DistrictCard } from './DistrictCard'
-export { default as DistrictMicroToponymList } from './DistrictMicroToponymList'
-export { default as AsideFooterDistrict } from './AsideFooterDistrict'
diff --git a/src/app/carte-base-adresse-nationale/components/micro-toponym/MicroToponymCard.tsx b/src/app/carte-base-adresse-nationale/components/micro-toponym/MicroToponymCard.tsx
deleted file mode 100644
index 25a7d622e..000000000
--- a/src/app/carte-base-adresse-nationale/components/micro-toponym/MicroToponymCard.tsx
+++ /dev/null
@@ -1,41 +0,0 @@
-import Link from 'next/link'
-
-import {
- MicroToponymHeaderWrapper,
- MicroToponymLabelWrapper,
- MicroToponymDistrictLabelPrefix,
- MicroToponymDistrictLabel,
- MicroToponymLabel,
- MicroToponymLabelAlt,
- MicroToponymLabelFlag,
-} from './MicroToponymCard.styles'
-
-import type { TypeMicroToponymExtended } from '../../types/LegacyBan.types'
-
-interface MicroToponymCardProps {
- microToponym: TypeMicroToponymExtended
-}
-
-function MicroToponymCard({ microToponym }: MicroToponymCardProps) {
- const district = microToponym.commune
-
- return (
- <>
-
-
- {microToponym.nomVoie}
- {microToponym?.nomVoieAlt && Object.entries(microToponym.nomVoieAlt).map(([lang, odonyme]) => (
-
- {' '}
- {odonyme}
-
- ))}
- Commune de
- {district.nom} (COG {district.code})
-
-
- >
- )
-}
-
-export default MicroToponymCard
diff --git a/src/app/carte-base-adresse-nationale/components/micro-toponym/index.ts b/src/app/carte-base-adresse-nationale/components/micro-toponym/index.ts
deleted file mode 100644
index 12184e418..000000000
--- a/src/app/carte-base-adresse-nationale/components/micro-toponym/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export { default as MicroToponymCard } from './MicroToponymCard'
-export { default as MicroToponymAddressList } from './MicroToponymAddressList'
-export { default as AsideFooterMicroToponym } from './AsideFooterMicroToponym'
diff --git a/src/app/carte-base-adresse-nationale/layout.styles.tsx b/src/app/carte-base-adresse-nationale/layout.styles.tsx
index 954d07ee4..908296d04 100644
--- a/src/app/carte-base-adresse-nationale/layout.styles.tsx
+++ b/src/app/carte-base-adresse-nationale/layout.styles.tsx
@@ -27,9 +27,11 @@ export const CartoWrapper = styled.div`
position: relative;
display: flex;
height: calc(100vh - 10.3rem);
+ height: calc(100dvh - 10.3rem);
- @media (min-width: ${({ theme }) => theme.breakpoints.md}) {
- height: calc(100vh - 7.4rem - 3.5rem);
+ @media (min-width: ${({ theme }) => theme.breakpoints.lg}) {
+ height: calc(100vh - 7.4rem - 3.5rem + 3.5rem);
+ height: calc(100dvh - 7.4rem - 3.5rem + 3.5rem);
}
&::before {
@@ -102,7 +104,7 @@ export const MapParamsWrapper = styled.div.attrs({
position: relative;
z-index: 1;
- @media (min-width: ${({ theme }) => theme.breakpoints.md}) {
+ @media (min-width: ${({ theme }) => theme.breakpoints.lg}) {
justify-content: space-between;
}
`
@@ -124,7 +126,7 @@ export const RingButtonStyled = styled.button.attrs({
box-shadow: 0rem 0.3rem 0.7rem -0.25rem rgba(0, 0, 0, .5),
0rem 0.3rem 0.7rem -0.15rem rgba(255, 255, 255, .5),
${({ $isTypeRadio, $isActive }) => !$isTypeRadio || $isActive ? css`0rem 0rem 0rem -0rem rgba(0, 0, 0, .5) inset` : css`0rem 0.3rem 0.7rem -0.25rem rgba(0, 0, 0, .5) inset`},
- ${({ $isActive }) => $isActive ? css`0rem 0rem 1px 2px #fff inset` : css`0rem 0rem 0px 0px #fff inset`},
+ ${({ $isActive }) => $isActive ? css`0rem 0rem 1px 2px var(--background-raised-grey) inset` : css`0rem 0rem 0px 0px var(--background-raised-grey) inset`},
${({ $isActive }) => $isActive ? css`0rem 0rem 1px 3px currentColor inset` : css`0rem 0rem 0px 0px currentColor inset`};
margin: 0 0.5rem 0 0;
color: var(--text-action-high-blue-france);
diff --git a/src/app/carte-base-adresse-nationale/layout.tsx b/src/app/carte-base-adresse-nationale/layout.tsx
index 43c8d7fde..a04c9e7af 100644
--- a/src/app/carte-base-adresse-nationale/layout.tsx
+++ b/src/app/carte-base-adresse-nationale/layout.tsx
@@ -5,6 +5,7 @@ import { Tooltip } from '@codegouvfr/react-dsfr/Tooltip'
import SearchBAN from '@/components/SearchBAN'
import { BALWidgetContext } from '@/contexts/BALWidget.context'
+import { useMainLayout } from '@/layouts/MainLayout'
import { BanMapProvider, useBanMapConfig } from './components/ban-map/BanMap.context'
import { theme } from './components/ban-map/theme'
@@ -34,11 +35,19 @@ const RingButton = ({ tooltip, ...props }: { tooltip?: string, [key: string]: an
}
function Carto({ children }: { children: JSX.Element }) {
+ const { setTypeLayout } = useMainLayout()
+
const [isLegendVisible, setIsLegendVisible] = useState(false)
const banMapConfigState = useBanMapConfig()
const [banMapConfig, dispatchToBanMapConfig] = banMapConfigState
const { mapStyle, displayLandRegister } = banMapConfig
+ useEffect(() => {
+ setTypeLayout('full-screen')
+ window?.setTimeout(() => window?.scrollTo(0, 1), 1000)
+ return () => setTypeLayout('default')
+ }, [setTypeLayout])
+
const toggleLegend = useCallback(() => {
setIsLegendVisible(!isLegendVisible)
}, [isLegendVisible])
@@ -59,9 +68,9 @@ function Carto({ children }: { children: JSX.Element }) {
- handleMapStyleChange('ign-vector')} $isActive={banMapConfig.mapStyle === 'ign-vector'} $isTypeRadio />
handleMapStyleChange('osm-vector')} $isActive={banMapConfig.mapStyle === 'osm-vector'} $isTypeRadio />
- handleMapStyleChange('ign-ortho')} $isActive={banMapConfig.mapStyle === 'ign-ortho'} $isTypeRadio />
+ handleMapStyleChange('ign-vector')} $isActive={banMapConfig.mapStyle === 'ign-vector'} $isTypeRadio />
+ handleMapStyleChange('ign-ortho')} $isActive={banMapConfig.mapStyle === 'ign-ortho'} $isTypeRadio />
diff --git a/src/app/carte-base-adresse-nationale/page.styles.tsx b/src/app/carte-base-adresse-nationale/page.styles.tsx
index 7a4fc8b01..c4d45624d 100644
--- a/src/app/carte-base-adresse-nationale/page.styles.tsx
+++ b/src/app/carte-base-adresse-nationale/page.styles.tsx
@@ -4,14 +4,15 @@ import styled from 'styled-components'
export const MapSearchResultsWrapper = styled.div`
min-height: 200%;
- padding: 8.5rem 1rem 1rem;
- background-color: var(--background-default-grey);
+ padding: 1rem;
scroll-snap-align: start;
- pointer-events: auto;
- @media (min-width: ${({ theme }) => theme.breakpoints.md}) {
+ @media (min-width: ${({ theme }) => theme.breakpoints.lg}) {
width: 100%;
min-height: 100%;
margin-top: 0;
}
`
+
+export const MapSearchResultsHead = styled.div``
+export const MapSearchResultsBody = styled.div``
diff --git a/src/app/carte-base-adresse-nationale/page.tsx b/src/app/carte-base-adresse-nationale/page.tsx
index 44d57b442..4c54bf25d 100644
--- a/src/app/carte-base-adresse-nationale/page.tsx
+++ b/src/app/carte-base-adresse-nationale/page.tsx
@@ -2,25 +2,22 @@
import { useState, useEffect, useRef, Suspense, useCallback } from 'react'
import { AttributionControl, MapProvider, Map, NavigationControl, ScaleControl } from 'react-map-gl/maplibre'
-import { useSearchParams } from 'next/navigation'
+import { useRouter, useSearchParams } from 'next/navigation'
import type { MapRef } from 'react-map-gl/maplibre'
import { getCommuneFlag } from '@/lib/api-wikidata'
import { getBanItem, getDistrict } from '@/lib/api-ban'
import Aside from './components/Aside'
-import MapBreadcrumb from './components/MapBreadcrumb'
-import MapDataLoader from './components/MapDataLoader'
-import { AddressCard, AsideFooterAddress } from './components/address'
-import { MicroToponymCard, MicroToponymAddressList, AsideFooterMicroToponym } from './components/micro-toponym'
-import { DistrictCard, DistrictMicroToponymList, AsideFooterDistrict } from './components/district'
-import {
- MapSearchResultsWrapper,
-
-} from './page.styles'
+import LoadingBar from './components/LoadingBar'
+import { PanelAddressHeader, PanelAddress, PanelAddressFooter } from './components/PanelAddress'
+import { PanelMicroToponymHeader, PanelMicroToponym, PanelMicroToponymFooter } from './components/PanelMicroToponym'
+import { PanelDistrictHeader, PanelDistrict, PanelDistrictFooter } from './components/PanelDistrict'
+import { MapSearchResultsWrapper } from './page.styles'
import BanMap from './components/ban-map'
+import type { MapBreadcrumbPath } from './components/MapBreadcrumb'
import type {
TypeAddressExtended,
TypeMicroToponymPartial,
@@ -28,7 +25,6 @@ import type {
TypeDistrictExtended,
TypeDistrict,
} from './types/LegacyBan.types'
-import { useRouter } from 'next/navigation'
import { useBanMapConfig } from './components/ban-map/BanMap.context'
@@ -39,7 +35,6 @@ interface LinkProps {
href: string
target?: string
}
-type MapBreadcrumbPathSegment = string | { label: string, linkProps?: LinkProps }
const DEFAULT_CENTER = [1.7, 46.9]
const DEFAULT_ZOOM = 6
@@ -99,18 +94,35 @@ function CartoView() {
const [isMenuVisible, setIsMenuVisible] = useState(false)
const [mapSearchResults, setMapSearchResults] = useState()
const [districtLogo, setDistrictLogo] = useState()
- const [mapBreadcrumbPath, setMapBreadcrumbPath] = useState([])
+ const [mapBreadcrumbPath, setMapBreadcrumbPath] = useState([])
const [withCertificate, setWithCertificate] = useState(false)
const [isLoadMapSearchResults, setIsLoadMapSearchResults] = useState(false)
const [isLoadMapTiles, setIsLoadMapTiles] = useState(false)
-
+ const router = useRouter()
const banMapConfigState = useBanMapConfig()
- const [banMapConfig, dispatchToBanMapConfig] = banMapConfigState
+ const [banMapConfig] = banMapConfigState
const { mapStyle, displayLandRegister } = banMapConfig
const banItemId = searchParams?.get('id')
const typeView = getBanItemTypes(mapSearchResults)
+ const closeMapSearchResults = useCallback(() => {
+ setIsMenuVisible(false)
+ const timer = setTimeout(() => {
+ setMapSearchResults(undefined)
+ setDistrictLogo(undefined)
+ }, 1000)
+ return () => {
+ setMapSearchResults(undefined)
+ setDistrictLogo(undefined)
+ clearTimeout(timer)
+ }
+ }, [])
+
+ const selectBanItem = useCallback(({ id }: { id: string }) => router.push(`${URL_CARTOGRAPHY_BAN}?id=${id}`), [router])
+
+ const unselectBanItem = useCallback(() => router.push(`${URL_CARTOGRAPHY_BAN}`), [router])
+
useEffect(() => {
isMapReady ? setIsLoadMapTiles(false) : setIsLoadMapTiles(true)
}, [isMapReady])
@@ -129,7 +141,10 @@ function CartoView() {
setIsLoadMapSearchResults(false)
})()
}
- }, [banItemId])
+ else {
+ return closeMapSearchResults()
+ }
+ }, [banItemId, closeMapSearchResults])
useEffect(() => {
if (isMapReady && mapSearchResults) {
@@ -173,14 +188,9 @@ function CartoView() {
}
, [isMapReady, mapSearchResults])
- const router = useRouter()
-
- const selectAddress = useCallback(({ id }: { id: string }) => {
- router.push(`${URL_CARTOGRAPHY_BAN}?id=${id}`)
- }, [router])
-
return (
+
-
-
- Chargement des données de la BAN...
-
-
-
- Chargement des données cartographiques...
-
-
-
setIsMenuVisible(!isMenuVisible))}
isOpen={isMenuVisible}
+ path={mapBreadcrumbPath}
+ header={
+ ((typeView === 'district') && ( ))
+ || ((typeView === 'micro-toponym') && ( ))
+ || ((typeView === 'address') && ( ))
+ }
footer={
- ((typeView === 'address') && (
-
- ))
- || ((typeView === 'micro-toponym') && (
-
- ))
- || ((typeView === 'district') && (
-
- ))
+ ((typeView === 'district') && ( ))
+ || ((typeView === 'micro-toponym') && ( ))
+ || ((typeView === 'address') && ( ))
}
>
{mapSearchResults
? (
-
- {(typeView === 'district') && (
- <>
-
-
- >
- )}
-
- {(typeView === 'micro-toponym') && (
- <>
-
-
- >
- )}
-
- {(typeView === 'address') && (
-
- )}
+ {(typeView === 'district') && ( )}
+ {(typeView === 'micro-toponym') && ( )}
+ {(typeView === 'address') && ( )}
)
: null}
diff --git a/src/app/global.styles.ts b/src/app/global.styles.ts
index 843efea7d..c508f23fd 100644
--- a/src/app/global.styles.ts
+++ b/src/app/global.styles.ts
@@ -13,6 +13,11 @@ body {
max-width: 100vw;
overflow-x: hidden;
}
+
+// Quik fix for DSFR Table component
+.fr-table > table {
+ display: table;
+}
`
export default GlobalStyle
diff --git a/src/app/layout.styles.tsx b/src/app/layout.styles.tsx
new file mode 100644
index 000000000..04e4814e1
--- /dev/null
+++ b/src/app/layout.styles.tsx
@@ -0,0 +1,15 @@
+'use client'
+
+import styled from 'styled-components'
+
+export const StyledLayout = styled.div`
+ min-height: 100vh;
+ display: grid;
+ grid-template-rows: auto auto 1fr auto;
+`
+
+export const PageWrapper = styled.div`
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+`
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index 0b2fcc881..4640a59e6 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -6,11 +6,11 @@ import { DsfrProvider } from '@codegouvfr/react-dsfr/next-appdir/DsfrProvider'
import { getHtmlAttributes } from '@codegouvfr/react-dsfr/next-appdir/getHtmlAttributes'
import { StartDsfr } from '@/providers'
+import { LayoutProvider } from '@/layouts/MainLayout'
import Header from '@/layouts/Header'
import Footer from '@/layouts/Footer'
-import Breadcrumb from '@/layouts/Breadcrumb'
import { defaultColorScheme } from '@/theme/defaultColorScheme'
-import styled, { ThemeProvider } from 'styled-components'
+import { ThemeProvider } from 'styled-components'
import StyledComponentsRegistry from '@/providers/StyledComponentsRegistry'
import theme from '@/theme'
import GlobalStyle from './global.styles'
@@ -19,23 +19,21 @@ import { init as matomoInit } from '@socialgouv/matomo-next'
import { BALWidgetProvider } from '@/contexts/BALWidget.context'
import { PublicEnvScript, env } from 'next-runtime-env'
-const StyledLayout = styled.div`
- min-height: 100vh;
- display: grid;
- grid-template-rows: auto auto 1fr auto;
-
- .pageWrapper {
- display: flex;
- flex-direction: column;
- height: 100%;
- }
-`
+import {
+ StyledLayout,
+ PageWrapper,
+} from './layout.styles'
export default function RootLayout({ children }: { children: JSX.Element }) {
const lang = 'fr'
+ // TODO : Connect to Grist API
+ const sampleNotice = {
+ text: 'Nouveau service : le calculateur de distance',
+ }
+
const dataNotices = {
- data: [],
+ data: [sampleNotice],
duration: 4000,
}
@@ -64,19 +62,20 @@ export default function RootLayout({ children }: { children: JSX.Element }) {
-
-
-
-
-
-
- {/* */}
- {children}
-
-
-
-
-
+
+
+
+
+
+
+
+ {children}
+
+
+
+
+
+
diff --git a/src/components/Notices/Notices.tsx b/src/components/Notices/Notices.tsx
index 804e28bf6..eb7be8346 100644
--- a/src/components/Notices/Notices.tsx
+++ b/src/components/Notices/Notices.tsx
@@ -14,11 +14,13 @@ interface NoticeProps {
}
}[]
duration?: number
+ className?: string
}
function Notice({
data = [],
duration = 4000,
+ className,
}: NoticeProps) {
const [titleId, setTitleId] = useState(0)
@@ -35,7 +37,7 @@ function Notice({
const title = text && (data.length > 1 ? `(${titleId + 1}/${data.length}) ${text}` : text)
return title && (
-
+
{title}}
isClosable
diff --git a/src/layouts/Footer.styles.tsx b/src/layouts/Footer.styles.tsx
new file mode 100644
index 000000000..25f8f2546
--- /dev/null
+++ b/src/layouts/Footer.styles.tsx
@@ -0,0 +1,85 @@
+'use client'
+
+import styled, { css } from 'styled-components'
+
+const footerDisplayButtonHeight = '2.5rem'
+const transitionDelaiOnOpen = '0.75s'
+const transitionDelaiOnClose = '0.35s'
+
+export const FooterWrapper = styled.footer<{ $isHidden: boolean }>`
+ display: block;
+ width: 100%;
+ transition: transform 0.3s ease ${transitionDelaiOnClose}, z-index 0s ease ${transitionDelaiOnClose};
+
+ ${({ $isHidden }) => $isHidden
+ ? css`
+ position: fixed;
+ z-index: 5;
+ max-height: 75dvh;
+ overflow: visible;
+ bottom: 0;
+ transform: translateY(calc(100% - ${footerDisplayButtonHeight}));
+
+ .footer-display-button {
+ display: flex;
+ }
+ `
+ : css`position: static;`
+ }
+
+ &:hover,
+ &:focus-within {
+ overflow: auto;
+ z-index: 1000;
+ transform: translateY(0);
+ transition: transform 0.3s ease ${transitionDelaiOnOpen}, z-index 0s ease ${transitionDelaiOnOpen};
+
+ .footer-display-button {
+ max-height: 0;
+ opacity: 0;
+ pointer-events: none;
+
+ &::before {
+ transform: rotate(180deg);
+ }
+ }
+ }
+`
+
+export const FooterDisplayButton = styled.button.attrs({
+ className: 'footer-display-button',
+})`
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ width: 100%;
+ height: ${footerDisplayButtonHeight};
+ max-height: ${footerDisplayButtonHeight};
+ background-color: var(--background-raised-grey);
+ font-size: 0.8rem;
+ line-height: 1.5;
+ border: none;
+ opacity: 0.1;
+ cursor: pointer;
+ transition: max-height 0.15s ease 0s,
+ opacity 0.15s ease 0s,
+ transform 0.15s ease ${transitionDelaiOnClose};
+
+ &::before {
+ content: '▲';
+ display: inline-block;
+ margin-right: 0.5rem;
+ transition: opacity 0.15s ease ${transitionDelaiOnOpen}, transform 0.15s ease ${transitionDelaiOnOpen};
+ }
+
+ display: none;
+`
+
+export const FooterBody = styled.div`
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: stretch;
+ background-color: var(--background-raised-grey);
+ width: 100%;
+`
diff --git a/src/layouts/Footer.tsx b/src/layouts/Footer.tsx
index a04b76872..c53a061f5 100644
--- a/src/layouts/Footer.tsx
+++ b/src/layouts/Footer.tsx
@@ -1,11 +1,19 @@
+import { useCallback, useState, useMemo } from 'react'
+import dynamic from 'next/dynamic'
+import Link from 'next/link'
+import { env } from 'next-runtime-env'
import { Footer as FooterDSFR } from '@codegouvfr/react-dsfr/Footer'
import { Follow } from '@codegouvfr/react-dsfr/Follow'
import { headerFooterDisplayItem } from '@codegouvfr/react-dsfr/Display'
-import { useCallback, useState } from 'react'
-import dynamic from 'next/dynamic'
-import Link from 'next/link'
+
import { newsletterOptIn } from '@/lib/api-brevo'
-import { env } from 'next-runtime-env'
+import { useMainLayout } from '@/layouts/MainLayout'
+
+import {
+ FooterWrapper,
+ FooterDisplayButton,
+ FooterBody,
+} from './Footer.styles'
const SOCIAL_NETWORKS_URL_MASTODON = env('NEXT_PUBLIC_SOCIAL_NETWORKS_URL_MASTODON')
const SOCIAL_NETWORKS_URL_FACEBOOK = env('NEXT_PUBLIC_SOCIAL_NETWORKS_URL_FACEBOOK')
@@ -19,10 +27,13 @@ const NewsletterOptinWithNoSSR = dynamic(
)
export default function Footer() {
+ const { typeLayout } = useMainLayout()
const [success, setSuccess] = useState(false)
const [email, setEmail] = useState('')
const [showCaptcha, setShowCaptcha] = useState(false)
+ const size = useMemo(() => (typeLayout === 'full-screen' ? 'hidden' : 'default'), [typeLayout])
+
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
setShowCaptcha(true)
@@ -39,128 +50,131 @@ export default function Footer() {
}, [email])
return (
- <>
-
+
+
+
+ Recevez toutes les informations de la base adresse nationale !
+
+
+ Découvrez nos dernières newsletters
+
+ >),
+ form: {
+ formComponent: ({ children }) => {children} ,
+ successMessage: 'Vous êtes bien inscrit à la newsletter',
+ success,
+ inputProps: {
+ value: email,
+ onChange: (e: React.ChangeEvent) => setEmail(e.target.value),
+ type: 'email',
+ } as any,
+ },
+ }}
+ social={{
+ buttons: [
+ {
+ linkProps: {
+ href: SOCIAL_NETWORKS_URL_XCOM as unknown as URL ?? '',
+ target: '_blank',
+ },
+ type: 'twitter-x',
+ },
+ {
+ linkProps: {
+ href: SOCIAL_NETWORKS_URL_MASTODON as unknown as URL ?? '',
+ target: '_blank',
+ },
+ type: 'mastodon',
+ },
+ {
+ linkProps: {
+ href: SOCIAL_NETWORKS_URL_LINKEDIN as unknown as URL ?? '',
+ target: '_blank',
+ },
+ type: 'linkedin',
+ },
+ {
+ linkProps: {
+ href: SOCIAL_NETWORKS_URL_GITHUB as unknown as URL ?? '',
+ target: '_blank',
+ },
+ type: 'github',
+ },
+ ],
+ }}
+ />
+
- Recevez toutes les informations de la base adresse nationale !
+ RÉPUBLIQUE
-
- Découvrez nos dernières newsletters
-
- >),
- form: {
- formComponent: ({ children }) => {children} ,
- successMessage: 'Vous êtes bien inscrit à la newsletter',
- success,
- inputProps: {
- value: email,
- onChange: (e: React.ChangeEvent) => setEmail(e.target.value),
- type: 'email',
- } as any,
- },
- }}
- social={{
- buttons: [
+ FRANÇAISE
+ >
+ )}
+ accessibility="non compliant"
+ operatorLogo={{
+ alt: '[À MODIFIER - texte alternatif de l’image]',
+ imgUrl: '/logo-ban-site.svg',
+ orientation: 'vertical',
+ }}
+ contentDescription={(
+ <>
+ Adresse.data.gouv .fr - Le site national officiel de l’adresse.
+ Service public gratuit pour référencer l’intégralité des adresses du
+ territoire et les rendre utilisables par tous. Retrouvez-y toutes
+ les informations et démarches administratives nécessaires à la
+ création et à la gestion des adresses.
+ >
+ )}
+ homeLinkProps={{
+ href: '/',
+ title: 'Adresse.data.gouv.fr - Accueil',
+ }}
+ accessibilityLinkProps={{
+ href: '/accessibilite',
+ }}
+ termsLinkProps={{
+ href: '/mentions-legales',
+ }}
+ bottomItems={[
{
- linkProps: {
- href: SOCIAL_NETWORKS_URL_XCOM as unknown as URL ?? '',
- target: '_blank',
- },
- type: 'twitter-x',
+ text: 'CGU',
+ linkProps: { href: '/cgu' },
},
{
- linkProps: {
- href: SOCIAL_NETWORKS_URL_MASTODON as unknown as URL ?? '',
- target: '_blank',
- },
- type: 'mastodon',
+ text: 'Statistiques',
+ linkProps: { href: '/stats' },
+ },
+ {
+ text: 'Contact',
+ linkProps: { href: '/nous-contacter' },
},
{
+ text: 'Documentation',
linkProps: {
- href: SOCIAL_NETWORKS_URL_LINKEDIN as unknown as URL ?? '',
+ href: 'https://doc.adresse.data.gouv.fr/',
target: '_blank',
},
- type: 'linkedin',
},
{
+ text: 'Supervision BAN/BAL',
linkProps: {
- href: SOCIAL_NETWORKS_URL_GITHUB as unknown as URL ?? '',
+ href: 'https://status.adresse.data.gouv.fr/',
target: '_blank',
},
- type: 'github',
- },
- ],
- }}
- />
-
- RÉPUBLIQUE
-
- FRANÇAISE
- >
- )}
- accessibility="non compliant"
- operatorLogo={{
- alt: '[À MODIFIER - texte alternatif de l’image]',
- imgUrl: '/logo-ban-site.svg',
- orientation: 'vertical',
- }}
- contentDescription={(
- <>
- Adresse.data.gouv .fr - Le site national officiel de l’adresse.
- Service public gratuit pour référencer l’intégralité des adresses du
- territoire et les rendre utilisables par tous. Retrouvez-y toutes
- les informations et démarches administratives nécessaires à la
- création et à la gestion des adresses.
- >
- )}
- homeLinkProps={{
- href: '/',
- title: 'Adresse.data.gouv.fr - Accueil',
- }}
- accessibilityLinkProps={{
- href: '/accessibilite',
- }}
- termsLinkProps={{
- href: '/mentions-legales',
- }}
- bottomItems={[
- {
- text: 'CGU',
- linkProps: { href: '/cgu' },
- },
- {
- text: 'Statistiques',
- linkProps: { href: '/stats' },
- },
- {
- text: 'Contact',
- linkProps: { href: '/nous-contacter' },
- },
- {
- text: 'Documentation',
- linkProps: {
- href: 'https://doc.adresse.data.gouv.fr/',
- target: '_blank',
- },
- },
- {
- text: 'Supervision BAN/BAL',
- linkProps: {
- href: 'https://status.adresse.data.gouv.fr/',
- target: '_blank',
},
- },
- headerFooterDisplayItem,
- ]}
- />
- >
+ headerFooterDisplayItem,
+ ]}
+ />
+
+
)
}
diff --git a/src/layouts/Header.styles.tsx b/src/layouts/Header.styles.tsx
index 3c7b756d0..9c717bd00 100644
--- a/src/layouts/Header.styles.tsx
+++ b/src/layouts/Header.styles.tsx
@@ -1,6 +1,74 @@
'use client'
-import styled from 'styled-components'
+import styled, { css } from 'styled-components'
+
+export const HeaderWrapper = styled.header<{ $size?: 'default' | 'small' }>`
+ position: relative;
+ z-index: 1000;
+
+ .dsfr-notice {
+ ${({ $size }) => $size === 'small' ? css`position: absolute;` : css`position: static;`}
+ z-index: 1;
+ width: 100%;
+ bottom: 0;
+ transition: transform .4s ease;
+ transform: translateY(0);
+ }
+
+
+
+
+ @media (min-width: ${({ theme }) => theme.breakpoints.lg}) {
+ .header-spacer {
+ position: relative;
+ transition: height .3s ease;
+
+ ${({ $size }) => $size === 'small' && css`z-index: 1000;`}
+ ${({ $size }) => $size === 'small'
+ ? css`height: 7.4rem;`
+ : css`height: 14.4rem;`
+ }
+ }
+
+ .dsfr-notice {
+ position: absolute;
+ }
+
+ .dsfr-header {
+ position: absolute;
+ top: 0;
+ z-index: 1000;
+
+ .fr-header__body {
+ margin-bottom: 0;
+ ${({ $size }) => $size === 'small' && css`margin-bottom: -3.5rem;`}
+ background: var(--background-raised-grey);
+ transition: margin-bottom .3s ease;
+ }
+
+ .fr-header__menu {
+ position: relative;
+ z-index: -1;
+ max-height: 3.5rem;
+ }
+ }
+
+ ${({ $size }) => $size === 'small' && css`
+ &:hover,
+ &:focus-within {
+ .dsfr-header {
+ .fr-header__body {
+ margin-bottom: 0;
+ }
+ }
+
+ .dsfr-notice {
+ transform: translateY(calc(100% + 3.4rem));
+ }
+ }
+ `}
+ }
+`
export const CornerRibbons = styled.div.attrs<{
$positionHorizontal?: 'left' | 'right'
@@ -8,23 +76,40 @@ export const CornerRibbons = styled.div.attrs<{
$color?: string
}>(({ $positionHorizontal = 'top', $positionVertical = 'right' }) => ({
- className: `ri-meteor-fill cr-${$positionVertical} cr-${$positionHorizontal}`,
+ className: `cr-${$positionVertical} cr-${$positionHorizontal}`,
}))`
+ position: fixed;
+ z-index: 1001;
width: 200px;
padding: .75rem;
- text-align: center;
color: #f0f0f0;
font-size: 1rem;
font-weight: bold;
-
- position: fixed;
- z-index: 1000;
-
+ text-align: center;
opacity: 0.65;
pointer-events: none;
${({ $color = 'var(--background-action-high-red-marianne)' }) => `background-color: ${$color};`}
+ &::before {
+ content: 'β';
+ display: inline-flex;
+ justify-content: center;
+ align-items: center;
+ width: 1.5em;
+ height: 1.5em;
+ padding: 0 0.5em;
+ margin: 0 0.25em;
+ font-size: 1rem;
+ font-weight: bold;
+ text-shadow: 0 0 1px rgba(0, 0, 0, 0.5);
+ background-color: #f0f0f0;
+ border-radius: 1.5em;
+
+ ${({ $color = 'var(--background-action-high-red-marianne)' }) => `color: ${$color};`}
+
+ }
+
&.cr-top { top: 25px; }
&.cr-bottom { bottom: 25px; }
&.cr-left { left: -50px; }
diff --git a/src/layouts/Header.tsx b/src/layouts/Header.tsx
index 0904b3a15..206091190 100644
--- a/src/layouts/Header.tsx
+++ b/src/layouts/Header.tsx
@@ -2,14 +2,18 @@
import { useMemo } from 'react'
import { usePathname } from 'next/navigation'
+import { env } from 'next-runtime-env'
import { Header as HeaderDSFR } from '@codegouvfr/react-dsfr/Header'
import { MainNavigationProps } from '@codegouvfr/react-dsfr/MainNavigation'
import { Tooltip } from '@codegouvfr/react-dsfr/Tooltip'
import Notices from '@/components/Notices'
+import { useMainLayout } from './MainLayout'
-import { CornerRibbons } from './Header.styles'
-import { env } from 'next-runtime-env'
+import {
+ HeaderWrapper,
+ CornerRibbons,
+} from './Header.styles'
const URL_CARTOGRAPHY_BAN = env('NEXT_PUBLIC_URL_CARTOGRAPHY_BAN')
@@ -93,7 +97,6 @@ export const navEntries: MainNavigationProps.Item[] = [
// { text: 'Signalement', linkProps: { href: '#' } },
{
text: 'Télécharger les données',
- // linkProps: { href: '/donnees-nationales' }, // TODO: Use redirection
linkProps: { href: '/outils/telechargements' },
},
{ text: 'Validateur BAL', linkProps: { href: '/outils/validateur-bal' } },
@@ -149,10 +152,21 @@ interface Notices {
duration: number
}
-export default function Header({ notices = {
- data: [],
- duration: 4000,
-} }: { notices: Notices }) {
+interface HeaderProps {
+ notices?: Notices
+ isBeta?: boolean
+}
+
+export default function Header(
+ {
+ notices = {
+ data: [],
+ duration: 4000,
+ },
+ isBeta = true, // TODO : Use env variable
+ }: HeaderProps
+) {
+ const { typeLayout } = useMainLayout()
const pathname = usePathname()
const selectedNavigationLinks = useMemo(
@@ -160,11 +174,15 @@ export default function Header({ notices = {
[pathname]
)
+ const size = useMemo(() => (typeLayout === 'default' ? 'default' : 'small'), [typeLayout])
+
return (
- <>
- Version bêta
+
+
+ {isBeta && Version βετα }
RÉPUBLIQUE
@@ -215,7 +233,7 @@ export default function Header({ notices = {
]}
navigation={selectedNavigationLinks as MainNavigationProps.Item[]}
/>
- {notices && notices.data.length > 0 && }
- >
+ {notices && notices.data.length > 0 && }
+
)
}
diff --git a/src/layouts/MainLayout.tsx b/src/layouts/MainLayout.tsx
new file mode 100644
index 000000000..16d0bb4cc
--- /dev/null
+++ b/src/layouts/MainLayout.tsx
@@ -0,0 +1,32 @@
+'use client'
+
+import { createContext, useContext, useState } from 'react'
+
+type TypeLayout = 'default' | 'small' | 'full-screen'
+
+interface DefaultMainLayout {
+ typeLayout: TypeLayout
+ setTypeLayout: (v: TypeLayout) => void
+}
+
+const defaultMainLayout: DefaultMainLayout = {
+ typeLayout: 'default',
+ setTypeLayout: (v: TypeLayout) => void v,
+}
+
+const LayoutContext = createContext(defaultMainLayout)
+
+export const LayoutProvider = ({ children }: { children: JSX.Element }) => {
+ const [typeLayout, setTypeLayout] = useState('default')
+ const mainLayout = {
+ typeLayout,
+ setTypeLayout,
+ }
+ return {children}
+}
+
+export default LayoutProvider
+
+export const useMainLayout = () => {
+ return useContext(LayoutContext)
+}