diff --git a/.drone.yml b/.drone.yml index 5d11346e..05861eed 100644 --- a/.drone.yml +++ b/.drone.yml @@ -846,6 +846,7 @@ steps: depends_on: - make-diwansport + --- kind: pipeline type: docker @@ -900,3 +901,56 @@ steps: depends_on: - make-fqtv + +--- +kind: pipeline +type: docker +name: deploy india.insports.tv + +concurrency: + limit: 1 + +platform: + os: linux + arch: amd64 + +trigger: + ref: + - refs/heads/india.insports.tv + +steps: + - name: npm-install + image: node:16-alpine + environment: + REACT_APP_STRIPE_PK: + from_secret: REACT_APP_STRIPE_PK + commands: + - apk add --no-cache make + - npm install --legacy-peer-deps + + - name: make-india + image: node:16-alpine + environment: + REACT_APP_STRIPE_PK: + from_secret: REACT_APP_STRIPE_PK + commands: + - apk add --no-cache make + - make india-prod + depends_on: + - npm-install + + - name: deploy-india + image: amazon/aws-cli:latest + environment: + AWS_ACCESS_KEY_ID: + from_secret: AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY: + from_secret: AWS_SECRET_ACCESS_KEY + AWS_DEFAULT_REGION: + from_secret: AWS_DEFAULT_REGION + AWS_MAX_ATTEMPTS: 10 + commands: + - aws s3 sync build_india s3://insports-india --delete + - aws cloudfront create-invalidation --distribution-id E5DKN8IPOMASO --paths "/*" + depends_on: + - make-india diff --git a/src/features/App/index.tsx b/src/features/App/index.tsx index d65ffd0a..21812be1 100644 --- a/src/features/App/index.tsx +++ b/src/features/App/index.tsx @@ -32,13 +32,24 @@ setClientTitleAndDescription(client.title, client.description) const Main = () => { const [isToken, setIsToken] = useState(false) - const { userInfo } = useAuthStore() + const { user, userInfo } = useAuthStore() const queryClient = new QueryClient() useEffect(() => { if (userInfo) readToken() && setIsToken(true) }, [userInfo]) + // отправляем идентификаторы пользователей в гугл аналитику + useEffect(() => { + if (user) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (window as any)?.dataLayer.push({ + event: 'userData', + userId: user.profile?.sub, + }) + } + }, [user]) + // имеется действующий токен return isToken ? ( diff --git a/src/features/BuyMatchPopup/components/IframePayment/hooks.tsx b/src/features/BuyMatchPopup/components/IframePayment/hooks.tsx index 2cd13cc4..54b3f4d3 100644 --- a/src/features/BuyMatchPopup/components/IframePayment/hooks.tsx +++ b/src/features/BuyMatchPopup/components/IframePayment/hooks.tsx @@ -2,6 +2,7 @@ import { MouseEvent, useCallback, useEffect, + useMemo, useState, } from 'react' @@ -14,9 +15,10 @@ import isNumber from 'lodash/isNumber' import { useLexicsStore } from 'features/LexicsStore' import { useBuyMatchPopupStore } from 'features/BuyMatchPopup/store' import { getProfileUrl } from 'features/ProfileLink/helpers' +import { SubscriptionType } from 'features/BuyMatchPopup/types' import { getMatchInfo } from 'requests/getMatchInfo' -import { getPaymentUrl } from 'requests/getPaymentUrl' +import { SubscriptionAction, getPaymentUrl } from 'requests/getPaymentUrl' import { redirectToUrl } from 'helpers' @@ -49,6 +51,7 @@ export const useIframePayment = ({ nameLexic, originalObject, pass, + type, } = selectedPackage const teams = isNumber(nameLexic) ? translate(String(nameLexic)) : name @@ -60,6 +63,13 @@ export const useIframePayment = ({ sportType, }) + const defaultAction: SubscriptionAction = useMemo(() => { + if (type === SubscriptionType.Month) { + return SubscriptionAction.CreateSubscription + } + return SubscriptionAction.OnePayment + }, [type]) + const closePopup = useCallback(async (e?: MouseEvent) => { e?.stopPropagation() @@ -81,18 +91,18 @@ export const useIframePayment = ({ const paymentRequest = async () => { let url_cancel let url_return - let action: Parameters[0]['action'] + let action: SubscriptionAction switch (paymentSystem) { case PaymentSystem.Paymee: - url_cancel = `${window.origin}/failed-paymee` + url_cancel = `${window.origin}${PAGES.failedPaymee}` url_return = null // paymee не умеет работать с подписками - action = 'one_payment' + action = SubscriptionAction.OnePayment break default: url_return = `${window.location.origin}${PAGES.thanksForSubscribe}` - action = pass === 'pass_match_access' ? 'one_payment' : 'create_subscription' + action = defaultAction break } diff --git a/src/features/BuyMatchPopup/index.tsx b/src/features/BuyMatchPopup/index.tsx index b8efaa2d..a0932bc6 100644 --- a/src/features/BuyMatchPopup/index.tsx +++ b/src/features/BuyMatchPopup/index.tsx @@ -23,10 +23,10 @@ export const BuyMatchPopup = () => { const { close, currentStep, - match, + isPopupOpen, } = useBuyMatchPopupStore() - if (!match || !currentStep) return null + if (!isPopupOpen || !currentStep) return null const Step = components[currentStep] diff --git a/src/features/BuyMatchPopup/store/hooks/index.tsx b/src/features/BuyMatchPopup/store/hooks/index.tsx index 4de6393c..2f16a9d7 100644 --- a/src/features/BuyMatchPopup/store/hooks/index.tsx +++ b/src/features/BuyMatchPopup/store/hooks/index.tsx @@ -33,6 +33,9 @@ import { SubscriptionType, } from 'features/BuyMatchPopup/types' import { getProfileUrl } from 'features/ProfileLink/helpers' +import { MatchAccess } from 'features/Matches/helpers/getMatchClickAction' + +import { useToggle } from 'hooks' import { isSubscribePopup } from 'helpers' @@ -57,6 +60,11 @@ export const useBuyMatchPopup = () => { const [disabledBuyBtn, setDisabledBuyBtn] = useState(false) const [showClearBtn, setShowClearBtn] = useState(false) const [lastSelectedPackage, setLastSelectedPackage] = useState('') + const { + close, + isOpen, + open, + } = useToggle() const setDataHighlights = useSetRecoilState(dataForPayHighlights) const goTo = useCallback( @@ -93,8 +101,9 @@ export const useBuyMatchPopup = () => { const openPopup = useCallback((matchData: Match) => { setMatch(matchData) + open() setSteps([]) - }, []) + }, [open]) useEffect(() => { if (isEmpty(matchSubscriptions)) return @@ -108,7 +117,7 @@ export const useBuyMatchPopup = () => { }, [matchSubscriptions, onSubscriptionSelect]) const closePopup = () => { - setMatch(null) + close() setSteps([]) setError('') resetSubscriptions() @@ -132,6 +141,7 @@ export const useBuyMatchPopup = () => { const postPaymentHandler = () => { if (!match) return if (!isSubscribePopup()) { + setMatch((prev) => prev && { ...prev, access: MatchAccess.RedirectToProfile }) redirectToMatchProfile(match) } closePopup() @@ -215,6 +225,7 @@ export const useBuyMatchPopup = () => { goBack, goTo, hasPreviousStep: size(steps) > 1, + isPopupOpen: isOpen, lastSelectedPackage, loader, match, diff --git a/src/features/BuyMatchPopup/types.tsx b/src/features/BuyMatchPopup/types.tsx index c72f6fa9..370fc8cb 100644 --- a/src/features/BuyMatchPopup/types.tsx +++ b/src/features/BuyMatchPopup/types.tsx @@ -2,6 +2,7 @@ import type { SubscriptionResponse, Subscription } from 'requests/getSubscriptio import type { LexicsId, Values } from 'features/LexicsStore/types' import type { Match as MatchBase } from 'features/Matches/hooks' +import { MatchAccess } from 'features/Matches/helpers/getMatchClickAction' export enum Steps { CardSelection = 'CardSelection', @@ -42,7 +43,9 @@ export type Match = Pick +)> & { + access?: MatchAccess, +} export type MatchSubscription = Pick { - const { profile: matchProfile } = useMatchPageStore() - const { open: openBuyMatchPopup } = useBuyMatchPopupStore() + const { profile: matchProfile, setMatchProfile } = useMatchPageStore() + const { match, open: openBuyMatchPopup } = useBuyMatchPopupStore() const { profileId: matchId, sportType } = usePageParams() const { user } = useAuthStore() + const history = useHistory() + + const checkAccess = async () => { + const profile = await getMatchInfo(sportType, matchId) + + if (!profile?.sub) { + history.replace(PAGES.home) + } + } useEffect(() => { + let timer: NodeJS.Timeout + if ((user && matchProfile - && !matchProfile.sub) + && !matchProfile.sub + && match?.access !== MatchAccess.RedirectToProfile) || (matchProfile && isSubscribePopup())) { const profile = prepareMatchProfile({ matchId, @@ -32,12 +50,26 @@ export const SubscriptionGuard = ({ children }: Props) => { }) openBuyMatchPopup(profile) } + + if (match?.access === MatchAccess.RedirectToProfile) { + setMatchProfile((profile) => profile && { + ...profile, + access: true, + sub: true, + }) + + timer = setTimeout(checkAccess, 30000) + } + + return () => timer && clearTimeout(timer) + // eslint-disable-next-line react-hooks/exhaustive-deps }, [ matchId, openBuyMatchPopup, - matchProfile, + matchProfile?.sub, sportType, user, + match?.access, ]) return ( diff --git a/src/features/MatchPage/store/hooks/index.tsx b/src/features/MatchPage/store/hooks/index.tsx index e4624170..280c4ede 100644 --- a/src/features/MatchPage/store/hooks/index.tsx +++ b/src/features/MatchPage/store/hooks/index.tsx @@ -453,6 +453,7 @@ export const useMatchPage = () => { setIsPlayingFiltersEpisodes: isStatsPlaylist ? setStatsIsPlayinFiltersEpisodes : setIsPlayersStatsFetching, + setMatchProfile, setPlaingOrder: isStatsPlaylist ? setStatsPlaingOrder : setPlaingOrder, setPlayingData, setPlayingProgress, diff --git a/src/helpers/callApi/logoutIfUnauthorized.tsx b/src/helpers/callApi/logoutIfUnauthorized.tsx index d9958362..e815f1fc 100644 --- a/src/helpers/callApi/logoutIfUnauthorized.tsx +++ b/src/helpers/callApi/logoutIfUnauthorized.tsx @@ -1,12 +1,11 @@ -import * as Sentry from '@sentry/react' +// import * as Sentry from '@sentry/react' export const logoutIfUnauthorized = async (response: Response) => { /* отключили из-за доступа без авторизации */ - const body = await response.json() - if (response.status === 400) { - Sentry.captureException(body) - } + // if (response.status === 400) { + // Sentry.captureException(body) + // } if (response.status === 401 || response.status === 403) { window.dispatchEvent(new Event('FORBIDDEN_REQUEST')) @@ -16,5 +15,6 @@ export const logoutIfUnauthorized = async (response: Response) => { // eslint-disable-next-line no-console console.error(error) + const body = await response.json() return Promise.reject(body) } diff --git a/src/index.tsx b/src/index.tsx index 32b41c61..16d8318c 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -5,24 +5,23 @@ import { } from 'react' import ReactDOM from 'react-dom' -import * as Sentry from '@sentry/react' -import { BrowserTracing } from '@sentry/react' - -import { isIOS, ENV } from 'config' - -// import { makeServer } from 'utilits/mirage/Mirage' +import { isIOS } from 'config/userAgent' +// import { makeServer } from 'utilits/mirage/server' +// import * as Sentry from '@sentry/react' +// import { BrowserTracing } from '@sentry/react' import * as serviceWorker from './serviceWorker' - -if (process.env.NODE_ENV !== 'development') { - Sentry.init({ - dsn: 'https://bbe0cdfb954644ebaf3be16bb472cc3d@sentry.insports.tv/21', - environment: ENV, - integrations: [new BrowserTracing()], - normalizeDepth: 5, - tracesSampleRate: 1.0, - }) -} +// import { ENV } from './config' + +// if (process.env.NODE_ENV !== 'development') { +// Sentry.init({ +// dsn: 'https://bbe0cdfb954644ebaf3be16bb472cc3d@sentry.insports.tv/21', +// environment: ENV, +// integrations: [new BrowserTracing()], +// normalizeDepth: 5, +// tracesSampleRate: 1.0, +// }) +// } export const App = process.env.REACT_APP_TYPE === 'auth-service' ? lazy(() => import('features/AuthServiceApp')) diff --git a/src/requests/getPaymentUrl.tsx b/src/requests/getPaymentUrl.tsx index 325a513d..781a3a81 100644 --- a/src/requests/getPaymentUrl.tsx +++ b/src/requests/getPaymentUrl.tsx @@ -4,8 +4,13 @@ import { callApi } from 'helpers' import type { SubscriptionResponse } from 'requests/getSubscriptions' +export enum SubscriptionAction { + CreateSubscription = 'create_subscription', + OnePayment = 'one_payment' +} + type Props = { - action: 'one_payment' | 'create_subscription', + action: SubscriptionAction, item: SubscriptionResponse, product_name: string, service: string,