Skip to content

Commit

Permalink
(PC-32642) refactor(NewXPCine): refactor new XP Cine (#7151)
Browse files Browse the repository at this point in the history
* fix: display calendar in new XP offers

* refactor: add displayCalendar to MovieCalendarProvider

* refactor: replace moviesAfter15Days by moviesAfterNbDays

* refactor: rename movies -> screenings

* refactor: remove useless check for empty array for more lisibility

* refactor: remove newXP names
  • Loading branch information
xlecunff-pass authored Nov 21, 2024
1 parent c1fc411 commit f52657c
Show file tree
Hide file tree
Showing 16 changed files with 101 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,8 @@ import { FlatList } from 'react-native-gesture-handler'
import { Easing } from 'react-native-reanimated'
import styled from 'styled-components/native'

import { OfferResponseV2 } from 'api/gen'
import { MovieCalendar } from 'features/offer/components/MovieCalendar/MovieCalendar'
import { handleMovieCalendarScroll } from 'features/offer/components/MoviesScreeningCalendar/utils'
import { useGetVenuesByDay } from 'features/offer/helpers/useGetVenueByDay/useGetVenuesByDay'
import { useNextDays } from 'features/offer/helpers/useNextDays/useNextDays'
import { Anchor } from 'ui/components/anchor/Anchor'
import { useScrollToAnchor } from 'ui/components/anchor/AnchorContext'
Expand All @@ -25,6 +23,7 @@ import { useLayout } from 'ui/hooks/useLayout'
type MovieCalendarContextType = {
selectedDate: Date
goToDate: (date: Date) => void
displayCalendar: (shouldDisplayCalendar: boolean) => void
}

const MovieCalendarContext = createContext<MovieCalendarContextType | undefined>(undefined)
Expand Down Expand Up @@ -76,13 +75,13 @@ export const MovieCalendarProvider: React.FC<{
nbOfDays: number
children: React.ReactNode
containerStyle?: ViewStyle
offer?: OfferResponseV2
}> = ({ nbOfDays, containerStyle, offer, children }) => {
}> = ({ nbOfDays, containerStyle, children }) => {
const { dates, selectedDate, setSelectedDate } = useNextDays(nbOfDays)
const flatListRef = useRef<FlatList | null>(null)
const { width: flatListWidth, onLayout: onFlatListLayout } = useLayout()
const { width: itemWidth, onLayout: onItemLayout } = useLayout()
const scrollToAnchor = useScrollToAnchor()
const [isVisible, setIsVisible] = useState<boolean>(true)

const scrollToMiddleElement = useCallback(
(currentIndex: number) => {
Expand Down Expand Up @@ -118,13 +117,14 @@ export const MovieCalendarProvider: React.FC<{
[scrollToAnchor, setSelectedDate]
)

const value = useMemo(() => ({ selectedDate, goToDate }), [selectedDate, goToDate])

const { hasStocksOnlyAfter15Days } = useGetVenuesByDay(selectedDate, offer)
const value = useMemo(
() => ({ selectedDate, goToDate, displayCalendar: setIsVisible }),
[selectedDate, goToDate]
)

return (
<MovieCalendarContext.Provider value={value}>
{hasStocksOnlyAfter15Days ? null : (
{isVisible ? (
<View style={containerStyle}>
<Anchor name="movie-calendar">
<MovieCalendar
Expand All @@ -139,7 +139,7 @@ export const MovieCalendarProvider: React.FC<{
/>
</Anchor>
</View>
)}
) : null}

<AnimatedCalendarView selectedDate={selectedDate}>{children}</AnimatedCalendarView>
</MovieCalendarContext.Provider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,5 @@ import { MovieOffer } from 'features/offer/components/MoviesScreeningCalendar/ge
import { moviesOfferBuilder } from 'features/offer/components/MoviesScreeningCalendar/moviesOffer.builder'

export const filterOffersStocksByDate = (offers: OfferResponseV2[], date: Date): MovieOffer[] => {
if (!offers.length) {
return []
}

return moviesOfferBuilder(offers).withMoviesOnDay(date).sortedByLast30DaysBooking().build()
return moviesOfferBuilder(offers).withScreeningsOnDay(date).sortedByLast30DaysBooking().build()
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,9 @@ export const getNextMoviesByDate = (
offersWithStocks: OfferResponseV2[],
date: Date
): MovieOffer[] => {
if (!offersWithStocks.length) {
return []
}

return moviesOfferBuilder(offersWithStocks)
.withoutMoviesAfter15Days()
.withoutMoviesOnDay(date)
.withoutScreeningsAfterNbDays(15)
.withoutScreeningsOnDay(date)
.withNextScreeningFromDate(date)
.sortedByLast30DaysBooking()
.build()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ describe('useMoviesScreeningsList', () => {
const mockOfferIds = [1, 2, 3]

beforeEach(() => {
jest
.spyOn(useMovieCalendarModule, 'useMovieCalendar')
.mockReturnValue({ selectedDate: mockSelectedDate, goToDate: jest.fn })
jest.spyOn(useMovieCalendarModule, 'useMovieCalendar').mockReturnValue({
selectedDate: mockSelectedDate,
goToDate: jest.fn(),
displayCalendar: jest.fn(),
})
})

it('should return filtered movie offers', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ describe('moviesOfferBuilder', () => {
.build()

const result = moviesOfferBuilder([offer1, offer2])
.withMoviesOnDay(selectedDate)
.withScreeningsOnDay(selectedDate)
.buildOfferResponse()

expect(result).toHaveLength(1)
Expand Down Expand Up @@ -125,43 +125,26 @@ describe('moviesOfferBuilder', () => {
})
})

describe('withoutMoviesAfter15Days', () => {
it('should filter out movies after 15 days', () => {
describe('withoutMoviesAfterNbDays', () => {
it('should filter out movies within the specified range of days', () => {
const offer1 = offerResponseBuilder()
.withId(1)
.withStocks([stockBuilder().withBeginningDatetime(addDays(now, 10).toString()).build()])
.withStocks([stockBuilder().withBeginningDatetime(addDays(now, 5).toString()).build()])
.build()
const offer2 = offerResponseBuilder()
.withId(2)
.withStocks([stockBuilder().withBeginningDatetime(addDays(now, 20).toString()).build()])
.build()

const result = moviesOfferBuilder([offer1, offer2])
.withoutMoviesAfter15Days()
.buildOfferResponse()

expect(result).toHaveLength(1)
expect(result[0]?.id).toBe(offer1.id)
})
})

describe('withMoviesAfter15Days', () => {
it('should only return movies after 15 days', () => {
const offer1 = offerResponseBuilder()
.withId(1)
.withStocks([stockBuilder().withBeginningDatetime(now.toString()).build()])
.withStocks([stockBuilder().withBeginningDatetime(addDays(now, 10).toString()).build()])
.build()
const offer2 = offerResponseBuilder()
.withId(2)
const offer3 = offerResponseBuilder()
.withId(3)
.withStocks([stockBuilder().withBeginningDatetime(addDays(now, 20).toString()).build()])
.build()

const result = moviesOfferBuilder([offer1, offer2])
.withMoviesAfter15Days()
const result = moviesOfferBuilder([offer1, offer2, offer3])
.withoutScreeningsAfterNbDays(15)
.buildOfferResponse()

expect(result).toHaveLength(1)
expect(result[0]?.id).toBe(offer2.id)
expect(result).toHaveLength(2)
})
})

Expand All @@ -188,6 +171,30 @@ describe('moviesOfferBuilder', () => {
})
})

describe('withMoviesAfterNbDays', () => {
it('should only return movies after the specified number of days from now', () => {
const offer1 = offerResponseBuilder()
.withId(1)
.withStocks([stockBuilder().withBeginningDatetime(addDays(now, 5).toString()).build()])
.build()
const offer2 = offerResponseBuilder()
.withId(2)
.withStocks([stockBuilder().withBeginningDatetime(addDays(now, 10).toString()).build()])
.build()
const offer3 = offerResponseBuilder()
.withId(3)
.withStocks([stockBuilder().withBeginningDatetime(addDays(now, 20).toString()).build()])
.build()

const result = moviesOfferBuilder([offer1, offer2, offer3])
.withScreeningsAfterNbDays(15)
.buildOfferResponse()

expect(result).toHaveLength(1)
expect(result[0]?.id).toBe(offer3.id)
})
})

describe('buildOfferResponse', () => {
it('should return an array of OfferResponseV2', () => {
const offer1 = offerResponseBuilder().build()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const moviesOfferBuilder = (offersWithStocks: OfferResponseV2[] = []) =>
}))

const builderObject = {
withoutMoviesOnDay: (selectedDate: Date) => {
withoutScreeningsOnDay: (selectedDate: Date) => {
movieOffers = movieOffers.filter(
({ offer }) =>
!offer.stocks.some((stock) => {
Expand All @@ -35,7 +35,7 @@ export const moviesOfferBuilder = (offersWithStocks: OfferResponseV2[] = []) =>
return builderObject
},

withMoviesOnDay: (selectedDate: Date) => {
withScreeningsOnDay: (selectedDate: Date) => {
movieOffers = movieOffers
.map(({ offer, ...rest }) => ({
...rest,
Expand Down Expand Up @@ -110,15 +110,15 @@ export const moviesOfferBuilder = (offersWithStocks: OfferResponseV2[] = []) =>
return builderObject
},

withMoviesAfter15Days: () => {
withScreeningsAfterNbDays: (nbDays: number) => {
movieOffers = movieOffers
.map(({ offer }) => {
const filteredStocks = offer.stocks.filter((stock) => {
if (!stock.beginningDatetime) {
return false
}

return isDateNotWithinNext15Days(new Date(), new Date(stock.beginningDatetime))
return isDateNotWithinNextNbDays(new Date(), new Date(stock.beginningDatetime), nbDays)
})
return {
nextDate: new Date(filteredStocks[0]?.beginningDatetime as string),
Expand All @@ -133,13 +133,13 @@ export const moviesOfferBuilder = (offersWithStocks: OfferResponseV2[] = []) =>
return builderObject
},

withoutMoviesAfter15Days: () => {
withoutScreeningsAfterNbDays: (nbDays: number) => {
movieOffers = movieOffers.filter(({ offer }) =>
offer.stocks.some((stock) => {
if (!stock.beginningDatetime) {
return false
}
if (isDateNotWithinNext15Days(new Date(), new Date(stock.beginningDatetime))) {
if (isDateNotWithinNextNbDays(new Date(), new Date(stock.beginningDatetime), nbDays)) {
return false
}
if (isDateBeforeToday(new Date(), new Date(stock.beginningDatetime))) {
Expand Down Expand Up @@ -183,10 +183,14 @@ export const moviesOfferBuilder = (offersWithStocks: OfferResponseV2[] = []) =>
return builderObject
}

export const isDateNotWithinNext15Days = (referenceDate: Date, targetDate: Date) => {
const datePlus15Days = addDays(startOfDay(referenceDate), 15)
export const isDateNotWithinNextNbDays = (
referenceDate: Date,
targetDate: Date,
nbDays: number
) => {
const datePlusNbDays = addDays(startOfDay(referenceDate), nbDays)

return isAfter(targetDate, datePlus15Days)
return isAfter(targetDate, datePlusNbDays)
}

const isDateBeforeToday = (referenceDate: Date, targetDate: Date) => {
Expand All @@ -200,7 +204,7 @@ const getNextDate = (offer: OfferResponseV2, date: Date) => {

const nextDate = findClosestFutureDate(dates, date)

if (nextDate && isDateNotWithinNext15Days(new Date(), nextDate)) {
if (nextDate && isDateNotWithinNextNbDays(new Date(), nextDate, 15)) {
return undefined
}
return findClosestFutureDate(dates, date)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const mockOffer = offerResponseBuilder().withVenue(mockOfferVenue).build()

const mockSelectedDate = new Date('2023-05-01')
const mockGoToDate = jest.fn()
const mockDisplayCalendar = jest.fn()

const mockOnPressOfferCTA = jest.fn()

Expand All @@ -42,6 +43,7 @@ describe('CineBlock', () => {
jest.spyOn(MovieCalendarContext, 'useMovieCalendar').mockReturnValue({
selectedDate: mockSelectedDate,
goToDate: mockGoToDate,
displayCalendar: mockDisplayCalendar,
})

mockUseSubcategoriesMapping.mockReturnValue({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import styled from 'styled-components/native'

import { OfferResponseV2 } from 'api/gen'
import { useMovieCalendar } from 'features/offer/components/MoviesScreeningCalendar/MovieCalendarContext'
import { isDateNotWithinNext15Days } from 'features/offer/components/MoviesScreeningCalendar/moviesOffer.builder'
import { isDateNotWithinNextNbDays } from 'features/offer/components/MoviesScreeningCalendar/moviesOffer.builder'
import { NextScreeningButton } from 'features/offer/components/MoviesScreeningCalendar/NextScreeningButton'
import { useOfferCTAButton } from 'features/offer/components/OfferCTAButton/useOfferCTAButton'
import { OfferEventCardList } from 'features/offer/components/OfferEventCardList/OfferEventCardList'
Expand Down Expand Up @@ -41,7 +41,7 @@ export const CineBlock: FunctionComponent<CineBlockProps> = ({
<NextScreeningButton
date={nextDate}
onPress={
isDateNotWithinNext15Days(new Date(), nextDate)
isDateNotWithinNextNbDays(new Date(), nextDate, 15)
? () => onPressOfferCTA()
: () => goToDate(nextDate)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ComponentMeta, ComponentStory } from '@storybook/react'
import React from 'react'

import { CineBlockSkeleton } from 'features/offer/components/OfferNewXPCine/CineBlockSkeleton'
import { CineBlockSkeleton } from 'features/offer/components/OfferCine/CineBlockSkeleton'

const meta: ComponentMeta<typeof CineBlockSkeleton> = {
title: 'features/offer/CineBlockSkeleton',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import styled, { useTheme } from 'styled-components/native'

import { OfferResponseV2 } from 'api/gen'
import { MovieCalendarProvider } from 'features/offer/components/MoviesScreeningCalendar/MovieCalendarContext'
import { OfferNewXPCineContent } from 'features/offer/components/OfferNewXPCine/OfferNewXPCineContent'
import { OfferCineContent } from 'features/offer/components/OfferCine/OfferCineContent'
import { AppThemeType } from 'theme'
import { getSpacing, Spacer, TypoDS } from 'ui/theme'
import { getHeadingAttrs } from 'ui/theme/typographyAttrs/getHeadingAttrs'
Expand All @@ -15,7 +15,7 @@ type Props = {
onSeeVenuePress?: VoidFunction
}

export const OfferNewXPCineBlock: FC<Props> = ({ title, onSeeVenuePress, offer }) => {
export const OfferCineBlock: FC<Props> = ({ title, onSeeVenuePress, offer }) => {
const theme = useTheme()

return (
Expand All @@ -24,8 +24,8 @@ export const OfferNewXPCineBlock: FC<Props> = ({ title, onSeeVenuePress, offer }
<TypoDS.Title3 {...getHeadingAttrs(2)}>{title}</TypoDS.Title3>
</TitleContainer>
<Spacer.Column numberOfSpaces={4} />
<MovieCalendarProvider offer={offer} nbOfDays={15} containerStyle={getCalendarStyle(theme)}>
<OfferNewXPCineContent offer={offer} onSeeVenuePress={onSeeVenuePress} />
<MovieCalendarProvider nbOfDays={15} containerStyle={getCalendarStyle(theme)}>
<OfferCineContent offer={offer} onSeeVenuePress={onSeeVenuePress} />
</MovieCalendarProvider>
</Container>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react'

import * as MovieCalendarContext from 'features/offer/components/MoviesScreeningCalendar/MovieCalendarContext'
import { offerResponseBuilder } from 'features/offer/components/MoviesScreeningCalendar/offersStockResponse.builder'
import { OfferNewXPCineContent } from 'features/offer/components/OfferNewXPCine/OfferNewXPCineContent'
import { OfferCineContent } from 'features/offer/components/OfferCine/OfferCineContent'
import * as useGetVenuesByDayModule from 'features/offer/helpers/useGetVenueByDay/useGetVenuesByDay'
import { LocationMode, Position } from 'libs/location/types'
import { render, screen } from 'tests/utils'
Expand Down Expand Up @@ -45,12 +45,14 @@ const spyUseGetVenuesByDay = jest.spyOn(useGetVenuesByDayModule, 'useGetVenuesBy

const mockSelectedDate = new Date('2023-05-01')
const mockGoToDate = jest.fn()
const mockDisplayCalendar = jest.fn()

describe('OfferNewXPCineContent', () => {
beforeEach(() => {
jest.spyOn(MovieCalendarContext, 'useMovieCalendar').mockReturnValue({
selectedDate: mockSelectedDate,
goToDate: mockGoToDate,
displayCalendar: mockDisplayCalendar,
})
})

Expand All @@ -60,15 +62,15 @@ describe('OfferNewXPCineContent', () => {
isLoading: true,
})

render(<OfferNewXPCineContent onSeeVenuePress={jest.fn()} offer={mockOffer} />)
render(<OfferCineContent onSeeVenuePress={jest.fn()} offer={mockOffer} />)

expect(screen.getByTestId('cine-block-skeleton')).toBeOnTheScreen()
})

it('should not display skeleton when data is loaded', async () => {
spyUseGetVenuesByDay.mockReturnValueOnce({ ...useGetVenueByDayReturn, isLoading: false })

render(<OfferNewXPCineContent onSeeVenuePress={jest.fn()} offer={mockOffer} />)
render(<OfferCineContent onSeeVenuePress={jest.fn()} offer={mockOffer} />)

expect(screen.queryByTestId('cine-block-skeleton')).not.toBeOnTheScreen()
})
Expand Down
Loading

0 comments on commit f52657c

Please sign in to comment.