From 06d90678f705b8470453d881ee3e7f7344381363 Mon Sep 17 00:00:00 2001 From: yleclercq-pass <62058919+yleclercq-pass@users.noreply.github.com> Date: Thu, 6 Feb 2025 18:18:35 +0100 Subject: [PATCH] WIP --- .../useSearchVenueOffers.native.test.ts | 13 --- .../useSearchVenueOffers.ts | 8 +- .../ArtistPlaylist/ArtistPlaylist.tsx | 6 +- .../ArtistTopOffers/ArtistTopOffers.tsx | 8 +- src/features/gtlPlaylist/types.ts | 4 +- .../api/helpers/mapOffersDataAndModules.ts | 4 +- .../home/api/useAlgoliaRecommendedOffers.ts | 6 +- src/features/home/api/useHighlightOffer.ts | 5 +- src/features/home/api/useVideoCarouselData.ts | 4 +- .../home/api/useVideoOffers.native.test.ts | 2 +- src/features/home/api/useVideoOffers.ts | 2 +- .../fetchOffersByArtist.test.ts | 6 +- .../fetchOffersByArtist.ts | 17 ++-- .../offer/api/useAlgoliaSimilarOffers.ts | 6 +- .../OfferPlaylist/OfferPlaylist.tsx | 6 +- .../useArtistResults/useArtistResults.tsx | 10 +- src/features/offer/types.ts | 4 +- .../search/pages/ThematicSearch/types.ts | 4 +- src/features/venue/api/useVenueOffers.test.ts | 97 +++++++++++++------ src/features/venue/api/useVenueOffers.ts | 36 ++++--- .../venue/components/VenueBody/VenueBody.tsx | 4 +- src/features/venue/types.ts | 1 + src/libs/algolia/enums/facetsEnums.ts | 2 + .../buildFacetFilters.ts | 9 ++ .../buildNumericFilters.ts | 5 + .../buildOfferSearchParameters.ts | 3 + .../buildFacetFiltersHelpers.ts | 4 + .../buildNumericFiltersHelpers.ts | 5 + .../fetchMultipleOffers.ts | 26 +++-- .../fetchAlgolia/fetchMultipleOffers/todo.md | 20 ++++ .../algolia/fetchAlgolia/transformOfferHit.ts | 18 ++-- src/libs/algolia/fixtures/algoliaFixtures.ts | 5 +- src/libs/algolia/types.ts | 52 ++++++---- src/shared/offer/types.ts | 38 +------- 34 files changed, 250 insertions(+), 190 deletions(-) create mode 100644 src/libs/algolia/fetchAlgolia/fetchMultipleOffers/todo.md diff --git a/src/api/useSearchVenuesOffer/useSearchVenueOffers.native.test.ts b/src/api/useSearchVenuesOffer/useSearchVenueOffers.native.test.ts index b6feb9314b4..9c05a01ac89 100644 --- a/src/api/useSearchVenuesOffer/useSearchVenueOffers.native.test.ts +++ b/src/api/useSearchVenuesOffer/useSearchVenueOffers.native.test.ts @@ -116,19 +116,6 @@ describe('useSearchVenueOffers', () => { }) describe('filterVenueOfferHit', () => { - it('should return false when subcategory hit is undefined', () => { - const shouldFilterVenueOfferHit = filterVenueOfferHit({ - hit: { - ...mockedAlgoliaResponse.hits[0], - offer: { ...mockedAlgoliaResponse.hits[0].offer, subcategoryId: undefined }, - }, - offerId: 102283, - venueId: 2, - }) - - expect(shouldFilterVenueOfferHit).toEqual(false) - }) - it('should return false when object id hit = offerId param', () => { const shouldFilterVenueOfferHit = filterVenueOfferHit({ hit: toMutable(mockedAlgoliaResponse.hits)[0], diff --git a/src/api/useSearchVenuesOffer/useSearchVenueOffers.ts b/src/api/useSearchVenuesOffer/useSearchVenueOffers.ts index 007a59e26fa..19bef402d71 100644 --- a/src/api/useSearchVenuesOffer/useSearchVenueOffers.ts +++ b/src/api/useSearchVenuesOffer/useSearchVenueOffers.ts @@ -10,7 +10,7 @@ import { formatFullAddressStartsWithPostalCode } from 'libs/address/useFormatFul import { useSearchAnalyticsState } from 'libs/algolia/analytics/SearchAnalyticsWrapper' import { FetchOffersResponse, fetchOffers } from 'libs/algolia/fetchAlgolia/fetchOffers' import { useTransformOfferHits } from 'libs/algolia/fetchAlgolia/transformOfferHit' -import { AlgoliaHit, Geoloc } from 'libs/algolia/types' +import { AlgoliaOffer, Geoloc } from 'libs/algolia/types' import { Position, useLocation } from 'libs/location' import { LocationMode } from 'libs/location/types' import { formatDistance } from 'libs/parsers/formatDistance' @@ -39,7 +39,7 @@ type OfferVenueType = VenueListItem & { } type FilterVenueOfferType = { - hit: AlgoliaHit + hit: AlgoliaOffer offerId: number venueId: number | undefined } @@ -89,9 +89,7 @@ export function getVenueList(hits: Offer[], userLocation: Position) { } export const filterVenueOfferHit = ({ hit, offerId, venueId }: FilterVenueOfferType): boolean => - typeof hit.offer.subcategoryId !== 'undefined' && - hit.objectID !== String(offerId) && - hit.venue.id !== venueId + hit.objectID !== String(offerId) && hit.venue.id !== venueId export const useSearchVenueOffers = ({ allocineId, diff --git a/src/features/artist/components/ArtistPlaylist/ArtistPlaylist.tsx b/src/features/artist/components/ArtistPlaylist/ArtistPlaylist.tsx index 5084b3f72a4..4d3e0d2f748 100644 --- a/src/features/artist/components/ArtistPlaylist/ArtistPlaylist.tsx +++ b/src/features/artist/components/ArtistPlaylist/ArtistPlaylist.tsx @@ -1,9 +1,9 @@ import React, { FunctionComponent } from 'react' import { OfferResponseV2 } from 'api/gen' -import { HitOfferWithArtistAndEan } from 'features/offer/api/fetchOffersByArtist/fetchOffersByArtist' import { OfferPlaylistItem } from 'features/offer/components/OfferPlaylistItem/OfferPlaylistItem' import { PlaylistType } from 'features/offer/enums' +import { AlgoliaOfferWithArtistAndEan } from 'libs/algolia/types' import { usePlaylistItemDimensionsFromLayout } from 'libs/contentful/usePlaylistItemDimensionsFromLayout' import { getDisplayedPrice } from 'libs/parsers/getDisplayedPrice' import { useCategoryIdMapping } from 'libs/subcategories' @@ -16,10 +16,10 @@ import { PassPlaylist } from 'ui/components/PassPlaylist' type ArtistPlaylistProps = { offer: OfferResponseV2 artistName: string - items: HitOfferWithArtistAndEan[] + items: AlgoliaOfferWithArtistAndEan[] } -const keyExtractor = (item: Offer | HitOfferWithArtistAndEan) => item.objectID +const keyExtractor = (item: Offer | AlgoliaOfferWithArtistAndEan) => item.objectID export const ArtistPlaylist: FunctionComponent = ({ offer, diff --git a/src/features/artist/components/ArtistTopOffers/ArtistTopOffers.tsx b/src/features/artist/components/ArtistTopOffers/ArtistTopOffers.tsx index 8f64c471802..7adf0fb31af 100644 --- a/src/features/artist/components/ArtistTopOffers/ArtistTopOffers.tsx +++ b/src/features/artist/components/ArtistTopOffers/ArtistTopOffers.tsx @@ -2,7 +2,7 @@ import React, { FunctionComponent } from 'react' import { FlatList } from 'react-native' import styled from 'styled-components/native' -import { HitOfferWithArtistAndEan } from 'features/offer/api/fetchOffersByArtist/fetchOffersByArtist' +import { AlgoliaOfferWithArtistAndEan } from 'libs/algolia/types' import { Offer } from 'shared/offer/types' import { theme } from 'theme' import { Separator } from 'ui/components/Separator' @@ -11,16 +11,16 @@ import { Spacer, TypoDS, getSpacing } from 'ui/theme' type Props = { artistName: string - items: HitOfferWithArtistAndEan[] + items: AlgoliaOfferWithArtistAndEan[] } -const keyExtractor = (item: Offer | HitOfferWithArtistAndEan) => item.objectID +const keyExtractor = (item: Offer | AlgoliaOfferWithArtistAndEan) => item.objectID const renderItem = ({ item, artistName, }: { - item: HitOfferWithArtistAndEan + item: AlgoliaOfferWithArtistAndEan artistName: string }) => { const subtitles = item.offer.bookFormat ? [item.offer.bookFormat] : undefined diff --git a/src/features/gtlPlaylist/types.ts b/src/features/gtlPlaylist/types.ts index f8bf3dbe585..47a053606dc 100644 --- a/src/features/gtlPlaylist/types.ts +++ b/src/features/gtlPlaylist/types.ts @@ -1,5 +1,5 @@ import { OffersModuleParameters } from 'features/home/types' -import { AlgoliaHit } from 'libs/algolia/types' +import { AlgoliaOffer } from 'libs/algolia/types' import { Layout, DisplayParametersFields } from 'libs/contentful/types' export type GtlPlaylistRequest = { @@ -10,7 +10,7 @@ export type GtlPlaylistRequest = { export type GtlPlaylistData = { title: string - offers: { hits: AlgoliaHit[] } + offers: { hits: AlgoliaOffer[] } layout: Layout minNumberOfOffers: number entryId: string diff --git a/src/features/home/api/helpers/mapOffersDataAndModules.ts b/src/features/home/api/helpers/mapOffersDataAndModules.ts index faccb49f2d5..1bb58d35f02 100644 --- a/src/features/home/api/helpers/mapOffersDataAndModules.ts +++ b/src/features/home/api/helpers/mapOffersDataAndModules.ts @@ -4,7 +4,7 @@ import { UseQueryResult } from 'react-query' import { ModuleData, OfferModuleParamsInfo } from 'features/home/types' import { filterOfferHit } from 'libs/algolia/fetchAlgolia/transformOfferHit' -import { AlgoliaHit } from 'libs/algolia/types' +import { AlgoliaOffer } from 'libs/algolia/types' import { Offer } from 'shared/offer/types' const isOfferModuleParamsInfo = (module: unknown): module is OfferModuleParamsInfo => @@ -15,7 +15,7 @@ const hasParams = (module: OfferModuleParamsInfo) => module.adaptedPlaylistParam interface MapProps { results: UseQueryResult[], unknown> modulesParams: (OfferModuleParamsInfo | undefined)[] - transformHits: (hit: AlgoliaHit) => AlgoliaHit + transformHits: (hit: AlgoliaOffer) => AlgoliaOffer } export const mapOffersDataAndModules = ({ results, modulesParams, transformHits }: MapProps) => { diff --git a/src/features/home/api/useAlgoliaRecommendedOffers.ts b/src/features/home/api/useAlgoliaRecommendedOffers.ts index f081c6ca666..4aea0c40e52 100644 --- a/src/features/home/api/useAlgoliaRecommendedOffers.ts +++ b/src/features/home/api/useAlgoliaRecommendedOffers.ts @@ -4,7 +4,7 @@ import { useQuery } from 'react-query' import { useIsUserUnderage } from 'features/profile/helpers/useIsUserUnderage' import { fetchOffersByIds } from 'libs/algolia/fetchAlgolia/fetchOffersByIds' import { filterOfferHit, useTransformOfferHits } from 'libs/algolia/fetchAlgolia/transformOfferHit' -import { IncompleteSearchHit } from 'libs/algolia/types' +import { AlgoliaOffer } from 'libs/algolia/types' import { QueryKeys } from 'libs/queryKeys' import { getSimilarOrRecoOffersInOrder } from 'shared/offer/getSimilarOrRecoOffersInOrder' import { Offer } from 'shared/offer/types' @@ -29,9 +29,9 @@ export const useAlgoliaRecommendedOffers = ( if (shouldPreserveIdsOrder) { const offers = getSimilarOrRecoOffersInOrder(ids, hits) - return (offers as IncompleteSearchHit[]).filter(filterOfferHit).map(transformHits) as Offer[] + return (offers as AlgoliaOffer[]).filter(filterOfferHit).map(transformHits) as Offer[] } - return (hits as IncompleteSearchHit[]).filter(filterOfferHit).map(transformHits) as Offer[] + return (hits as AlgoliaOffer[]).filter(filterOfferHit).map(transformHits) as Offer[] }, [hits, shouldPreserveIdsOrder, ids, transformHits]) } diff --git a/src/features/home/api/useHighlightOffer.ts b/src/features/home/api/useHighlightOffer.ts index e544f7864bb..637e460929a 100644 --- a/src/features/home/api/useHighlightOffer.ts +++ b/src/features/home/api/useHighlightOffer.ts @@ -5,11 +5,12 @@ import { fetchOffersByEan } from 'libs/algolia/fetchAlgolia/fetchOffersByEan' import { fetchOffersByIds } from 'libs/algolia/fetchAlgolia/fetchOffersByIds' import { fetchOffersByTags } from 'libs/algolia/fetchAlgolia/fetchOffersByTags' import { useTransformOfferHits } from 'libs/algolia/fetchAlgolia/transformOfferHit' +import { AlgoliaGeoloc } from 'libs/algolia/types' import { useLocation } from 'libs/location' import { Position } from 'libs/location/types' import { computeDistanceInMeters } from 'libs/parsers/formatDistance' import { QueryKeys } from 'libs/queryKeys' -import { Offer, OfferLocation } from 'shared/offer/types' +import { Offer } from 'shared/offer/types' type UseHightlightOfferParams = { id: string @@ -104,7 +105,7 @@ export const useHighlightOffer = ({ const shouldDisplayHighlightOffer = ( position: Position, - offerLocation?: OfferLocation, + offerLocation?: AlgoliaGeoloc, isGeolocated?: boolean, aroundRadius?: number ) => { diff --git a/src/features/home/api/useVideoCarouselData.ts b/src/features/home/api/useVideoCarouselData.ts index a4398fa653c..e546060ae88 100644 --- a/src/features/home/api/useVideoCarouselData.ts +++ b/src/features/home/api/useVideoCarouselData.ts @@ -9,7 +9,7 @@ import { fetchCarouselVideoOffers } from 'libs/algolia/fetchAlgolia/fetchCarouse import { buildVideoCarouselOffersQueries } from 'libs/algolia/fetchAlgolia/fetchMultipleOffers/helpers/buildVideoCarouselOffersQueries' import { searchResponsePredicate } from 'libs/algolia/fetchAlgolia/searchResponsePredicate' import { filterOfferHit, useTransformOfferHits } from 'libs/algolia/fetchAlgolia/transformOfferHit' -import { AlgoliaHit, OfferModuleQuery } from 'libs/algolia/types' +import { AlgoliaOffer, OfferModuleQuery } from 'libs/algolia/types' import { useLocation } from 'libs/location' import { QueryKeys } from 'libs/queryKeys' import { Offer } from 'shared/offer/types' @@ -31,7 +31,7 @@ const getRedirectionMode = (item: VideoCarouselItem): RedirectionMode => { const mapDataAndItem = ( offersResultList: UseQueryResult[], unknown>, - transformOfferHits: (hit: AlgoliaHit) => AlgoliaHit + transformOfferHits: (hit: AlgoliaOffer) => AlgoliaOffer ) => { const { data } = offersResultList diff --git a/src/features/home/api/useVideoOffers.native.test.ts b/src/features/home/api/useVideoOffers.native.test.ts index f9dcbaa7318..067ba251818 100644 --- a/src/features/home/api/useVideoOffers.native.test.ts +++ b/src/features/home/api/useVideoOffers.native.test.ts @@ -70,7 +70,7 @@ describe('useVideoOffers', () => { }) it('should return offers when only OffersModuleParameters are provided', async () => { - mockFetchMultipleOffers.mockResolvedValueOnce({ hits: mockOffers, nbHits: 6 }) + mockFetchMultipleOffers.mockResolvedValueOnce([{ hits: mockOffers, nbHits: 6 }]) const { result } = renderHook( () => useVideoOffers([{}] as OffersModuleParameters[], 'moduleId', undefined, undefined), diff --git a/src/features/home/api/useVideoOffers.ts b/src/features/home/api/useVideoOffers.ts index 6be1e301cb5..697debd3f7b 100644 --- a/src/features/home/api/useVideoOffers.ts +++ b/src/features/home/api/useVideoOffers.ts @@ -74,7 +74,7 @@ export const useVideoOffers = ( isUserUnderage, }) - return result.hits + return result.flatMap((data) => data.hits) } const queryByQueryMode = { [QueryMode.OFFER_IDS]: offersByIdsQuery, diff --git a/src/features/offer/api/fetchOffersByArtist/fetchOffersByArtist.test.ts b/src/features/offer/api/fetchOffersByArtist/fetchOffersByArtist.test.ts index cdc5d72ae97..eaf4a319fe6 100644 --- a/src/features/offer/api/fetchOffersByArtist/fetchOffersByArtist.test.ts +++ b/src/features/offer/api/fetchOffersByArtist/fetchOffersByArtist.test.ts @@ -2,12 +2,12 @@ import { SearchResponse } from '@algolia/client-search' import { SearchGroupNameEnumv2 } from 'api/gen' import { - HitOfferWithArtistAndEan, buildAlgoliaFilter, fetchOffersByArtist, } from 'features/offer/api/fetchOffersByArtist/fetchOffersByArtist' import { offerAttributesToRetrieve } from 'libs/algolia/fetchAlgolia/buildAlgoliaParameters/offerAttributesToRetrieve' import * as multipleQueries from 'libs/algolia/fetchAlgolia/multipleQueries' +import { AlgoliaOfferWithArtistAndEan } from 'libs/algolia/types' import { Position } from 'libs/location' const mockMultipleQueries = jest.spyOn(multipleQueries, 'multipleQueries') @@ -19,10 +19,10 @@ describe('fetchOffersByArtist', () => { mockMultipleQueries.mockResolvedValueOnce([ { hits: [], - } as unknown as SearchResponse, + } as unknown as SearchResponse, { hits: [], - } as unknown as SearchResponse, + } as unknown as SearchResponse, ]) await fetchOffersByArtist({ artists: 'Eiichiro Oda', diff --git a/src/features/offer/api/fetchOffersByArtist/fetchOffersByArtist.ts b/src/features/offer/api/fetchOffersByArtist/fetchOffersByArtist.ts index ca10b9bb217..6717438ace0 100644 --- a/src/features/offer/api/fetchOffersByArtist/fetchOffersByArtist.ts +++ b/src/features/offer/api/fetchOffersByArtist/fetchOffersByArtist.ts @@ -5,9 +5,9 @@ import { EXCLUDED_ARTISTS } from 'features/offer/helpers/constants' import { captureAlgoliaError } from 'libs/algolia/fetchAlgolia/AlgoliaError' import { offerAttributesToRetrieve } from 'libs/algolia/fetchAlgolia/buildAlgoliaParameters/offerAttributesToRetrieve' import { multipleQueries } from 'libs/algolia/fetchAlgolia/multipleQueries' +import { AlgoliaOfferWithArtistAndEan } from 'libs/algolia/types' import { env } from 'libs/environment/env' import { Position } from 'libs/location' -import { HitOffer, Offer } from 'shared/offer/types' type BuildAlgoliaFilterType = { artists?: string | null @@ -18,13 +18,6 @@ export type FetchOfferByArtist = BuildAlgoliaFilterType & { userLocation: Position } -export type HitOfferWithArtistAndEan = Offer & { - offer: HitOffer & { - artist: string - ean: string - } -} - export const fetchOffersByArtist = async ({ artists, searchGroupName, @@ -75,9 +68,11 @@ export const fetchOffersByArtist = async ({ return { playlistHits: [], topOffersHits: [] } try { - const [playlistResponse, topOffersResponse] = (await multipleQueries( - queries - )) as [SearchResponse, SearchResponse] + const [playlistResponse, topOffersResponse] = + (await multipleQueries(queries)) as [ + SearchResponse, + SearchResponse, + ] return { playlistHits: playlistResponse.hits, topOffersHits: topOffersResponse.hits } } catch (error) { diff --git a/src/features/offer/api/useAlgoliaSimilarOffers.ts b/src/features/offer/api/useAlgoliaSimilarOffers.ts index e961cbfed7a..884ac785aef 100644 --- a/src/features/offer/api/useAlgoliaSimilarOffers.ts +++ b/src/features/offer/api/useAlgoliaSimilarOffers.ts @@ -4,7 +4,7 @@ import { useQuery } from 'react-query' import { useIsUserUnderage } from 'features/profile/helpers/useIsUserUnderage' import { fetchOffersByIds } from 'libs/algolia/fetchAlgolia/fetchOffersByIds' import { filterOfferHit, useTransformOfferHits } from 'libs/algolia/fetchAlgolia/transformOfferHit' -import { IncompleteSearchHit } from 'libs/algolia/types' +import { AlgoliaOffer } from 'libs/algolia/types' import { QueryKeys } from 'libs/queryKeys' import { getSimilarOrRecoOffersInOrder } from 'shared/offer/getSimilarOrRecoOffersInOrder' import { Offer } from 'shared/offer/types' @@ -27,9 +27,9 @@ export const useAlgoliaSimilarOffers = ( if (shouldPreserveIdsOrder) { const offers = getSimilarOrRecoOffersInOrder(ids, hits) - return (offers as IncompleteSearchHit[]).filter(filterOfferHit).map(transformHits) as Offer[] + return (offers as AlgoliaOffer[]).filter(filterOfferHit).map(transformHits) as Offer[] } - return (hits as IncompleteSearchHit[]).filter(filterOfferHit).map(transformHits) as Offer[] + return (hits as AlgoliaOffer[]).filter(filterOfferHit).map(transformHits) as Offer[] }, [hits, ids, shouldPreserveIdsOrder, transformHits]) } diff --git a/src/features/offer/components/OfferPlaylist/OfferPlaylist.tsx b/src/features/offer/components/OfferPlaylist/OfferPlaylist.tsx index a8dac41e95c..7aa71a58ad3 100644 --- a/src/features/offer/components/OfferPlaylist/OfferPlaylist.tsx +++ b/src/features/offer/components/OfferPlaylist/OfferPlaylist.tsx @@ -2,13 +2,13 @@ import React from 'react' import { View } from 'react-native' import styled from 'styled-components/native' -import { HitOfferWithArtistAndEan } from 'features/offer/api/fetchOffersByArtist/fetchOffersByArtist' import { PlaylistType } from 'features/offer/enums' +import { AlgoliaOfferWithArtistAndEan } from 'libs/algolia/types' import { Offer } from 'shared/offer/types' import { PassPlaylist } from 'ui/components/PassPlaylist' interface OfferPlaylistProps { - items: Offer[] | HitOfferWithArtistAndEan[] + items: Offer[] | AlgoliaOfferWithArtistAndEan[] renderItem: (props: { item: Offer width: number @@ -22,7 +22,7 @@ interface OfferPlaylistProps { onEndReached?: () => void } -const keyExtractor = (item: Offer | HitOfferWithArtistAndEan) => item.objectID +const keyExtractor = (item: Offer | AlgoliaOfferWithArtistAndEan) => item.objectID export function OfferPlaylist({ items, diff --git a/src/features/offer/helpers/useArtistResults/useArtistResults.tsx b/src/features/offer/helpers/useArtistResults/useArtistResults.tsx index ed0f0910b27..0fd0021459a 100644 --- a/src/features/offer/helpers/useArtistResults/useArtistResults.tsx +++ b/src/features/offer/helpers/useArtistResults/useArtistResults.tsx @@ -3,11 +3,9 @@ import { useCallback, useMemo } from 'react' import { useQuery } from 'react-query' import { SearchGroupNameEnumv2 } from 'api/gen' -import { - HitOfferWithArtistAndEan, - fetchOffersByArtist, -} from 'features/offer/api/fetchOffersByArtist/fetchOffersByArtist' +import { fetchOffersByArtist } from 'features/offer/api/fetchOffersByArtist/fetchOffersByArtist' import { useTransformOfferHits } from 'libs/algolia/fetchAlgolia/transformOfferHit' +import { AlgoliaOfferWithArtistAndEan } from 'libs/algolia/types' import { useLocation } from 'libs/location' import { formatDistance } from 'libs/parsers/formatDistance' import { QueryKeys } from 'libs/queryKeys' @@ -37,7 +35,7 @@ export const useArtistResults = ({ artists, searchGroupName }: UseArtistResultsP ) const getSortedHits = useCallback( - (hits: Hit[]) => { + (hits: Hit[]) => { if (hits.length === 0) return [] const transformedHitsWithDistance = hits.map((hit) => { @@ -54,7 +52,7 @@ export const useArtistResults = ({ artists, searchGroupName }: UseArtistResultsP return sortedHits.map( ({ distance: _distance, ...rest }) => rest - ) as HitOfferWithArtistAndEan[] + ) as AlgoliaOfferWithArtistAndEan[] }, [transformHits, userLocation] ) diff --git a/src/features/offer/types.ts b/src/features/offer/types.ts index bfeaa926554..09ba59f30c7 100644 --- a/src/features/offer/types.ts +++ b/src/features/offer/types.ts @@ -10,14 +10,14 @@ import { import { ChronicleCardData } from 'features/chronicle/type' import { Referrals } from 'features/navigation/RootNavigator/types' import { PlaylistType } from 'features/offer/enums' +import { AlgoliaGeoloc } from 'libs/algolia/types' import { Subcategory } from 'libs/subcategories/types' -import { OfferLocation } from 'shared/offer/types' export interface OfferTileProps { categoryId: CategoryIdEnum | null | undefined categoryLabel: string | null subcategoryId: SubcategoryIdEnum - offerLocation: OfferLocation + offerLocation: AlgoliaGeoloc date?: string name?: string isDuo?: boolean diff --git a/src/features/search/pages/ThematicSearch/types.ts b/src/features/search/pages/ThematicSearch/types.ts index b0fb924d5f6..5d745eb7b90 100644 --- a/src/features/search/pages/ThematicSearch/types.ts +++ b/src/features/search/pages/ThematicSearch/types.ts @@ -1,6 +1,6 @@ -import { AlgoliaHit } from 'libs/algolia/types' +import { AlgoliaOffer } from 'libs/algolia/types' export type ThematicSearchPlaylistData = { title: string - offers: { hits: AlgoliaHit[] } + offers: { hits: AlgoliaOffer[] } } diff --git a/src/features/venue/api/useVenueOffers.test.ts b/src/features/venue/api/useVenueOffers.test.ts index d4f6abfee31..ad24207ea11 100644 --- a/src/features/venue/api/useVenueOffers.test.ts +++ b/src/features/venue/api/useVenueOffers.test.ts @@ -131,6 +131,37 @@ const EXPECTED_CALL_PARAM = { }, }, }, + { + locationParams: { + aroundMeRadius: 100, + aroundPlaceRadius: 100, + selectedLocationMode: 'AROUND_ME', + userLocation: { latitude: 48.90374, longitude: 2.48171 }, + }, + offerParams: { + beginningDatetime: undefined, + date: null, + endingDatetime: undefined, + hitsPerPage: 50, + isDigital: false, + isHeadline: true, + locationFilter: { locationType: 'EVERYWHERE' }, + offerCategories: [], + offerIsDuo: false, + offerIsFree: false, + offerSubcategories: [], + priceRange: [0, 300], + query: '', + tags: [], + timeRange: null, + venue: { + _geoloc: { lat: 48.8536, lng: 2.34199 }, + info: 'PARIS 6', + label: 'Cinéma St André des Arts', + venueId: 26235, + }, + }, + }, ], } @@ -143,10 +174,12 @@ describe('useVenueOffers', () => { }) it('should return empty artists when there are no offers', async () => { - mockFetchMultipleOffers.mockResolvedValueOnce({ - hits: [], - nbHits: 0, - }) + mockFetchMultipleOffers.mockResolvedValueOnce([ + { + hits: [], + nbHits: 0, + }, + ]) const { result } = renderHook(() => useVenueOffers(mockVenueResponse), { wrapper: ({ children }) => reactQueryProviderHOC(children), @@ -158,34 +191,36 @@ describe('useVenueOffers', () => { }) it('should return artists after filtering and transforming hits', async () => { - mockFetchMultipleOffers.mockResolvedValueOnce({ - hits: [ - { - offer: { - dates: [], - isDigital: false, - isDuo: false, - name: 'I want something more', - prices: [28.0], - subcategoryId: SubcategoryIdEnum.CONCERT, - thumbUrl: - 'https://storage.googleapis.com/passculture-metier-prod-production-assets-fine-grained/thumbs/mediations/CDZQ', - artist: 'Céline Dion', - }, - _geoloc: { lat: 4.90339, lng: -52.31663 }, - objectID: '102310', - venue: { - id: 4, - name: 'Lieu 4', - publicName: 'Lieu 4', - address: '4 rue de la paix', - postalCode: '75000', - city: 'Paris', + mockFetchMultipleOffers.mockResolvedValueOnce([ + { + hits: [ + { + offer: { + dates: [], + isDigital: false, + isDuo: false, + name: 'I want something more', + prices: [28.0], + subcategoryId: SubcategoryIdEnum.CONCERT, + thumbUrl: + 'https://storage.googleapis.com/passculture-metier-prod-production-assets-fine-grained/thumbs/mediations/CDZQ', + artist: 'Céline Dion', + }, + _geoloc: { lat: 4.90339, lng: -52.31663 }, + objectID: '102310', + venue: { + id: 4, + name: 'Lieu 4', + publicName: 'Lieu 4', + address: '4 rue de la paix', + postalCode: '75000', + city: 'Paris', + }, }, - }, - ], - nbHits: 1, - }) + ], + nbHits: 1, + }, + ]) const { result } = renderHook(() => useVenueOffers(mockVenueResponse), { wrapper: ({ children }) => reactQueryProviderHOC(children), diff --git a/src/features/venue/api/useVenueOffers.ts b/src/features/venue/api/useVenueOffers.ts index 5e7728239b4..72b12d2bf39 100644 --- a/src/features/venue/api/useVenueOffers.ts +++ b/src/features/venue/api/useVenueOffers.ts @@ -14,7 +14,6 @@ import { SearchQueryParameters } from 'libs/algolia/types' import { env } from 'libs/environment/env' import { useLocation } from 'libs/location' import { QueryKeys } from 'libs/queryKeys' -import { Offer } from 'shared/offer/types' export const useVenueOffers = (venue?: VenueResponse): UseQueryResult => { // TODO(PC-33493): hook refacto @@ -24,7 +23,7 @@ export const useVenueOffers = (venue?: VenueResponse): UseQueryResult ({ locationParams: { userLocation, @@ -37,31 +36,38 @@ export const useVenueOffers = (venue?: VenueResponse): UseQueryResult fetchMultipleOffers({ - paramsList: [ - buildPlaylistOfferParams({ - ...searchState, - venue: venueSearchParams.venue, - hitsPerPage: venueSearchParams.hitsPerPage, - }), - buildPlaylistOfferParams(venueSearchParams), - ], + paramsList, isUserUnderage, indexName: env.ALGOLIA_TOP_OFFERS_INDEX_NAME, }), { enabled: !!venue, - select: ({ hits, nbHits }) => { - const filteredHits = hits.filter(filterOfferHit).map(transformHits) + select: ([venueSearchedOffersResults, venueTopOffersResults, headlineOfferResults]) => { + const hits = [venueSearchedOffersResults, venueTopOffersResults] + .flatMap((result) => result?.hits) + .filter(filterOfferHit) + .map(transformHits) - const offers = filteredHits.filter((hit): hit is Offer => hit !== null) + const headlineOffer = headlineOfferResults?.hits[0] return { - hits: uniqBy(offers, 'objectID'), - nbHits, + hits: uniqBy(hits, 'objectID'), + nbHits: hits.length, + headlineOffer, } }, } diff --git a/src/features/venue/components/VenueBody/VenueBody.tsx b/src/features/venue/components/VenueBody/VenueBody.tsx index c1da958bf7f..1f96c9a4463 100644 --- a/src/features/venue/components/VenueBody/VenueBody.tsx +++ b/src/features/venue/components/VenueBody/VenueBody.tsx @@ -16,7 +16,6 @@ import { useLocation } from 'libs/location' import { useCategoryHomeLabelMapping, useCategoryIdMapping } from 'libs/subcategories' import { useGetCurrencyToDisplay } from 'shared/currency/useGetCurrencyToDisplay' import { useGetPacificFrancToEuroRate } from 'shared/exchangeRates/useGetPacificFrancToEuroRate' -import { offersFixture } from 'shared/offer/offer.fixture' import { SectionWithDivider } from 'ui/components/SectionWithDivider' import { ViewGap } from 'ui/components/ViewGap/ViewGap' import { TypoDS, getSpacing } from 'ui/theme' @@ -47,8 +46,7 @@ export const VenueBody: FunctionComponent = ({ const SectionContainer = isLargeScreen ? View : SectionWithDivider const headlineData = offerToHeadlineOfferData({ - // Fake data to remove - offer: offersFixture[0], + offer: venueOffers?.headlineOffer ?? null, transformParameters: { currency, euroToPacificFrancRate, diff --git a/src/features/venue/types.ts b/src/features/venue/types.ts index 3b659c03930..3aa50e61e1b 100644 --- a/src/features/venue/types.ts +++ b/src/features/venue/types.ts @@ -60,6 +60,7 @@ export type TabType = { export type VenueOffers = { hits: Offer[] nbHits: number + headlineOffer?: Offer } export type Artist = { diff --git a/src/libs/algolia/enums/facetsEnums.ts b/src/libs/algolia/enums/facetsEnums.ts index 7ada8e7b7f3..866db8db398 100644 --- a/src/libs/algolia/enums/facetsEnums.ts +++ b/src/libs/algolia/enums/facetsEnums.ts @@ -11,6 +11,7 @@ export enum FACETS_FILTERS_ENUM { OFFER_IS_DUO = 'offer.isDuo', OFFER_IS_EDUCATIONAL = 'offer.isEducational', OFFER_IS_EVENT = 'offer.isEvent', + OFFER_IS_HEADLINE = 'offer.isHeadline', OFFER_IS_THING = 'offer.isThing', OFFER_MOVIE_GENRES = 'offer.movieGenres', OFFER_MUSIC_TYPE = 'offer.musicType', @@ -27,6 +28,7 @@ export enum FACETS_FILTERS_ENUM { } export enum NUMERIC_FILTERS_ENUM { + OFFER_IS_HEADLINE_UNTIL = 'offer.isHeadlineUntil', OFFER_PRICES = 'offer.prices', OFFER_DATES = 'offer.dates', OFFER_TIMES = 'offer.times', diff --git a/src/libs/algolia/fetchAlgolia/buildAlgoliaParameters/buildFacetFilters.ts b/src/libs/algolia/fetchAlgolia/buildAlgoliaParameters/buildFacetFilters.ts index 7d076413136..096798cd7ea 100644 --- a/src/libs/algolia/fetchAlgolia/buildAlgoliaParameters/buildFacetFilters.ts +++ b/src/libs/algolia/fetchAlgolia/buildAlgoliaParameters/buildFacetFilters.ts @@ -4,6 +4,7 @@ import { buildAccessibiltyFiltersPredicate, buildAllocineIdPredicate, buildEanPredicate, + buildHeadlinePredicate, buildObjectIdsPredicate, buildOfferCategoriesPredicate, buildOfferGenreTypesPredicate, @@ -25,6 +26,7 @@ export const buildFacetFilters = ({ allocineId, isUserUnderage, objectIds, + isHeadline, offerCategories, offerGenreTypes, offerGtlLabel, @@ -49,6 +51,7 @@ export const buildFacetFilters = ({ | 'isDigital' | 'tags' | 'gtls' + | 'isHeadline' > & { isUserUnderage: boolean objectIds?: string[] @@ -124,5 +127,11 @@ export const buildFacetFilters = ({ const accessibilityFilters = buildAccessibiltyFiltersPredicate(disabilitiesProperties) facetFilters.push(...accessibilityFilters) } + + if (isHeadline) { + const isHeadlineFilter = buildHeadlinePredicate(isHeadline) + facetFilters.push(isHeadlineFilter) + } + return { facetFilters } } diff --git a/src/libs/algolia/fetchAlgolia/buildAlgoliaParameters/buildNumericFilters.ts b/src/libs/algolia/fetchAlgolia/buildAlgoliaParameters/buildNumericFilters.ts index 2dd6cc36be7..4703108a0fd 100644 --- a/src/libs/algolia/fetchAlgolia/buildAlgoliaParameters/buildNumericFilters.ts +++ b/src/libs/algolia/fetchAlgolia/buildAlgoliaParameters/buildNumericFilters.ts @@ -1,5 +1,6 @@ import { buildDatePredicate, + buildHeadlineUntilPredicate, buildHomepageDatePredicate, buildOfferLast30DaysBookings, buildOfferPriceRangePredicate, @@ -17,6 +18,7 @@ export const buildNumericFilters = ({ maxPrice, maxPossiblePrice, minBookingsThreshold, + isHeadline, }: Pick< SearchQueryParameters, | 'beginningDatetime' @@ -29,6 +31,7 @@ export const buildNumericFilters = ({ | 'maxPrice' | 'maxPossiblePrice' | 'minBookingsThreshold' + | 'isHeadline' >): null | { numericFilters: FiltersArray } => { @@ -42,12 +45,14 @@ export const buildNumericFilters = ({ const datePredicate = buildDatePredicate({ date, timeRange }) const homepageDatePredicate = buildHomepageDatePredicate({ beginningDatetime, endingDatetime }) const last30DaysBookingsPredicate = buildOfferLast30DaysBookings(minBookingsThreshold) + const headlineUntilPredicate = buildHeadlineUntilPredicate(isHeadline) const numericFilters: FiltersArray = [] if (priceRangePredicate) numericFilters.push(priceRangePredicate) if (datePredicate) numericFilters.push(datePredicate) if (homepageDatePredicate) numericFilters.push(homepageDatePredicate) if (last30DaysBookingsPredicate) numericFilters.push(last30DaysBookingsPredicate) + if (headlineUntilPredicate) numericFilters.push(headlineUntilPredicate) return numericFilters.length > 0 ? { numericFilters } : null } diff --git a/src/libs/algolia/fetchAlgolia/buildAlgoliaParameters/buildOfferSearchParameters.ts b/src/libs/algolia/fetchAlgolia/buildAlgoliaParameters/buildOfferSearchParameters.ts index 814032137df..68e0c3754f4 100644 --- a/src/libs/algolia/fetchAlgolia/buildAlgoliaParameters/buildOfferSearchParameters.ts +++ b/src/libs/algolia/fetchAlgolia/buildAlgoliaParameters/buildOfferSearchParameters.ts @@ -25,6 +25,7 @@ export const buildOfferSearchParameters = ( endingDatetime = undefined, excludedObjectIds = [], isFullyDigitalOffersCategory = false, + isHeadline = false, maxPossiblePrice = '', maxPrice = '', minBookingsThreshold = 0, @@ -72,6 +73,7 @@ export const buildOfferSearchParameters = ( tags, gtls, disabilitiesProperties, + isHeadline, }), ...buildNumericFilters({ beginningDatetime, @@ -84,6 +86,7 @@ export const buildOfferSearchParameters = ( offerIsFree, priceRange, timeRange, + isHeadline, }), ...locationParameter, ...buildFilters({ excludedObjectIds }), diff --git a/src/libs/algolia/fetchAlgolia/buildAlgoliaParameters/helpers/buildFacetFiltersHelpers/buildFacetFiltersHelpers.ts b/src/libs/algolia/fetchAlgolia/buildAlgoliaParameters/helpers/buildFacetFiltersHelpers/buildFacetFiltersHelpers.ts index 578f5acb7db..65af8b9f010 100644 --- a/src/libs/algolia/fetchAlgolia/buildAlgoliaParameters/helpers/buildFacetFiltersHelpers/buildFacetFiltersHelpers.ts +++ b/src/libs/algolia/fetchAlgolia/buildAlgoliaParameters/helpers/buildFacetFiltersHelpers/buildFacetFiltersHelpers.ts @@ -82,6 +82,10 @@ export const buildTagsPredicate = ( return undefined } +export const buildHeadlinePredicate = (isHeadline: boolean) => [ + `${FACETS_FILTERS_ENUM.OFFER_IS_HEADLINE}:${isHeadline.toString()}`, +] + export const buildAccessibiltyFiltersPredicate = ({ isAudioDisabilityCompliant, isMentalDisabilityCompliant, diff --git a/src/libs/algolia/fetchAlgolia/buildAlgoliaParameters/helpers/buildNumericFiltersHelpers/buildNumericFiltersHelpers.ts b/src/libs/algolia/fetchAlgolia/buildAlgoliaParameters/helpers/buildNumericFiltersHelpers/buildNumericFiltersHelpers.ts index d053bcec20d..df70802d340 100644 --- a/src/libs/algolia/fetchAlgolia/buildAlgoliaParameters/helpers/buildNumericFiltersHelpers/buildNumericFiltersHelpers.ts +++ b/src/libs/algolia/fetchAlgolia/buildAlgoliaParameters/helpers/buildNumericFiltersHelpers/buildNumericFiltersHelpers.ts @@ -137,3 +137,8 @@ export const buildDateOnlyPredicate = ( export const getDatePredicate = (lowerDate: number, higherDate: number): string => `${NUMERIC_FILTERS_ENUM.OFFER_DATES}: ${lowerDate} TO ${higherDate}` + +export const buildHeadlineUntilPredicate = (isHeadline?: boolean) => + isHeadline + ? [`${NUMERIC_FILTERS_ENUM.OFFER_IS_HEADLINE_UNTIL} >= ${TIMESTAMP.getFromDate(new Date())}`] + : undefined diff --git a/src/libs/algolia/fetchAlgolia/fetchMultipleOffers/fetchMultipleOffers.ts b/src/libs/algolia/fetchAlgolia/fetchMultipleOffers/fetchMultipleOffers.ts index 67e4cf9aca0..198f772a6ca 100644 --- a/src/libs/algolia/fetchAlgolia/fetchMultipleOffers/fetchMultipleOffers.ts +++ b/src/libs/algolia/fetchAlgolia/fetchMultipleOffers/fetchMultipleOffers.ts @@ -1,13 +1,11 @@ -import flatten from 'lodash/flatten' - import { PlaylistOffersParams } from 'features/home/types' -import { VenueOffers } from 'features/venue/types' import { captureAlgoliaError } from 'libs/algolia/fetchAlgolia/AlgoliaError' import { buildOfferSearchParameters } from 'libs/algolia/fetchAlgolia/buildAlgoliaParameters/buildOfferSearchParameters' import { offerAttributesToRetrieve } from 'libs/algolia/fetchAlgolia/buildAlgoliaParameters/offerAttributesToRetrieve' import { multipleQueries } from 'libs/algolia/fetchAlgolia/multipleQueries' import { searchResponsePredicate } from 'libs/algolia/fetchAlgolia/searchResponsePredicate' import { buildHitsPerPage } from 'libs/algolia/fetchAlgolia/utils' +import { MultipleOffersResult } from 'libs/algolia/types' import { env } from 'libs/environment/env' import { Offer } from 'shared/offer/types' @@ -15,13 +13,14 @@ type FetchMultipleOffersArgs = { paramsList: PlaylistOffersParams[] isUserUnderage: boolean indexName?: string + venueId?: number } export const fetchMultipleOffers = async ({ paramsList, isUserUnderage, indexName = env.ALGOLIA_OFFERS_INDEX_NAME, -}: FetchMultipleOffersArgs): Promise => { +}: FetchMultipleOffersArgs): Promise => { const queries = paramsList.map((params) => ({ indexName, query: params.offerParams.query, @@ -29,7 +28,7 @@ export const fetchMultipleOffers = async ({ ...buildHitsPerPage(params.offerParams.hitsPerPage), ...buildOfferSearchParameters(params.offerParams, params.locationParams, isUserUnderage), attributesToHighlight: [], // We disable highlighting because we don't need it - attributesToRetrieve: offerAttributesToRetrieve, + attributesToRetrieve: [...offerAttributesToRetrieve, 'offer.isHeadline'], }, })) @@ -37,12 +36,25 @@ export const fetchMultipleOffers = async ({ const results = await multipleQueries(queries) const searchResponseResults = results.filter(searchResponsePredicate) + /* + results renvoie un tableau avec 3 objet ce qui nous intéresse c'est + de prendre le dernier qui est notre ajout à la requête + Et ensuite il faut récupérer le premier objet dans hits qui est notre offer + qui est l'offre à la une + */ + + /* const headlineResponse = searchResponseResults.at(-1) + const headlineOffer = headlineResponse?.hits?.[0] + return { hits: flatten(searchResponseResults.map(({ hits }) => hits)), nbHits: searchResponseResults.reduce((prev, curr) => prev + curr.nbHits, 0), - } + headlineOffer, + } */ + + return searchResponseResults } catch (error) { captureAlgoliaError(error) - return { hits: [] as Offer[], nbHits: 0 } + return [] } } diff --git a/src/libs/algolia/fetchAlgolia/fetchMultipleOffers/todo.md b/src/libs/algolia/fetchAlgolia/fetchMultipleOffers/todo.md new file mode 100644 index 00000000000..388821fdb2d --- /dev/null +++ b/src/libs/algolia/fetchAlgolia/fetchMultipleOffers/todo.md @@ -0,0 +1,20 @@ +# TODO + +## Links + +- [PC-TicketNumber](https://passculture.atlassian.net/browse/PC-TicketNumber) +- [MobTime](https://mobtime.hadrienmp.fr/mob/pass-culture) + +--- + +## Tasks + +- [ ] Compléter et ajuster les tests nécesaire +- [ ] Gérer le champ isHeadlineUntil par rapport à la timestamps +- [ ] + +--- + +## Tasks for another US + +- [ ] \ No newline at end of file diff --git a/src/libs/algolia/fetchAlgolia/transformOfferHit.ts b/src/libs/algolia/fetchAlgolia/transformOfferHit.ts index 950a007f3af..6a3d89a1bc5 100644 --- a/src/libs/algolia/fetchAlgolia/transformOfferHit.ts +++ b/src/libs/algolia/fetchAlgolia/transformOfferHit.ts @@ -1,28 +1,28 @@ import { useCallback } from 'react' import { useSettingsContext } from 'features/auth/context/SettingsContext' -import { AlgoliaHit, IncompleteSearchHit } from 'libs/algolia/types' +import { AlgoliaOffer, HitOffer } from 'libs/algolia/types' import { convertEuroToCents } from 'libs/parsers/pricesConversion' // Go to https://github.com/pass-culture/pass-culture-api/blob/master/src/pcapi/algolia/infrastructure/builder.py // to see how the data is indexed into the search client (algolia => app search) -type Offer = AlgoliaHit['offer'] +// type HitOffer = AlgoliaHit['offer'] // Prices are stored in euros in Algolia, but retrieved as cents in OfferResponseV2 // To follow good frontend practices (see https://frontstuff.io/how-to-handle-monetary-values-in-javascript) // we convert all prices in Algolia to cents, use cents in the frontend code, // and when we display the prices to the user, we format the price knowing that there are cents. -const convertAlgoliaOfferToCents = (offer: T): T => ({ +const convertAlgoliaOfferToCents = (offer: T): T => ({ ...offer, prices: offer.prices ? offer.prices.map((price) => convertEuroToCents(price)) : undefined, }) // (PC-8526): due to the migration to GCP, we extract the path to the image export const parseThumbUrl = ( - thumbUrl: Offer['thumbUrl'], + thumbUrl: HitOffer['thumbUrl'], urlPrefix?: string -): Offer['thumbUrl'] => { +): HitOffer['thumbUrl'] => { if (!thumbUrl) return undefined if (!urlPrefix) return thumbUrl const [base, suffix] = thumbUrl.split('/thumbs') @@ -32,16 +32,16 @@ export const parseThumbUrl = ( // The _geoloc is hardcoded for digital offers (without position) so that the results appear in the Search: // original PR: https://github.com/pass-culture/pass-culture-api/pull/1334 // Here we dehardcode those coordinates, so that we don't show a wrong distance to the user. -const parseGeoloc = (hit: AlgoliaHit): AlgoliaHit['_geoloc'] => +const parseGeoloc = (hit: AlgoliaOffer): AlgoliaOffer['_geoloc'] => hit.offer.isDigital ? { lat: null, lng: null } : hit._geoloc // We don't want to display offers without image nor subcategoryId -export const filterOfferHit = (hit: IncompleteSearchHit): boolean => - hit?.offer && !!hit.offer.thumbUrl && typeof hit.offer.subcategoryId !== 'undefined' +export const filterOfferHit = (hit?: AlgoliaOffer): hit is AlgoliaOffer => + !!hit && hit?.offer && !!hit.offer.thumbUrl && typeof hit.offer.subcategoryId !== 'undefined' export const transformOfferHit = (urlPrefix?: string) => - (hit: AlgoliaHit): AlgoliaHit => ({ + (hit: AlgoliaOffer): AlgoliaOffer => ({ ...hit, offer: { ...hit.offer, diff --git a/src/libs/algolia/fixtures/algoliaFixtures.ts b/src/libs/algolia/fixtures/algoliaFixtures.ts index 72b62257e4b..8fc7c942797 100644 --- a/src/libs/algolia/fixtures/algoliaFixtures.ts +++ b/src/libs/algolia/fixtures/algoliaFixtures.ts @@ -2,8 +2,7 @@ import { SearchResponse } from '@algolia/client-search' import type { ReadonlyDeep } from 'type-fest' import { SubcategoryIdEnum, VenueTypeCodeKey } from 'api/gen' -import { HitOfferWithArtistAndEan } from 'features/offer/api/fetchOffersByArtist/fetchOffersByArtist' -import { AlgoliaVenue } from 'libs/algolia/types' +import { AlgoliaOfferWithArtistAndEan, AlgoliaVenue } from 'libs/algolia/types' import { Offer } from 'shared/offer/types' import { toMutable } from 'shared/types/toMutable' @@ -1103,4 +1102,4 @@ export const mockedAlgoliaOffersWithSameArtistResponse = toMutable([ }, objectID: '12759', }, -] as const satisfies ReadonlyDeep) +] as const satisfies ReadonlyDeep) diff --git a/src/libs/algolia/types.ts b/src/libs/algolia/types.ts index fb5f552ecdd..4216c3ec7da 100644 --- a/src/libs/algolia/types.ts +++ b/src/libs/algolia/types.ts @@ -16,30 +16,41 @@ import { BooksNativeCategoriesEnum } from 'features/search/types' import { Venue } from 'features/venue/types' import { FACETS_FILTERS_ENUM } from 'libs/algolia/enums/facetsEnums' import { BuildLocationParameterParams } from 'libs/algolia/fetchAlgolia/buildAlgoliaParameters/buildLocationParameter' -import { AlgoliaHit as BaseAlgoliaHit } from 'libs/algolia/types' import { VenueTypeCode } from 'libs/parsers/venueType' import { Range } from 'libs/typesUtils/typeHelpers' import { GtlLevel } from 'shared/gtl/types' -interface AlgoliaGeoloc { +export type HitOffer = { + dates?: number[] + isDigital?: boolean + isDuo?: boolean + isEducational?: boolean + name?: string + prices?: number[] + subcategoryId: SubcategoryIdEnum + thumbUrl?: string + searchGroupName?: SearchGroupNameEnumv2 + releaseDate?: number | string + bookFormat?: string | null + artist?: string + ean?: string + publicationDate?: number +} + +export type AlgoliaOfferWithArtistAndEan = AlgoliaOffer< + HitOffer & { + artist: NonNullable + ean: NonNullable + } +> + +export interface AlgoliaGeoloc { lat?: number | null lng?: number | null } -export interface AlgoliaHit { - offer: { - dates?: number[] - isDigital?: boolean - isDuo?: boolean - isEducational?: boolean - name?: string - prices?: number[] - subcategoryId?: SubcategoryIdEnum - thumbUrl?: string - searchGroupName?: SearchGroupNameEnumv2 - bookFormat?: string | null - artist?: string - } +export interface AlgoliaOffer { + offer: T _geoloc: Geoloc objectID: string venue: { @@ -120,6 +131,7 @@ export type SearchQueryParameters = { maxPrice?: string minBookingsThreshold?: number minPrice?: string + isHeadline?: boolean offerCategories: SearchGroupNameEnumv2[] offerGenreTypes?: OfferGenreType[] offerGtlLabel?: string @@ -141,9 +153,6 @@ export type SearchQueryParameters = { objectIds?: string[] } -// An incomplete search hit may not have a subcategoryId (for retrocompatibility) -export type IncompleteSearchHit = BaseAlgoliaHit - export type Geoloc = AlgoliaGeoloc export type VenueHit = Pick< @@ -243,3 +252,8 @@ export type NativeCategoryFacetData = Record< type GenreTypeFacetData = Record export type FacetData = NativeCategoryFacetData | GenreTypeFacetData + +export type MultipleOffersResult = { + hits: AlgoliaOffer[] + nbHits: number +}[] diff --git a/src/shared/offer/types.ts b/src/shared/offer/types.ts index 2467c257f6c..52988db3323 100644 --- a/src/shared/offer/types.ts +++ b/src/shared/offer/types.ts @@ -1,40 +1,8 @@ -import { RecommendationApiParams, SubcategoryIdEnum } from 'api/gen' +import { RecommendationApiParams } from 'api/gen' import { PlaylistType } from 'features/offer/enums' +import { AlgoliaOffer } from 'libs/algolia/types' -export type OfferLocation = { - lat?: number | null - lng?: number | null -} - -export type HitOffer = { - dates?: number[] - isDigital?: boolean - isDuo?: boolean - isEducational?: boolean - name?: string - prices?: number[] - subcategoryId: SubcategoryIdEnum - thumbUrl?: string - releaseDate?: number | string - bookFormat?: string | null - artist?: string - publicationDate?: number -} - -export interface Offer { - offer: HitOffer - objectID: string - _geoloc: OfferLocation - venue: { - departmentCode?: string - id?: number - name?: string - publicName?: string - address?: string - postalCode?: string - city?: string - } -} +export type Offer = AlgoliaOffer export type SimilarOfferPlaylist = { type: PlaylistType