diff --git a/src/config/lexics/indexLexics.tsx b/src/config/lexics/indexLexics.tsx index 45a3b65f..d828d2fa 100644 --- a/src/config/lexics/indexLexics.tsx +++ b/src/config/lexics/indexLexics.tsx @@ -47,6 +47,7 @@ const buyMatchPopupLexics = { for_month: 13561, for_view: 15064, for_year: 13562, + next_choose: 15156, pass_league: 15065, pass_match_access: 15067, pass_team: 15066, diff --git a/src/features/BuyMatchPopup/components/SelectSubscription/index.tsx b/src/features/BuyMatchPopup/components/SelectSubscription/index.tsx new file mode 100644 index 00000000..6b12f02e --- /dev/null +++ b/src/features/BuyMatchPopup/components/SelectSubscription/index.tsx @@ -0,0 +1,118 @@ +import { useState } from 'react' + +import styled from 'styled-components/macro' + +import map from 'lodash/map' + +import { MDASH } from 'config' +import { SelectSubscriptionData } from 'requests' + +import { Name as Names } from 'features/Name' +import { T9n } from 'features/T9n' +import { useBuyMatchPopupStore } from 'features/BuyMatchPopup/store' +import { CloseButton, HeaderActions } from 'features/PopupComponents' +import { ArrowLoader } from 'features/ArrowLoader' + +import { + Body, + Button, + Footer, + Header, + HeaderTitle, + Wrapper, +} from 'features/BuyMatchPopup/styled' +import { + Description, + InfoWrapper, + Item, + List, + Name, + Pass, +} from '../SubscriptionsList/styled' + +export const ChooseSub = styled.div` + font-weight: 600; + font-size: 16px; + margin: 30px 0; +` + +export const SelectSubscriptionStep = () => { + const [active, setActive] = useState(null) + + const { + close, + initialSubscription, + loader, + match, + onChooseSub, + onSubscriptionPackagesSelect, + selectedSubscriptionPackage, + setSelectSubName, + } = useBuyMatchPopupStore() + + if (!match || !initialSubscription) return null + + const onItemClick = (subscription: SelectSubscriptionData, index: number) => { + onSubscriptionPackagesSelect({ + ...subscription.packages, + season: initialSubscription.season, + }) + setActive(index) + setSelectSubName(subscription.lexic) + } + + return ( + +
+ + + {` ${MDASH} `} + + + + + + + + +
+ + + { + map(initialSubscription.data, (subscription, index) => ( + onItemClick(subscription, index)} + active={active === index} + > + + + + + + + + + + + + + )) + } + + +
+ {loader + ? + : ( + + )} +
+
+ ) +} diff --git a/src/features/BuyMatchPopup/components/SubscriptionSelectionStep/index.tsx b/src/features/BuyMatchPopup/components/SubscriptionSelectionStep/index.tsx index 14a694f4..6637ea7d 100644 --- a/src/features/BuyMatchPopup/components/SubscriptionSelectionStep/index.tsx +++ b/src/features/BuyMatchPopup/components/SubscriptionSelectionStep/index.tsx @@ -1,4 +1,4 @@ -import { useEffect } from 'react' +import { Fragment, useEffect } from 'react' import isNull from 'lodash/isNull' @@ -21,6 +21,7 @@ import { Body, Footer, Button, + ButtonPrevious, Header, HeaderTitle, } from '../../styled' @@ -33,10 +34,13 @@ export const SubscriptionSelectionStep = () => { const { close, + getSub, loader, match, onBuyClick, + selectedSubName, selectedSubscription, + selectedSubStep, } = useBuyMatchPopupStore() useEffect(() => { @@ -50,10 +54,25 @@ export const SubscriptionSelectionStep = () => { return (
+ {selectedSubStep + && ( + + + + )} - - {` ${MDASH} `} - + {selectedSubStep + ? + : ( + + + {` ${MDASH} `} + + + )} diff --git a/src/features/BuyMatchPopup/components/SubscriptionsList/styled.tsx b/src/features/BuyMatchPopup/components/SubscriptionsList/styled.tsx index b382a08f..2d1fc843 100644 --- a/src/features/BuyMatchPopup/components/SubscriptionsList/styled.tsx +++ b/src/features/BuyMatchPopup/components/SubscriptionsList/styled.tsx @@ -63,6 +63,7 @@ export const Item = styled.li.attrs(() => ({ justify-content: space-between; align-items: center; cursor: pointer; + overflow: auto; :not(:last-child) { margin-bottom: 20px; diff --git a/src/features/BuyMatchPopup/index.tsx b/src/features/BuyMatchPopup/index.tsx index 6b88dd38..bee6cac0 100644 --- a/src/features/BuyMatchPopup/index.tsx +++ b/src/features/BuyMatchPopup/index.tsx @@ -2,6 +2,7 @@ import { CardStep } from './components/CardStep' import { ErrorStep } from './components/ErrorStep' import { SuccessStep } from './components/SuccessStep' import { SubscriptionSelectionStep } from './components/SubscriptionSelectionStep' +import { SelectSubscriptionStep } from './components/SelectSubscription' import { Steps } from './types' import { Modal } from './styled' @@ -15,6 +16,7 @@ const components = { [Steps.CardSelection]: CardStep, [Steps.Success]: SuccessStep, [Steps.Error]: ErrorStep, + [Steps.SelectSubscription]: SelectSubscriptionStep, } export const BuyMatchPopup = () => { diff --git a/src/features/BuyMatchPopup/store/helpers.tsx b/src/features/BuyMatchPopup/store/helpers.tsx index aff6f9a7..193d2e62 100644 --- a/src/features/BuyMatchPopup/store/helpers.tsx +++ b/src/features/BuyMatchPopup/store/helpers.tsx @@ -50,7 +50,7 @@ const transformSubscription = ({ team: teamName, }, }, - id: `${key} ${subscription.id}`, + id: `${key} ${subscription.sub.id}`, name: teamName, originalObject: subscription, pass: passLexics[key], diff --git a/src/features/BuyMatchPopup/store/hooks/index.tsx b/src/features/BuyMatchPopup/store/hooks/index.tsx index 44d6e175..99988e3d 100644 --- a/src/features/BuyMatchPopup/store/hooks/index.tsx +++ b/src/features/BuyMatchPopup/store/hooks/index.tsx @@ -9,6 +9,7 @@ import { useHistory } from 'react-router-dom' import type { PaymentIntent, StripeError } from '@stripe/stripe-js' import last from 'lodash/last' +import isEmpty from 'lodash/isEmpty' import { PAGES, ProfileTypes } from 'config' @@ -48,6 +49,8 @@ export const useBuyMatchPopup = () => { const [match, setMatch] = useState(null) const [error, setError] = useState('') const [loader, setLoader] = useState(false) + const [selectedSubStep, setSelectedSubStep] = useState(false) + const [selectedSubName, setSelectSubName] = useState(0) const goTo = useCallback( (step: Steps, e?: MouseEvent) => setSteps((state) => { @@ -65,27 +68,48 @@ export const useBuyMatchPopup = () => { return newState }), []) - const openPopup = useCallback((matchData: Match) => { - setMatch(matchData) - setSteps([Steps.Subscriptions]) - }, []) - const { fetchSubscriptions, + fetchSubscriptionsPackages, + initialSubscription, matchSubscriptions, onPeriodSelect, + onSubscriptionPackagesSelect, onSubscriptionSelect, resetSubscriptions, selectedPeriod, selectedSubscription, + selectedSubscriptionPackage, + setSelectedSubscriptionPackage, subscriptions, } = useSubscriptions() + const onChooseSub = () => { + if (match) { + fetchSubscriptionsPackages(match) + setSelectedSubStep(true) + } + } + + const openPopup = useCallback((matchData: Match) => { + setMatch(matchData) + }, []) + + useEffect(() => { + if (!isEmpty(initialSubscription)) { + !initialSubscription?.data + ? setSteps([Steps.Subscriptions]) + : setSteps([Steps.SelectSubscription]) + } + }, [subscriptions, initialSubscription]) + const closePopup = () => { setMatch(null) setSteps([]) setError('') resetSubscriptions() + setSelectedSubscriptionPackage(null) + setSelectedSubStep(false) if (isMatchPage()) history.push(PAGES.home) } @@ -158,28 +182,40 @@ export const useBuyMatchPopup = () => { } } - useEffect(() => { + const getSub = useCallback(() => { if (match) { fetchSubscriptions(match) } }, [match, fetchSubscriptions]) + useEffect(() => { + getSub() + }, [getSub]) + return { close: closePopup, currentStep: last(steps), error, + getSub, goBack, goTo, + initialSubscription, loader, match, matchSubscriptions, onBuyClick, + onChooseSub, onPeriodSelect, + onSubscriptionPackagesSelect, onSubscriptionSelect, open: openPopup, postPaymentHandler, selectedPeriod, + selectedSubName, + selectedSubStep, selectedSubscription, + selectedSubscriptionPackage, + setSelectSubName, subscriptions, } } diff --git a/src/features/BuyMatchPopup/store/hooks/useSubscriptions.tsx b/src/features/BuyMatchPopup/store/hooks/useSubscriptions.tsx index 7951c11d..c449d2db 100644 --- a/src/features/BuyMatchPopup/store/hooks/useSubscriptions.tsx +++ b/src/features/BuyMatchPopup/store/hooks/useSubscriptions.tsx @@ -8,7 +8,7 @@ import find from 'lodash/find' import isEmpty from 'lodash/isEmpty' import first from 'lodash/first' -import { getSubscriptions } from 'requests' +import { getSubscriptions, SubscriptionsByPeriods } from 'requests' import { useLexicsStore } from 'features/LexicsStore' @@ -19,6 +19,7 @@ import type { } from '../../types' import { SubscriptionType } from '../../types' import { transformSubsciptions } from '../helpers' +import { useSubscriptionsLexics } from './useSubscriptionsLexics' const defaultSubscriptions: MatchSubscriptions = { [SubscriptionType.Month]: [], @@ -28,24 +29,53 @@ const defaultSubscriptions: MatchSubscriptions = { export const useSubscriptions = () => { const { suffix } = useLexicsStore() + const { fetchLexics } = useSubscriptionsLexics() const [selectedPeriod, setSelectedPeriod] = useState(SubscriptionType.Month) const [matchSubscriptions, setMatchSubscriptionsList] = useState(defaultSubscriptions) const [selectedSubscription, setSelectedSubscription] = useState(null) + const [ + initialSubscription, setInitialSubscription, + ] = useState(null) + const [ + selectedSubscriptionPackage, setSelectedSubscriptionPackage, + ] = useState(null) - const fetchSubscriptions = useCallback((match: Match) => { - getSubscriptions(match.sportType, match.id) - .then((subscriptions) => transformSubsciptions({ + const fetchSubscriptions = useCallback(async (match: Match) => { + const subscriptions = await getSubscriptions(match.sportType, match.id) + if (!subscriptions.data) { + const convertedSubscriptions = transformSubsciptions({ match, subscriptions, suffix, - })) - .then((subscriptions) => { - setMatchSubscriptionsList(subscriptions) - const firstSubscription = find(subscriptions, (subscription) => !isEmpty(subscription)) - setSelectedPeriod(first(firstSubscription)?.type || SubscriptionType.Month) }) - }, [suffix]) + setInitialSubscription(subscriptions) + setMatchSubscriptionsList(convertedSubscriptions) + const firstSubscription = find( + convertedSubscriptions, (subscription) => !isEmpty(subscription), + ) + setSelectedPeriod(first(firstSubscription)?.type || SubscriptionType.Month) + } else { + setInitialSubscription(subscriptions) + fetchLexics(subscriptions.data) + } + }, [fetchLexics, suffix]) + + const fetchSubscriptionsPackages = useCallback((match) => { + if (selectedSubscriptionPackage) { + const convertedSubscriptions = transformSubsciptions({ + match, + subscriptions: selectedSubscriptionPackage, + suffix, + }) + setInitialSubscription(selectedSubscriptionPackage) + setMatchSubscriptionsList(convertedSubscriptions) + const firstSubscription = find( + convertedSubscriptions, (subscription) => !isEmpty(subscription), + ) + setSelectedPeriod(first(firstSubscription)?.type || SubscriptionType.Month) + } + }, [selectedSubscriptionPackage, suffix]) const resetSubscriptions = useCallback(() => { setSelectedSubscription(null) @@ -56,6 +86,10 @@ export const useSubscriptions = () => { setSelectedSubscription(subscription === selectedSubscription ? null : subscription) } + const onSubscriptionPackagesSelect = (packages: SubscriptionsByPeriods) => { + setSelectedSubscriptionPackage(packages === selectedSubscriptionPackage ? null : packages) + } + useEffect(() => { const isOnlySubscriptionVariant = matchSubscriptions[selectedPeriod].length === 1 if (isOnlySubscriptionVariant) { @@ -67,12 +101,17 @@ export const useSubscriptions = () => { return { fetchSubscriptions, + fetchSubscriptionsPackages, + initialSubscription, matchSubscriptions, onPeriodSelect: setSelectedPeriod, + onSubscriptionPackagesSelect, onSubscriptionSelect, resetSubscriptions, selectedPeriod, selectedSubscription, + selectedSubscriptionPackage, + setSelectedSubscriptionPackage, subscriptions: matchSubscriptions[selectedPeriod], } } diff --git a/src/features/BuyMatchPopup/store/hooks/useSubscriptionsLexics.tsx b/src/features/BuyMatchPopup/store/hooks/useSubscriptionsLexics.tsx new file mode 100644 index 00000000..b2255b33 --- /dev/null +++ b/src/features/BuyMatchPopup/store/hooks/useSubscriptionsLexics.tsx @@ -0,0 +1,29 @@ +import { useCallback } from 'react' + +import isEmpty from 'lodash/isEmpty' +import flatMap from 'lodash/flatMap' +import uniq from 'lodash/uniq' + +import type { SelectSubscriptionData } from 'requests' + +import { useLexicsStore } from 'features/LexicsStore' + +export const useSubscriptionsLexics = () => { + const { addLexicsConfig } = useLexicsStore() + + const fetchLexics = useCallback((data: Array) => { + const lexics = uniq(flatMap(data, ({ + lexic, + lexic2, + lexic3, + }) => [lexic, lexic2, lexic3])) + + if (!isEmpty(lexics)) { + addLexicsConfig(lexics) + } + + return data + }, [addLexicsConfig]) + + return { fetchLexics } +} diff --git a/src/features/BuyMatchPopup/styled.tsx b/src/features/BuyMatchPopup/styled.tsx index 5fecfbcb..92628770 100644 --- a/src/features/BuyMatchPopup/styled.tsx +++ b/src/features/BuyMatchPopup/styled.tsx @@ -5,6 +5,7 @@ import { isMobileDevice } from 'config/userAgent' import { ButtonSolid } from 'features/Common' import { ModalWindow } from 'features/Modal/styled' import { Modal as BaseModal } from 'features/Modal' +import { Arrow } from 'features/HeaderFilters/components/DateFilter/styled' export const Modal = styled(BaseModal)` background-color: rgba(0, 0, 0, 0.7); @@ -183,3 +184,9 @@ export const ResultText = styled.span` export const SmallButton = styled(Button)` min-width: 70px; ` + +export const ButtonPrevious = styled(Arrow)` + top: 30px; + left: 30px; + cursor: pointer; +` diff --git a/src/features/BuyMatchPopup/types.tsx b/src/features/BuyMatchPopup/types.tsx index 1418bbc7..9318fc7b 100644 --- a/src/features/BuyMatchPopup/types.tsx +++ b/src/features/BuyMatchPopup/types.tsx @@ -5,6 +5,7 @@ import type { SubscriptionResponse } from 'requests' export enum Steps { CardSelection = 'CardSelection', Error = 'Error', + SelectSubscription = 'SelectSubscription', Subscriptions = 'Subscriptions', Success = 'Success', } diff --git a/src/requests/getSubscriptions.tsx b/src/requests/getSubscriptions.tsx index 822d5cbd..a70b2018 100644 --- a/src/requests/getSubscriptions.tsx +++ b/src/requests/getSubscriptions.tsx @@ -8,13 +8,28 @@ import { callApi } from 'helpers' const proc = PROCEDURES.get_match_subscriptions +export type SelectSubscriptionData = { + id: number, + lexic: number, + lexic2: number, + lexic3: number, + packages: SelectSubscriptionPackages, +} + export type SubscriptionsByPeriods = { + data?: Array, month: Subscriptions, pay_per_view: SubscriptionResponse, season: Season, year: Subscriptions, } +export type SelectSubscriptionPackages = Pick + export type Subscriptions = { all: SubscriptionResponse, team1: SubscriptionResponse,