From 75f6911da1bf3ba94c0fca0ebcc68cae24ec7a13 Mon Sep 17 00:00:00 2001 From: Mirlan Date: Mon, 8 Feb 2021 19:33:49 +0600 Subject: [PATCH] Ott 799 buy match popup (#295) * Ott 799 part 1 (#289) * refactor(799): moved reusable popup components into PopupComponents * feat(799): added subscriptions request * fix(799): fixed subscription types * Ott 799 part 2 (#293) * refactor(799): moved Price into features * refactor(799): moved popupScrollbarStyles into PopupComponents feature * refactor(799): created config of currency symbols * feat(799): added buy popup and its subscriptions selection step (#294) * feat(799): added buy popup and its subscriptions selection step * refactor(799): review comments fix --- src/config/currencies.tsx | 4 + src/config/dashes.tsx | 1 + src/config/index.tsx | 2 + src/config/lexics/indexLexics.tsx | 11 +++ src/features/App/AuthenticatedApp.tsx | 54 +++++------ .../components/MatchSubscriptions/index.tsx | 67 ++++++++++++++ .../components/PaymentPeriods/index.tsx | 59 ++++++++++++ .../components/SelectedCard/index.tsx | 45 ++++++++++ .../components/Subscriptions/index.tsx | 31 +++++++ .../components/SubscriptionsList/index.tsx | 52 +++++++++++ .../components/SubscriptionsList/styled.tsx | 80 +++++++++++++++++ src/features/BuyMatchPopup/index.tsx | 39 ++++++++ .../BuyMatchPopup/store/hooks/index.tsx | 71 +++++++++++++++ .../store/hooks/useSubscriptions.tsx | 53 +++++++++++ src/features/BuyMatchPopup/store/index.tsx | 20 +++++ src/features/BuyMatchPopup/styled.tsx | 39 ++++++++ src/features/BuyMatchPopup/types.tsx | 7 ++ .../MatchCard/CardFrontside/index.tsx | 21 +++-- .../components/BackButton/index.tsx | 5 +- .../components/CloseButton/index.tsx | 13 --- .../components/FinishedMatchPopup/index.tsx | 2 - .../components/FinishedPlaylistPage/index.tsx | 22 +++-- .../components/LivePlaylistPage/index.tsx | 14 ++- .../components/PlayersListDesktop/index.tsx | 15 +--- .../components/SettingsButton/index.tsx | 5 +- .../components/SettingsPage/index.tsx | 77 ++++++++-------- src/features/MatchPopup/styled.tsx | 89 +------------------ .../PopupComponents/BaseButton/index.tsx | 29 ++++++ .../PopupComponents/CloseButton/index.tsx | 15 ++++ src/features/PopupComponents/Header/index.tsx | 69 ++++++++++++++ src/features/PopupComponents/index.tsx | 4 + .../popupScrollbarStyles/index.tsx | 18 ++++ src/features/Price/index.tsx | 30 +++++++ .../components => }/Price/styled.tsx | 0 .../AdditionalSubscription/index.tsx | 2 +- .../components/MainSubscription/index.tsx | 2 +- .../Register/components/Price/index.tsx | 31 ------- .../components/CardNumber/styled.tsx | 17 ++-- .../components/Subscription/index.tsx | 2 +- .../components/TextNoBorder/index.tsx | 2 +- .../UserAccountSubscription/index.tsx | 2 +- .../UserAccountSubscriptionMatch/index.tsx | 2 +- src/requests/getMatchSubscriptions.tsx | 28 ++++++ src/requests/index.tsx | 1 + 44 files changed, 901 insertions(+), 251 deletions(-) create mode 100644 src/config/currencies.tsx create mode 100644 src/config/dashes.tsx create mode 100644 src/features/BuyMatchPopup/components/MatchSubscriptions/index.tsx create mode 100644 src/features/BuyMatchPopup/components/PaymentPeriods/index.tsx create mode 100644 src/features/BuyMatchPopup/components/SelectedCard/index.tsx create mode 100644 src/features/BuyMatchPopup/components/Subscriptions/index.tsx create mode 100644 src/features/BuyMatchPopup/components/SubscriptionsList/index.tsx create mode 100644 src/features/BuyMatchPopup/components/SubscriptionsList/styled.tsx create mode 100644 src/features/BuyMatchPopup/index.tsx create mode 100644 src/features/BuyMatchPopup/store/hooks/index.tsx create mode 100644 src/features/BuyMatchPopup/store/hooks/useSubscriptions.tsx create mode 100644 src/features/BuyMatchPopup/store/index.tsx create mode 100644 src/features/BuyMatchPopup/styled.tsx create mode 100644 src/features/BuyMatchPopup/types.tsx delete mode 100644 src/features/MatchPopup/components/CloseButton/index.tsx create mode 100644 src/features/PopupComponents/BaseButton/index.tsx create mode 100644 src/features/PopupComponents/CloseButton/index.tsx create mode 100644 src/features/PopupComponents/Header/index.tsx create mode 100644 src/features/PopupComponents/index.tsx create mode 100644 src/features/PopupComponents/popupScrollbarStyles/index.tsx create mode 100644 src/features/Price/index.tsx rename src/features/{Register/components => }/Price/styled.tsx (100%) delete mode 100644 src/features/Register/components/Price/index.tsx create mode 100644 src/requests/getMatchSubscriptions.tsx diff --git a/src/config/currencies.tsx b/src/config/currencies.tsx new file mode 100644 index 00000000..03cf0426 --- /dev/null +++ b/src/config/currencies.tsx @@ -0,0 +1,4 @@ +export const currencySymbols = { + dollar: '$', + ruble: '₽', +} diff --git a/src/config/dashes.tsx b/src/config/dashes.tsx new file mode 100644 index 00000000..1053f668 --- /dev/null +++ b/src/config/dashes.tsx @@ -0,0 +1 @@ +export const MDASH = '\u2014' diff --git a/src/config/index.tsx b/src/config/index.tsx index ab2ad3fe..d03692c7 100644 --- a/src/config/index.tsx +++ b/src/config/index.tsx @@ -6,3 +6,5 @@ export * from './sportTypes' export * from './profileTypes' export * from './history' export * from './devices' +export * from './currencies' +export * from './dashes' diff --git a/src/config/lexics/indexLexics.tsx b/src/config/lexics/indexLexics.tsx index 4613aecf..e6f62c6a 100644 --- a/src/config/lexics/indexLexics.tsx +++ b/src/config/lexics/indexLexics.tsx @@ -19,6 +19,16 @@ const matchPopupLexics = { watch_live_stream: 13020, } +const buyMatchPopupLexics = { + buy_subscription: 13565, + change_card: 13564, + choose_subscription: 13563, + for_month: 13561, + for_year: 13562, + per_month: 13573, + per_year: 13574, +} + export const indexLexics = { add_to_favorites: 1701, add_to_favorites_error: 12943, @@ -69,4 +79,5 @@ export const indexLexics = { ...proceduresLexics, ...matchPopupLexics, + ...buyMatchPopupLexics, } diff --git a/src/features/App/AuthenticatedApp.tsx b/src/features/App/AuthenticatedApp.tsx index e803a398..16274879 100644 --- a/src/features/App/AuthenticatedApp.tsx +++ b/src/features/App/AuthenticatedApp.tsx @@ -20,6 +20,7 @@ import { UserAccountForm } from 'features/UserAccount' import { MatchSwitchesStore } from 'features/MatchSwitches' import { UserFavoritesStore } from 'features/UserFavorites/store' import { MatchPopupStore } from 'features/MatchPopup' +import { BuyMatchPopup, BuyMatchPopupStore } from 'features/BuyMatchPopup' export const AuthenticatedApp = () => { useLexicsConfig(indexLexics) @@ -29,32 +30,35 @@ export const AuthenticatedApp = () => { + + - {/* в Switch как прямой children можно рендерить только Route или Redirect */} - - - - - - - - - - - - - - - - - - - - - - - - + {/* в Switch как прямой children можно рендерить только Route или Redirect */} + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/features/BuyMatchPopup/components/MatchSubscriptions/index.tsx b/src/features/BuyMatchPopup/components/MatchSubscriptions/index.tsx new file mode 100644 index 00000000..24ce4084 --- /dev/null +++ b/src/features/BuyMatchPopup/components/MatchSubscriptions/index.tsx @@ -0,0 +1,67 @@ +import styled from 'styled-components/macro' + +import isEmpty from 'lodash/isEmpty' + +import { MDASH } from 'config' + +import { T9n } from 'features/T9n' +import { useBuyMatchPopupStore } from 'features/BuyMatchPopup' +import { + CloseButton, + Header, + HeaderActions, + HeaderTitle, +} from 'features/PopupComponents' +import { Name } from 'features/Name' +import { Steps } from 'features/BuyMatchPopup/types' + +import { SelectedCard } from '../SelectedCard' +import { Subscriptions } from '../Subscriptions' +import { Button } from '../../styled' + +const Wrapper = styled.div` + width: 870px; + height: 695px; +` + +const Center = styled.div` + width: 100%; + display: flex; + justify-content: center; +` + +export const MatchSubscriptionsStep = () => { + const { + close, + goTo, + match, + selectedSubscriptions, + } = useBuyMatchPopupStore() + + if (!match) return null + + return ( + +
+ + + {' '} {MDASH} {' '} + + + + + +
+ + +
+ +
+
+ ) +} diff --git a/src/features/BuyMatchPopup/components/PaymentPeriods/index.tsx b/src/features/BuyMatchPopup/components/PaymentPeriods/index.tsx new file mode 100644 index 00000000..ec5d5966 --- /dev/null +++ b/src/features/BuyMatchPopup/components/PaymentPeriods/index.tsx @@ -0,0 +1,59 @@ +import styled, { css } from 'styled-components/macro' + +import { SubscriptionType } from 'requests' + +import { T9n } from 'features/T9n' +import { useBuyMatchPopupStore } from 'features/BuyMatchPopup/store' + +const List = styled.ul` + display: flex; + padding: 0 35px; + margin-top: 9px; +` + +type ItemProps = { + active?: boolean, +} + +const Item = styled.li.attrs(() => ({ + tabIndex: 0, +}))` + width: 50%; + font-size: 20px; + line-height: 42px; + + display: flex; + align-items: center; + justify-content: center; + color: rgba(255, 255, 255, 0.5); + cursor: pointer; + + ${({ active }) => ( + active + ? css` + border-bottom: 3px solid #fff; + color: #fff; + ` + : '' + )} +` + +export const PaymentPeriods = () => { + const { onPeriodSelect, selectedPeriod } = useBuyMatchPopupStore() + return ( + + onPeriodSelect(SubscriptionType.Month)} + > + + + onPeriodSelect(SubscriptionType.Year)} + > + + + + ) +} diff --git a/src/features/BuyMatchPopup/components/SelectedCard/index.tsx b/src/features/BuyMatchPopup/components/SelectedCard/index.tsx new file mode 100644 index 00000000..d9c046aa --- /dev/null +++ b/src/features/BuyMatchPopup/components/SelectedCard/index.tsx @@ -0,0 +1,45 @@ +import styled from 'styled-components/macro' + +import { T9n } from 'features/T9n' +import { ButtonOutline } from 'features/Common' + +const Wrapper = styled.div` + display: flex; + margin-top: 40px; + margin-bottom: 30px; + padding: 0 35px; +` + +const CardInfo = styled.span` + font-weight: 500; + font-size: 18px; + line-height: 20px; + color: rgba(255, 255, 255, 0.7); +` + +const ChangeCardButton = styled(ButtonOutline)` + border: none; + padding: 0; + width: auto; + height: auto; + + padding: 0 10px; + margin-left: 10px; + line-height: 20px; + font-size: 14px; + color: rgba(255, 255, 255, 0.5); + cursor: pointer; + + :hover { + color: rgba(255, 255, 255); + } +` + +export const SelectedCard = () => ( + + Mastercard •••• 4432 + + + + +) diff --git a/src/features/BuyMatchPopup/components/Subscriptions/index.tsx b/src/features/BuyMatchPopup/components/Subscriptions/index.tsx new file mode 100644 index 00000000..a1e79b80 --- /dev/null +++ b/src/features/BuyMatchPopup/components/Subscriptions/index.tsx @@ -0,0 +1,31 @@ +import styled from 'styled-components/macro' + +import { T9n } from 'features/T9n' + +import { PaymentPeriods } from '../PaymentPeriods' +import { SubscriptionsList } from '../SubscriptionsList' + +const Wrapper = styled.div` + width: 100%; + display: flex; + flex-direction: column; +` + +const Title = styled.span` + font-weight: normal; + font-size: 20px; + line-height: 21px; + text-transform: uppercase; + margin-top: 30px; + padding: 0 35px; +` + +export const Subscriptions = () => ( + + + + <T9n t='choose_subscription' /> + + + +) diff --git a/src/features/BuyMatchPopup/components/SubscriptionsList/index.tsx b/src/features/BuyMatchPopup/components/SubscriptionsList/index.tsx new file mode 100644 index 00000000..6b10e1e3 --- /dev/null +++ b/src/features/BuyMatchPopup/components/SubscriptionsList/index.tsx @@ -0,0 +1,52 @@ +import map from 'lodash/map' +import includes from 'lodash/includes' + +import { useBuyMatchPopupStore } from 'features/BuyMatchPopup/store' + +import { + List, + Item, + InfoWrapper, + Header, + Description, + Price, +} from './styled' + +export const SubscriptionsList = () => { + const { + onSubscriptionSelect, + selectedSubscriptions, + subscriptions, + } = useBuyMatchPopupStore() + + return ( + + { + map(subscriptions, ({ + description, + header, + price, + subscription_id, + type, + }) => ( + onSubscriptionSelect(subscription_id)} + active={includes(selectedSubscriptions, subscription_id)} + > + +
+ {header} +
+ + {description} + +
+ + +
+ )) + } +
+ ) +} diff --git a/src/features/BuyMatchPopup/components/SubscriptionsList/styled.tsx b/src/features/BuyMatchPopup/components/SubscriptionsList/styled.tsx new file mode 100644 index 00000000..a4268558 --- /dev/null +++ b/src/features/BuyMatchPopup/components/SubscriptionsList/styled.tsx @@ -0,0 +1,80 @@ +import styled from 'styled-components/macro' + +import { popupScrollbarStyles } from 'features/PopupComponents' +import { Price as BasePrice } from 'features/Price' +import { PriceAmount, PriceDetails } from 'features/Price/styled' + +export const List = styled.ul` + height: 364px; + display: flex; + flex-direction: column; + overflow-y: auto; + margin-top: 20px; + padding: 0 35px; + + ${popupScrollbarStyles} +` + +type ItemProps = { + active?: boolean, +} + +export const Item = styled.li.attrs(() => ({ + tabIndex: 0, +}))` + width: 100%; + min-height: 108px; + padding: 20px; + background: linear-gradient(180deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0) 100%), #5C5C5C; + box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3); + border-radius: 2px; + + display: flex; + justify-content: space-between; + align-items: center; + cursor: pointer; + + :first-child { + margin-top: 2px; + } + + :not(:last-child) { + margin-bottom: 20px; + } + + ${({ active }) => ( + active ? 'background-color: #294FC3' : '' + )}; +` + +export const InfoWrapper = styled.div` + width: 80%; +` + +export const Header = styled.span` + font-weight: 600; + font-size: 20px; + line-height: 23px; + letter-spacing: 0.03em; +` + +export const Description = styled.p` + margin-top: 10px; + font-weight: 500; + font-size: 17px; + letter-spacing: 0.03em; +` + +export const Price = styled(BasePrice)` + ${PriceAmount} { + font-size: 24px; + line-height: 24px; + font-weight: normal; + } + + ${PriceDetails} { + font-weight: 500; + font-size: 12px; + line-height: 18px; + } +` diff --git a/src/features/BuyMatchPopup/index.tsx b/src/features/BuyMatchPopup/index.tsx new file mode 100644 index 00000000..ce76de14 --- /dev/null +++ b/src/features/BuyMatchPopup/index.tsx @@ -0,0 +1,39 @@ +import { useBuyMatchPopupStore } from 'features/BuyMatchPopup' + +import { MatchSubscriptionsStep } from './components/MatchSubscriptions' +import { Modal } from './styled' +import { Steps } from './types' + +export * from './store' + +const Empty = () => null + +const components = { + [Steps.Subscriptions]: MatchSubscriptionsStep, + [Steps.CardSelection]: Empty, + [Steps.Confirmation]: Empty, + [Steps.Success]: Empty, + [Steps.Error]: Empty, +} + +export const BuyMatchPopup = () => { + const { + close, + currentStep, + match, + } = useBuyMatchPopupStore() + + if (!match || !currentStep) return null + + const Step = components[currentStep] + + return ( + + + + ) +} diff --git a/src/features/BuyMatchPopup/store/hooks/index.tsx b/src/features/BuyMatchPopup/store/hooks/index.tsx new file mode 100644 index 00000000..bad5d886 --- /dev/null +++ b/src/features/BuyMatchPopup/store/hooks/index.tsx @@ -0,0 +1,71 @@ +import type { MouseEvent } from 'react' +import { useCallback, useState } from 'react' + +import last from 'lodash/last' + +import type { Match } from 'features/Matches/hooks' +import { useMatchPopupStore } from 'features/MatchPopup' +import { Steps } from 'features/BuyMatchPopup/types' + +import { useSubscriptions } from './useSubscriptions' + +type MatchData = Pick | null + +export const useBuyMatchPopup = () => { + const { closePopup: closeMatchPopup } = useMatchPopupStore() + const [steps, setSteps] = useState>([]) + const [match, setMatch] = useState(null) + const { + onPeriodSelect, + onSubscriptionSelect, + resetSubscriptions, + selectedPeriod, + selectedSubscriptions, + subscriptions, + } = useSubscriptions() + + const goTo = useCallback( + (e: MouseEvent, step: Steps) => setSteps((state) => { + e.stopPropagation() + return [...state, step] + }), + [], + ) + const goBack = useCallback(() => setSteps((state) => { + const newState = [...state] + newState.pop() + return newState + }), []) + + const openPopup = (e: MouseEvent, matchData: MatchData) => { + closeMatchPopup() + e.stopPropagation() + setMatch(matchData) + setSteps([Steps.Subscriptions]) + } + + const closePopup = () => { + setMatch(null) + setSteps([]) + resetSubscriptions() + } + + return { + close: closePopup, + currentStep: last(steps), + goBack, + goTo, + match, + onPeriodSelect, + onSubscriptionSelect, + open: openPopup, + resetSubscriptions, + selectedPeriod, + selectedSubscriptions, + subscriptions, + } +} diff --git a/src/features/BuyMatchPopup/store/hooks/useSubscriptions.tsx b/src/features/BuyMatchPopup/store/hooks/useSubscriptions.tsx new file mode 100644 index 00000000..b0fa8e95 --- /dev/null +++ b/src/features/BuyMatchPopup/store/hooks/useSubscriptions.tsx @@ -0,0 +1,53 @@ +import { + useMemo, + useState, + useEffect, + useCallback, +} from 'react' + +import filter from 'lodash/filter' +import includes from 'lodash/includes' + +import type { MatchSubscriptions } from 'requests' +import { SubscriptionType, getMatchSubscriptions } from 'requests' + +export const useSubscriptions = () => { + const [selectedPeriod, setSelectedPeriod] = useState(SubscriptionType.Month) + const [subscriptionsList, setSubscriptionsList] = useState([]) + const [selectedSubscriptions, setSelectedSubscriptions] = useState>([]) + + useEffect(() => { + getMatchSubscriptions().then(setSubscriptionsList) + }, []) + + const subscriptions = useMemo( + () => filter(subscriptionsList, { type: selectedPeriod }), + [selectedPeriod, subscriptionsList], + ) + + const onSubscriptionSelect = (id: number) => { + if (includes(selectedSubscriptions, id)) { + const newSubscriptions = filter( + selectedSubscriptions, + (subscriptionId) => subscriptionId !== id, + ) + setSelectedSubscriptions(newSubscriptions) + } else { + setSelectedSubscriptions([...selectedSubscriptions, id]) + } + } + + const resetSubscriptions = useCallback(() => { + setSelectedPeriod(SubscriptionType.Month) + setSelectedSubscriptions([]) + }, []) + + return { + onPeriodSelect: setSelectedPeriod, + onSubscriptionSelect, + resetSubscriptions, + selectedPeriod, + selectedSubscriptions, + subscriptions, + } +} diff --git a/src/features/BuyMatchPopup/store/index.tsx b/src/features/BuyMatchPopup/store/index.tsx new file mode 100644 index 00000000..6e94cc80 --- /dev/null +++ b/src/features/BuyMatchPopup/store/index.tsx @@ -0,0 +1,20 @@ +import type { ReactNode } from 'react' +import { createContext, useContext } from 'react' + +import { useBuyMatchPopup } from './hooks' + +type Context = ReturnType +type Props = { children: ReactNode } + +const BuyMatchPopupContext = createContext({} as Context) + +export const BuyMatchPopupStore = ({ children }: Props) => { + const value = useBuyMatchPopup() + return ( + + {children} + + ) +} + +export const useBuyMatchPopupStore = () => useContext(BuyMatchPopupContext) diff --git a/src/features/BuyMatchPopup/styled.tsx b/src/features/BuyMatchPopup/styled.tsx new file mode 100644 index 00000000..c584600a --- /dev/null +++ b/src/features/BuyMatchPopup/styled.tsx @@ -0,0 +1,39 @@ +import styled from 'styled-components/macro' + +import { devices } from 'config' + +import { Modal as BaseModal } from 'features/Modal' +import { ModalWindow } from 'features/Modal/styled' +import { ButtonSolid } from 'features/Common' + +export const Modal = styled(BaseModal)` + background-color: rgba(0, 0, 0, 0.7); + + ${ModalWindow} { + min-width: 517px; + min-height: 310px; + padding: 20px 0; + background-color: #3F3F3F; + border-radius: 5px; + + @media ${devices.mobile} { + width: 100vw; + height: 100vh; + padding: 0; + } + } +` + +export const Button = styled(ButtonSolid)` + min-width: 142px; + width: auto; + height: 50px; + padding: 0 20px; + background-color: #294FC4; + box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3); + border-radius: 5px; + + :disabled { + opacity: 0.5; + } +` diff --git a/src/features/BuyMatchPopup/types.tsx b/src/features/BuyMatchPopup/types.tsx new file mode 100644 index 00000000..be52b946 --- /dev/null +++ b/src/features/BuyMatchPopup/types.tsx @@ -0,0 +1,7 @@ +export enum Steps { + CardSelection = 'CardSelection', + Confirmation = 'Confirmation', + Error = 'Error', + Subscriptions = 'Subscriptions', + Success = 'Success', +} diff --git a/src/features/MatchCard/CardFrontside/index.tsx b/src/features/MatchCard/CardFrontside/index.tsx index 9669bd19..0d5d6f8a 100644 --- a/src/features/MatchCard/CardFrontside/index.tsx +++ b/src/features/MatchCard/CardFrontside/index.tsx @@ -7,6 +7,7 @@ import { ProfileTypes } from 'config' import type { Match } from 'features/Matches' import { SportName } from 'features/Common' import { useMatchSwitchesStore } from 'features/MatchSwitches' +import { useBuyMatchPopupStore } from 'features/BuyMatchPopup' import { useName } from 'features/Name' import { NoAccessMessage } from '../NoAccessMessage' @@ -36,7 +37,12 @@ type Props = { } export const CardFrontside = ({ - match: { + match, + onClick, + onKeyPress, + showSportName, +}: Props) => { + const { accessibleBySubscription, accessibleInUsersCountry, date, @@ -49,12 +55,9 @@ export const CardFrontside = ({ team2, time, tournament, - }, - onClick, - onKeyPress, - showSportName, -}: Props) => { + } = match const tournamentName = useName(tournament) + const { open } = useBuyMatchPopupStore() const { isScoreHidden } = useMatchSwitchesStore() const { selectedMatchStatus } = useHeaderFiltersStore() const unixTimeOfMatch = getUnixTime(date) @@ -95,7 +98,11 @@ export const CardFrontside = ({ ) } - {!accessibleBySubscription && } + {!accessibleBySubscription && ( + open(e, match)} + /> + )} {(accessibleBySubscription && !accessibleInUsersCountry) && } {formattedDate} diff --git a/src/features/MatchPopup/components/BackButton/index.tsx b/src/features/MatchPopup/components/BackButton/index.tsx index c495cf6a..7c40dea6 100644 --- a/src/features/MatchPopup/components/BackButton/index.tsx +++ b/src/features/MatchPopup/components/BackButton/index.tsx @@ -1,8 +1,7 @@ import styled from 'styled-components/macro' -import { useMatchPopupStore } from 'features/MatchPopup/store' - -import { BaseButton } from '../../styled' +import { useMatchPopupStore } from 'features/MatchPopup' +import { BaseButton } from 'features/PopupComponents' const Button = styled(BaseButton)` background-image: url(/images/back-icon.svg); diff --git a/src/features/MatchPopup/components/CloseButton/index.tsx b/src/features/MatchPopup/components/CloseButton/index.tsx deleted file mode 100644 index cdc8fb18..00000000 --- a/src/features/MatchPopup/components/CloseButton/index.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { Close } from 'features/Icons/Close' -import { useMatchPopupStore } from 'features/MatchPopup/store' - -import { BaseButton } from '../../styled' - -export const CloseButton = () => { - const { closePopup } = useMatchPopupStore() - return ( - - - - ) -} diff --git a/src/features/MatchPopup/components/FinishedMatchPopup/index.tsx b/src/features/MatchPopup/components/FinishedMatchPopup/index.tsx index 7033211f..c4d6274d 100644 --- a/src/features/MatchPopup/components/FinishedMatchPopup/index.tsx +++ b/src/features/MatchPopup/components/FinishedMatchPopup/index.tsx @@ -9,8 +9,6 @@ import { FinishedPlaylistPage } from '../../components/FinishedPlaylistPage' import { PopupPages } from '../../types' import { Modal } from './styled' -export * from '../../store' - export const FinishedMatchPopup = () => { const { closePopup, diff --git a/src/features/MatchPopup/components/FinishedPlaylistPage/index.tsx b/src/features/MatchPopup/components/FinishedPlaylistPage/index.tsx index c41f685e..1871325b 100644 --- a/src/features/MatchPopup/components/FinishedPlaylistPage/index.tsx +++ b/src/features/MatchPopup/components/FinishedPlaylistPage/index.tsx @@ -6,22 +6,26 @@ import { useMatchSwitchesStore } from 'features/MatchSwitches' import { Name } from 'features/Name' import { MediaQuery } from 'features/MediaQuery' import { useMatchPopupStore } from 'features/MatchPopup' +import { + CloseButton, + Header, + HeaderActions, + HeaderTitle, +} from 'features/PopupComponents' import { SettingsButton } from '../SettingsButton' -import { CloseButton } from '../CloseButton' import { BackButton } from '../BackButton' import { FinishedMatchPlaylist } from '../FinishedMatchPlaylist' import { PlayersListDesktop } from '../PlayersListDesktop' import { PlayersListMobile } from '../PlayersListMobile' -import { - Content, - Header, - HeaderActions, - HeaderTitle, -} from '../../styled' +import { Content } from '../../styled' export const FinishedPlaylistPage = () => { - const { match, matchPlaylists } = useMatchPopupStore() + const { + closePopup, + match, + matchPlaylists, + } = useMatchPopupStore() const { isScoreHidden } = useMatchSwitchesStore() if (!match) return null @@ -50,7 +54,7 @@ export const FinishedPlaylistPage = () => { - + diff --git a/src/features/MatchPopup/components/LivePlaylistPage/index.tsx b/src/features/MatchPopup/components/LivePlaylistPage/index.tsx index c35ff9cf..cdac1619 100644 --- a/src/features/MatchPopup/components/LivePlaylistPage/index.tsx +++ b/src/features/MatchPopup/components/LivePlaylistPage/index.tsx @@ -1,7 +1,9 @@ +import { MDASH } from 'config' + import { Name } from 'features/Name' import { useMatchPopupStore } from 'features/MatchPopup' +import { CloseButton } from 'features/PopupComponents' -import { CloseButton } from '../CloseButton' import { LiveMatchPlaylist } from '../LiveMatchPlaylist' import { @@ -12,7 +14,11 @@ import { } from './styled' export const LivePlaylistPage = () => { - const { match, matchPlaylists } = useMatchPopupStore() + const { + closePopup, + match, + matchPlaylists, + } = useMatchPopupStore() if (!match) return null const { team1, team2 } = match @@ -22,12 +28,12 @@ export const LivePlaylistPage = () => {
- {' '} — {' '} + {' '} {MDASH} {' '} - +
diff --git a/src/features/MatchPopup/components/PlayersListDesktop/index.tsx b/src/features/MatchPopup/components/PlayersListDesktop/index.tsx index bdcea602..a69c2291 100644 --- a/src/features/MatchPopup/components/PlayersListDesktop/index.tsx +++ b/src/features/MatchPopup/components/PlayersListDesktop/index.tsx @@ -1,7 +1,7 @@ import styled from 'styled-components/macro' import { T9n } from 'features/T9n' -import { customScrollbar } from 'features/Common' +import { popupScrollbarStyles } from 'features/PopupComponents' import { useMatchPopupStore } from 'features/MatchPopup' import { Teams } from '../../types' @@ -24,18 +24,7 @@ const ListsWrapper = styled.div` flex-direction: row; justify-content: space-around; - ${customScrollbar}; - - ::-webkit-scrollbar-thumb { - border-radius: 3px; - background: rgba(196, 196, 196, 0.3); - } - - ::-webkit-scrollbar-track, - ::-webkit-scrollbar-corner { - border-radius: 3px; - background: rgba(103, 103, 103, 0.3); - } + ${popupScrollbarStyles}; ` export const PlayersListDesktop = () => { diff --git a/src/features/MatchPopup/components/SettingsButton/index.tsx b/src/features/MatchPopup/components/SettingsButton/index.tsx index 832f78c4..1989bd52 100644 --- a/src/features/MatchPopup/components/SettingsButton/index.tsx +++ b/src/features/MatchPopup/components/SettingsButton/index.tsx @@ -1,8 +1,7 @@ import styled from 'styled-components/macro' -import { useMatchPopupStore } from 'features/MatchPopup/store' - -import { BaseButton } from '../../styled' +import { useMatchPopupStore } from 'features/MatchPopup' +import { BaseButton } from 'features/PopupComponents' const Button = styled(BaseButton)` background-image: url(/images/settings.svg); diff --git a/src/features/MatchPopup/components/SettingsPage/index.tsx b/src/features/MatchPopup/components/SettingsPage/index.tsx index 514da38b..2544768c 100644 --- a/src/features/MatchPopup/components/SettingsPage/index.tsx +++ b/src/features/MatchPopup/components/SettingsPage/index.tsx @@ -2,17 +2,18 @@ import styled from 'styled-components/macro' import { MediaQuery } from 'features/MediaQuery' import { T9n } from 'features/T9n' - -import { CloseButton } from '../CloseButton' -import { BackButton } from '../BackButton' -import { SettingsDesktop } from '../SettingsDesktop' -import { SettingsMobile } from '../SettingsMobile' import { - Content, + CloseButton, Header, HeaderActions, HeaderTitle, -} from '../../styled' +} from 'features/PopupComponents' + +import { useMatchPopupStore } from '../../store' +import { BackButton } from '../BackButton' +import { SettingsDesktop } from '../SettingsDesktop' +import { SettingsMobile } from '../SettingsMobile' +import { Content } from '../../styled' const ButtonLabel = styled(T9n)` display: flex; @@ -23,38 +24,42 @@ const ButtonLabel = styled(T9n)` color: rgba(255, 255, 255, 0.5); ` -export const SettingsPage = () => ( - -
- - - - +export const SettingsPage = () => { + const { closePopup } = useMatchPopupStore() + + return ( + +
+ + + + + + + + + + + - - - - - - + + + + + +
- - - + -
- - - - - - - -
-) + + + + + ) +} diff --git a/src/features/MatchPopup/styled.tsx b/src/features/MatchPopup/styled.tsx index 74abdd11..e575f6fd 100644 --- a/src/features/MatchPopup/styled.tsx +++ b/src/features/MatchPopup/styled.tsx @@ -1,35 +1,9 @@ -import styled, { css } from 'styled-components/macro' +import styled from 'styled-components/macro' import { devices } from 'config' import { customScrollbar } from 'features/Common' -export const BaseButton = styled.button` - padding: 0; - border: none; - background: none; - - cursor: pointer; - width: 34px; - height: 34px; - color: white; - background-color: rgba(255, 255, 255, 0.12); - background-position: center; - background-repeat: no-repeat; - border-radius: 50%; - - :hover { - background-color: rgba(255, 255, 255, 0.22); - } - - @media ${devices.mobile} { - width: 24px; - height: 24px; - background-color: transparent; - border-radius: 0; - } -` - type ContentProps = { height?: number, } @@ -51,67 +25,6 @@ export const Content = styled.div` } ` -export const Header = styled.div` - position: relative; - height: 35px; - display: flex; - align-items: center; - - @media ${devices.mobile} { - height: 52px; - background-color: rgba(255, 255, 255, 0.1); - padding: 0 12px; - } -` - -type HeaderActionsProps = { - marginLeft?: number, - position: 'left' | 'right', -} - -export const HeaderActions = styled.div` - position: absolute; - display: flex; - - ${({ marginLeft = 0, position }) => css` - ${position}: 20px; - margin-left: ${marginLeft}px; - `} - - @media ${devices.mobile} { - ${({ position }) => css` - ${position}: 12px; - margin-left: 0; - `} - } - - ${BaseButton}:not(:last-child) { - margin-right: 20px; - } -` - -export const HeaderTitle = styled.h2` - position: absolute; - width: 70%; - left: 50%; - transform: translateX(-50%); - - font-weight: 600; - font-size: 24px; - line-height: 42px; - color: #FFFFFF; - text-align: center; - - @media ${devices.mobile} { - font-size: 19px; - line-height: 28px; - text-align: center; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - } -` - export const BlockTitle = styled.h3` font-weight: normal; font-size: 20px; diff --git a/src/features/PopupComponents/BaseButton/index.tsx b/src/features/PopupComponents/BaseButton/index.tsx new file mode 100644 index 00000000..742f41b2 --- /dev/null +++ b/src/features/PopupComponents/BaseButton/index.tsx @@ -0,0 +1,29 @@ +import styled from 'styled-components/macro' + +import { devices } from 'config' + +export const BaseButton = styled.button` + padding: 0; + border: none; + background: none; + + cursor: pointer; + width: 34px; + height: 34px; + color: white; + background-color: rgba(255, 255, 255, 0.12); + background-position: center; + background-repeat: no-repeat; + border-radius: 50%; + + :hover { + background-color: rgba(255, 255, 255, 0.22); + } + + @media ${devices.mobile} { + width: 24px; + height: 24px; + background-color: transparent; + border-radius: 0; + } +` diff --git a/src/features/PopupComponents/CloseButton/index.tsx b/src/features/PopupComponents/CloseButton/index.tsx new file mode 100644 index 00000000..30f5e7e3 --- /dev/null +++ b/src/features/PopupComponents/CloseButton/index.tsx @@ -0,0 +1,15 @@ +import type { MouseEvent } from 'react' + +import { Close } from 'features/Icons/Close' + +import { BaseButton } from '../BaseButton' + +type Props = { + onClick: (e: MouseEvent) => void, +} + +export const CloseButton = ({ onClick }: Props) => ( + + + +) diff --git a/src/features/PopupComponents/Header/index.tsx b/src/features/PopupComponents/Header/index.tsx new file mode 100644 index 00000000..d2e57b5a --- /dev/null +++ b/src/features/PopupComponents/Header/index.tsx @@ -0,0 +1,69 @@ +import styled, { css } from 'styled-components/macro' + +import { devices } from 'config' + +import { BaseButton } from '../BaseButton' + +type HeaderProps = { + height?: number, +} + +export const Header = styled.div` + position: relative; + height: ${({ height = 35 }) => height}px; + display: flex; + + @media ${devices.mobile} { + height: 52px; + background-color: rgba(255, 255, 255, 0.1); + padding: 0 12px; + } +` + +type HeaderActionsProps = { + marginLeft?: number, + position: 'left' | 'right', +} + +export const HeaderActions = styled.div` + position: absolute; + display: flex; + + ${({ marginLeft = 0, position }) => css` + ${position}: 20px; + margin-left: ${marginLeft}px; + `} + + @media ${devices.mobile} { + ${({ position }) => css` + ${position}: 12px; + margin-left: 0; + `} + } + + ${BaseButton}:not(:last-child) { + margin-right: 20px; + } +` + +export const HeaderTitle = styled.h2` + position: absolute; + width: 70%; + left: 50%; + transform: translateX(-50%); + + font-weight: 600; + font-size: 24px; + line-height: 42px; + color: #FFFFFF; + text-align: center; + + @media ${devices.mobile} { + font-size: 19px; + line-height: 28px; + text-align: center; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + } +` diff --git a/src/features/PopupComponents/index.tsx b/src/features/PopupComponents/index.tsx new file mode 100644 index 00000000..9b85c26b --- /dev/null +++ b/src/features/PopupComponents/index.tsx @@ -0,0 +1,4 @@ +export * from './BaseButton' +export * from './CloseButton' +export * from './Header' +export * from './popupScrollbarStyles' diff --git a/src/features/PopupComponents/popupScrollbarStyles/index.tsx b/src/features/PopupComponents/popupScrollbarStyles/index.tsx new file mode 100644 index 00000000..7ec1720c --- /dev/null +++ b/src/features/PopupComponents/popupScrollbarStyles/index.tsx @@ -0,0 +1,18 @@ +import { css } from 'styled-components/macro' + +import { customScrollbar } from 'features/Common' + +export const popupScrollbarStyles = css` + ${customScrollbar} + + ::-webkit-scrollbar-thumb { + border-radius: 3px; + background: rgba(196, 196, 196, 0.3); + } + + ::-webkit-scrollbar-track, + ::-webkit-scrollbar-corner { + border-radius: 3px; + background: rgba(103, 103, 103, 0.3); + } +` diff --git a/src/features/Price/index.tsx b/src/features/Price/index.tsx new file mode 100644 index 00000000..d8ba71e7 --- /dev/null +++ b/src/features/Price/index.tsx @@ -0,0 +1,30 @@ +import { currencySymbols } from 'config' + +import { T9n } from 'features/T9n' + +import { + PriceWrapper, + PriceAmount, + PriceDetails, +} from './styled' + +type Props = { + amount: number, + className?: string, + currency?: string, + perPeriod?: string, +} + +export const Price = ({ + amount, + className, + currency = currencySymbols.ruble, + perPeriod = 'month', +}: Props) => ( + + {amount} + + {currency} / + + +) diff --git a/src/features/Register/components/Price/styled.tsx b/src/features/Price/styled.tsx similarity index 100% rename from src/features/Register/components/Price/styled.tsx rename to src/features/Price/styled.tsx diff --git a/src/features/Register/components/AdditionalSubscription/index.tsx b/src/features/Register/components/AdditionalSubscription/index.tsx index 3105b923..bb70d7a4 100644 --- a/src/features/Register/components/AdditionalSubscription/index.tsx +++ b/src/features/Register/components/AdditionalSubscription/index.tsx @@ -1,7 +1,7 @@ import { Checkbox } from 'features/Common' import { MediaQuery } from 'features/MediaQuery' +import { Price } from 'features//Price' -import { Price } from '../Price' import { PriceItemTitle, PriceItem, diff --git a/src/features/Register/components/MainSubscription/index.tsx b/src/features/Register/components/MainSubscription/index.tsx index 93170df4..33ea7da4 100644 --- a/src/features/Register/components/MainSubscription/index.tsx +++ b/src/features/Register/components/MainSubscription/index.tsx @@ -1,7 +1,7 @@ import { Radio } from 'features/Common' import { MediaQuery } from 'features/MediaQuery' +import { Price } from 'features/Price' -import { Price } from '../Price' import { SubscriptionWrapper, SubscriptionTitle, diff --git a/src/features/Register/components/Price/index.tsx b/src/features/Register/components/Price/index.tsx deleted file mode 100644 index fad97f58..00000000 --- a/src/features/Register/components/Price/index.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { useLexicsStore } from 'features/LexicsStore' - -import { - PriceWrapper, - PriceAmount, - PriceDetails, -} from './styled' - -type Props = { - amount: number, - currency?: string, - perPeriod?: string, -} - -export const Price = ({ - amount, - currency = '₽', - perPeriod = 'month', -}: Props) => { - const { translate } = useLexicsStore() - const perPeriodTranslated = translate(perPeriod) - - return ( - - {amount} - - {currency} / {perPeriodTranslated} - - - ) -} diff --git a/src/features/UserAccount/components/CardNumber/styled.tsx b/src/features/UserAccount/components/CardNumber/styled.tsx index 26df887f..025a8dde 100644 --- a/src/features/UserAccount/components/CardNumber/styled.tsx +++ b/src/features/UserAccount/components/CardNumber/styled.tsx @@ -1,9 +1,9 @@ -import styled, { css } from 'styled-components/macro' +import styled from 'styled-components/macro' import { devices } from 'config/devices' import { Label } from 'features/Common/Radio/styled' -import { PriceAmount, PriceDetails } from 'features/Register/components/Price/styled' +import { PriceAmount, PriceDetails } from 'features/Price/styled' export const CardNumberWrapper = styled.div` display: flex; @@ -28,8 +28,8 @@ export const CardNumberWrapper = styled.div` max-width: 415px; ${Label} { - font-size: 16px; - + font-size: 16px; + &::before { margin-left: 12px; margin-right: 12px; @@ -76,11 +76,11 @@ export const CardNumberTextWrapper = styled(TextWrapper)` } ` -export type Props = { +type Props = { noMarginRight?: boolean, } -export const priceWrapperStyles = css` +export const PriceWrapper = styled.div` margin-left: auto; margin-right: 24px; @@ -103,8 +103,3 @@ export const priceWrapperStyles = css` } } ` - -export const PriceWrapper = styled.div` - ${priceWrapperStyles} - -` diff --git a/src/features/UserAccount/components/Subscription/index.tsx b/src/features/UserAccount/components/Subscription/index.tsx index 83c69368..c8afa5db 100644 --- a/src/features/UserAccount/components/Subscription/index.tsx +++ b/src/features/UserAccount/components/Subscription/index.tsx @@ -1,4 +1,4 @@ -import { Price } from 'features/Register/components/Price' +import { Price } from 'features/Price' import { Radio } from 'features/Common/Radio' import { Checkbox } from 'features/Common/Checkbox' diff --git a/src/features/UserAccount/components/TextNoBorder/index.tsx b/src/features/UserAccount/components/TextNoBorder/index.tsx index 65759aff..c37b59a0 100644 --- a/src/features/UserAccount/components/TextNoBorder/index.tsx +++ b/src/features/UserAccount/components/TextNoBorder/index.tsx @@ -1,4 +1,4 @@ -import { Price } from 'features/Register/components/Price' +import { Price } from 'features/Price' import { TextNoBorderWrapper, TextNoBorderTextWrapper } from './styled' import { PriceWrapper } from '../CardNumber/styled' diff --git a/src/features/UserAccount/components/UserAccountSubscription/index.tsx b/src/features/UserAccount/components/UserAccountSubscription/index.tsx index cee2e7a9..d952b7b5 100644 --- a/src/features/UserAccount/components/UserAccountSubscription/index.tsx +++ b/src/features/UserAccount/components/UserAccountSubscription/index.tsx @@ -1,7 +1,7 @@ import { T9n } from 'features/T9n' import type { ObjectWithName } from 'features/Name' import { Name } from 'features/Name' -import { Price } from 'features/Register/components/Price' +import { Price } from 'features/Price' import { UserAccountSubscriptionWrapper, diff --git a/src/features/UserAccount/components/UserAccountSubscriptionMatch/index.tsx b/src/features/UserAccount/components/UserAccountSubscriptionMatch/index.tsx index 9d06e07c..7b3a3d4d 100644 --- a/src/features/UserAccount/components/UserAccountSubscriptionMatch/index.tsx +++ b/src/features/UserAccount/components/UserAccountSubscriptionMatch/index.tsx @@ -4,7 +4,7 @@ import format from 'date-fns/format' import type { Match } from 'features/UserAccount/hooks/useUserSubscriptions' import { Name } from 'features/Name' -import { Price } from 'features/Register/components/Price' +import { Price } from 'features/Price' import { T9n } from 'features/T9n' import { diff --git a/src/requests/getMatchSubscriptions.tsx b/src/requests/getMatchSubscriptions.tsx new file mode 100644 index 00000000..024495dc --- /dev/null +++ b/src/requests/getMatchSubscriptions.tsx @@ -0,0 +1,28 @@ +import { API_ROOT } from 'config' +import { callApi } from 'helpers' + +export enum SubscriptionType { + Month = 'month', + Year = 'year', +} + +type MatchSubscription = { + description: string, + header: string, + price: number, + subscription_id: number, + type: SubscriptionType, +} + +export type MatchSubscriptions = Array + +export const getMatchSubscriptions = (): Promise => { + const config = { + method: 'GET', + } + + return callApi({ + config, + url: `${API_ROOT}/account/get-subscriptions`, + }) +} diff --git a/src/requests/index.tsx b/src/requests/index.tsx index 78ee6a53..c4c397b0 100644 --- a/src/requests/index.tsx +++ b/src/requests/index.tsx @@ -24,3 +24,4 @@ export * from './getMatchesPreviewImages' export * from './getSportActions' export * from './getMatchPlaylists' export * from './getPlayerPlaylists' +export * from './getMatchSubscriptions'