Skip to content

Commit

Permalink
Merge pull request #1892 from BaseAdresseNationale/feat/multiple-quic…
Browse files Browse the repository at this point in the history
…k-fix

Feat/multiple quick fix
  • Loading branch information
nkokla authored Nov 18, 2024
2 parents eaf16c7 + da437b6 commit 263be79
Show file tree
Hide file tree
Showing 30 changed files with 529 additions and 245 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export const AsideWrapper = styled.div<{
@media (min-width: ${({ theme }) => theme.breakpoints.md}) {
display: flex;
flex-direction: row-reverse;
min-width: 200px;
min-width: calc(340px + 2rem);
width: calc(400px + 2rem);
max-width: calc(25% + 2rem);
overflow: hidden;
Expand Down Expand Up @@ -97,7 +97,7 @@ export const AsideTogglerButtonWrapper = styled.div`
align-items: center;
height: 2.5rem;
max-height: 2.5rem;
pointer-events: auto;
pointer-events: none;
&::after {
content: '';
Expand Down Expand Up @@ -153,6 +153,7 @@ export const AsideWrapperTogglerButton = styled.button.attrs<{ $isOpen: boolean
background-repeat: repeat-x;
transform: rotateX(0deg) rotateY(0deg);
transition: background 0.5s ease, transform 0.5s ease;
pointer-events: auto;
&.md {
display: none;
Expand Down Expand Up @@ -195,3 +196,16 @@ export const AsideWrapperTogglerButton = styled.button.attrs<{ $isOpen: boolean
}
}
`

export const AsideFooter = styled.footer`
position: sticky;
z-index: 1;
bottom: 0;
left: 0;
right: 0;
padding: 1rem;
border-radius: 0.5rem 0.5rem 0 0;
box-shadow: 0 0 .5rem -0.125rem rgba(0, 0, 0, 0.7);
background: var(--background-default-grey);
pointer-events: auto;
`
12 changes: 10 additions & 2 deletions src/app/carte-base-adresse-nationale/components/Aside/Aside.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@ import {
AsideWrapper,
AsideTogglerButtonWrapper,
AsideWrapperTogglerButton,
AsideFooter,
} from './Aside.styles'

interface AsideProps {
children: React.ReactNode
footer?: React.ReactNode
onClickToggler?: (args: { isOpen: boolean, togglerButtonType: 'horizontal' | 'vertical' }) => void
isOpen?: boolean
isInfo?: boolean
}

function Aside({ children, onClickToggler, isOpen = true, isInfo }: AsideProps) {
function Aside({ children, footer, onClickToggler, isOpen = true, isInfo }: AsideProps) {
const withTogglerButton = Boolean(onClickToggler)

return (
Expand All @@ -25,7 +27,7 @@ function Aside({ children, onClickToggler, isOpen = true, isInfo }: AsideProps)
<AsideTogglerButtonWrapper>
<AsideWrapperTogglerButton
className="ri-arrow-up-double-fill sm"
// TODO : Add onClick event for auto scroll to top
// TODO : Add onClick event for auto scroll to top on mobile
onClick={() => {
onClickToggler?.({
isOpen,
Expand All @@ -50,6 +52,12 @@ function Aside({ children, onClickToggler, isOpen = true, isInfo }: AsideProps)

<div className="body">
{children}

{footer && (
<AsideFooter>
{footer}
</AsideFooter>
)}
</div>
</AsideWrapper>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export const AddressDetailsWrapper = styled.ul`
margin: 2rem 0;
`

export const AddressDetailsItem = styled.li`
const AddressDetailsItemStyle = styled.li`
display: flex;
flex-direction: row;
margin-bottom: 0.2em;
Expand All @@ -93,6 +93,18 @@ export const AddressDetailsItem = styled.li`
}
`

interface AddressDetailsItemProps extends React.HTMLAttributes<HTMLLIElement> {
children: React.ReactNode
}

export const AddressDetailsItem = ({ children, ...props }: AddressDetailsItemProps) => (
<AddressDetailsItemStyle {...props}>
<div>
{children}
</div>
</AddressDetailsItemStyle>
)

export const AddressDetailsItemValue = styled.pre`
font-size: small;
font-weight: 700;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import Link from 'next/link'

import {
AddressDetailsItemValue,

Expand All @@ -17,23 +15,48 @@ import {
AddressDetailsWrapper,
AddressDetailsItem,
} from './AddressCard.styles'
import { isNumeroCertifiable } from '@/lib/ban'
import DownloadCertificate from './download-certificate'
import type { TypeAddressExtended } from '../../types/LegacyBan.types'

interface AddressCardProps {
address: TypeAddressExtended
withCertificate: boolean
}

function AddressCard({ address, withCertificate }: AddressCardProps) {
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 (
<>
<AddressHeaderWrapper>
Expand Down Expand Up @@ -92,41 +115,25 @@ function AddressCard({ address, withCertificate }: AddressCardProps) {
Libellé d’acheminement : <br />
{address.libelleAcheminement}
</AddressDetailsItem>
<AddressDetailsItem className="ri-map-pin-range-line">
Position : <br />
{address.positionType}
</AddressDetailsItem>
<AddressDetailsItem className="ri-focus-3-line">
Coordonnées : <br />
{address.position.coordinates[0]}, {address.position.coordinates[1]}
<AddressDetailsItem className="ri-map-pin-line">
{isMultiPosition ? 'Position Principale' : 'Position'} : <br />
<span>Type / {mainPosition.positionType}</span> <br />
<span>Coordonnées / {mainPosition.position.coordinates[0]}, {mainPosition.position.coordinates[1]}</span>
</AddressDetailsItem>
{isMultiPosition && (
<AddressDetailsItem className="ri-map-pin-2-line">
Position Secondaire : <br />
<ol>
{secondariesPositions.map((entry, index) => (
<li key={index}>
<span>Type / {entry.positionType}</span> <br />
<span>Coordonnées / {entry.position.coordinates[0]}, {entry.position.coordinates[1]}</span>
</li>
))}
</ol>
</AddressDetailsItem>
)}
</AddressDetailsWrapper>

{/* Ajout du composant DownloadCertificate sous les coordonnées */}

{ withCertificate && (
isNumeroCertifiable({
banId: address.banId ?? '',
sources: Array.isArray(address.sourcePosition) ? address.sourcePosition : [address.sourcePosition],
certifie: address.certifie,
parcelles: address.parcelles,
})
? (
<div className="certificate">
<DownloadCertificate
id={address.id}
title="Télécharger le Certificat d'adressage"
/>
</div>
)
: (
<div className="certificate">
<div />
<span>Certificat d&apos;adressage indisponible pour cette adresse, veuillez contacter votre mairie.</span>
</div>
)
)}

</>
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
'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;
`
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { useMemo } from 'react'

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 {
AsideFooterWrapper,
ActionWrapper,
ActionList,
} from './AsideFooterAddress.styles'

import type { TypeAddressExtended } from '../../types/LegacyBan.types'

interface AsideFooterAddressProps {
banItem: TypeAddressExtended
withCertificate: boolean
children?: React.ReactNode
}

function AsideFooterAddress({ banItem: address, withCertificate, children }: AsideFooterAddressProps) {
const focusOnMap = useFocusOnMap(address)

const isCertifiable = useMemo(() => isNumeroCertifiable({
banId: address.banId ?? '',
sources: Array.isArray(address.sourcePosition) ? address.sourcePosition : [address.sourcePosition],
certifie: address.certifie,
parcelles: address.parcelles,
}), [address])

const handleClick = (evt: React.MouseEvent<HTMLButtonElement>) => {
evt.preventDefault()
focusOnMap()
}

return (
<AsideFooterWrapper>
{children}
{!withCertificate && (
<div>
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.
</div>
)}
{withCertificate && !isCertifiable && (
<div>
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.
</div>
)}
<ActionWrapper>
<ActionList>
<Button
iconId="ri-focus-3-line"
onClick={handleClick}
priority="tertiary no outline"
>
Centrer la carte sur l’adresse
</Button>

</ActionList>

{ withCertificate && (
isCertifiable
? (
<ActionList className="certificate">
<DownloadCertificate
id={address.id}
/>
</ActionList>
)
: (
<ActionList className="certificate">
<div />
<span>Certificat d&apos;adressage indisponible pour cette adresse, veuillez contacter votre mairie.</span>
</ActionList>
)
)}
</ActionWrapper>
</AsideFooterWrapper>
)
}

export default AsideFooterAddress
Loading

0 comments on commit 263be79

Please sign in to comment.