From 35ab359fd5d0ef4fcdb79fdcd64f6db3c39d87c0 Mon Sep 17 00:00:00 2001 From: Xavier Le Cunff Date: Tue, 19 Nov 2024 17:22:24 +0100 Subject: [PATCH] wip --- .../components/OfferCine/CineContentCTA.tsx | 30 ++++++++ .../components/OfferCine/OfferCineBlock.tsx | 27 +++++-- .../OfferContent/OfferCTAProvider.tsx | 43 +++++++++++ .../components/OfferContent/OfferContent.tsx | 24 ++++--- .../OfferContent/OfferContent.web.tsx | 35 ++++----- .../OfferContent/OfferContentBase.tsx | 9 ++- .../OfferPlace/OfferPlace.native.test.tsx | 16 +++-- .../VenueContent/VenueContent.native.test.tsx | 66 ++++++++++++----- .../components/VenueContent/VenueContent.tsx | 71 ++++++++++--------- .../VenueOffers/VenueOffers.native.test.tsx | 5 +- .../components/VenueOffers/VenueOffers.tsx | 27 ++++++- src/features/venue/pages/Venue/Venue.tsx | 17 +++-- src/ui/components/anchor/AnchorContext.tsx | 18 ++++- src/ui/components/anchor/anchor-name.ts | 5 +- 14 files changed, 290 insertions(+), 103 deletions(-) create mode 100644 src/features/offer/components/OfferCine/CineContentCTA.tsx create mode 100644 src/features/offer/components/OfferContent/OfferCTAProvider.tsx diff --git a/src/features/offer/components/OfferCine/CineContentCTA.tsx b/src/features/offer/components/OfferCine/CineContentCTA.tsx new file mode 100644 index 00000000000..72ea7f7e79c --- /dev/null +++ b/src/features/offer/components/OfferCine/CineContentCTA.tsx @@ -0,0 +1,30 @@ +import React, { FC } from 'react' +import styled from 'styled-components/native' + +import { useOfferCTA } from 'features/offer/components/OfferContent/OfferCTAProvider' +import { ButtonWithLinearGradient } from 'ui/components/buttons/buttonWithLinearGradient/ButtonWithLinearGradient' +import { StickyBottomWrapper } from 'ui/components/StickyBottomWrapper/StickyBottomWrapper' +import { Spacer } from 'ui/theme' + +export const CineContentCTA: FC = () => { + const { onPress, wording } = useOfferCTA() + + return ( + + + + + + + + ) +} + +const CallToActionContainer = styled.View(({ theme }) => ({ + alignSelf: 'center', + paddingHorizontal: theme.contentPage.marginHorizontal, + width: '100%', + ...(!theme.isMobileViewport && { + maxWidth: theme.contentPage.maxWidth, + }), +})) diff --git a/src/features/offer/components/OfferCine/OfferCineBlock.tsx b/src/features/offer/components/OfferCine/OfferCineBlock.tsx index 23bd905a99a..f71943cd51f 100644 --- a/src/features/offer/components/OfferCine/OfferCineBlock.tsx +++ b/src/features/offer/components/OfferCine/OfferCineBlock.tsx @@ -1,11 +1,15 @@ -import React, { FC } from 'react' +import React, { FC, useEffect } from 'react' import { View, ViewStyle } from 'react-native' +import { InView } from 'react-native-intersection-observer' import styled, { useTheme } from 'styled-components/native' import { OfferResponseV2 } from 'api/gen' import { MovieCalendarProvider } from 'features/offer/components/MoviesScreeningCalendar/MovieCalendarContext' import { OfferCineContent } from 'features/offer/components/OfferCine/OfferCineContent' +import { useOfferCTA } from 'features/offer/components/OfferContent/OfferCTAProvider' import { AppThemeType } from 'theme' +import { Anchor } from 'ui/components/anchor/Anchor' +import { useScrollToAnchor } from 'ui/components/anchor/AnchorContext' import { getSpacing, Spacer, TypoDS } from 'ui/theme' import { getHeadingAttrs } from 'ui/theme/typographyAttrs/getHeadingAttrs' @@ -17,12 +21,27 @@ type Props = { export const OfferCineBlock: FC = ({ title, onSeeVenuePress, offer }) => { const theme = useTheme() + const { setButton, showButton } = useOfferCTA() + const scrollToAnchor = useScrollToAnchor() + + useEffect(() => { + setButton('Accéder aux séances', () => { + scrollToAnchor('offer-cine-availabilities') + }) + }, [scrollToAnchor, setButton]) return ( - - {title} - + + { + showButton(!inView) + }}> + + {title} + + + diff --git a/src/features/offer/components/OfferContent/OfferCTAProvider.tsx b/src/features/offer/components/OfferContent/OfferCTAProvider.tsx new file mode 100644 index 00000000000..5f9ec4c02e5 --- /dev/null +++ b/src/features/offer/components/OfferContent/OfferCTAProvider.tsx @@ -0,0 +1,43 @@ +import React, { createContext, useContext, ReactNode, useState, useCallback, useMemo } from 'react' + +interface OfferCTAContextValue { + wording: string + onPress: () => void + setButton: (wording: string, onPress: () => void) => void + showButton: (isVisible: boolean) => void + isButtonVisible: boolean +} + +const OfferCTAContext = createContext(undefined) + +interface OfferCTAProviderProps { + children: ReactNode +} + +export const OfferCTAProvider: React.FC = ({ children }) => { + const [wording, setWording] = useState('') + const [isVisible, setIsVisible] = useState(false) + const [onPress, setOnPress] = useState<() => void>(() => () => { + return + }) + + const setButton = useCallback((newWording: string, newOnPress: () => void) => { + setWording(newWording) + setOnPress(() => newOnPress) + }, []) + + const value = useMemo( + () => ({ wording, onPress, setButton, showButton: setIsVisible, isButtonVisible: isVisible }), + [isVisible, onPress, setButton, wording] + ) + + return {children} +} + +export const useOfferCTA = (): OfferCTAContextValue => { + const context = useContext(OfferCTAContext) + if (!context) { + throw new Error('useOfferCTAButton must be used within an OfferCTAProvider') + } + return context +} diff --git a/src/features/offer/components/OfferContent/OfferContent.tsx b/src/features/offer/components/OfferContent/OfferContent.tsx index da521367c54..097d45bdba8 100644 --- a/src/features/offer/components/OfferContent/OfferContent.tsx +++ b/src/features/offer/components/OfferContent/OfferContent.tsx @@ -4,6 +4,7 @@ import styled from 'styled-components/native' import { UseNavigationType } from 'features/navigation/RootNavigator/types' import { OfferContentBase } from 'features/offer/components/OfferContent/OfferContentBase' +import { OfferCTAProvider } from 'features/offer/components/OfferContent/OfferCTAProvider' import { OfferCTAButton } from 'features/offer/components/OfferCTAButton/OfferCTAButton' import { useOfferBatchTracking } from 'features/offer/helpers/useOfferBatchTracking/useOfferBatchTracking' import { OfferContentProps } from 'features/offer/types' @@ -18,11 +19,10 @@ export const OfferContent: FunctionComponent = ({ subcategory, }) => { const { navigate } = useNavigation() - const { trackEventHasSeenOfferOnce } = useOfferBatchTracking(subcategory.id) - const handlePress = (defaultIndex = 0) => { navigate('OfferPreview', { id: offer.id, defaultIndex }) } + const { trackEventHasSeenOfferOnce } = useOfferBatchTracking(subcategory.id) const footer = useMemo( () => ( @@ -36,15 +36,17 @@ export const OfferContent: FunctionComponent = ({ ) return ( - + + + ) } diff --git a/src/features/offer/components/OfferContent/OfferContent.web.tsx b/src/features/offer/components/OfferContent/OfferContent.web.tsx index 58b00a189ea..5d0abbea1eb 100644 --- a/src/features/offer/components/OfferContent/OfferContent.web.tsx +++ b/src/features/offer/components/OfferContent/OfferContent.web.tsx @@ -4,6 +4,7 @@ import styled from 'styled-components/native' import { OfferImageResponse } from 'api/gen' import { OfferContentBase } from 'features/offer/components/OfferContent/OfferContentBase' +import { OfferCTAProvider } from 'features/offer/components/OfferContent/OfferCTAProvider' import { OfferCTAButton } from 'features/offer/components/OfferCTAButton/OfferCTAButton' import { useOfferBatchTracking } from 'features/offer/helpers/useOfferBatchTracking/useOfferBatchTracking' import { OfferContentProps } from 'features/offer/types' @@ -53,22 +54,24 @@ export const OfferContent: FunctionComponent = ({ ) return ( - - - - + + + + + + ) } diff --git a/src/features/offer/components/OfferContent/OfferContentBase.tsx b/src/features/offer/components/OfferContent/OfferContentBase.tsx index 86bcc443c70..851e9fa4ff3 100644 --- a/src/features/offer/components/OfferContent/OfferContentBase.tsx +++ b/src/features/offer/components/OfferContent/OfferContentBase.tsx @@ -19,8 +19,10 @@ import styled from 'styled-components/native' import { OfferImageResponse, OfferResponseV2 } from 'api/gen' import { OfferBody } from 'features/offer/components/OfferBody/OfferBody' +import { useOfferCTA } from 'features/offer/components/OfferContent/OfferCTAProvider' import { OfferHeader } from 'features/offer/components/OfferHeader/OfferHeader' import { OfferImageContainer } from 'features/offer/components/OfferImageContainer/OfferImageContainer' +import { CineContentCTA } from 'features/offer/components/OfferNewXPCine/CineContentCTA' import { OfferPlaylistList } from 'features/offer/components/OfferPlaylistList/OfferPlaylistList' import { OfferWebMetaHeader } from 'features/offer/components/OfferWebMetaHeader' import { useOfferBatchTracking } from 'features/offer/helpers/useOfferBatchTracking/useOfferBatchTracking' @@ -59,6 +61,7 @@ export const OfferContentBase: FunctionComponent = ({ } = useOfferPlaylist({ offer, offerSearchGroup: subcategory.searchGroupName, searchGroupList }) const scrollViewRef = useRef(null) const scrollYRef = useRef(0) + const { isButtonVisible } = useOfferCTA() const logConsultWholeOffer = useFunctionOnce(() => { analytics.logConsultWholeOffer(offer.id) @@ -120,9 +123,9 @@ export const OfferContentBase: FunctionComponent = ({ return ( - - + + = ({ apiRecoParamsOtherCategories={apiRecoParamsOtherCategories} /> + {isButtonVisible ? : footer} - {footer} ) } diff --git a/src/features/offer/components/OfferPlace/OfferPlace.native.test.tsx b/src/features/offer/components/OfferPlace/OfferPlace.native.test.tsx index 0a68dee5965..5be783a05d6 100644 --- a/src/features/offer/components/OfferPlace/OfferPlace.native.test.tsx +++ b/src/features/offer/components/OfferPlace/OfferPlace.native.test.tsx @@ -4,6 +4,7 @@ import React, { ComponentProps } from 'react' import { navigate } from '__mocks__/@react-navigation/native' import { OfferResponseV2, SubcategoryIdEnum } from 'api/gen' import { mockOffer } from 'features/bookOffer/fixtures/offer' +import { OfferCTAProvider } from 'features/offer/components/OfferContent/OfferCTAProvider' import { OfferPlace, OfferPlaceProps } from 'features/offer/components/OfferPlace/OfferPlace' import { mockSubcategory } from 'features/offer/fixtures/mockSubcategory' import { analytics } from 'libs/analytics' @@ -633,7 +634,14 @@ const renderOfferPlace = ({ subcategory = mockSubcategory, isDesktopViewport, }: RenderOfferPlaceType) => - render(reactQueryProviderHOC(), { - theme: { isDesktopViewport: isDesktopViewport ?? false }, - wrapper: AnchorProvider, - }) + render( + reactQueryProviderHOC( + + + + ), + { + theme: { isDesktopViewport: isDesktopViewport ?? false }, + wrapper: AnchorProvider, + } + ) diff --git a/src/features/venue/components/VenueContent/VenueContent.native.test.tsx b/src/features/venue/components/VenueContent/VenueContent.native.test.tsx index d2d21b5d856..636a5a55a50 100644 --- a/src/features/venue/components/VenueContent/VenueContent.native.test.tsx +++ b/src/features/venue/components/VenueContent/VenueContent.native.test.tsx @@ -1,18 +1,27 @@ import mockdate from 'mockdate' -import React from 'react' +import React, { createRef } from 'react' +import { ScrollView } from 'react-native' import { push } from '__mocks__/@react-navigation/native' +import { VenueTypeCodeKey } from 'api/gen' +import { OfferCTAProvider } from 'features/offer/components/OfferContent/OfferCTAProvider' import { VenueContent } from 'features/venue/components/VenueContent/VenueContent' import { venueDataTest } from 'features/venue/fixtures/venueDataTest' -import { VenueOffersResponseSnap } from 'features/venue/fixtures/venueOffersResponseSnap' -import * as useFeatureFlag from 'libs/firebase/firestore/featureFlags/useFeatureFlag' +import { + VenueMoviesOffersResponseSnap, + VenueOffersResponseSnap, +} from 'features/venue/fixtures/venueOffersResponseSnap' import { LocationMode } from 'libs/location/types' import { BatchEvent, BatchUser } from 'libs/react-native-batch' import { reactQueryProviderHOC } from 'tests/reactQueryProviderHOC' import { act, fireEvent, render, screen, waitFor } from 'tests/utils' +import { AnchorProvider } from 'ui/components/anchor/AnchorContext' import * as useModalAPI from 'ui/components/modals/useModal' -jest.spyOn(useFeatureFlag, 'useFeatureFlag').mockReturnValue(false) +let mockFFValue = false +jest.mock('libs/firebase/firestore/featureFlags/useFeatureFlag', () => ({ + useFeatureFlag: () => mockFFValue, +})) jest.useFakeTimers() @@ -59,16 +68,23 @@ jest.spyOn(useModalAPI, 'useModal').mockReturnValue({ toggleModal: jest.fn(), }) +const renderVenueContent = (props?: Partial>) => { + return render( + reactQueryProviderHOC( + ()} handleCheckScrollY={() => 0}> + + + + + ) + ) +} + describe('', () => { it('should search the offers associated when pressing "Rechercher une offre"', async () => { - render( - reactQueryProviderHOC( - - ) - ) + renderVenueContent({ + venueOffers: { hits: VenueOffersResponseSnap, nbHits: 4 }, + }) fireEvent.press(screen.getByText('Rechercher une offre')) @@ -92,7 +108,7 @@ describe('', () => { }) it('should not display "Rechercher une offre" button if there is no offer', async () => { - render(reactQueryProviderHOC()) + renderVenueContent() await screen.findAllByText('Le Petit Rintintin 1') expect(screen.queryByText('Rechercher une offre')).not.toBeOnTheScreen() @@ -100,7 +116,7 @@ describe('', () => { describe('Batch trigger', () => { it('should trigger event after 5 seconds', async () => { - render(reactQueryProviderHOC()) + renderVenueContent() await act(async () => { jest.advanceTimersByTime(BATCH_TRIGGER_DELAY_IN_MS) @@ -110,7 +126,7 @@ describe('', () => { }) it('should not trigger event before 5 seconds have elapsed', async () => { - render(reactQueryProviderHOC()) + renderVenueContent() await act(async () => { jest.advanceTimersByTime(BATCH_TRIGGER_DELAY_IN_MS - 100) @@ -121,22 +137,36 @@ describe('', () => { }) it('should display default background image when no banner for venue', async () => { - render(reactQueryProviderHOC()) + renderVenueContent() expect(await screen.findByTestId('defaultVenueBackground')).toBeOnTheScreen() }) it('should display fake video player', async () => { - render(reactQueryProviderHOC()) + renderVenueContent({ videoSectionVisible: true }) expect(await screen.findByLabelText('Faux lecteur vidéo')).toBeOnTheScreen() }) it('should open survey modal when fake video player is pressed', async () => { - render(reactQueryProviderHOC()) + renderVenueContent({ videoSectionVisible: true }) fireEvent.press(await screen.findByLabelText('Faux lecteur vidéo')) expect(mockShowModal).toHaveBeenCalledWith() }) + + describe('movie screening access button', () => { + const venueMoviesOffersMock = { hits: VenueMoviesOffersResponseSnap, nbHits: 4 } + + mockFFValue = true + renderVenueContent({ + venue: { ...venueDataTest, venueTypeCode: VenueTypeCodeKey.MOVIE }, + venueOffers: venueMoviesOffersMock, + }) + + it.only('should be tested', () => { + expect(true).toBeTruthy() + }) + }) }) diff --git a/src/features/venue/components/VenueContent/VenueContent.tsx b/src/features/venue/components/VenueContent/VenueContent.tsx index 2743f3bc98f..682ae79f2b5 100644 --- a/src/features/venue/components/VenueContent/VenueContent.tsx +++ b/src/features/venue/components/VenueContent/VenueContent.tsx @@ -1,11 +1,13 @@ -import React, { Fragment, useCallback, useEffect, useRef } from 'react' +import React, { useCallback, useEffect, useRef } from 'react' import { NativeScrollEvent, NativeSyntheticEvent, Platform, ScrollView } from 'react-native' import { IOScrollView as IntersectionObserverScrollView } from 'react-native-intersection-observer' import Animated, { FadeOut, Layout } from 'react-native-reanimated' import styled, { useTheme } from 'styled-components/native' -import { VenueResponse } from 'api/gen' +import { VenueResponse, VenueTypeCodeKey } from 'api/gen' import { GtlPlaylistData } from 'features/gtlPlaylist/types' +import { useOfferCTA } from 'features/offer/components/OfferContent/OfferCTAProvider' +import { CineContentCTA } from 'features/offer/components/OfferNewXPCine/CineContentCTA' import { VenueOffers } from 'features/venue/api/useVenueOffers' import { VenueBody } from 'features/venue/components/VenueBody/VenueBody' import { VenueCTA } from 'features/venue/components/VenueCTA/VenueCTA' @@ -79,7 +81,7 @@ export const VenueContent: React.FunctionComponent = ({ const headerHeight = useGetHeaderHeight() const isLargeScreen = isDesktopViewport || isTabletViewport const { visible, hideModal, showModal } = useModal() - + const { isButtonVisible, wording } = useOfferCTA() const closeModal = () => { onCloseVideoFakeDoor?.() hideModal() @@ -100,10 +102,18 @@ export const VenueContent: React.FunctionComponent = ({ } const shouldDisplayCTA = - (venueOffers && venueOffers.hits.length > 0) || (gtlPlaylists && gtlPlaylists.length > 0) + venue.venueTypeCode !== VenueTypeCodeKey.MOVIE && + ((venueOffers && venueOffers.hits.length > 0) || (gtlPlaylists && gtlPlaylists.length > 0)) + + const renderVenueCTA = useCallback(() => { + if (wording.length) { + return isButtonVisible ? : null + } + return shouldDisplayCTA ? : null + }, [isButtonVisible, shouldDisplayCTA, venue, wording.length]) return ( - + = ({ {/* On web VenueHeader is called before Body for accessibility navigate order */} {isWeb ? : null} - - - {isLargeScreen ? : null} - - - {videoSectionVisible ? ( - - - - ) : null} - - + + {isLargeScreen ? : null} + + + {videoSectionVisible ? ( + + - - + ) : null} + + + + {/* On native VenueHeader is called after Body to implement the BlurView for iOS */} {isWeb ? null : } - {shouldDisplayCTA ? : null} + {renderVenueCTA()} - + ) } diff --git a/src/features/venue/components/VenueOffers/VenueOffers.native.test.tsx b/src/features/venue/components/VenueOffers/VenueOffers.native.test.tsx index 6cdc1940c8c..db746284d5b 100644 --- a/src/features/venue/components/VenueOffers/VenueOffers.native.test.tsx +++ b/src/features/venue/components/VenueOffers/VenueOffers.native.test.tsx @@ -8,6 +8,7 @@ import { VenueResponse, VenueTypeCodeKey } from 'api/gen' import { gtlPlaylistAlgoliaSnapshot } from 'features/gtlPlaylist/fixtures/gtlPlaylistAlgoliaSnapshot' import * as useGTLPlaylists from 'features/gtlPlaylist/hooks/useGTLPlaylists' import { GtlPlaylistData } from 'features/gtlPlaylist/types' +import { OfferCTAProvider } from 'features/offer/components/OfferContent/OfferCTAProvider' import { initialSearchState } from 'features/search/context/reducer' import * as useVenueOffers from 'features/venue/api/useVenueOffers' import { VenueOffers } from 'features/venue/components/VenueOffers/VenueOffers' @@ -240,7 +241,9 @@ const renderVenueOffers = ({ return render( reactQueryProviderHOC( ()} handleCheckScrollY={() => 0}> - + + + ) ) diff --git a/src/features/venue/components/VenueOffers/VenueOffers.tsx b/src/features/venue/components/VenueOffers/VenueOffers.tsx index 400cd4754d0..98791563516 100644 --- a/src/features/venue/components/VenueOffers/VenueOffers.tsx +++ b/src/features/venue/components/VenueOffers/VenueOffers.tsx @@ -1,4 +1,5 @@ -import React from 'react' +import React, { useEffect } from 'react' +import { InView } from 'react-native-intersection-observer' import { useTheme } from 'styled-components' import styled from 'styled-components/native' @@ -6,12 +7,15 @@ import { SubcategoryIdEnum, VenueResponse } from 'api/gen' import { useGTLPlaylists } from 'features/gtlPlaylist/hooks/useGTLPlaylists' import { GtlPlaylistData } from 'features/gtlPlaylist/types' import { MoviesScreeningCalendar } from 'features/offer/components/MoviesScreeningCalendar/MoviesScreeningCalendar' +import { useOfferCTA } from 'features/offer/components/OfferContent/OfferCTAProvider' import { useVenueOffers } from 'features/venue/api/useVenueOffers' import type { VenueOffers } from 'features/venue/api/useVenueOffers' import { NoOfferPlaceholder } from 'features/venue/components/Placeholders/NoOfferPlaceholder' import { VenueOffersList } from 'features/venue/components/VenueOffers/VenueOffersList' import { useFeatureFlag } from 'libs/firebase/firestore/featureFlags/useFeatureFlag' import { RemoteStoreFeatureFlags } from 'libs/firebase/firestore/types' +import { Anchor } from 'ui/components/anchor/Anchor' +import { useScrollToAnchor } from 'ui/components/anchor/AnchorContext' import { OfferPlaylistSkeleton, TileSize } from 'ui/components/placeholders/OfferPlaylistSkeleton' import { getSpacing, Spacer, TypoDS } from 'ui/theme' import { getHeadingAttrs } from 'ui/theme/typographyAttrs/getHeadingAttrs' @@ -31,10 +35,27 @@ export const LoadingState: React.FC = () => ( const MovieScreening: React.FC<{ venueOffers: VenueOffers }> = ({ venueOffers }) => { const { isDesktopViewport } = useTheme() + const { setButton, showButton } = useOfferCTA() + const scrollToAnchor = useScrollToAnchor() + + useEffect(() => { + console.log('yo') + setButton('Accéder aux séances', () => { + scrollToAnchor('venue-cine-availabilities') + }) + }, [setButton]) + return ( - {'Les films à l’affiche'} + + { + showButton(!inView) + }}> + {'Les films à l’affiche'} + + @@ -52,6 +73,8 @@ export function VenueOffers({ venue, venueOffers, playlists }: Readonly } diff --git a/src/features/venue/pages/Venue/Venue.tsx b/src/features/venue/pages/Venue/Venue.tsx index a8fc2725eb4..1a09479fe9a 100644 --- a/src/features/venue/pages/Venue/Venue.tsx +++ b/src/features/venue/pages/Venue/Venue.tsx @@ -3,6 +3,7 @@ import React, { FunctionComponent, useEffect, useState } from 'react' import { useGTLPlaylists } from 'features/gtlPlaylist/hooks/useGTLPlaylists' import { UseRouteType } from 'features/navigation/RootNavigator/types' +import { OfferCTAProvider } from 'features/offer/components/OfferContent/OfferCTAProvider' import { useVenue } from 'features/venue/api/useVenue' import { useVenueOffers } from 'features/venue/api/useVenueOffers' import { VenueContent } from 'features/venue/components/VenueContent/VenueContent' @@ -43,12 +44,14 @@ export const Venue: FunctionComponent = () => { if (!venue) return null return videoAlreadySeen === undefined ? null : ( - + + + ) } diff --git a/src/ui/components/anchor/AnchorContext.tsx b/src/ui/components/anchor/AnchorContext.tsx index 17ecc7033fe..11f07b015df 100644 --- a/src/ui/components/anchor/AnchorContext.tsx +++ b/src/ui/components/anchor/AnchorContext.tsx @@ -1,6 +1,7 @@ import React, { createContext, useContext, useRef, RefObject, useMemo, useCallback } from 'react' import { ScrollView, View } from 'react-native' import { useSafeAreaInsets } from 'react-native-safe-area-context' +import { useTheme } from 'styled-components/native' import { AnchorName } from 'ui/components/anchor/anchor-name' @@ -25,6 +26,7 @@ export const AnchorProvider = ({ children, }: AnchorProviderProps) => { const { top } = useSafeAreaInsets() + const { appBarHeight, isDesktopViewport, navTopHeight, isTabletViewport } = useTheme() const anchors = useRef>>>({}) @@ -32,6 +34,8 @@ export const AnchorProvider = ({ anchors.current[name] = ref }, []) + const headerHeight = isTabletViewport || isDesktopViewport ? navTopHeight : 0 + const scrollToAnchor = useCallback( (name: AnchorName) => { const anchorRef = anchors.current[name] @@ -41,20 +45,20 @@ export const AnchorProvider = ({ _x: number, _y: number, _width: number, - height: number, + _height: number, _pageX: number, pageY: number ) => { const currentPageScroll = handleCheckScrollY() scrollViewRef.current?.scrollTo({ - y: pageY + currentPageScroll - height - top - offset, + y: pageY + currentPageScroll - appBarHeight - headerHeight - top - offset, animated: true, }) } ) } }, - [handleCheckScrollY, offset, scrollViewRef, top] + [appBarHeight, handleCheckScrollY, headerHeight, offset, scrollViewRef, top] ) const value = useMemo( @@ -87,3 +91,11 @@ export const useRegisterAnchor = () => { return context.registerAnchor } + +// - doit s'afficher sur les pages cine +// - ne doit pas être affiché sur les pages livres +// - doit faire un scroll + +// - même chose sur les venues + +// - faire les screens de PR diff --git a/src/ui/components/anchor/anchor-name.ts b/src/ui/components/anchor/anchor-name.ts index e9699fdd61e..603212127c7 100644 --- a/src/ui/components/anchor/anchor-name.ts +++ b/src/ui/components/anchor/anchor-name.ts @@ -1 +1,4 @@ -export type AnchorName = 'movie-calendar' +export type AnchorName = + | 'movie-calendar' + | 'offer-cine-availabilities' + | 'venue-cine-availabilities'