develop #120

Merged
andrey.dekterev merged 18 commits from develop into master 3 years ago
  1. 111
      .drone.yml
  2. 2
      package.json
  3. 22
      public/images/score-switch-tunisia-off.svg
  4. 29
      public/images/score-switch-tunisia-on.svg
  5. BIN
      public/images/tunisia-logo-white.png
  6. 9
      public/index.html
  7. 15
      public/silent-refresh.html
  8. 2
      src/components/ItemInfo/ItemInfo.tsx
  9. 2
      src/config/clients/tunisia.tsx
  10. 2
      src/config/clients/types.tsx
  11. 13
      src/features/AddCardForm/components/Form/index.tsx
  12. 11
      src/features/AddCardForm/index.tsx
  13. 2
      src/features/App/index.tsx
  14. 4
      src/features/AuthServiceApp/components/ChangePassword/index.tsx
  15. 6
      src/features/AuthServiceApp/components/LanguageSelect/styled.tsx
  16. 14
      src/features/AuthServiceApp/components/Login/index.tsx
  17. 14
      src/features/AuthServiceApp/components/RecoveryPopup/index.tsx
  18. 17
      src/features/AuthServiceApp/components/RecoveryPopup/styled.tsx
  19. 4
      src/features/AuthServiceApp/components/RegisterPopup/index.tsx
  20. 10
      src/features/AuthServiceApp/components/RegisterPopup/styled.tsx
  21. 4
      src/features/AuthServiceApp/components/Registration/index.tsx
  22. 4
      src/features/AuthServiceApp/components/Registration/styled.tsx
  23. 1
      src/features/AuthServiceApp/config/clients/facr.tsx
  24. 4
      src/features/AuthServiceApp/config/clients/tunisia.tsx
  25. 2
      src/features/AuthServiceApp/config/clients/types.tsx
  26. 8
      src/features/AuthServiceApp/hooks/useAuthFields.tsx
  27. 10
      src/features/AuthServiceApp/styled.tsx
  28. 5
      src/features/AuthStore/config.tsx
  29. 2
      src/features/AuthStore/helpers.tsx
  30. 103
      src/features/AuthStore/hooks/useAuth.tsx
  31. 6
      src/features/BuyMatchPopup/components/CardStep/index.tsx
  32. 1
      src/features/BuyMatchPopup/components/IframePayment/styled.tsx
  33. 8
      src/features/BuyMatchPopup/components/PackageSelectionStep/index.tsx
  34. 2
      src/features/BuyMatchPopup/components/PackagesList/styled.tsx
  35. 2
      src/features/BuyMatchPopup/styled.tsx
  36. 27
      src/features/Combobox/styled.tsx
  37. 2
      src/features/Common/Input/styled.tsx
  38. 2
      src/features/Common/Tabs/index.tsx
  39. 2
      src/features/FavoritesMobilePopup/components/GroupBlock/styled.tsx
  40. 38
      src/features/GlobalStores/index.tsx
  41. 4
      src/features/HeaderFilters/components/DatePicker/styled.tsx
  42. 3
      src/features/HeaderMobile/styled.tsx
  43. 2
      src/features/ItemsList/styled.tsx
  44. 2
      src/features/MatchCard/CardFrontside/MatchCardMobile/styled.tsx
  45. 4
      src/features/MatchCard/styled.tsx
  46. 4
      src/features/MatchPage/components/FavouriteTeam/hooks.tsx
  47. 4
      src/features/MatchPage/components/FavouriteTeam/styled.tsx
  48. 1
      src/features/MatchPage/components/FinishedMatch/styled.tsx
  49. 5
      src/features/MatchPage/index.tsx
  50. 2
      src/features/MatchPage/store/hooks/useTournamentData.tsx
  51. 1
      src/features/MatchPopup/components/LiveMatchPopup/styled.tsx
  52. 4
      src/features/MatchPopup/components/LivePlaylistPage/styled.tsx
  53. 9
      src/features/MatchPopup/components/SimplePlaylistButton/styled.tsx
  54. 4
      src/features/MatchSidePlaylists/components/FiltersPopup/styled.tsx
  55. 6
      src/features/MatchSidePlaylists/components/TabStats/styled.tsx
  56. 7
      src/features/MatchSidePlaylists/styled.tsx
  57. 3
      src/features/MatchesGrid/index.tsx
  58. 2
      src/features/Modal/styled.tsx
  59. 1
      src/features/NoNetworkPopup/styled.tsx
  60. 1
      src/features/PreferencesPopup/styled.tsx
  61. 14
      src/features/ProfileHeader/index.tsx
  62. 25
      src/features/ProfileHeader/styled.tsx
  63. 12
      src/features/Search/index.tsx
  64. 8
      src/features/Search/styled.tsx
  65. 1
      src/features/SportsFilter/components/SelectSportPopup/styled.tsx
  66. 16
      src/features/StreamPlayer/hooks/index.tsx
  67. 1
      src/features/StreamPlayer/index.tsx
  68. 66
      src/features/Theme/config.tsx
  69. 28
      src/features/Theme/index.tsx
  70. 1
      src/features/TournamentLanding/hooks.tsx
  71. 3
      src/features/TournamentLanding/index.tsx
  72. 30
      src/features/TournamentLanding/styled.tsx
  73. 2
      src/features/TournamentList/components/CollapseTournament/index.tsx
  74. 2
      src/features/TournamentList/components/CollapseTournament/styled.tsx
  75. 2
      src/features/TournamentList/components/TournamentMobile/styled.tsx
  76. 28
      src/features/TournamentList/hooks.tsx
  77. 18
      src/features/TournamentList/index.tsx
  78. 1
      src/features/TournamentsPopup/styled.tsx
  79. 2
      src/features/UserAccount/components/BankCard/styled.tsx
  80. 8
      src/features/UserAccount/components/CancelSubPopup/styled.tsx
  81. 1
      src/features/UserAccount/components/ChangeCardPopup/styled.tsx
  82. 1
      src/features/UserAccount/components/PageBankCards/styled.tsx
  83. 2
      src/features/UserAccount/components/PageSubscriptions/styled.tsx
  84. 4
      src/features/UserAccount/components/PersonalInfoForm/hooks/useUserInfo.tsx
  85. 4
      src/features/UserAccount/components/PersonalInfoForm/index.tsx
  86. 2
      src/features/UserAccount/components/PersonalInfoForm/styled.tsx
  87. 3
      src/features/UserAccount/index.tsx
  88. 2
      src/features/UserAccount/styled.tsx
  89. 3
      src/features/VideoPlayer/index.tsx
  90. 11
      src/helpers/getSwitchScoreIconName/index.tsx
  91. 3
      src/helpers/index.tsx
  92. 3
      src/helpers/isMatchPage/index.tsx
  93. 2
      src/helpers/token/index.tsx
  94. 78
      src/pages/DiwanInsportsTv/index.tsx
  95. 301
      src/pages/DiwanInsportsTv/styled.tsx
  96. 1
      src/pages/HighlightsPage/components/ThanksPopup/styled.tsx
  97. 2
      src/requests/getFavouriteTeam.tsx
  98. 2
      src/requests/index.tsx

@ -174,34 +174,34 @@ steps:
depends_on: depends_on:
- make-lff - make-lff
# - name: make-diwansport - name: make-diwansport
# image: node:16-alpine image: node:16-alpine
# environment: environment:
# REACT_APP_STRIPE_PK: REACT_APP_STRIPE_PK:
# from_secret: REACT_APP_STRIPE_PK from_secret: REACT_APP_STRIPE_PK
# commands: commands:
# - apk add --no-cache make - apk add --no-cache make
# - make diwansport-prod - make diwansport-prod
# depends_on: depends_on:
# - npm-install - npm-install
# - name: deploy-diwansport - name: deploy-diwansport
# image: amazon/aws-cli:latest image: amazon/aws-cli:latest
# environment: environment:
# AWS_ACCESS_KEY_ID: AWS_ACCESS_KEY_ID:
# from_secret: AWS_ACCESS_KEY_ID from_secret: AWS_ACCESS_KEY_ID
# AWS_SECRET_ACCESS_KEY: AWS_SECRET_ACCESS_KEY:
# from_secret: AWS_SECRET_ACCESS_KEY from_secret: AWS_SECRET_ACCESS_KEY
# AWS_DEFAULT_REGION: AWS_DEFAULT_REGION:
# from_secret: AWS_DEFAULT_REGION from_secret: AWS_DEFAULT_REGION
# AWS_MAX_ATTEMPTS: 10 AWS_MAX_ATTEMPTS: 10
# commands: commands:
# - aws s3 sync build_insports-diwansport s3://insports-diwansport --delete - aws s3 sync build_insports-diwansport s3://insports-diwansport --delete
# - aws cloudfront create-invalidation --distribution-id E3LKAH6TR4O2JL --paths "/*" # # diwansport.net - aws cloudfront create-invalidation --distribution-id E3LKAH6TR4O2JL --paths "/*" # # diwansport.net
# - aws cloudfront create-invalidation --distribution-id E3NJ2G0QSB6MVI --paths "/*" # tunisia.insports.tv - aws cloudfront create-invalidation --distribution-id E3NJ2G0QSB6MVI --paths "/*" # tunisia.insports.tv
# depends_on: depends_on:
# - make-diwansport - make-diwansport
--- ---
kind: pipeline kind: pipeline
@ -754,3 +754,58 @@ steps:
- rsync -v -r -C build_auth/ ubuntu@auth.insports.tv:/home/ubuntu/ott-auth/src/frontend/ - rsync -v -r -C build_auth/ ubuntu@auth.insports.tv:/home/ubuntu/ott-auth/src/frontend/
depends_on: depends_on:
- make-auth - make-auth
---
kind: pipeline
type: docker
name: deploy diwan.insports.tv
concurrency:
limit: 1
platform:
os: linux
arch: amd64
trigger:
ref:
- refs/heads/diwan.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-diwansport
image: node:16-alpine
environment:
REACT_APP_STRIPE_PK:
from_secret: REACT_APP_STRIPE_PK
commands:
- apk add --no-cache make
- make diwansport-prod
depends_on:
- npm-install
- name: deploy-diwansport
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_tunisia s3://insports-diwansport --delete
- aws cloudfront create-invalidation --distribution-id E3LKAH6TR4O2JL --paths "/*" # # diwansport.net
- aws cloudfront create-invalidation --distribution-id E3NJ2G0QSB6MVI --paths "/*" # tunisia.insports.tv
depends_on:
- make-diwansport

@ -17,7 +17,7 @@
"facr": "REACT_APP_CLIENT=facr react-scripts start", "facr": "REACT_APP_CLIENT=facr react-scripts start",
"lff": "REACT_APP_CLIENT=lff react-scripts start", "lff": "REACT_APP_CLIENT=lff react-scripts start",
"india": "REACT_APP_CLIENT=india react-scripts start", "india": "REACT_APP_CLIENT=india react-scripts start",
"tunis": "REACT_APP_CLIENT=tunis react-scripts start", "tunisia": "REACT_APP_CLIENT=tunisia react-scripts start",
"insports": "REACT_APP_CLIENT=insports react-scripts start" "insports": "REACT_APP_CLIENT=insports react-scripts start"
}, },
"dependencies": { "dependencies": {

@ -0,0 +1,22 @@
<svg width="38" height="23" viewBox="0 0 38 23" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M31 18H11C7.1 18 4 14.9 4 11C4 7.1 7.1 4 11 4H31C34.9 4 38 7.1 38 11C38 14.9 34.9 18 31 18Z" fill="white" fill-opacity="0.4"/>
<g filter="url(#filter0_dd_1_1015)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M11 21C16.5228 21 21 16.5228 21 11C21 5.47715 16.5228 1 11 1C5.47715 1 1 5.47715 1 11C1 16.5228 5.47715 21 11 21Z" fill="#E1E1E1"/>
</g>
<defs>
<filter id="filter0_dd_1_1015" x="0" y="0" width="22" height="23" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="1"/>
<feGaussianBlur stdDeviation="0.5"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.237602 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1_1015"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="0.5"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.12 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_1_1015" result="effect2_dropShadow_1_1015"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_1_1015" result="shape"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

@ -0,0 +1,29 @@
<svg width="38" height="23" viewBox="0 0 38 23" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M7 4L27 4C30.9 4 34 7.1 34 11C34 14.9 30.9 18 27 18L7 18C3.1 18 2.71011e-07 14.9 6.11959e-07 11C9.52908e-07 7.1 3.1 4 7 4Z"
fill="#0E8F84" />
<g filter="url(#filter0_dd_1_1076)">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M27 0.999999C21.4772 0.999999 17 5.47715 17 11C17 16.5228 21.4772 21 27 21C32.5228 21 37 16.5228 37 11C37 5.47715 32.5228 1 27 0.999999Z"
fill="#E1E1E1" />
</g>
<defs>
<filter id="filter0_dd_1_1076" x="16" y="0" width="22" height="23" filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix" />
<feColorMatrix in="SourceAlpha" type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dy="1" />
<feGaussianBlur stdDeviation="0.5" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.237602 0" />
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1_1076" />
<feColorMatrix in="SourceAlpha" type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset />
<feGaussianBlur stdDeviation="0.5" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.12 0" />
<feBlend mode="normal" in2="effect1_dropShadow_1_1076" result="effect2_dropShadow_1_1076" />
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_1_1076" result="shape" />
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

@ -59,5 +59,14 @@
<!-- Start of ChromeCast script --> <!-- Start of ChromeCast script -->
<script src="//www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script> <script src="//www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>
<!-- End of ChromeCast script --> <!-- End of ChromeCast script -->
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-LZXGB5GJG0"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-LZXGB5GJG0');
</script>
</body> </body>
</html> </html>

@ -1,15 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/oidc-client/1.11.5/oidc-client.min.js" integrity="sha512-pGtU1n/6GJ8fu6bjYVGIOT9Dphaw5IWPwVlqkpvVgqBxFkvdNbytUh0H8AP15NYF777P4D3XEeA/uDWFCpSQ1g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script>
new Oidc.UserManager().signinSilentCallback()
.catch((err) => {
console.error('OIDC: silent refresh callback error', err);
});
</script>
</body>
</html>

@ -29,7 +29,7 @@ export const ItemInfo = ({
type, type,
}: ItemInfoType) => ( }: ItemInfoType) => (
<ScWrapper onClick={onClick}> <ScWrapper onClick={onClick}>
<ScLogo src={`${URL_AWS}media/${PROFILE_NAMES[type]}/${SportTypes[sportId]}/${id}/logo.jpg`} /> <ScLogo src={`${URL_AWS}/media/${PROFILE_NAMES[type]}/${sportId}/${id}/logo.jpg`} />
<ScName active={active}>{name}</ScName> <ScName active={active}>{name}</ScName>
</ScWrapper> </ScWrapper>
) )

@ -34,7 +34,7 @@ export const tunisia: ClientConfig = {
logo: 'tunis-logo.svg', logo: 'tunis-logo.svg',
logoHeight: 1.922, logoHeight: 1.922,
logoLeft: 1.1, logoLeft: 1.1,
logoTop: 1.74, logoTop: 1.14,
logoWidth: 9, logoWidth: 9,
matchLogoHeight: 1.922, matchLogoHeight: 1.922,
matchLogoTopMargin: 1, matchLogoTopMargin: 1,

@ -11,7 +11,7 @@ export enum ClientIds {
Insports = 'insports-ott-web', Insports = 'insports-ott-web',
Instat = 'ott-web', Instat = 'ott-web',
Lff = 'lff-ott-web', Lff = 'lff-ott-web',
Tunisia = 'tunis-ott-web', Tunisia = 'tunisia-ott-web',
} }
export enum ClientNames { export enum ClientNames {

@ -11,6 +11,7 @@ import { PAGES } from 'config/pages'
import { T9n } from 'features/T9n' import { T9n } from 'features/T9n'
import { useCardsStore } from 'features/CardsStore' import { useCardsStore } from 'features/CardsStore'
import { ArrowLoader } from 'features/ArrowLoader' import { ArrowLoader } from 'features/ArrowLoader'
import { SolidButton } from 'features/UserAccount/styled'
import { ElementContainer } from '../ElementContainer' import { ElementContainer } from '../ElementContainer'
@ -54,10 +55,7 @@ const baseStyles = isMobileDevice
const options = { placeholder: '', style: { base: baseStyles } } const options = { placeholder: '', style: { base: baseStyles } }
export const AddCardFormInner = (props: Props) => { export const AddCardFormInner = (props: Props) => {
const { const { inputsBackground } = props
children,
inputsBackground,
} = props
const { error: cardError } = useCardsStore() const { error: cardError } = useCardsStore()
const isUserAccountPage = useRouteMatch(PAGES.useraccount)?.path === PAGES.useraccount const isUserAccountPage = useRouteMatch(PAGES.useraccount)?.path === PAGES.useraccount
@ -234,7 +232,12 @@ export const AddCardFormInner = (props: Props) => {
<T9n t={cardError} /> <T9n t={cardError} />
</Errors> </Errors>
) } ) }
{loader ? <ArrowLoader disabled width='204px' /> : children} <SolidButton type='submit'>
{loader
? <ArrowLoader disabled /> : (
<T9n t='save' />
)}
</SolidButton>
</ButtonsBlock> </ButtonsBlock>
</Form> </Form>
) )

@ -1,12 +1,13 @@
import type { MouseEvent } from 'react' import type { MouseEvent } from 'react'
import { useTheme } from 'styled-components'
import { useToggle } from 'hooks' import { useToggle } from 'hooks'
import { T9n } from 'features/T9n' import { T9n } from 'features/T9n'
import { import {
OutlineButton, OutlineButton,
Icon, Icon,
SolidButton,
} from 'features/UserAccount/styled' } from 'features/UserAccount/styled'
import type { Props } from './components/Form/hooks' import type { Props } from './components/Form/hooks'
@ -17,6 +18,7 @@ export const AddCardForm = ({
onAddSuccess, onAddSuccess,
}: Props) => { }: Props) => {
const { isOpen, toggle } = useToggle(initialformOpen) const { isOpen, toggle } = useToggle(initialformOpen)
const { colors } = useTheme()
const onAddClick = (e: MouseEvent) => { const onAddClick = (e: MouseEvent) => {
e.stopPropagation() e.stopPropagation()
@ -33,11 +35,8 @@ export const AddCardForm = ({
? ( ? (
<AddCardFormInner <AddCardFormInner
onAddSuccess={onSuccess} onAddSuccess={onSuccess}
> inputsBackground={colors.inputs}
<SolidButton type='submit'> />
<T9n t='save' />
</SolidButton>
</AddCardFormInner>
) )
: ( : (
<OutlineButton <OutlineButton

@ -35,7 +35,7 @@ const Main = () => {
const queryClient = new QueryClient() const queryClient = new QueryClient()
useEffect(() => { useEffect(() => {
readToken() && setIsToken(true) if (userInfo) readToken() && setIsToken(true)
}, [userInfo]) }, [userInfo])
// имеется действующий токен // имеется действующий токен

@ -1,5 +1,4 @@
import { T9n } from 'features/T9n' import { T9n } from 'features/T9n'
import { ArrowLoader } from 'features/ArrowLoader'
import { PasswordInput } from '../PasswordInput' import { PasswordInput } from '../PasswordInput'
import { Logo } from '../Logo' import { Logo } from '../Logo'
@ -19,6 +18,7 @@ import {
ChangePasswordModalTitle, ChangePasswordModalTitle,
ChangePasswordModalText, ChangePasswordModalText,
ChangePasswordModalButton, ChangePasswordModalButton,
ScArrowLoader,
} from '../../styled' } from '../../styled'
const ChangePassword = () => { const ChangePassword = () => {
@ -88,7 +88,7 @@ const ChangePassword = () => {
<ButtonSolid disabled={isSubmitDisabled}> <ButtonSolid disabled={isSubmitDisabled}>
{ {
isFetching isFetching
? <ArrowLoader /> ? <ScArrowLoader />
: <T9n t='change_password' /> : <T9n t='change_password' />
} }
</ButtonSolid> </ButtonSolid>

@ -50,7 +50,7 @@ export const ListWrapper = styled.div`
top: calc(100% - 4px); top: calc(100% - 4px);
left: 0; left: 0;
padding: 10px; padding: 10px;
background-color: #333333; background-color: ${({ theme }) => theme.colors.comboboxBackground};
box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3); box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3);
border-radius: 2px; border-radius: 2px;
` `
@ -142,8 +142,8 @@ type FlagIconProps = {
export const FlagIcon = styled.span<FlagIconProps>` export const FlagIcon = styled.span<FlagIconProps>`
display: inline-block; display: inline-block;
width: 20px; width: 24px;
height: 14px; height: 16px;
background-image: url('/images/flags-sprite.png'); background-image: url('/images/flags-sprite.png');
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 360px; background-size: 360px;

@ -1,5 +1,4 @@
import { T9n } from 'features/T9n' import { T9n } from 'features/T9n'
import { ArrowLoader } from 'features/ArrowLoader'
import { RecoveryPopup } from 'features/AuthServiceApp/components/RecoveryPopup' import { RecoveryPopup } from 'features/AuthServiceApp/components/RecoveryPopup'
import { client } from 'features/AuthServiceApp/config/clients' import { client } from 'features/AuthServiceApp/config/clients'
@ -33,6 +32,7 @@ import {
LanguageSelectWrapper, LanguageSelectWrapper,
Wrapper, Wrapper,
ScLoaderWrapper, ScLoaderWrapper,
ScArrowLoader,
} from '../../styled' } from '../../styled'
import { CompanyInfo } from '../../../CompanyInfo' import { CompanyInfo } from '../../../CompanyInfo'
@ -109,18 +109,18 @@ const Login = () => {
<T9n t={formError} /> <T9n t={formError} />
<T9n t={authError} /> <T9n t={authError} />
</Error> </Error>
<ButtonSolid type='submit' disabled={isSubmitDisabled}>
{ {
isFetching isFetching
? ( ? (
<ScLoaderWrapper> <ScLoaderWrapper>
<ArrowLoader /> <ScArrowLoader />
</ScLoaderWrapper> </ScLoaderWrapper>
) : ( ) : (<T9n t='login' />)
<ButtonSolid type='submit' disabled={isSubmitDisabled}>
<T9n t='login' />
</ButtonSolid>
)
} }
</ButtonSolid>
<RegisterButton to={`${PAGES.registration}${window.location.search}`}> <RegisterButton to={`${PAGES.registration}${window.location.search}`}>
<T9n t='register' /> <T9n t='register' />
</RegisterButton> </RegisterButton>

@ -3,7 +3,6 @@ import { Fragment } from 'react'
import { T9n } from 'features/T9n' import { T9n } from 'features/T9n'
import { ArrowLoader } from 'features/ArrowLoader' import { ArrowLoader } from 'features/ArrowLoader'
import { client } from 'features/AuthServiceApp/config/clients'
import { useRecovery } from './hooks' import { useRecovery } from './hooks'
import { import {
@ -15,10 +14,11 @@ import {
ApplyButton, ApplyButton,
Text, Text,
Body, Body,
ScInput,
ScInputGroup,
} from './styled' } from './styled'
import { Input } from '../../../../components/Input' import { Error } from '../../styled'
import { InputGroup, Error } from '../../styled'
type Props = { type Props = {
isModalOpen: boolean, isModalOpen: boolean,
@ -57,8 +57,8 @@ export const RecoveryPopup = (props: Props) => {
</Text> </Text>
) : ( ) : (
<Fragment> <Fragment>
<InputGroup> <ScInputGroup>
<Input <ScInput
autoFocus autoFocus
type='email' type='email'
name='email' name='email'
@ -66,7 +66,7 @@ export const RecoveryPopup = (props: Props) => {
placeholderLexic='registration_email' placeholderLexic='registration_email'
onChange={onEmailChange} onChange={onEmailChange}
/> />
</InputGroup> </ScInputGroup>
<Error> <Error>
<T9n t={error} /> <T9n t={error} />
</Error> </Error>
@ -76,7 +76,7 @@ export const RecoveryPopup = (props: Props) => {
{!isSendMessage ? ( {!isSendMessage ? (
<ApplyButton onClick={handleSubmit} disabled={isSendBtnDisabled}> <ApplyButton onClick={handleSubmit} disabled={isSendBtnDisabled}>
{isFetching {isFetching
? <ArrowLoader color={client.styles.popupLoader} /> ? <ArrowLoader />
: <T9n t='send' />} : <T9n t='send' />}
</ApplyButton> </ApplyButton>
) : ( ) : (

@ -10,6 +10,10 @@ import { Header as BaseHeader } from 'features/PopupComponents'
import { ButtonSolid } from 'features/Common' import { ButtonSolid } from 'features/Common'
import { client } from 'features/AuthServiceApp/config/clients' import { client } from 'features/AuthServiceApp/config/clients'
import { Input } from 'components/Input'
import { InputGroup } from '../../styled'
export const Modal = styled(BaseModal)` export const Modal = styled(BaseModal)`
background-color: rgba(0, 0, 0, 0.7); background-color: rgba(0, 0, 0, 0.7);
padding: 0 60px; padding: 0 60px;
@ -18,8 +22,7 @@ export const Modal = styled(BaseModal)`
width: 577px; width: 577px;
max-width: 577px; max-width: 577px;
max-height: 414px; max-height: 414px;
padding-top: 60px; padding-top: 40px;
background-color: #333333;
border-radius: 5px; border-radius: 5px;
@media (max-width: 1370px) { @media (max-width: 1370px) {
@ -105,11 +108,19 @@ export const Body = styled.div`
: ''}; : ''};
` `
export const ScInput = styled(Input)`
background-color: ${({ theme }) => theme.colors.inputs};
`
export const ScInputGroup = styled(InputGroup)`
${client.styles.forgotPasswordInput}
`
export const Footer = styled.div` export const Footer = styled.div`
width: 100%; width: 100%;
display: flex; display: flex;
justify-content: center; justify-content: center;
padding: 1.89rem; padding: 10px 0 25px;
${isMobileDevice ${isMobileDevice
? css` ? css`
@media ${devices.mobile}{ @media ${devices.mobile}{

@ -8,8 +8,8 @@ import {
Body, Body,
Footer, Footer,
ApplyButton, ApplyButton,
// SendConfirmationButton,
Text, Text,
ScEmail,
} from './styled' } from './styled'
type Props = { type Props = {
@ -36,7 +36,7 @@ export const RegisterPopup = (props: Props) => {
<Body> <Body>
<Text> <Text>
<T9n t='to_email' />&nbsp; <T9n t='to_email' />&nbsp;
{email}&nbsp; <ScEmail>{email}</ScEmail>&nbsp;
<T9n t='send_confirm' />&nbsp; <T9n t='send_confirm' />&nbsp;
</Text> </Text>
<Text> <Text>

@ -15,10 +15,9 @@ export const Modal = styled(BaseModal)`
padding: 0 60px; padding: 0 60px;
${ModalWindow} { ${ModalWindow} {
max-width: 757px; max-width: 949px;
min-height: 414px; min-height: 414px;
padding-top: 60px; padding-top: 60px;
background-color: #333333;
border-radius: 5px; border-radius: 5px;
@media (max-width: 1370px) { @media (max-width: 1370px) {
@ -110,7 +109,8 @@ export const Footer = styled.div`
width: 100%; width: 100%;
display: flex; display: flex;
justify-content: center; justify-content: center;
padding: 1.89rem; padding: 10px 0 25px;
${isMobileDevice ${isMobileDevice
? css` ? css`
@media ${devices.mobile}{ @media ${devices.mobile}{
@ -149,3 +149,7 @@ export const ApplyButton = styled(ButtonSolid)`
export const Text = styled.span` export const Text = styled.span`
margin-bottom: 20px; margin-bottom: 20px;
` `
export const ScEmail = styled.span`
font-weight: 700;
`

@ -4,7 +4,6 @@ import { useHistory } from 'react-router'
import { T9n } from 'features/T9n' import { T9n } from 'features/T9n'
import { Checkbox } from 'features/Common/Checkbox' import { Checkbox } from 'features/Common/Checkbox'
import { ArrowLoader } from 'features/ArrowLoader'
import { RegisterPopup } from 'features/AuthServiceApp/components/RegisterPopup' import { RegisterPopup } from 'features/AuthServiceApp/components/RegisterPopup'
import { client } from 'features/AuthServiceApp/config/clients' import { client } from 'features/AuthServiceApp/config/clients'
import { CompanyInfo } from 'features/CompanyInfo' import { CompanyInfo } from 'features/CompanyInfo'
@ -26,6 +25,7 @@ import {
Error, Error,
LanguageSelectWrapper, LanguageSelectWrapper,
Wrapper, Wrapper,
ScArrowLoader,
} from '../../styled' } from '../../styled'
import { import {
Label, Label,
@ -134,7 +134,7 @@ const Registration = () => {
<ButtonSolid disabled={isSubmitDisabled} type='submit'> <ButtonSolid disabled={isSubmitDisabled} type='submit'>
{ {
isFetching isFetching
? <ArrowLoader /> ? <ScArrowLoader />
: <T9n t='sign_up' /> : <T9n t='sign_up' />
} }
</ButtonSolid> </ButtonSolid>

@ -47,4 +47,8 @@ export const Link = styled.a`
color: ${({ theme }) => theme.colors.white}; color: ${({ theme }) => theme.colors.white};
text-decoration: underline; text-decoration: underline;
margin-left: 6px; margin-left: 6px;
:hover {
font-weight: 700;
}
` `

@ -56,7 +56,6 @@ export const facr: ClientConfig = {
background-color: #00257A; background-color: #00257A;
color: ${({ theme }) => theme.colors.white}; color: ${({ theme }) => theme.colors.white};
`, `,
popupLoader: '#FFFFFF',
submitButton: css` submitButton: css`
background-color: ${({ theme }) => theme.colors.white}; background-color: ${({ theme }) => theme.colors.white};
color: #00257A; color: #00257A;

@ -30,6 +30,9 @@ export const tunisia: ClientConfig = {
} }
` : ''}; ` : ''};
`, `,
forgotPasswordInput: css`
border: none;
`,
input: css` input: css`
background-color: transparent; background-color: transparent;
:not(:last-of-type) { :not(:last-of-type) {
@ -59,7 +62,6 @@ export const tunisia: ClientConfig = {
background-color: #0E8F84; background-color: #0E8F84;
color: ${({ theme }) => theme.colors.white}; color: ${({ theme }) => theme.colors.white};
`, `,
popupLoader: '#FFFFFF',
submitButton: css` submitButton: css`
background-color: ${({ theme }) => theme.colors.white}; background-color: ${({ theme }) => theme.colors.white};
color: #0B2E4D; color: #0B2E4D;

@ -17,12 +17,12 @@ export type ClientConfig = {
privacyLink: string, privacyLink: string,
styles: { styles: {
centerBlock?: StyledCss, centerBlock?: StyledCss,
forgotPasswordInput?: StyledCss,
input?: StyledCss, input?: StyledCss,
inputGroup?: StyledCss, inputGroup?: StyledCss,
loader?: StyledCss, loader?: StyledCss,
logo: StyledCss, logo: StyledCss,
popupApplyButton?: StyledCss, popupApplyButton?: StyledCss,
popupLoader?: string,
submitButton?: StyledCss, submitButton?: StyledCss,
}, },
termsLink: string, termsLink: string,

@ -7,6 +7,8 @@ import { useState } from 'react'
import { isValidEmail } from 'features/AuthServiceApp/helpers/isValidEmail' import { isValidEmail } from 'features/AuthServiceApp/helpers/isValidEmail'
import { isValidPassword } from 'features/AuthServiceApp/helpers/isValidPassword' import { isValidPassword } from 'features/AuthServiceApp/helpers/isValidPassword'
import { PAGES } from 'features/AuthServiceApp/config/pages'
export const useAuthFields = (page: 'login'|'registration') => { export const useAuthFields = (page: 'login'|'registration') => {
const [email, setEmail] = useState('') const [email, setEmail] = useState('')
const [password, setPassword] = useState('') const [password, setPassword] = useState('')
@ -20,12 +22,16 @@ export const useAuthFields = (page: 'login'|'registration') => {
const onEmailChange = ({ target: { value } }: ChangeEvent<HTMLInputElement>) => { const onEmailChange = ({ target: { value } }: ChangeEvent<HTMLInputElement>) => {
setError('') setError('')
setEmail(value) setEmail(value)
const isRegisterPage = page === PAGES.registration
if (password.length && !checkPassword(password) && isRegisterPage) {
setError('check_password')
}
} }
const onPasswordChange = ({ target: { value } }: ChangeEvent<HTMLInputElement>) => { const onPasswordChange = ({ target: { value } }: ChangeEvent<HTMLInputElement>) => {
setError('') setError('')
setPassword(value) setPassword(value)
const isRegisterPage = page === 'registration' const isRegisterPage = page === PAGES.registration
if (!checkPassword(value) && isRegisterPage) { if (!checkPassword(value) && isRegisterPage) {
setError('check_password') setError('check_password')
} }

@ -4,6 +4,7 @@ import { isMobileDevice } from 'config/userAgent'
import { ButtonSolid as BaseButtonSolid } from 'features/Common/Button' import { ButtonSolid as BaseButtonSolid } from 'features/Common/Button'
import { T9n } from 'features/T9n' import { T9n } from 'features/T9n'
import { ArrowLoader } from 'features/ArrowLoader'
import { client } from 'features/AuthServiceApp/config/clients' import { client } from 'features/AuthServiceApp/config/clients'
@ -166,6 +167,7 @@ export const ChangePasswordModalWrapper = styled.div`
left: 0; left: 0;
top: 0; top: 0;
display: flex; display: flex;
background: rgba(0, 0, 0, 0.7);
` `
export const ChangePasswordModal = styled.div` export const ChangePasswordModal = styled.div`
@ -173,7 +175,7 @@ export const ChangePasswordModal = styled.div`
justify-content: center; justify-content: center;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
background: #333333; background: ${({ theme }) => theme.colors.modalBackground};
border-radius: 5px; border-radius: 5px;
font-weight: 700; font-weight: 700;
height: 414px; height: 414px;
@ -222,4 +224,10 @@ export const ChangePasswordModalButton = styled(ButtonSolid)`
width: fit-content; width: fit-content;
padding: 0 50px; padding: 0 50px;
cursor: pointer; cursor: pointer;
background: ${({ theme }) => theme.colors.button};
color: ${({ theme }) => theme.colors.white};
`
export const ScArrowLoader = styled(ArrowLoader)`
color: ${({ theme }) => theme.colors.loaderAuth}
` `

@ -0,0 +1,5 @@
import { UserManager } from 'oidc-client'
import { getClientSettings } from './helpers'
export const userManager = new UserManager(getClientSettings())

@ -61,7 +61,6 @@ const redirectUrl = () => {
export const getClientSettings = (): Settings => ({ export const getClientSettings = (): Settings => ({
authority: AUTH_SERVICE, authority: AUTH_SERVICE,
automaticSilentRenew: true,
client_id: client.auth.clientId, client_id: client.auth.clientId,
filterProtocolClaims: false, filterProtocolClaims: false,
loadUserInfo: false, loadUserInfo: false,
@ -70,7 +69,6 @@ export const getClientSettings = (): Settings => ({
response_mode: 'query', response_mode: 'query',
response_type: 'id_token token', response_type: 'id_token token',
scope: 'openid', scope: 'openid',
silent_redirect_uri: `${window.location.origin ?? window.origin}/silent-refresh.html`,
userStore: new WebStorageStateStore({ store: window.localStorage }), userStore: new WebStorageStateStore({ store: window.localStorage }),
}) })

@ -7,7 +7,6 @@ import {
import { useHistory } from 'react-router' import { useHistory } from 'react-router'
import type { User } from 'oidc-client' import type { User } from 'oidc-client'
import { UserManager } from 'oidc-client'
import isString from 'lodash/isString' import isString from 'lodash/isString'
import isBoolean from 'lodash/isBoolean' import isBoolean from 'lodash/isBoolean'
@ -16,34 +15,34 @@ import { PAGES } from 'config'
import { import {
addLanguageUrlParam, addLanguageUrlParam,
} from 'helpers/languageUrlParam'
import {
writeToken, writeToken,
removeToken, removeToken,
readToken, readToken,
} from 'helpers/token'
import {
setCookie, setCookie,
removeCookie, removeCookie,
} from 'helpers/cookie' isMatchPage,
import { isMatchPage } from 'helpers/isMatchPage' TOKEN_KEY,
} from 'helpers'
import { import {
useLocalStore, useLocalStore,
useSessionStore, useSessionStore,
useToggle, useToggle,
useEventListener,
} from 'hooks' } from 'hooks'
import { useLexicsStore } from 'features/LexicsStore' import { useLexicsStore } from 'features/LexicsStore'
import { queryParamStorage } from 'features/QueryParamsStorage' import { queryParamStorage } from 'features/QueryParamsStorage'
import { getUserInfo, UserInfo } from 'requests/getUserInfo' import type { UserInfo, FailedResponse } from 'requests'
import { checkDevice, FailedResponse } from 'requests/checkDevice' import {
import { getTokenVirtualUser } from 'requests/getTokenVirtualUser' getUserInfo,
checkDevice,
getTokenVirtualUser,
} from 'requests'
// eslint-disable-next-line import { userManager } from '../config'
import { getClientSettings, needCheckNewDeviсe } from '../helpers' import { needCheckNewDeviсe } from '../helpers'
export const useAuth = () => { export const useAuth = () => {
const { changeLang, lang } = useLexicsStore() const { changeLang, lang } = useLexicsStore()
@ -55,11 +54,10 @@ export const useAuth = () => {
const [user, setUser] = useState<User>() const [user, setUser] = useState<User>()
const [isNewDeviceLogin, setIsNewDeviceLogin] = useState(false) const [isNewDeviceLogin, setIsNewDeviceLogin] = useState(false)
const [userInfo, setUserInfo] = useState<UserInfo>() const [userInfo, setUserInfo] = useState<UserInfo>()
const userManager = useMemo(() => new UserManager(getClientSettings()), [])
const login = useCallback(async () => { const login = useCallback(async () => {
userManager.signinRedirect({ extraQueryParams: { lang } }) userManager.signinRedirect({ extraQueryParams: { lang } })
}, [userManager, lang]) }, [lang])
const logout = useCallback((key?: string) => { const logout = useCallback((key?: string) => {
setPage(history.location.pathname) setPage(history.location.pathname)
@ -73,7 +71,7 @@ export const useAuth = () => {
removeCookie('access_token') removeCookie('access_token')
} }
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [userManager, lang]) }, [lang])
const storeUser = useCallback((loadedUser: User) => { const storeUser = useCallback((loadedUser: User) => {
setUser(loadedUser) setUser(loadedUser)
@ -102,7 +100,6 @@ export const useAuth = () => {
return loadedUser return loadedUser
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [ }, [
userManager,
storeUser, storeUser,
markUserLoaded, markUserLoaded,
]) ])
@ -173,12 +170,32 @@ export const useAuth = () => {
}).catch(login) }).catch(login)
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [ }, [
userManager,
login, login,
storeUser, storeUser,
markUserLoaded, markUserLoaded,
]) ])
useEventListener({
callback: useCallback(async (e: StorageEvent) => {
const loadedUser = await userManager.getUser()
if (
e.storageArea !== localStorage
|| e.key !== TOKEN_KEY
|| !e.newValue
|| !loadedUser
|| loadedUser.access_token === e.newValue
) return
userManager.storeUser({
...loadedUser,
access_token: e.newValue,
toStorageString: loadedUser.toStorageString,
})
}, []),
event: 'storage',
})
useEffect(() => { useEffect(() => {
const isRedirectedBackFromAuthProvider = history.location.pathname === '/redirect' const isRedirectedBackFromAuthProvider = history.location.pathname === '/redirect'
isRedirectedBackFromAuthProvider ? signinRedirectCallback() : checkUser() isRedirectedBackFromAuthProvider ? signinRedirectCallback() : checkUser()
@ -200,34 +217,41 @@ export const useAuth = () => {
setTimeout(logout, 10000) setTimeout(logout, 10000)
} }
}) })
}, [logout, userManager]) }, [logout])
// eslint-disable-next-line
const checkNewDevice = useCallback(async () => { const checkNewDevice = useCallback(async () => {
const loadedUser = await userManager.getUser() const loadedUser = await userManager.getUser()
if (!loadedUser) return if (!loadedUser) return
checkDevice(loadedUser.access_token).catch(() => { checkDevice(loadedUser.access_token).catch(() => {
setTimeout(reChekNewDevice, 2000) setTimeout(reChekNewDevice, 5000)
}) })
}, [reChekNewDevice, userManager]) }, [reChekNewDevice])
// useEffect(() => { useEffect(() => {
// if (!needCheckNewDeviсe && !user) return undefined if (!needCheckNewDeviсe && !user) return undefined
// const startCheckDevice = setInterval(checkNewDevice, 20000) const startCheckDevice = setInterval(checkNewDevice, 20000)
// isNewDeviceLogin && clearInterval(startCheckDevice) isNewDeviceLogin && clearInterval(startCheckDevice)
// return () => clearInterval(startCheckDevice) return () => clearInterval(startCheckDevice)
//
// // eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
// }, [ }, [
// checkNewDevice, checkNewDevice,
// isNewDeviceLogin, isNewDeviceLogin,
// setIsNewDeviceLogin, setIsNewDeviceLogin,
// ]) ])
useEffect(() => { useEffect(() => {
// попытаемся обновить токен используя refresh_token // попытаемся обновить токен используя refresh_token
const tryRenewToken = () => { const tryRenewToken = () => {
const tokenLastUpdated = Number(localStorage.getItem('token_updated'))
// предотвращаем одновременное обновление токена в разных окнах/вкладках
const needRenewToken = Date.now() - tokenLastUpdated >= userManager.settings.clockSkew! * 1e3
if (!needRenewToken) return
localStorage.setItem('token_updated', String(Date.now()))
userManager.signinSilent() userManager.signinSilent()
.catch(() => user && logout()) .catch(() => user && logout())
} }
@ -241,14 +265,7 @@ export const useAuth = () => {
userManager.events.removeAccessTokenExpired(tryRenewToken) userManager.events.removeAccessTokenExpired(tryRenewToken)
} }
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [userManager, logout]) }, [logout])
useEffect(() => {
// событие срабатывает после получения токена(первый
// логин и обновление токена)
userManager.events.addUserLoaded(storeUser)
return () => userManager.events.removeUserLoaded(storeUser)
}, [userManager, storeUser])
const fetchUserInfo = useCallback(async () => { const fetchUserInfo = useCallback(async () => {
try { try {

@ -1,5 +1,7 @@
import { useState } from 'react' import { useState } from 'react'
import { useTheme } from 'styled-components'
import isEmpty from 'lodash/isEmpty' import isEmpty from 'lodash/isEmpty'
import { AddCardFormInner } from 'features/AddCardForm/components/Form' import { AddCardFormInner } from 'features/AddCardForm/components/Form'
@ -43,7 +45,7 @@ export const CardStep = ({
goBack, goBack,
showClearBtn, showClearBtn,
} = useBuyMatchPopupStore() } = useBuyMatchPopupStore()
const { colors } = useTheme()
const emptyCards = isEmpty(cards) const emptyCards = isEmpty(cards)
return ( return (
@ -64,7 +66,7 @@ export const CardStep = ({
<AddCardFormInner <AddCardFormInner
onAddSuccess={goBack} onAddSuccess={goBack}
initialformOpen={emptyCards} initialformOpen={emptyCards}
inputsBackground='rgba(255, 255, 255, 0.1)' inputsBackground={colors.inputs}
clearInputs={clearInputs} clearInputs={clearInputs}
setClearInputs={setClearInputs} setClearInputs={setClearInputs}
> >

@ -12,7 +12,6 @@ export const ScModal = styled(BaseModal)`
${ModalWindow} { ${ModalWindow} {
width: 800px; width: 800px;
padding: 50px; padding: 50px;
background-color: #333333;
border-radius: 5px; border-radius: 5px;
justify-content: center; justify-content: center;

@ -142,9 +142,6 @@ export const PackageSelectionStep = () => {
{!isIframePayment && <SelectedCard />} {!isIframePayment && <SelectedCard />}
</Body> </Body>
<Footer> <Footer>
{loader ? (
<ArrowLoader width='204px' disabled />
) : (
<Button <Button
disabled={!selectedPackage || disabledBuyBtn} disabled={!selectedPackage || disabledBuyBtn}
onClick={(e) => { onClick={(e) => {
@ -156,9 +153,12 @@ export const PackageSelectionStep = () => {
} }
}} }}
> >
{loader ? (
<ArrowLoader disabled />
) : (
<T9n t='buy_subscription' /> <T9n t='buy_subscription' />
</Button>
)} )}
</Button>
</Footer> </Footer>
{selectedPackage && isIframePayment && ( {selectedPackage && isIframePayment && (
<IframePayment <IframePayment

@ -52,7 +52,7 @@ export const Item = styled.li.attrs(() => ({
width: 100%; width: 100%;
min-height: 140px; min-height: 140px;
padding: 20px 30px 20px 20px; padding: 20px 30px 20px 20px;
background: linear-gradient(180deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0) 100%), #3F3F3F; background: ${({ theme }) => theme.colors.packageBackground};
box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3); box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3);
border-radius: 2px; border-radius: 2px;

@ -11,7 +11,6 @@ export const Modal = styled(BaseModal)`
z-index: 52; z-index: 52;
${ModalWindow} { ${ModalWindow} {
padding: 0; padding: 0;
background-color: #333333;
border-radius: 5px; border-radius: 5px;
${isMobileDevice ${isMobileDevice
@ -34,7 +33,6 @@ export const Header = styled.div`
` `
export const HeaderTitle = styled.h2` export const HeaderTitle = styled.h2`
font-weight: 600;
font-size: 24px; font-size: 24px;
color: #FFFFFF; color: #FFFFFF;
text-align: center; text-align: center;

@ -17,7 +17,7 @@ export const PopOver = styled.ul`
left: -1px; left: -1px;
overflow: auto; overflow: auto;
z-index: 2; z-index: 2;
background: rgb(102, 102, 102); background: ${({ theme }) => theme.colors.comboboxBackground};
${customScrollbar}; ${customScrollbar};
${customStylesMixin}; ${customStylesMixin};
@ -30,25 +30,24 @@ export const ListOption = styled.li.attrs(() => ({
width: 100%; width: 100%;
height: 48px; height: 48px;
font-size: 16px; font-size: 16px;
font-weight: bold; font-weight: 400;
display: flex; display: flex;
align-items: center; align-items: center;
padding-left: 24px; padding-left: 24px;
color: ${({ isHighlighted }) => ( color: ${({ theme }) => theme.colors.white70};
isHighlighted background-color: transparent;
? '#fff'
: '#ccc' ${({ isHighlighted }) => isHighlighted && css`
)}; color: ${({ theme }) => theme.colors.white};
background-color: ${({ isHighlighted }) => ( font-weight: 600;
isHighlighted `}
? '#999'
: '#3F3F3F'
)};
cursor: pointer; cursor: pointer;
&:hover { &:hover {
background-color: #999; background-color: ${({ theme }) => theme.colors.comboboxItemHover};
color: #fff; color: ${({ theme }) => theme.colors.white};
font-weight: 600;
} }
${isMobileDevice ${isMobileDevice

@ -23,7 +23,7 @@ export const wrapperStyles = css<WrapperProps>`
padding-bottom: 0.519rem; padding-bottom: 0.519rem;
display: flex; display: flex;
align-items: center; align-items: center;
background-color: #3F3F3F; background-color: ${({ theme }) => theme.colors.inputs};
box-shadow: 0px 1px 1px rgba(43, 30, 30, 0.3); box-shadow: 0px 1px 1px rgba(43, 30, 30, 0.3);
border-radius: 2px; border-radius: 2px;
border: 1px solid ${(({ error }) => (isNil(error) ? 'transparent' : '#E64646'))}; border: 1px solid ${(({ error }) => (isNil(error) ? 'transparent' : '#E64646'))};

@ -39,7 +39,7 @@ export const Tab = styled.button.attrs(({ selected }: TabProps) => ({
color: #FFFFFF; color: #FFFFFF;
:hover { :hover {
background-color: #484848; background-color: ${theme.colors.searchBtnHover};
} }
` `
)} )}

@ -26,7 +26,7 @@ export const TitleWrapper = styled.div`
export const ContentWrapper = styled.div` export const ContentWrapper = styled.div`
margin-top: 10px; margin-top: 10px;
background-color: #3F3F3F; background-color: ${({ theme }) => theme.colors.modalBackground};
border-radius: 1.4px; border-radius: 1.4px;
` `

@ -1,52 +1,20 @@
import { import { ReactNode } from 'react'
ReactNode,
useEffect,
useState,
} from 'react'
import { useLocation } from 'react-router'
import { getLanguageUrlParam } from 'helpers/languageUrlParam' import { getLanguageUrlParam } from 'helpers/languageUrlParam'
import { AuthStore } from 'features/AuthStore' import { AuthStore } from 'features/AuthStore'
import { LexicsStore } from 'features/LexicsStore' import { LexicsStore } from 'features/LexicsStore'
import { getGeoInfo } from 'requests'
import { redirectToUrl } from 'helpers'
const initialLanguage = getLanguageUrlParam() const initialLanguage = getLanguageUrlParam()
type Props = { type Props = {
children: ReactNode, children: ReactNode,
} }
export const GlobalStores = ({ children }: Props) => { export const GlobalStores = ({ children }: Props) => (
const { pathname, search } = useLocation()
const [isGeoReady, setIsGeoReady] = useState(false)
useEffect(() => {
(async () => {
if (pathname === '/' && search === '') {
const geo = await getGeoInfo()
if (geo.country_code === 'TN') {
redirectToUrl('https://diwan.insports.tv')
return
}
}
setIsGeoReady(true)
})()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
if (!isGeoReady) return null
return (
<LexicsStore initialLanguage={initialLanguage}> <LexicsStore initialLanguage={initialLanguage}>
<AuthStore> <AuthStore>
{children} {children}
</AuthStore> </AuthStore>
</LexicsStore> </LexicsStore>
) )
}

@ -24,7 +24,7 @@ export const Wrapper = styled.div`
margin: 0; margin: 0;
border: none; border: none;
width: 13.6rem; width: 13.6rem;
background-color: #333333; background-color: ${({ theme }) => theme.colors.modalBackground};
box-shadow: 0px 2px 2.32rem #000000; box-shadow: 0px 2px 2.32rem #000000;
border-radius: 2px; border-radius: 2px;
font-family: inherit; font-family: inherit;
@ -46,7 +46,7 @@ export const Wrapper = styled.div`
border: none; border: none;
border-radius: 2; border-radius: 2;
padding-top: 0.567rem; padding-top: 0.567rem;
background-color: #333333; background-color: ${({ theme }) => theme.colors.modalBackground};
} }
.react-datepicker__month-container { .react-datepicker__month-container {

@ -14,7 +14,7 @@ export const DEFAULT_HEADER_COLOR = 'rgba(53, 96, 225, 0.56)'
export const defaultHeaderStyles = ( export const defaultHeaderStyles = (
color: string = DEFAULT_HEADER_COLOR, headerImage: string | undefined | null, color: string = DEFAULT_HEADER_COLOR, headerImage: string | undefined | null,
) => { ) => {
if (['lff', 'tunis'].includes(client.name)) { if (['lff', 'tunisia'].includes(client.name)) {
return client.styles.homePageHeader return client.styles.homePageHeader
} }
@ -143,7 +143,6 @@ export const ScModal = styled(BaseModal)`
${ModalWindow} { ${ModalWindow} {
min-width: 280px; min-width: 280px;
max-height: 250px; max-height: 250px;
background-color: #333333;
border-radius: 0px; border-radius: 0px;
padding: 0; padding: 0;
${customScrollbar} ${customScrollbar}

@ -37,7 +37,7 @@ export const StyledLink = styled(ProfileLink)`
:focus-within, :focus-within,
:hover { :hover {
background-color: #3b3b3b; background-color: ${({ theme }) => theme.colors.searchBtnHover};
outline: none; outline: none;
} }
${isMobileDevice ${isMobileDevice

@ -36,7 +36,7 @@ export const CardWrapper = styled.div`
right: 0; right: 0;
padding-bottom: 0.75rem; padding-bottom: 0.75rem;
border-radius: 2px; border-radius: 2px;
background-color: #3F3F3F; background-color: ${({ theme }) => theme.colors.matchCardBackground};
box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.4); box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.4);
cursor: pointer; cursor: pointer;
${isMobileDevice ${isMobileDevice

@ -41,7 +41,7 @@ export const CardWrapper = styled.div<CardProps>`
right: 0; right: 0;
padding: ${({ isMatchPage }) => (isMatchPage ? '0.5rem 0.625rem 1.8rem' : '0 0 0.75rem')}; padding: ${({ isMatchPage }) => (isMatchPage ? '0.5rem 0.625rem 1.8rem' : '0 0 0.75rem')};
border-radius: 3px; border-radius: 3px;
background-color: #3F3F3F; background-color: ${({ theme }) => theme.colors.matchCardBackground};
box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.4); box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.4);
cursor: pointer; cursor: pointer;
@ -188,7 +188,7 @@ export const Info = styled.div<CardProps>`
flex-direction: column; flex-direction: column;
padding: ${({ isMatchPage }) => (isMatchPage ? '0 5px 5px 0' : '0.85rem 0.472rem 0 0.519rem')}; padding: ${({ isMatchPage }) => (isMatchPage ? '0 5px 5px 0' : '0.85rem 0.472rem 0 0.519rem')};
color: #fff; color: #fff;
z-index: 1; z-index: 2;
${isMobileDevice ${isMobileDevice
? css` ? css`

@ -38,13 +38,13 @@ export const useFavouriteTeam = () => {
useEffect(() => { useEffect(() => {
(async () => { (async () => {
const { data: teams1, status }: ResponseType = await getFavouriteTeam({ const { data: { data: teams1 }, status }: ResponseType = await getFavouriteTeam({
country_id: 77, country_id: 77,
season: 30, season: 30,
sport_id: 1, sport_id: 1,
tournament_id: 131, tournament_id: 131,
}) })
const { data: teams2 }: ResponseType = await getFavouriteTeam({ const { data: { data: teams2 } }: ResponseType = await getFavouriteTeam({
country_id: 77, country_id: 77,
season: 30, season: 30,
sport_id: 1, sport_id: 1,

@ -13,7 +13,6 @@ export const ScModalContainer = styled(BaseModal)`
width: 1446px; width: 1446px;
height: 670px; height: 670px;
padding: 0; padding: 0;
background: #333333;
border-radius: 5px; border-radius: 5px;
${customScrollbar} ${customScrollbar}
@ -143,7 +142,8 @@ export const ButtonsBlock = styled.div`
export const Button = styled(ButtonSolid)` export const Button = styled(ButtonSolid)`
width: 134px; width: 134px;
height: 50px; height: 50px;
background: #294FC4; background: ${({ theme }) => theme.colors.button};
color: ${({ theme }) => theme.colors.white};
border-radius: 5px; border-radius: 5px;
${isMobileDevice ${isMobileDevice

@ -11,7 +11,6 @@ export const Modal = styled(BaseModal)`
${ModalWindow} { ${ModalWindow} {
width: 1222px; width: 1222px;
padding: 20px 0; padding: 20px 0;
background-color: #3F3F3F;
border-radius: 5px; border-radius: 5px;
@media ${devices.tablet} { @media ${devices.tablet} {

@ -1,6 +1,8 @@
import { useEffect } from 'react' import { useEffect } from 'react'
import { useHistory } from 'react-router' import { useHistory } from 'react-router'
import { useTheme } from 'styled-components'
import { ProfileHeader } from 'features/ProfileHeader' import { ProfileHeader } from 'features/ProfileHeader'
import { UserFavorites } from 'features/UserFavorites' import { UserFavorites } from 'features/UserFavorites'
import { useUserFavoritesStore } from 'features/UserFavorites/store' import { useUserFavoritesStore } from 'features/UserFavorites/store'
@ -30,6 +32,7 @@ const MatchPageComponent = () => {
usePageLogger() usePageLogger()
const history = useHistory() const history = useHistory()
const { addRemoveFavorite, userFavorites } = useUserFavoritesStore() const { addRemoveFavorite, userFavorites } = useUserFavoritesStore()
const { colors } = useTheme()
const { const {
isStarted, isStarted,
@ -89,7 +92,7 @@ const MatchPageComponent = () => {
return ( return (
<PageWrapper isIOS={isIOS}> <PageWrapper isIOS={isIOS}>
<ProfileHeader color='#2B2A28' height={client.name === 'facr' ? 5 : 4.5} /> <ProfileHeader color={colors.matchHeaderBackground} height={client.name === 'facr' ? 5 : 4.5} />
<Main> <Main>
<UserFavorites /> <UserFavorites />
<SubscriptionGuard> <SubscriptionGuard>

@ -31,8 +31,6 @@ export const useTournamentData = (matchProfile: MatchInfo) => {
useEffect(() => { useEffect(() => {
if (!isNull(tournamentId)) { if (!isNull(tournamentId)) {
if (matchProfile?.live && Number(matchProfile.c_match_calc_status) <= 1) return
(async () => { (async () => {
const matchesBySection = await getTournamentMatches({ const matchesBySection = await getTournamentMatches({
limit: 1000, limit: 1000,

@ -13,7 +13,6 @@ export const Modal = styled(BaseModal)`
width: 27.22rem; width: 27.22rem;
min-height: 14.859rem; min-height: 14.859rem;
padding: 1.416rem 0.71rem; padding: 1.416rem 0.71rem;
background-color: #333;
border-radius: 5px; border-radius: 5px;
${isMobileDevice ${isMobileDevice

@ -13,7 +13,7 @@ export const Content = styled.div`
? css` ? css`
width: 90%; width: 90%;
margin-top: 30%; margin-top: 30%;
background: #333; background: ${({ theme }) => theme.colors.modalBackground};
border-radius: 4px; border-radius: 4px;
padding: 20px 0 30px 0; padding: 20px 0 30px 0;
@ -55,7 +55,7 @@ export const HeaderActions = styled.div`
export const HeaderTitle = styled.h2` export const HeaderTitle = styled.h2`
margin: 0 auto; margin: 0 auto;
width: 70%; width: 70%;
font-weight: 600; font-weight: 700;
font-size: 1.14rem; font-size: 1.14rem;
line-height: 1.982rem; line-height: 1.982rem;
color: #FFFFFF; color: #FFFFFF;

@ -18,17 +18,12 @@ export const StyledLink = styled(Link)`
width: 100%; width: 100%;
height: 100%; height: 100%;
padding: 0 1.18rem; padding: 0 1.18rem;
background: linear-gradient( background: ${({ theme }) => theme.colors.liveMatchPlaylistBtnBackground};
180deg,
rgba(255, 255, 255, 0.1) 0%,
rgba(255, 255, 255, 0) 100%
),
#3F3F3F;
box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3); box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3);
border-radius: 2px; border-radius: 2px;
:hover { :hover {
background-color: #555555; background-color: ${({ theme }) => theme.colors.liveMatchPlaylistBtnHover};;
} }
${isMobileDevice ${isMobileDevice

@ -18,7 +18,7 @@ type PlayerNumberProps = {
} }
export const PopupContainer = styled.div` export const PopupContainer = styled.div`
background: #333333; background: ${({ theme }) => theme.colors.modalBackground};
box-shadow: 0px 2px 40px rgba(0, 0, 0, 0.6); box-shadow: 0px 2px 40px rgba(0, 0, 0, 0.6);
border-radius: 2px; border-radius: 2px;
display: flex; display: flex;
@ -203,7 +203,7 @@ export const ButtonConatiner = styled.div`
export const Button = styled.button` export const Button = styled.button`
height: 41px; height: 41px;
background: #294FC4; background: ${({ theme }) => theme.colors.button};
box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3); box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3);
border-radius: 5px; border-radius: 5px;
border: none; border: none;

@ -48,9 +48,9 @@ export const TabTitle = styled.span<TabTitleProps>`
left: -8px; left: -8px;
top: 50%; top: 50%;
translate: 0 -50%; translate: 0 -50%;
width: 5px; width: 6px;
height: 5px; height: 6px;
outline: ${teamColor.toUpperCase() === theme.colors.white ? 'none' : `0.5px solid ${theme.colors.white}`}; border: ${teamColor.toUpperCase() === theme.colors.white ? 'none' : `0.5px solid ${theme.colors.white}`};
border-radius: 50%; border-radius: 50%;
background-color: ${teamColor}; background-color: ${teamColor};
} }

@ -155,12 +155,7 @@ export const Button = styled.button<ButtonProps>`
align-items: center; align-items: center;
width: 100%; width: 100%;
height: 100%; height: 100%;
background: linear-gradient( background: ${({ theme }) => theme.colors.playerActionBtnBackground};
180deg,
rgba(255, 255, 255, 0.1) 0%,
rgba(255, 255, 255, 0) 100%
),
#3F3F3F;
box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3); box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3);
border-radius: 2px; border-radius: 2px;

@ -44,7 +44,7 @@ export const MatchesGrid = memo(({ matches }: MatchesGridProps) => {
) )
} }
if (isHomePage && selectedLeague.length && !isShowTournament) { if (isHomePage && selectedLeague.length && !isShowTournament) {
return matches.filter((match) => ((selectedLeague.indexOf(match.tournament.id) >= 0 return matches.filter((match) => ((selectedLeague.indexOf(`${match.sportType}_${match.tournament.id}`) >= 0
|| selectedLeague[0] === 'all_competitions'))) || selectedLeague[0] === 'all_competitions')))
} }
@ -73,6 +73,7 @@ export const MatchesGrid = memo(({ matches }: MatchesGridProps) => {
updateSportIds(matches) updateSportIds(matches)
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedDate, matches]) }, [selectedDate, matches])
return ( return (
<Wrapper> <Wrapper>
{isHomePage && isShowTournament ? ( {isHomePage && isShowTournament ? (

@ -17,7 +17,7 @@ export const ModalContainer = styled.div`
` `
export const ModalWindow = styled.div` export const ModalWindow = styled.div`
background-color: #313131; background-color: ${({ theme }) => theme.colors.modalBackground};
position: relative; position: relative;
padding: 15px; padding: 15px;
box-shadow: 0px 5px 30px rgba(0, 0, 0, 0.7); box-shadow: 0px 5px 30px rgba(0, 0, 0, 0.7);

@ -15,7 +15,6 @@ export const ScModalContainer = styled(BaseModal)`
width: 577px; width: 577px;
height: 367px; height: 367px;
border-radius: 5px; border-radius: 5px;
background-color: #333333;
padding: 50px 0; padding: 50px 0;
${isMobileDevice ${isMobileDevice

@ -20,7 +20,6 @@ export const Modal = styled(BaseModal)`
width: 1066px; width: 1066px;
height: 781px; height: 781px;
padding: 0; padding: 0;
background-color: #333333;
border-radius: 5px; border-radius: 5px;
@media (max-width: 1370px) { @media (max-width: 1370px) {

@ -15,8 +15,6 @@ import { Menu } from 'features/Menu'
import { Search } from 'features/Search' import { Search } from 'features/Search'
import { ScoreSwitch } from 'features/MatchSwitches' import { ScoreSwitch } from 'features/MatchSwitches'
import { isMatchPage } from 'helpers/isMatchPage'
import { usePageParams } from 'hooks/usePageParams' import { usePageParams } from 'hooks/usePageParams'
import { useProfileColor } from './hooks' import { useProfileColor } from './hooks'
@ -35,6 +33,11 @@ type Props = {
profileId?: number, profileId?: number,
} }
const profileWithImage = {
316: 'Ligue 1',
5704: 'NSDF Futsal Invitation Championship',
}
export const ProfileHeader = ({ export const ProfileHeader = ({
children, children,
color: headerColor, color: headerColor,
@ -48,7 +51,8 @@ export const ProfileHeader = ({
} = usePageParams() } = usePageParams()
const color = useProfileColor(profileId) const color = useProfileColor(profileId)
const imageHeader = (profileId === 5704 || 316) // @ts-ignore
const imageHeader = Boolean(profileWithImage[profileId])
&& sportType === SportTypes.FOOTBALL && sportType === SportTypes.FOOTBALL
&& profileType === ProfileTypes.TOURNAMENTS ? `/images/${profileId}` : headerImage && profileType === ProfileTypes.TOURNAMENTS ? `/images/${profileId}` : headerImage
@ -58,16 +62,14 @@ export const ProfileHeader = ({
headerImage={imageHeader} headerImage={imageHeader}
color={headerColor || color} color={headerColor || color}
height={height} height={height}
isMatchPage={isMatchPage()}
> >
<Position <Position
isMatchPage={isMatchPage()}
top={client.styles.logoTop} top={client.styles.logoTop}
left={client.styles.logoLeft} left={client.styles.logoLeft}
> >
<HeaderGroup> <HeaderGroup>
<Link to={PAGES.home}> <Link to={PAGES.home}>
<HeaderLogo isMatchPage={isMatchPage()} /> <HeaderLogo />
</Link> </Link>
{client.showSearch && <Search />} {client.showSearch && <Search />}

@ -9,12 +9,15 @@ import { ClientNames } from 'config/clients/types'
import { Logo } from 'features/Logo' import { Logo } from 'features/Logo'
import { ScoreSwitch } from 'features/MatchSwitches' import { ScoreSwitch } from 'features/MatchSwitches'
import { isMatchPage } from 'helpers/isMatchPage'
export const DEFAULT_HEADER_COLOR = 'rgba(53, 96, 225, 0.56)' export const DEFAULT_HEADER_COLOR = 'rgba(53, 96, 225, 0.56)'
export const defaultHeaderStyles = ( export const defaultHeaderStyles = (
color: string = DEFAULT_HEADER_COLOR, headerImage: string | undefined | null, color: string = DEFAULT_HEADER_COLOR, headerImage: string | undefined | null,
) => { ) => {
if ([ClientNames.Lff, ClientNames.Tunisia, ClientNames.Facr].includes(client.name)) { if ([ClientNames.Lff, ClientNames.Tunisia, ClientNames.Facr].includes(client.name)
&& !isMatchPage()) {
return client.styles.homePageHeader return client.styles.homePageHeader
} }
@ -60,25 +63,17 @@ export const HeaderStyled = styled.header<HeaderProps>`
${({ color, headerImage }) => defaultHeaderStyles(color, headerImage)} ${({ color, headerImage }) => defaultHeaderStyles(color, headerImage)}
${({ color }) => ( ${({ color }) => (
client.name === 'lff' ? css` client.name === ClientNames.Lff || client.name === ClientNames.Facr || client.name === ClientNames.Tunisia ? css`
background: ${color};
` : ''
)}
${({ color }) => (
client.name === 'facr' ? css`
background: ${color}; background: ${color};
` : '' ` : ''
)} )}
${({ isMatchPage }) => css`
${isMobileDevice ${isMobileDevice
? css` ? css`
height: ${(isMatchPage ? '40px' : '114px')}; height: ${() => (isMatchPage() ? '40px' : '114px')};
padding: 8px; padding: 8px;
` `
: ''} : ''}
`}
` `
type Props = { type Props = {
@ -102,7 +97,7 @@ export const HeaderGroup = styled.div<Props>`
` `
export const HeaderLogo = styled(Logo)` export const HeaderLogo = styled(Logo)`
${({ isMatchPage }) => (isMatchPage ? css` ${() => (isMatchPage() ? css`
width: ${client.styles.matchLogoWidth}rem; width: ${client.styles.matchLogoWidth}rem;
height: ${client.styles.matchLogoHeight}rem; height: ${client.styles.matchLogoHeight}rem;
@ -126,8 +121,6 @@ export const HeaderLogo = styled(Logo)`
} }
` : ''} ` : ''}
`)} `)}
` `
type PositionProps = { type PositionProps = {
@ -140,8 +133,8 @@ type PositionProps = {
export const Position = styled.div<PositionProps>` export const Position = styled.div<PositionProps>`
position: absolute; position: absolute;
top: ${({ isMatchPage, top = 1.14 }) => ( top: ${({ top = 1.14 }) => (
isMatchPage isMatchPage()
? client.styles.matchLogoTopMargin ?? top ? client.styles.matchLogoTopMargin ?? top
: top : top
)}rem; )}rem;

@ -1,3 +1,5 @@
import { useRef, useEffect } from 'react'
import { useRouteMatch } from 'react-router-dom' import { useRouteMatch } from 'react-router-dom'
import isEmpty from 'lodash/isEmpty' import isEmpty from 'lodash/isEmpty'
@ -39,6 +41,12 @@ export const Search = () => {
showResults, showResults,
} = useSearch() } = useSearch()
const listRef = useRef<null | HTMLDivElement>(null)
useEffect(() => {
listRef.current?.scrollTo(0, 0)
}, [selectedTab])
const isMatch = useRouteMatch(`/:sportName${PAGES.match}/:pageId`)?.isExact || false const isMatch = useRouteMatch(`/:sportName${PAGES.match}/:pageId`)?.isExact || false
return ( return (
<OutsideClick onClick={close}> <OutsideClick onClick={close}>
@ -62,7 +70,7 @@ export const Search = () => {
</LoaderWrapper> </LoaderWrapper>
)} )}
</Form> </Form>
{showResults && ( {(showResults && query !== '') && (
<Results> <Results>
<TabsGroup> <TabsGroup>
<Tab <Tab
@ -87,7 +95,7 @@ export const Search = () => {
<T9n t='player' /> <T9n t='player' />
</Tab> </Tab>
</TabsGroup> </TabsGroup>
<ListWrapper> <ListWrapper ref={listRef}>
<ItemsList <ItemsList
list={searchItems[selectedTab]} list={searchItems[selectedTab]}
close={close} close={close}

@ -55,7 +55,7 @@ type FormProps = {
const expandedStyles = css` const expandedStyles = css`
${InputWrapper} { ${InputWrapper} {
width: 19.3rem; width: 19.3rem;
background: #292929; background: ${({ theme }) => theme.colors.inputs};
border-radius: 10px; border-radius: 10px;
box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3); box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3);
${isMobileDevice ${isMobileDevice
@ -167,7 +167,7 @@ export const ListWrapper = styled.div`
${isMobileDevice ${isMobileDevice
? css` ? css`
margin-top: 15px; margin-top: 15px;
max-height: 100%; max-height: 75vh;
` `
: ''}; : ''};
` `
@ -177,10 +177,10 @@ export const Results = styled.div`
top: 2rem; top: 2rem;
width: 19.3rem; width: 19.3rem;
padding: 1.226rem 0.95rem; padding: 1.226rem 0.95rem;
background-color: #333333; background-color: ${({ theme }) => theme.colors.modalBackground};
box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3); box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3);
border-radius: 2px; border-radius: 2px;
z-index: 3; z-index: 5;
${isMobileDevice ${isMobileDevice
? css` ? css`
top: 33px; top: 33px;

@ -154,7 +154,6 @@ export const ScModal = styled(BaseModal)`
left: 4.7rem; left: 4.7rem;
min-width: 14.9%; min-width: 14.9%;
max-height: 290px; max-height: 290px;
background-color: #333333;
border-radius: 0px; border-radius: 0px;
padding: 0; padding: 0;
overflow-y: auto; overflow-y: auto;

@ -115,10 +115,15 @@ export const useVideoPlayer = ({
const [isPausedTime, setIsPausedTime] = useState(false) const [isPausedTime, setIsPausedTime] = useState(false)
const [pausedProgress, setPausedProgress] = useState(0) const [pausedProgress, setPausedProgress] = useState(0)
const getActiveChapter = useCallback(
(index: number = activeChapterIndex) => chapters[index],
[chapters, activeChapterIndex],
)
const chaptersDuration = useDuration(chapters) const chaptersDuration = useDuration(chapters)
const duration = (isLive && chapters[0]?.isFullMatchChapter) const duration = (isLive && chapters[0]?.isFullMatchChapter)
? fullMatchDuration ? fullMatchDuration - getActiveChapter().startOffsetMs
: chaptersDuration : chaptersDuration
const { const {
@ -133,11 +138,6 @@ export const useVideoPlayer = ({
onPlaylistSelect(matchPlaylists.match[0]) onPlaylistSelect(matchPlaylists.match[0])
} }
const getActiveChapter = useCallback(
(index: number = activeChapterIndex) => chapters[index],
[chapters, activeChapterIndex],
)
const { const {
isFullscreen, isFullscreen,
onFullscreenClick, onFullscreenClick,
@ -245,7 +245,7 @@ export const useVideoPlayer = ({
setIsLiveTime(true) setIsLiveTime(true)
} }
const liveProgressMs = Math.max(duration - 30000, 0) const liveProgressMs = Math.max(fullMatchDuration - 30000, 0)
setPlayerState({ playedProgress: liveProgressMs, seek: liveProgressMs / 1000 }) setPlayerState({ playedProgress: liveProgressMs, seek: liveProgressMs / 1000 })
if (liveProgressMs > 0) setIsLiveTime(false) if (liveProgressMs > 0) setIsLiveTime(false)
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
@ -333,7 +333,7 @@ export const useVideoPlayer = ({
}) })
} }
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [isLive]) }, [isLive, chaptersProps[0].startOffsetMs])
useEffect(() => { useEffect(() => {
if (((isLive || chapters[0].duration === chaptersProps[0].duration) if (((isLive || chapters[0].duration === chaptersProps[0].duration)

@ -140,7 +140,6 @@ export const StreamPlayer = (props: Props) => {
onPlaying={onPlaying} onPlaying={onPlaying}
onWaiting={onWaiting} onWaiting={onWaiting}
onError={onError} onError={onError}
crossOrigin='use-credentials'
/> />
{isMobileDevice && isFullscreen && mainControlsVisible && profile && ( {isMobileDevice && isFullscreen && mainControlsVisible && profile && (

@ -1,27 +1,4 @@
export const lightTheme = { export const defaultTheme = {
colors: {
background: '',
black: '',
black40: '',
black70: '',
button: '',
buttonHover: '',
dateButton: '',
dateFilter: '',
error: '',
inputs: '',
loader: '',
primary: '',
secondary: '',
shadow: '',
white: '',
white50: '',
white70: '',
},
name: 'light' as Name,
}
export const defaultTheme: CustomTheme = {
colors: { colors: {
background: ` background: `
radial-gradient( radial-gradient(
@ -35,11 +12,22 @@ export const defaultTheme: CustomTheme = {
black70: 'rgba(0, 0, 0, 0.7)', black70: 'rgba(0, 0, 0, 0.7)',
button: '#294FC3', button: '#294FC3',
buttonHover: '#3255be', buttonHover: '#3255be',
collapseTournamentBackground: 'linear-gradient(236.13deg, rgba(53, 96, 225, 0.56) -4.49%, rgba(0, 0, 0, 0) 98.29%), #3F3F3F',
comboboxBackground: '#3F3F3F',
comboboxItemHover: '#999999',
dateButton: 'rgba(255, 255, 255, 0.5)', dateButton: 'rgba(255, 255, 255, 0.5)',
dateFilter: '#656565', dateFilter: '#656565',
error: 'rgba(235, 87, 87, 1)', error: 'rgba(235, 87, 87, 1)',
inputs: '#3F3F3F', inputs: '#3F3F3F',
liveMatchPlaylistBtnBackground: 'linear-gradient(180deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0) 100%), #3F3F3F',
liveMatchPlaylistBtnHover: '#555555',
loader: '#FFFFFF', loader: '#FFFFFF',
loaderAuth: '#FFFFFF',
matchCardBackground: '#3F3F3F',
matchHeaderBackground: '#2B2A28',
modalBackground: '#333333',
packageBackground: 'linear-gradient(180deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0) 100%), #3F3F3F',
playerActionBtnBackground: 'linear-gradient(180deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0) 100%), #3F3F3F',
primary: ` primary: `
linear-gradient( linear-gradient(
180deg, 180deg,
@ -49,8 +37,15 @@ export const defaultTheme: CustomTheme = {
), ),
#0033CC #0033CC
`, `,
searchBtnHover: '#3b3b3b',
secondary: '#999999', secondary: '#999999',
shadow: '0px 1px 1px rgba(0, 0, 0, 0.3)', shadow: '0px 1px 1px rgba(0, 0, 0, 0.3)',
unsubscribeItemBackground: `linear-gradient(
180deg,
rgba(255, 255, 255, 0.1) 0%,
rgba(255, 255, 255, 0) 100%
),
#3f3f3f`,
white: '#FFFFFF', white: '#FFFFFF',
white50: 'rgba(255, 255, 255, 0.5)', white50: 'rgba(255, 255, 255, 0.5)',
white70: 'rgba(255, 255, 255, 0.7)', white70: 'rgba(255, 255, 255, 0.7)',
@ -78,6 +73,7 @@ export const facrTheme: CustomTheme = {
...defaultTheme.colors, ...defaultTheme.colors,
button: '#00257A', button: '#00257A',
inputs: 'transparent', inputs: 'transparent',
loaderAuth: '#00257A',
}, },
name: 'facr', name: 'facr',
} }
@ -88,13 +84,27 @@ export const tunisTheme: CustomTheme = {
...defaultTheme.colors, ...defaultTheme.colors,
background: '#1D1D1D', background: '#1D1D1D',
button: '#0E8F84', button: '#0E8F84',
buttonHover: '#09aa9d', buttonHover: '#0E8F84',
collapseTournamentBackground: 'linear-gradient(236.13deg, rgba(42, 183, 170, 0.56) -4.49%, rgba(0, 0, 0, 0) 98.29%), #3A4849',
comboboxBackground: '#263233',
comboboxItemHover: '#0E8F84',
dateFilter: '#ffffff80', dateFilter: '#ffffff80',
error: '#FF4E77',
inputs: '#3A4849', inputs: '#3A4849',
liveMatchPlaylistBtnBackground: 'linear-gradient(180deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0) 100%), #3A4849',
liveMatchPlaylistBtnHover: '#0E8F84',
loaderAuth: '#0B2E4D',
matchCardBackground: '#3A4849',
matchHeaderBackground: '#030F1B',
modalBackground: '#263233',
packageBackground: 'linear-gradient(180deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0) 100%), #3A4849',
playerActionBtnBackground: 'linear-gradient(180deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0) 100%), #3A4849',
searchBtnHover: '#0E8F84',
unsubscribeItemBackground: 'linear-gradient(180deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0) 100%), #3A4849',
}, },
name: 'tunis', name: 'tunisia',
} }
type Name = 'light' | 'dark' | 'lff' | 'facr' | 'tunis' type Name = 'light' | 'dark' | 'lff' | 'facr' | 'tunisia'
export type CustomTheme = typeof lightTheme export type CustomTheme = typeof defaultTheme

@ -5,8 +5,12 @@ import {
useMemo, useMemo,
useEffect, useEffect,
} from 'react' } from 'react'
import { ThemeProvider } from 'styled-components' import { ThemeProvider } from 'styled-components'
import { client } from 'config/clients'
import { client as clientBase } from 'config/clients'
import { client as clientAuth } from 'features/AuthServiceApp/config/clients'
import { ClientNames } from 'config/clients/types'
import { import {
CustomTheme, CustomTheme,
@ -15,7 +19,6 @@ import {
lffTheme, lffTheme,
tunisTheme, tunisTheme,
} from './config' } from './config'
import { ClientNames } from '../../config/clients/types'
type Props = { type Props = {
children: ReactNode, children: ReactNode,
@ -24,6 +27,25 @@ type Props = {
export const Theme = ({ children }: Props) => { export const Theme = ({ children }: Props) => {
const [theme, setTheme] = useState<CustomTheme>(defaultTheme) const [theme, setTheme] = useState<CustomTheme>(defaultTheme)
const client = useMemo(() => {
if (process.env.REACT_APP_TYPE === 'auth-service') {
return clientAuth
}
return clientBase
}, [])
// настройка цветовой гаммы зендеска https://developer.zendesk.com/api-reference/widget/settings/#color
useEffect(() => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(window as any).zESettings = {
webWidget: {
color: {
theme: theme.colors.button,
},
},
}
}, [theme])
const switchTheme = useCallback(() => { const switchTheme = useCallback(() => {
switch (client.name) { switch (client.name) {
case ClientNames.Lff: case ClientNames.Lff:
@ -39,7 +61,7 @@ export const Theme = ({ children }: Props) => {
setTheme(defaultTheme) setTheme(defaultTheme)
break break
} }
}, []) }, [client])
useEffect(() => { useEffect(() => {
switchTheme() switchTheme()

@ -91,5 +91,6 @@ export const useTournamentLanding = () => {
sliderItemId, sliderItemId,
teams: tournamentInfo?.teams, teams: tournamentInfo?.teams,
title, title,
tournamentInfo,
} }
} }

@ -51,8 +51,11 @@ const TournamentLanding = () => {
sliderItemId, sliderItemId,
teams, teams,
title, title,
tournamentInfo,
} = useTournamentLanding() } = useTournamentLanding()
if (!tournamentInfo) return null
const currentYear = format(new Date(), 'Y') const currentYear = format(new Date(), 'Y')
return ( return (

@ -150,19 +150,6 @@ export const SliderContainer = styled.div`
height: 100%; height: 100%;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
${isMobileDevice
? css`
:before {
content: '';
z-index: 10;
width: 100%;
height: 100%;
position: absolute;
background: linear-gradient(0deg, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0) 30%);
}
`
: ''};
` `
export const SliderImg = styled.img<SliderImgProps>` export const SliderImg = styled.img<SliderImgProps>`
@ -174,6 +161,12 @@ export const SliderImg = styled.img<SliderImgProps>`
animation-iteration-count: 1; animation-iteration-count: 1;
animation-timing-function: ease-out; animation-timing-function: ease-out;
animation-duration: 5s; animation-duration: 5s;
object-fit: cover;
-webkit-mask: ${(
isMobileDevice
? 'linear-gradient(0deg, rgba(0, 0, 0, 0) 6.27%, rgba(0, 0, 0, 0.27) 15.48%, #000000 24.97%)'
: 'linear-gradient(90deg, #000000 79.51%, rgba(0, 0, 0, 0) 95.58%)'
)};
@keyframes sliderAnimation { @keyframes sliderAnimation {
0% { 0% {
@ -256,7 +249,7 @@ export const DateInfo = styled(T9n)`
font-size: 10px; font-size: 10px;
border-radius: 3px; border-radius: 3px;
background-color: rgba(0, 0, 0, 0.7); background-color: rgba(0, 0, 0, 0.7);
padding: 0.7em 2.5rem;` padding: 5px 10px;`
: ''}; : ''};
` `
@ -268,7 +261,7 @@ export const TournamentTitle = styled(T9n)`
${isMobileDevice ${isMobileDevice
? css` ? css`
font-size: 24px; font-size: 24px;
margin: 15px 0 0; margin: 8px 0 0;
` `
: css` : css`
width: 50%; width: 50%;
@ -288,9 +281,8 @@ export const TournamentButton = styled(ButtonSolid)<ButtonProps>`
${isMobileDevice ${isMobileDevice
? css` ? css`
width: 100%; width: 100%;
border-radius: 10px;
font-size: 17px; font-size: 17px;
padding: 20px 50px; padding: 10px 0;
margin-bottom: 0; margin-bottom: 0;
` `
: ''}; : ''};
@ -304,7 +296,9 @@ export const TournamentDescription = styled(T9n)`
${isMobileDevice ${isMobileDevice
? css` ? css`
font-size: 12px; font-size: 12px;
margin: 30px 0; line-height: 150%;
letter-spacing: 0.1px;
margin: 25px 0 30px;
` `
: ''}; : ''};
` `

@ -46,7 +46,7 @@ export const CollapseTournament = ({
const handleClick = () => { const handleClick = () => {
setIsShowTournament(false) setIsShowTournament(false)
setSelectedLeague([tournament.id]) setSelectedLeague([`${tournament.sportType}_${tournament.id}`])
setSelectTournament(tournament) setSelectTournament(tournament)
} }

@ -37,7 +37,7 @@ export const CardWrapper = styled.div`
right: 0; right: 0;
padding-bottom: 0.75rem; padding-bottom: 0.75rem;
border-radius: 2px; border-radius: 2px;
background: linear-gradient(236.13deg, rgba(53, 96, 225, 0.56) -4.49%, rgba(0, 0, 0, 0) 98.29%), #3F3F3F; background: ${({ theme }) => theme.colors.collapseTournamentBackground};
cursor: pointer; cursor: pointer;
${isMobileDevice ${isMobileDevice
? css` ? css`

@ -28,7 +28,7 @@ export const CardWrapper = styled.div<{
display: flex; display: flex;
align-items: center; align-items: center;
background-color: ${({ open, theme: { colors } }) => (open ? colors.button : '#3f3f3f')}; background-color: ${({ open, theme: { colors } }) => (open ? colors.button : colors.matchCardBackground)};
cursor: pointer; cursor: pointer;
${isMobileDevice ${isMobileDevice
? css` ? css`

@ -2,7 +2,7 @@ import { useMemo } from 'react'
import orderBy from 'lodash/orderBy' import orderBy from 'lodash/orderBy'
import { ProfileTypes } from 'config' import { ProfileTypes, SportTypes } from 'config'
import { TournamentListProps } from 'features/TournamentList' import { TournamentListProps } from 'features/TournamentList'
import type { Match } from 'features/Matches' import type { Match } from 'features/Matches'
import { useHeaderFiltersStore } from 'features/HeaderFilters' import { useHeaderFiltersStore } from 'features/HeaderFilters'
@ -13,6 +13,7 @@ interface TournamentsSortProps {
isFavorite: boolean, isFavorite: boolean,
isLive: boolean, isLive: boolean,
isSuperTournament: boolean, isSuperTournament: boolean,
sportType: SportTypes,
} }
export const useTournaments = (matches: Array<Match>) => { export const useTournaments = (matches: Array<Match>) => {
@ -23,7 +24,7 @@ export const useTournaments = (matches: Array<Match>) => {
} = useHeaderFiltersStore() } = useHeaderFiltersStore()
const { isInFavorites } = useUserFavoritesStore() const { isInFavorites } = useUserFavoritesStore()
const compareLeague = (id: number) => { const compareLeague = (id: number| string) => {
if (selectedLeague[0] === 'all_competitions') { if (selectedLeague[0] === 'all_competitions') {
return true return true
} }
@ -36,14 +37,16 @@ export const useTournaments = (matches: Array<Match>) => {
const tournaments = matches.reduce((acc: TournamentListProps, match: Match) => { const tournaments = matches.reduce((acc: TournamentListProps, match: Match) => {
if (matches.length === 0) return {} if (matches.length === 0) return {}
const uniqTournamentId = `${match.sportType}_${match.tournament.id}`
const tournamentInFavorites = isInFavorites( const tournamentInFavorites = isInFavorites(
ProfileTypes.TOURNAMENTS, ProfileTypes.TOURNAMENTS,
// в избранном могут быть только обычные турниры // в избранном могут быть только обычные турниры
match.tournament.is_super_tournament ? match.group.id : match.tournament.id, match.tournament.is_super_tournament ? match.group.id : match.tournament.id,
) )
if (!acc[match.tournament.id] && compareSport(match, selectedSport) if (!acc[`${match.sportType}_${match.tournament.id}`] && compareSport(match, selectedSport)
&& compareLeague(match.tournament.id)) { && compareLeague(uniqTournamentId)) {
const tournament = { const tournament = {
...match.tournament, ...match.tournament,
countryId: match.countryId, countryId: match.countryId,
@ -52,7 +55,7 @@ export const useTournaments = (matches: Array<Match>) => {
matches: [match], matches: [match],
sportType: match.sportType, sportType: match.sportType,
} }
acc[match.tournament.id] = { acc[uniqTournamentId] = {
tournament: { tournament: {
...tournament, ...tournament,
}, },
@ -63,17 +66,18 @@ export const useTournaments = (matches: Array<Match>) => {
isFavorite: tournamentInFavorites, isFavorite: tournamentInFavorites,
isLive: match.live, isLive: match.live,
isSuperTournament: Boolean(match.tournament.is_super_tournament), isSuperTournament: Boolean(match.tournament.is_super_tournament),
sportType: match.sportType,
}) })
} else if (compareSport(match, selectedSport) && compareLeague(match.tournament.id)) { } else if (compareSport(match, selectedSport) && compareLeague(uniqTournamentId)) {
acc[match.tournament.id] = { acc[uniqTournamentId] = {
...acc[match.tournament.id], ...acc[uniqTournamentId],
tournament: { tournament: {
...acc[match.tournament.id].tournament, ...acc[uniqTournamentId].tournament,
live: acc[match.tournament.id]?.tournament.live live: acc[uniqTournamentId]?.tournament.live
? acc[match.tournament.id]?.tournament.live ? acc[uniqTournamentId]?.tournament.live
: match.live, : match.live,
}, },
tournamentMatches: [...acc[match.tournament.id].tournamentMatches, match], tournamentMatches: [...acc[uniqTournamentId].tournamentMatches, match],
} }
} }
return acc return acc

@ -27,7 +27,7 @@ export type TournamentProps = {
} }
export type TournamentListProps = { export type TournamentListProps = {
[key: number]: TournamentProps, [key: string]: TournamentProps,
} }
export const TournamentList = ({ matches }: TournamentTypeProps) => { export const TournamentList = ({ matches }: TournamentTypeProps) => {
@ -38,11 +38,11 @@ export const TournamentList = ({ matches }: TournamentTypeProps) => {
case isMobileDevice && isHomePage: case isMobileDevice && isHomePage:
return ( return (
<> <>
{tournamentSort?.map(({ id }) => ( {tournamentSort?.map(({ id, sportType }) => (
<TournamentMobile <TournamentMobile
key={id} key={`${sportType}_${id}`}
tournament={tournaments[id].tournament} tournament={tournaments[`${sportType}_${id}`].tournament}
tournamentMatches={tournaments[id].tournamentMatches} tournamentMatches={tournaments[`${sportType}_${id}`].tournamentMatches}
/> />
))} ))}
</> </>
@ -50,11 +50,11 @@ export const TournamentList = ({ matches }: TournamentTypeProps) => {
case isHomePage && matches.length >= 12: case isHomePage && matches.length >= 12:
return ( return (
<> <>
{tournamentSort?.map(({ id }) => ( {tournamentSort?.map(({ id, sportType }) => (
<CollapseTournament <CollapseTournament
key={id} key={`${sportType}_${id}`}
tournament={tournaments[id].tournament} tournament={tournaments[`${sportType}_${id}`].tournament}
tournamentMatches={tournaments[id].tournamentMatches} tournamentMatches={tournaments[`${sportType}_${id}`].tournamentMatches}
/> />
))} ))}
</> </>

@ -17,7 +17,6 @@ export const ScModalContainer = styled(BaseModal)`
width: 679px; width: 679px;
max-height: 95vh; max-height: 95vh;
padding: 0; padding: 0;
background-color: #1E2127;
border-radius: 5px; border-radius: 5px;
overflow-y: auto; overflow-y: auto;

@ -17,7 +17,7 @@ export const CardNumberWrapper = styled.div`
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
background-color: #3F3F3F; background-color: ${({ theme }) => theme.colors.inputs};
border-radius: 2px; border-radius: 2px;
margin-bottom: 10px; margin-bottom: 10px;
overflow: hidden; overflow: hidden;

@ -16,7 +16,6 @@ export const Modal = styled(BaseModal)`
max-width: 642px; max-width: 642px;
max-height: 340px; max-height: 340px;
padding-top: 40px; padding-top: 40px;
background-color: #333333;
border-radius: 5px; border-radius: 5px;
${isMobileDevice ${isMobileDevice
@ -165,12 +164,7 @@ export const Text = styled.span`
export const ScCancelSub = styled.div` export const ScCancelSub = styled.div`
max-width: 562px; max-width: 562px;
height: 59px; height: 59px;
background: linear-gradient( background: ${({ theme }) => theme.colors.unsubscribeItemBackground};
180deg,
rgba(255, 255, 255, 0.1) 0%,
rgba(255, 255, 255, 0) 100%
),
#3f3f3f;
box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3); box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3);
border-radius: 2px; border-radius: 2px;
font-weight: 500; font-weight: 500;

@ -8,7 +8,6 @@ export const Modal = styled(BaseModal)`
${ModalWindow} { ${ModalWindow} {
padding: 0; padding: 0;
background-color: #333333;
border-radius: 5px; border-radius: 5px;
${isMobileDevice ${isMobileDevice

@ -51,7 +51,6 @@ export const Modal = styled(ModalBase)`
background-color: rgba(0, 0, 0, 0.7); background-color: rgba(0, 0, 0, 0.7);
${ModalWindow} { ${ModalWindow} {
padding: 40px 86px; padding: 40px 86px;
background: #333333;
border-radius: 5px; border-radius: 5px;
} }
` `

@ -145,7 +145,7 @@ export const ScCancelButton = styled.button`
padding: 0; padding: 0;
background-color: transparent; background-color: transparent;
cursor: pointer; cursor: pointer;
background: #294FC4; background: ${({ theme }) => theme.colors.button};
box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3); box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3);
border-radius: 5px; border-radius: 5px;
width: 100%; width: 100%;

@ -15,6 +15,8 @@ import { SaveUserInfo } from 'requests'
import { readToken } from 'helpers/token' import { readToken } from 'helpers/token'
import { client } from 'config/clients'
import { useUserInfoForm } from './useUserInfoForm' import { useUserInfoForm } from './useUserInfoForm'
import { useValidateForm } from './useValidateForm' import { useValidateForm } from './useValidateForm'
@ -110,7 +112,7 @@ export const useUserInfo = ({ loader, onSubmit }: Props) => {
} }
const resetPassword = useCallback(() => { const resetPassword = useCallback(() => {
window.location.href = `${AUTH_SERVICE}/change_password?token=${token}` window.location.href = `${AUTH_SERVICE}/change_password?client_id=${client.auth.clientId}&token=${token}`
}, [token]) }, [token])
return { return {

@ -113,15 +113,13 @@ export const PersonalInfoForm = (props: Props) => {
withError={false} withError={false}
/> />
<ButtonWrapper> <ButtonWrapper>
{loader ? <ArrowLoader disabled width='204px' /> : (
<SolidButton <SolidButton
disabled={!hasChanges()} disabled={!hasChanges()}
type='button' type='button'
onClick={handleSubmit} onClick={handleSubmit}
> >
<T9n t='save_changes' /> {loader ? <ArrowLoader disabled /> : <T9n t='save_changes' />}
</SolidButton> </SolidButton>
)}
<OutlineButton <OutlineButton
type='button' type='button'
onClick={resetPassword} onClick={resetPassword}

@ -63,12 +63,12 @@ export const ButtonWrapper = styled.div`
` `
export const PrivacyPolicyLink = styled.a` export const PrivacyPolicyLink = styled.a`
display: inline-block;
margin-top: 4px; margin-top: 4px;
font-size: 14px; font-size: 14px;
line-height: 18px; line-height: 18px;
color: #FFFFFF; color: #FFFFFF;
text-decoration: underline; text-decoration: underline;
width: fit-content;
` `
export const PrivacyWrapper = styled.div` export const PrivacyWrapper = styled.div`

@ -18,6 +18,7 @@ import {
isInSportsClient, isInSportsClient,
isInstatClient, isInstatClient,
isLffClient, isLffClient,
isTunisClient,
} from 'config/clients' } from 'config/clients'
import { Header } from './components/Header' import { Header } from './components/Header'
@ -74,7 +75,7 @@ const UserAccount = () => {
> >
<T9n t='my_devices' /> <T9n t='my_devices' />
</StyledLink> </StyledLink>
{!isLffClient && !isInSportsClient && ( {!isLffClient && !isInSportsClient && !isTunisClient && (
<StyledLink <StyledLink
target='_blank' target='_blank'
to={{ pathname: client.about_the_project ?? PAGES.about_the_project }} to={{ pathname: client.about_the_project ?? PAGES.about_the_project }}

@ -20,6 +20,8 @@ export const SolidButton = styled(ButtonSolid)`
display: flex; display: flex;
align-items: center; align-items: center;
margin-right: 15px; margin-right: 15px;
min-width: 182px;
justify-content: center;
@media ${devices.tablet} { @media ${devices.tablet} {
height: 5rem; height: 5rem;

@ -20,7 +20,6 @@ export const VideoPlayer = forwardRef<HTMLVideoElement, Props>((props: Props, re
const { const {
className, className,
controls, controls,
crossOrigin,
height, height,
hidden, hidden,
muted, muted,
@ -61,7 +60,7 @@ export const VideoPlayer = forwardRef<HTMLVideoElement, Props>((props: Props, re
onError={onError} onError={onError}
onWaiting={onWaiting} onWaiting={onWaiting}
onPlaying={onPlaying} onPlaying={onPlaying}
crossOrigin={crossOrigin} crossOrigin='use-credentials'
controls={controls} controls={controls}
/> />
) )

@ -1,15 +1,18 @@
import { isMobileDevice } from 'config/userAgent' import { isMobileDevice } from 'config/userAgent'
import { client } from 'config/clients' import { client } from 'config/clients'
import { ClientNames } from '../../config/clients/types'
export const getSwitchScoreIconName = () => { export const getSwitchScoreIconName = () => {
switch (true) { switch (true) {
case client.name === 'lff' && !isMobileDevice: case client.name === ClientNames.Lff && !isMobileDevice:
return 'score-switch-lff' return 'score-switch-lff'
case client.name === 'lff' && isMobileDevice: case client.name === ClientNames.Lff && isMobileDevice:
return 'score-switch-lff-mobile' return 'score-switch-lff-mobile'
case client.name !== 'lff' && !isMobileDevice: case client.name === ClientNames.Tunisia:
return 'score-switch-tunisia'
case client.name !== ClientNames.Lff && !isMobileDevice:
return 'score-switch' return 'score-switch'
case client.name !== 'lff' && isMobileDevice: case client.name !== ClientNames.Lff && isMobileDevice:
return 'score-switch-mobile' return 'score-switch-mobile'
default: default:
return 'score-switch' return 'score-switch'

@ -11,3 +11,6 @@ export * from './selectedApi'
export * from './openSubscribePopup' export * from './openSubscribePopup'
export * from './getCurrentYear' export * from './getCurrentYear'
export * from './getTeamAbbr' export * from './getTeamAbbr'
export * from './cookie'
export * from './isMatchPage'
export * from './languageUrlParam'

@ -1,6 +1,5 @@
import toNumber from 'lodash/toNumber' import toNumber from 'lodash/toNumber'
import isUndefined from 'lodash/isUndefined' import isUndefined from 'lodash/isUndefined'
import includes from 'lodash/includes'
export const isMatchPage = () => { export const isMatchPage = () => {
const splitPath = window.location.pathname.split('/') const splitPath = window.location.pathname.split('/')
@ -16,5 +15,3 @@ export const isMatchPageRFEF = () => {
return pageType === '1rfef' return pageType === '1rfef'
} }
export const isDiwanInsportsTvPage = () => includes(window.location.host, 'diwan')

@ -1,4 +1,4 @@
const TOKEN_KEY = 'token' export const TOKEN_KEY = 'token'
export const readToken = () => ( export const readToken = () => (
localStorage.getItem(TOKEN_KEY) localStorage.getItem(TOKEN_KEY)

@ -1,78 +0,0 @@
import { Fragment } from 'react'
import { isMobileDevice } from 'config'
import { joinMatchLexics } from 'config/lexics/joinMatch'
import { T9n } from 'features/T9n'
import { useLexicsConfig } from 'features/LexicsStore'
import { useAuthStore } from 'features/AuthStore'
import { getCurrentYear } from 'helpers'
import {
Wrapper,
TunisiaLogo,
HeaderWrapper,
Footer,
BlockWrapper,
MatchInfo,
LigueImgWrapper,
Season,
MainInfoTitle,
MainInfoButton,
MainInfoContainer,
MainInfoText,
FooterRights,
ClubsLogo,
InsportsLogo,
ScGradient,
LigueImg,
} from './styled'
export const DiwanInsportsTv = () => {
useLexicsConfig(joinMatchLexics)
const { login } = useAuthStore()
const currentYear = getCurrentYear()
return (
<Wrapper>
<HeaderWrapper>
<InsportsLogo />
{isMobileDevice && <TunisiaLogo />}
</HeaderWrapper>
<MainInfoContainer>
<BlockWrapper>
<LigueImgWrapper>
<ScGradient />
<LigueImg />
</LigueImgWrapper>
<MatchInfo>
<Season>
<T9n t='diwan_season' />
</Season>
<MainInfoTitle>
<T9n t='diwan_title' />
</MainInfoTitle>
<MainInfoText>
<T9n t='diwan_desc' />
</MainInfoText>
<MainInfoButton onClick={login}>
<T9n t='diwan_join' />
</MainInfoButton>
{!isMobileDevice && (
<Fragment>
<TunisiaLogo />
<ClubsLogo />
</Fragment>
)}
</MatchInfo>
</BlockWrapper>
</MainInfoContainer>
<Footer>
<FooterRights>©inSports.tv {currentYear}</FooterRights>
</Footer>
</Wrapper>
)
}

@ -1,301 +0,0 @@
import styled, { css } from 'styled-components/macro'
import { devices, isMobileDevice } from 'config'
import { ButtonSolid } from 'features/Common'
export const Wrapper = styled.div`
width: 100vw;
height: 100vh;
color: white;
display: flex;
flex-direction: column;
justify-content: space-between;
${isMobileDevice
? css`
height: 100%;
`
: ''};
`
export const HeaderWrapper = styled.div`
padding: 20px 0;
padding-left: 20%;
width: 100%;
background: rgba(19, 21, 27, 0.7);
backdrop-filter: blur(20px);
display: flex;
align-items: center;
@media ${devices.laptop} {
padding-left: 5%;
}
${isMobileDevice
? css`
background: #000000;
`
: ''};
`
export const TunisiaLogo = styled.div`
background-image: url(/images/tunis-logo.svg);
background-size: contain;
background-repeat: no-repeat;
width: 229px;
height: 49px;
margin-bottom: 50px;
${isMobileDevice
? css`
width: 66px;
height: 14px;
margin-bottom: 0;
`
: ''};
`
export const InsportsLogo = styled.div`
background-image: url(/images/insports-logo.svg);
background-size: contain;
background-repeat: no-repeat;
width: 80px;
height: 25px;
margin-right: 25px;
position: relative;
${isMobileDevice
? css`
width: 57px;
height: 18px;
::after {
content: '';
position: absolute;
width: 0.5px;
height: 25px;
background: #FFFFFF;
right: -13px;
top: -3px;
opacity: 0.6;
}
`
: ''};
`
export const ClubsLogo = styled.div`
background-image: url(/images/tunis_clubs.svg);
background-size: contain;
background-repeat: no-repeat;
width: 408px;
height: 86px;
`
export const MainInfoContainer = styled.div`
${isMobileDevice
? css`
margin-top: 50px;
height: 100%;
`
: ''};
`
export const BlockWrapper = styled.div`
height: 100%;
display: flex;
align-items: center;
padding-left: 20%;
width: 100%;
position: relative;
@media ${devices.laptop} {
padding-left: 5%;
}
@media ${devices.mobile} {
padding-left: 5.4rem;
}
${isMobileDevice
? css`
flex-direction: column;
padding: 5.4rem;
@media screen and (orientation: landscape){
padding-top: 20px;
height: auto;
}
`
: ''};
`
export const ScGradient = styled.div`
content: '';
position: absolute;
width: 620px;
height: 310px;
border-radius: 50%;
background: rgba(29, 185, 171, 0.4);
opacity: 0.7;
filter: blur(104.135px);
top: 30%;
left: 25px;
z-index: 1;
${isMobileDevice
? css`
filter: blur(50.135px);
border-radius: 40%;
width: 349px;
height: 210px;
left: -35px;
top: -71px;
`
: ''};
`
export const LigueImg = styled.div`
background-image: url(/images/landing_${() => (
isMobileDevice
? 'mobile_ligue_1.png'
: 'ligue_1.png'
)});
background-repeat: no-repeat;
background-position: center;
background-size: contain;
width: 670px;
height: 156px;
z-index: 2;
${isMobileDevice
? css`
width: 288px;
height: 66px;
`
: ''};
`
export const LigueImgWrapper = styled.div`
display: flex;
align-items: center;
height: 80%;
margin-right: 5%;
position: relative;
${isMobileDevice
? css`
margin-right: 0;
margin-bottom: 83px;
@media screen and (orientation: landscape){
display: block;
height: 100%;
width: 70%;
}
`
: ''};
`
export const MatchInfo = styled.div`
margin-bottom: 60px;
max-width: 670px;
${isMobileDevice
? css`
width: 100%;
height: 100%;
@media screen and (orientation: landscape){
padding-top: 0;
}
`
: ''};
`
export const Season = styled.div`
text-transform: uppercase;
background-color: rgba(0,0,0,0.4);
padding: 8px 25px;
color: #B9B9B9;
border-radius: 5px;
font-size: 13px;
font-weight: 600;
display: inline-flex;
margin-bottom: 50px;
${isMobileDevice
? css`
margin-bottom: 15px;
padding: 0.7em 2.5rem;
font-size: 10px;
`
: ''};
`
export const MainInfoTitle = styled.div`
font-weight: 600;
font-size: 2rem;
${isMobileDevice
? css`
font-size: 24px;
margin-bottom: 25px;
`
: ''};
`
export const MainInfoButton = styled(ButtonSolid)`
width: auto;
height: 70px;
font-size: 24px;
font-weight: 600;
border-radius: 5px;
margin-bottom: 50px;
${isMobileDevice
? css`
width: 100%;
font-size: 17px;
margin-bottom: 30px;
height: 40px;
`
: ''};
`
export const MainInfoText = styled.div`
margin: 40px 0;
font-size: 17px;
line-height: 150%;
${isMobileDevice
? css`
font-size: 12px;
margin: 0 0 25px;
letter-spacing: 0.1px;
`
: ''};
`
export const Footer = styled.div`
font-size: 14px;
background-color: black;
padding: 16px 0;
padding-left: 20%;
width: 100%;
@media ${devices.laptop} {
padding-left: 5%;
}
@media ${devices.mobile} {
padding-left: 35px;
}
${isMobileDevice
? css`
display: none;
`
: ''};
`
export const FooterRights = styled.div`
opacity: .5;
${isMobileDevice
? css`
font-size: 12px;
`
: ''};
`

@ -10,7 +10,6 @@ export const ScModal = styled(BaseModal)`
background-color: rgba(0, 0, 0, 0.7); background-color: rgba(0, 0, 0, 0.7);
${ModalWindow} { ${ModalWindow} {
background-color: #333333;
border-radius: 5px; border-radius: 5px;
display: flex; display: flex;
justify-content: center; justify-content: center;

@ -18,7 +18,9 @@ export type FavouriteTeams = {
} }
export type ResponseType = { export type ResponseType = {
data: {
data: Array<FavouriteTeams>, data: Array<FavouriteTeams>,
},
msg: string, msg: string,
status: string, status: string,
} }

@ -34,3 +34,5 @@ export * from './getTeamsStats'
export * from './getPlayersStats' export * from './getPlayersStats'
export * from './getMatchParticipants' export * from './getMatchParticipants'
export * from './getStatsEvents' export * from './getStatsEvents'
export * from './getTokenVirtualUser'
export * from './checkDevice'

Loading…
Cancel
Save