Améliore la navigation dans les intégrations pour l'assistant au choix du statut
parent
c8b48af193
commit
218a8ea059
|
@ -15,7 +15,6 @@ import {
|
|||
} from '@/hooks/useCurrentSimulatorData'
|
||||
import { useIsEmbedded } from '@/hooks/useIsEmbedded'
|
||||
import useSimulationConfig from '@/hooks/useSimulationConfig'
|
||||
import { useSitePaths } from '@/sitePaths'
|
||||
import { situationSelector } from '@/store/selectors/simulationSelectors'
|
||||
import { Merge } from '@/types/utils'
|
||||
|
||||
|
@ -57,7 +56,7 @@ export default function SimulateurOrAssistantPage() {
|
|||
autoloadLastSimulation,
|
||||
})
|
||||
useSearchParamsSimulationSharing()
|
||||
const { absoluteSitePaths } = useSitePaths()
|
||||
|
||||
const trackInfo = {
|
||||
chapter1:
|
||||
typeof tracking !== 'string' && tracking && 'chapter1' in tracking
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
import { useEffect, useState } from 'react'
|
||||
|
||||
import { getIframeOffset } from '@/utils'
|
||||
|
||||
export const useIFrameOffset = () => {
|
||||
const [offsetTop, setOffset] = useState<number | null | undefined>(
|
||||
window.parent !== window ? undefined : null
|
||||
)
|
||||
useEffect(() => {
|
||||
if (window.parent === window) {
|
||||
return
|
||||
}
|
||||
void getIframeOffset().then(setOffset)
|
||||
}, [])
|
||||
|
||||
return offsetTop
|
||||
}
|
|
@ -9,31 +9,18 @@ import {
|
|||
} from '@react-aria/overlays'
|
||||
import { AriaDialogProps } from '@react-types/dialog'
|
||||
import FocusTrap from 'focus-trap-react'
|
||||
import React, { RefObject, useEffect, useRef, useState } from 'react'
|
||||
import React, { RefObject, useRef } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled, { css, keyframes } from 'styled-components'
|
||||
|
||||
import { Grid } from '@/design-system/layout'
|
||||
import { getIframeOffset, wrapperDebounceEvents } from '@/utils'
|
||||
import { wrapperDebounceEvents } from '@/utils'
|
||||
|
||||
import { FocusStyle } from '../global-style'
|
||||
import { useIFrameOffset } from '../hooks'
|
||||
import { Container } from '../layout'
|
||||
import { H2 } from '../typography/heading'
|
||||
|
||||
const useIFrameOffset = () => {
|
||||
const [offsetTop, setOffset] = useState<number | null | undefined>(
|
||||
window.parent !== window ? undefined : null
|
||||
)
|
||||
useEffect(() => {
|
||||
if (window.parent === window) {
|
||||
return
|
||||
}
|
||||
void getIframeOffset().then(setOffset)
|
||||
}, [])
|
||||
|
||||
return offsetTop
|
||||
}
|
||||
|
||||
export default function Popover(
|
||||
props: OverlayProps &
|
||||
AriaDialogProps & {
|
||||
|
|
|
@ -17,15 +17,15 @@ export const useCurrentSimulatorData = () => {
|
|||
|
||||
const entries = Object.entries(simulatorsData)
|
||||
const [key, data] =
|
||||
(!isEmbedded
|
||||
? entries
|
||||
.sort((a, b) => b[1].path.length - a[1].path.length)
|
||||
.find(([, data]) => pathname.startsWith(data.path))
|
||||
: entries
|
||||
.sort((a, b) => b[1].iframePath.length - a[1].iframePath.length)
|
||||
.find(([, data]) =>
|
||||
pathname.startsWith('/iframes/' + data.iframePath)
|
||||
)) ?? []
|
||||
// Find the simulator with classic path
|
||||
entries
|
||||
.sort((a, b) => b[1].path.length - a[1].path.length)
|
||||
.find(([, data]) => pathname.startsWith(data.path)) ??
|
||||
// Find the simulator with iframe path
|
||||
entries
|
||||
.sort((a, b) => b[1].iframePath.length - a[1].iframePath.length)
|
||||
.find(([, data]) => pathname.startsWith('/iframes/' + data.iframePath)) ??
|
||||
[]
|
||||
|
||||
return {
|
||||
key: key as keyof typeof simulatorsData,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
import styled, { css } from 'styled-components'
|
||||
|
||||
import { TrackPage } from '@/components/ATInternetTracking'
|
||||
import { Button } from '@/design-system/buttons'
|
||||
|
@ -20,6 +20,7 @@ export default function Navigation({
|
|||
onPreviousStep, // TODO : prefer resetOnLeave
|
||||
assistantIsCompleted = false,
|
||||
children,
|
||||
small = false,
|
||||
}: {
|
||||
currentStepIsComplete: boolean
|
||||
nextStepLabel?: false | string
|
||||
|
@ -27,6 +28,7 @@ export default function Navigation({
|
|||
onPreviousStep?: () => void
|
||||
assistantIsCompleted?: false | Statuts
|
||||
children?: React.ReactNode
|
||||
small?: boolean
|
||||
}) {
|
||||
const { t } = useTranslation()
|
||||
const nextStep = useNextStep()
|
||||
|
@ -38,8 +40,8 @@ export default function Navigation({
|
|||
return (
|
||||
<>
|
||||
<TrackPage chapter3="pas_a_pas" name={currentStep} />
|
||||
<Spacing xs />
|
||||
<StyledNavigation>
|
||||
{!small && <Spacing xs />}
|
||||
<StyledNavigation $small={small}>
|
||||
<Grid container spacing={2}>
|
||||
{children && (
|
||||
<Grid item xs={12}>
|
||||
|
@ -49,6 +51,7 @@ export default function Navigation({
|
|||
<Grid item>
|
||||
<Button
|
||||
light
|
||||
size={small ? 'XS' : 'MD'}
|
||||
color={'secondary'}
|
||||
to={choixDuStatutPath[previousStep]}
|
||||
onPress={onPreviousStep}
|
||||
|
@ -59,6 +62,7 @@ export default function Navigation({
|
|||
{nextStep && !assistantIsCompleted && (
|
||||
<Grid item>
|
||||
<Button
|
||||
size={small ? 'XS' : 'MD'}
|
||||
onPress={onNextStep}
|
||||
to={choixDuStatutPath[nextStep]}
|
||||
isDisabled={!currentStepIsComplete}
|
||||
|
@ -86,17 +90,21 @@ export default function Navigation({
|
|||
)}
|
||||
</Grid>
|
||||
</StyledNavigation>
|
||||
<Shadow />
|
||||
{!small && <Shadow />}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const StyledNavigation = styled.div`
|
||||
const StyledNavigation = styled.div<{ $small: boolean }>`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 110px;
|
||||
${({ $small }) =>
|
||||
!$small &&
|
||||
css`
|
||||
height: 110px;
|
||||
`}
|
||||
position: sticky;
|
||||
padding: ${({ theme }) => theme.spacings.lg} 1rem;
|
||||
padding: ${({ theme, $small }) => theme.spacings[$small ? 'sm' : 'lg']} 1rem;
|
||||
margin: 0 -1rem;
|
||||
bottom: 0;
|
||||
background: ${({ theme }) =>
|
||||
|
|
|
@ -50,6 +50,8 @@ export default function StatutsPossibles() {
|
|||
const StyledMessage = styled(Message)`
|
||||
padding-top: 2rem;
|
||||
border: none;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
border-radius: 0.5rem;
|
||||
background: ${({ theme }) =>
|
||||
theme.darkMode
|
||||
|
|
|
@ -7,6 +7,7 @@ import { HelpButtonWithPopover } from '@/design-system/buttons'
|
|||
import { H5 } from '@/design-system/typography/heading'
|
||||
import { Link } from '@/design-system/typography/link'
|
||||
import { Body } from '@/design-system/typography/paragraphs'
|
||||
import { useIsEmbedded } from '@/hooks/useIsEmbedded'
|
||||
import { resetSimulation, updateSituation } from '@/store/actions/actions'
|
||||
|
||||
import SearchCodeAPE from '../recherche-code-ape/SearchCodeAPE'
|
||||
|
@ -17,11 +18,26 @@ export default function RechercheActivité() {
|
|||
const [codeApe, setCodeApe] = useState('')
|
||||
const { t } = useTranslation()
|
||||
const dispatch = useDispatch()
|
||||
|
||||
const isEmbedded = useIsEmbedded()
|
||||
useEffect(() => {
|
||||
dispatch(resetSimulation())
|
||||
}, [])
|
||||
|
||||
const NavigationComponent = (
|
||||
<Navigation
|
||||
small={!!codeApe && isEmbedded}
|
||||
currentStepIsComplete={!!codeApe}
|
||||
onNextStep={() => {
|
||||
dispatch(
|
||||
updateSituation(
|
||||
'entreprise . activités . principale . code APE',
|
||||
`'${codeApe}'`
|
||||
)
|
||||
)
|
||||
}}
|
||||
/>
|
||||
)
|
||||
|
||||
return (
|
||||
<>
|
||||
<Layout
|
||||
|
@ -57,18 +73,12 @@ export default function RechercheActivité() {
|
|||
</Trans>
|
||||
}
|
||||
>
|
||||
<SearchCodeAPE hideGuichetUnique onCodeAPESelected={setCodeApe} />
|
||||
<Navigation
|
||||
currentStepIsComplete={!!codeApe}
|
||||
onNextStep={() => {
|
||||
dispatch(
|
||||
updateSituation(
|
||||
'entreprise . activités . principale . code APE',
|
||||
`'${codeApe}'`
|
||||
)
|
||||
)
|
||||
}}
|
||||
<SearchCodeAPE
|
||||
hideGuichetUnique
|
||||
onCodeAPESelected={setCodeApe}
|
||||
underSelection={isEmbedded ? NavigationComponent : null}
|
||||
/>
|
||||
{(!codeApe || !isEmbedded) && NavigationComponent}
|
||||
</Layout>
|
||||
</>
|
||||
)
|
||||
|
|
|
@ -3,13 +3,13 @@ import { Trans, useTranslation } from 'react-i18next'
|
|||
import styled, { css } from 'styled-components'
|
||||
|
||||
import { Appear } from '@/components/ui/animate'
|
||||
import { Chip } from '@/design-system'
|
||||
import { Button, HelpButtonWithPopover } from '@/design-system/buttons'
|
||||
import { ChevronIcon } from '@/design-system/icons'
|
||||
import { Strong } from '@/design-system/typography'
|
||||
import { H4, H5 } from '@/design-system/typography/heading'
|
||||
import { H4, H5, H6 } from '@/design-system/typography/heading'
|
||||
import { Link } from '@/design-system/typography/link'
|
||||
import { Li, Ul } from '@/design-system/typography/list'
|
||||
import { Body } from '@/design-system/typography/paragraphs'
|
||||
import { Body, SmallBody } from '@/design-system/typography/paragraphs'
|
||||
|
||||
import GuichetInfo from './GuichetInfo'
|
||||
|
||||
|
@ -32,15 +32,15 @@ export const Result = ({ item, hideGuichetUnique }: ResultProps) => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<H4 as="h3">{title}</H4>
|
||||
<Body
|
||||
<H5 as="h3">{title}</H5>
|
||||
<SmallBody
|
||||
css={`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
`}
|
||||
>
|
||||
<Strong>Code APE : {codeApe}</Strong>
|
||||
<Chip>Code : {codeApe}</Chip>
|
||||
<Button
|
||||
size="XXS"
|
||||
light
|
||||
|
@ -53,12 +53,12 @@ export const Result = ({ item, hideGuichetUnique }: ResultProps) => {
|
|||
{!open ? t('En savoir plus') : t('Replier')}
|
||||
<StyledChevron aria-hidden $isOpen={open} />
|
||||
</Button>
|
||||
</Body>
|
||||
</SmallBody>
|
||||
{open && (
|
||||
<Appear id={`info-${codeApe}`}>
|
||||
{contenuCentral.length ? (
|
||||
<>
|
||||
<H5 as="h4">Contenu central de cette activité :</H5>
|
||||
<H6 as="h4">Contenu central de cette activité :</H6>
|
||||
<Ul>
|
||||
{contenuCentral.map((contenu, i) => (
|
||||
<Li key={i}>{contenu}</Li>
|
||||
|
@ -69,7 +69,7 @@ export const Result = ({ item, hideGuichetUnique }: ResultProps) => {
|
|||
|
||||
{contenuAnnexe.length ? (
|
||||
<>
|
||||
<H5 as="h4">Contenu annexe de cette activité :</H5>
|
||||
<H6 as="h4">Contenu annexe de cette activité :</H6>
|
||||
<Ul>
|
||||
{contenuAnnexe.map((contenu, i) => (
|
||||
<Li key={i}>{contenu}</Li>
|
||||
|
@ -80,7 +80,7 @@ export const Result = ({ item, hideGuichetUnique }: ResultProps) => {
|
|||
|
||||
{contenuExclu.length ? (
|
||||
<>
|
||||
<H5 as="h4">Contenu exclu de cette activité :</H5>
|
||||
<H6 as="h4">Contenu exclu de cette activité :</H6>
|
||||
<Ul>
|
||||
{contenuExclu.map((contenu, i) => (
|
||||
<Li key={i}>{contenu}</Li>
|
||||
|
|
|
@ -78,6 +78,7 @@ interface SearchCodeApeProps {
|
|||
hideGuichetUnique?: boolean
|
||||
onCodeAPESelected?: (codeAPE: string) => void
|
||||
trackSearch?: boolean
|
||||
underSelection?: React.ReactNode
|
||||
}
|
||||
|
||||
export default function SearchCodeAPE({
|
||||
|
@ -85,6 +86,7 @@ export default function SearchCodeAPE({
|
|||
hideGuichetUnique = false,
|
||||
onCodeAPESelected,
|
||||
trackSearch = false,
|
||||
underSelection,
|
||||
}: SearchCodeApeProps) {
|
||||
const { t } = useTranslation()
|
||||
const [searchQuery, setSearchQuery] = usePersistingState<string>(
|
||||
|
@ -250,18 +252,23 @@ export default function SearchCodeAPE({
|
|||
>
|
||||
{list.slice(0, 25).map(({ item, debug }) => {
|
||||
return (
|
||||
<RadioCardSkeleton
|
||||
isDisabled={disabled}
|
||||
value={item.codeApe}
|
||||
key={item.codeApe}
|
||||
visibleRadioAs="div"
|
||||
>
|
||||
<Result
|
||||
item={item}
|
||||
debug={debug}
|
||||
hideGuichetUnique={hideGuichetUnique}
|
||||
/>
|
||||
</RadioCardSkeleton>
|
||||
<>
|
||||
<RadioCardSkeleton
|
||||
isDisabled={disabled}
|
||||
value={item.codeApe}
|
||||
key={item.codeApe}
|
||||
visibleRadioAs="div"
|
||||
>
|
||||
<Result
|
||||
item={item}
|
||||
debug={debug}
|
||||
hideGuichetUnique={hideGuichetUnique}
|
||||
/>
|
||||
</RadioCardSkeleton>
|
||||
{underSelection && selected === item.codeApe && (
|
||||
<FromTop>{underSelection}</FromTop>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
})}
|
||||
</StyledRadioCardGroup>
|
||||
|
|
Loading…
Reference in New Issue