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. 26
      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. 32
      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. 48
      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. 33
      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. 16
      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. 4
      src/requests/getFavouriteTeam.tsx
  98. 2
      src/requests/index.tsx

@ -174,34 +174,34 @@ steps:
depends_on:
- make-lff
# - 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_insports-diwansport 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
- 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_insports-diwansport 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
---
kind: pipeline
@ -754,3 +754,58 @@ steps:
- rsync -v -r -C build_auth/ ubuntu@auth.insports.tv:/home/ubuntu/ott-auth/src/frontend/
depends_on:
- 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",
"lff": "REACT_APP_CLIENT=lff 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"
},
"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 -->
<script src="//www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></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>
</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,
}: ItemInfoType) => (
<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>
</ScWrapper>
)

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

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

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

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

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

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

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

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

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

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

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

@ -15,10 +15,9 @@ export const Modal = styled(BaseModal)`
padding: 0 60px;
${ModalWindow} {
max-width: 757px;
max-width: 949px;
min-height: 414px;
padding-top: 60px;
background-color: #333333;
border-radius: 5px;
@media (max-width: 1370px) {
@ -110,7 +109,8 @@ export const Footer = styled.div`
width: 100%;
display: flex;
justify-content: center;
padding: 1.89rem;
padding: 10px 0 25px;
${isMobileDevice
? css`
@media ${devices.mobile}{
@ -149,3 +149,7 @@ export const ApplyButton = styled(ButtonSolid)`
export const Text = styled.span`
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 { Checkbox } from 'features/Common/Checkbox'
import { ArrowLoader } from 'features/ArrowLoader'
import { RegisterPopup } from 'features/AuthServiceApp/components/RegisterPopup'
import { client } from 'features/AuthServiceApp/config/clients'
import { CompanyInfo } from 'features/CompanyInfo'
@ -26,6 +25,7 @@ import {
Error,
LanguageSelectWrapper,
Wrapper,
ScArrowLoader,
} from '../../styled'
import {
Label,
@ -134,7 +134,7 @@ const Registration = () => {
<ButtonSolid disabled={isSubmitDisabled} type='submit'>
{
isFetching
? <ArrowLoader />
? <ScArrowLoader />
: <T9n t='sign_up' />
}
</ButtonSolid>

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

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

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

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

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

@ -4,6 +4,7 @@ import { isMobileDevice } from 'config/userAgent'
import { ButtonSolid as BaseButtonSolid } from 'features/Common/Button'
import { T9n } from 'features/T9n'
import { ArrowLoader } from 'features/ArrowLoader'
import { client } from 'features/AuthServiceApp/config/clients'
@ -166,6 +167,7 @@ export const ChangePasswordModalWrapper = styled.div`
left: 0;
top: 0;
display: flex;
background: rgba(0, 0, 0, 0.7);
`
export const ChangePasswordModal = styled.div`
@ -173,7 +175,7 @@ export const ChangePasswordModal = styled.div`
justify-content: center;
flex-direction: column;
align-items: center;
background: #333333;
background: ${({ theme }) => theme.colors.modalBackground};
border-radius: 5px;
font-weight: 700;
height: 414px;
@ -222,4 +224,10 @@ export const ChangePasswordModalButton = styled(ButtonSolid)`
width: fit-content;
padding: 0 50px;
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 => ({
authority: AUTH_SERVICE,
automaticSilentRenew: true,
client_id: client.auth.clientId,
filterProtocolClaims: false,
loadUserInfo: false,
@ -70,7 +69,6 @@ export const getClientSettings = (): Settings => ({
response_mode: 'query',
response_type: 'id_token token',
scope: 'openid',
silent_redirect_uri: `${window.location.origin ?? window.origin}/silent-refresh.html`,
userStore: new WebStorageStateStore({ store: window.localStorage }),
})

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

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

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

@ -142,23 +142,23 @@ export const PackageSelectionStep = () => {
{!isIframePayment && <SelectedCard />}
</Body>
<Footer>
{loader ? (
<ArrowLoader width='204px' disabled />
) : (
<Button
disabled={!selectedPackage || disabledBuyBtn}
onClick={(e) => {
if (user) {
onHandleClick(e)
} else {
setSearch(window.location.search)
logout('saveToken')
}
}}
>
<Button
disabled={!selectedPackage || disabledBuyBtn}
onClick={(e) => {
if (user) {
onHandleClick(e)
} else {
setSearch(window.location.search)
logout('saveToken')
}
}}
>
{loader ? (
<ArrowLoader disabled />
) : (
<T9n t='buy_subscription' />
</Button>
)}
)}
</Button>
</Footer>
{selectedPackage && isIframePayment && (
<IframePayment

@ -52,7 +52,7 @@ export const Item = styled.li.attrs(() => ({
width: 100%;
min-height: 140px;
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);
border-radius: 2px;

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

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

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

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

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

@ -1,52 +1,20 @@
import {
ReactNode,
useEffect,
useState,
} from 'react'
import { useLocation } from 'react-router'
import { ReactNode } from 'react'
import { getLanguageUrlParam } from 'helpers/languageUrlParam'
import { AuthStore } from 'features/AuthStore'
import { LexicsStore } from 'features/LexicsStore'
import { getGeoInfo } from 'requests'
import { redirectToUrl } from 'helpers'
const initialLanguage = getLanguageUrlParam()
type Props = {
children: ReactNode,
}
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}>
<AuthStore>
{children}
</AuthStore>
</LexicsStore>
)
}
export const GlobalStores = ({ children }: Props) => (
<LexicsStore initialLanguage={initialLanguage}>
<AuthStore>
{children}
</AuthStore>
</LexicsStore>
)

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

@ -14,7 +14,7 @@ export const DEFAULT_HEADER_COLOR = 'rgba(53, 96, 225, 0.56)'
export const defaultHeaderStyles = (
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
}
@ -143,7 +143,6 @@ export const ScModal = styled(BaseModal)`
${ModalWindow} {
min-width: 280px;
max-height: 250px;
background-color: #333333;
border-radius: 0px;
padding: 0;
${customScrollbar}

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

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

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

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

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

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

@ -1,6 +1,8 @@
import { useEffect } from 'react'
import { useHistory } from 'react-router'
import { useTheme } from 'styled-components'
import { ProfileHeader } from 'features/ProfileHeader'
import { UserFavorites } from 'features/UserFavorites'
import { useUserFavoritesStore } from 'features/UserFavorites/store'
@ -30,6 +32,7 @@ const MatchPageComponent = () => {
usePageLogger()
const history = useHistory()
const { addRemoveFavorite, userFavorites } = useUserFavoritesStore()
const { colors } = useTheme()
const {
isStarted,
@ -89,7 +92,7 @@ const MatchPageComponent = () => {
return (
<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>
<UserFavorites />
<SubscriptionGuard>

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

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

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

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

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

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

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

@ -44,7 +44,7 @@ export const MatchesGrid = memo(({ matches }: MatchesGridProps) => {
)
}
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')))
}
@ -73,6 +73,7 @@ export const MatchesGrid = memo(({ matches }: MatchesGridProps) => {
updateSportIds(matches)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedDate, matches])
return (
<Wrapper>
{isHomePage && isShowTournament ? (

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

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

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

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

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

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

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

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

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

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

@ -1,27 +1,4 @@
export const lightTheme = {
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 = {
export const defaultTheme = {
colors: {
background: `
radial-gradient(
@ -35,11 +12,22 @@ export const defaultTheme: CustomTheme = {
black70: 'rgba(0, 0, 0, 0.7)',
button: '#294FC3',
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)',
dateFilter: '#656565',
error: 'rgba(235, 87, 87, 1)',
inputs: '#3F3F3F',
liveMatchPlaylistBtnBackground: 'linear-gradient(180deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0) 100%), #3F3F3F',
liveMatchPlaylistBtnHover: '#555555',
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: `
linear-gradient(
180deg,
@ -49,8 +37,15 @@ export const defaultTheme: CustomTheme = {
),
#0033CC
`,
searchBtnHover: '#3b3b3b',
secondary: '#999999',
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',
white50: 'rgba(255, 255, 255, 0.5)',
white70: 'rgba(255, 255, 255, 0.7)',
@ -78,6 +73,7 @@ export const facrTheme: CustomTheme = {
...defaultTheme.colors,
button: '#00257A',
inputs: 'transparent',
loaderAuth: '#00257A',
},
name: 'facr',
}
@ -88,13 +84,27 @@ export const tunisTheme: CustomTheme = {
...defaultTheme.colors,
background: '#1D1D1D',
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',
error: '#FF4E77',
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,
useEffect,
} from 'react'
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 {
CustomTheme,
@ -15,7 +19,6 @@ import {
lffTheme,
tunisTheme,
} from './config'
import { ClientNames } from '../../config/clients/types'
type Props = {
children: ReactNode,
@ -24,6 +27,25 @@ type Props = {
export const Theme = ({ children }: Props) => {
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(() => {
switch (client.name) {
case ClientNames.Lff:
@ -39,7 +61,7 @@ export const Theme = ({ children }: Props) => {
setTheme(defaultTheme)
break
}
}, [])
}, [client])
useEffect(() => {
switchTheme()

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

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

@ -150,19 +150,6 @@ export const SliderContainer = styled.div`
height: 100%;
position: relative;
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>`
@ -174,6 +161,12 @@ export const SliderImg = styled.img<SliderImgProps>`
animation-iteration-count: 1;
animation-timing-function: ease-out;
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 {
0% {
@ -256,7 +249,7 @@ export const DateInfo = styled(T9n)`
font-size: 10px;
border-radius: 3px;
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
? css`
font-size: 24px;
margin: 15px 0 0;
margin: 8px 0 0;
`
: css`
width: 50%;
@ -288,9 +281,8 @@ export const TournamentButton = styled(ButtonSolid)<ButtonProps>`
${isMobileDevice
? css`
width: 100%;
border-radius: 10px;
font-size: 17px;
padding: 20px 50px;
padding: 10px 0;
margin-bottom: 0;
`
: ''};
@ -304,7 +296,9 @@ export const TournamentDescription = styled(T9n)`
${isMobileDevice
? css`
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 = () => {
setIsShowTournament(false)
setSelectedLeague([tournament.id])
setSelectedLeague([`${tournament.sportType}_${tournament.id}`])
setSelectTournament(tournament)
}

@ -37,7 +37,7 @@ export const CardWrapper = styled.div`
right: 0;
padding-bottom: 0.75rem;
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;
${isMobileDevice
? css`

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

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

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

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

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

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

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

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

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

@ -15,6 +15,8 @@ import { SaveUserInfo } from 'requests'
import { readToken } from 'helpers/token'
import { client } from 'config/clients'
import { useUserInfoForm } from './useUserInfoForm'
import { useValidateForm } from './useValidateForm'
@ -110,7 +112,7 @@ export const useUserInfo = ({ loader, onSubmit }: Props) => {
}
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])
return {

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

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

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

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

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

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

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

@ -1,6 +1,5 @@
import toNumber from 'lodash/toNumber'
import isUndefined from 'lodash/isUndefined'
import includes from 'lodash/includes'
export const isMatchPage = () => {
const splitPath = window.location.pathname.split('/')
@ -16,5 +15,3 @@ export const isMatchPageRFEF = () => {
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 = () => (
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);
${ModalWindow} {
background-color: #333333;
border-radius: 5px;
display: flex;
justify-content: center;

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

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

Loading…
Cancel
Save