feat(#188): add payment for tunis

fix(#188): tunisia payment part 2

fix(#188): added favicon, terms and condition link, fix config tunisia

fix(#188): added tinisia landing page, redirect to diwan.insports.tv

fix(#188): fix pr comment

add autodeploy diwan.insports.tv

fix(#188): check geo initial mount, diwan update disabled for prod

fix(#188): changed action to one_payment for paymee, disabled check geo

fix(#188): failed paymee page

fix(#188): replaced DT to TND

fix(#188): added preloader

fix(#188): replaced history.push to redirectToUrl

fix(#188): changed error time to 1 min

fix(#286): stripe locale, payment plan displayng

fix(#286): fix styles
pull/82/head
Andrei Dekterev 3 years ago committed by Gitea
parent 6dad0f3758
commit a5757e44fe
  1. 6
      .drone.yml
  2. 17
      Makefile
  3. BIN
      public/clients/tunisia/favicon/android-chrome-192x192.png
  4. BIN
      public/clients/tunisia/favicon/android-chrome-512x512.png
  5. BIN
      public/clients/tunisia/favicon/apple-touch-icon.png
  6. 12
      public/clients/tunisia/favicon/browserconfig.xml
  7. BIN
      public/clients/tunisia/favicon/favicon-16x16.png
  8. BIN
      public/clients/tunisia/favicon/favicon-32x32.png
  9. BIN
      public/clients/tunisia/favicon/favicon.ico
  10. 19
      public/clients/tunisia/favicon/manifest.json
  11. BIN
      public/clients/tunisia/favicon/mstile-144x144.png
  12. BIN
      public/clients/tunisia/favicon/mstile-150x150.png
  13. BIN
      public/clients/tunisia/favicon/mstile-310x310.png
  14. BIN
      public/clients/tunisia/favicon/mstile-70x70.png
  15. 18
      public/clients/tunisia/favicon/safari-pinned-tab.svg
  16. 1550
      public/clients/tunisia/privacy-policy-and-statement.html
  17. 4368
      public/clients/tunisia/terms-and-conditions.html
  18. BIN
      public/images/landing_ligue_1.png
  19. BIN
      public/images/landing_mobile_ligue_1.png
  20. 29
      public/images/tunis_auth_logo_mobile.svg
  21. 84
      public/images/tunis_clubs.svg
  22. 6
      src/config/clients/index.tsx
  23. 1
      src/config/clients/lff.tsx
  24. 57
      src/config/clients/tunis.tsx
  25. 58
      src/config/clients/tunisia.tsx
  26. 7
      src/config/clients/types.tsx
  27. 1
      src/config/currencies.tsx
  28. 4
      src/config/lexics/joinMatch.tsx
  29. 2
      src/config/lexics/payment.tsx
  30. 1
      src/config/pages.tsx
  31. 22
      src/config/payments.tsx
  32. 4
      src/features/App/AuthenticatedApp.tsx
  33. 4
      src/features/AuthServiceApp/config/clients/index.tsx
  34. 9
      src/features/AuthServiceApp/config/clients/tunisia.tsx
  35. 8
      src/features/AuthStore/helpers.tsx
  36. 101
      src/features/BuyMatchPopup/components/BrazilPayment/hooks.tsx
  37. 4
      src/features/BuyMatchPopup/components/ErrorStep/index.tsx
  38. 173
      src/features/BuyMatchPopup/components/IframePayment/hooks.tsx
  39. 34
      src/features/BuyMatchPopup/components/IframePayment/index.tsx
  40. 6
      src/features/BuyMatchPopup/components/IframePayment/styled.tsx
  41. 45
      src/features/BuyMatchPopup/components/PackageSelectionStep/index.tsx
  42. 4
      src/features/BuyMatchPopup/components/SuccessStep/index.tsx
  43. 2
      src/features/BuyMatchPopup/styled.tsx
  44. 2
      src/features/CompanyInfo/index.tsx
  45. 2
      src/features/HeaderMobile/styled.tsx
  46. 1
      src/features/HomePage/index.tsx
  47. 6
      src/features/JoinMatchPage/index.tsx
  48. 5
      src/features/JoinMatchPageRFEF/index.tsx
  49. 1
      src/features/MatchPage/components/LiveMatch/index.tsx
  50. 1
      src/features/PopupComponents/Header/index.tsx
  51. 2
      src/features/ProfileCard/index.tsx
  52. 6
      src/features/ProfileHeader/styled.tsx
  53. 6
      src/features/StripeElements/index.tsx
  54. 15
      src/features/Theme/config.tsx
  55. 4
      src/features/Theme/index.tsx
  56. 15
      src/features/UserAccount/components/PageSubscriptions/index.tsx
  57. 5
      src/features/UserAccount/components/PageSubscriptions/styled.tsx
  58. 2
      src/features/UserAccount/index.tsx
  59. 3
      src/helpers/getCurrentYear/index.tsx
  60. 1
      src/helpers/index.tsx
  61. 3
      src/helpers/isMatchPage/index.tsx
  62. 78
      src/pages/DiwanInsportsTv/index.tsx
  63. 302
      src/pages/DiwanInsportsTv/styled.tsx
  64. 13
      src/pages/FailedPaymeePage/index.tsx
  65. 11
      src/pages/FailedPaymeePage/styled.tsx
  66. 6
      src/pages/Mailings/index.tsx
  67. 2
      src/react-app-env.d.ts
  68. 1
      src/requests/getGeoInfo.tsx
  69. 15
      src/requests/getPaymentUrl.tsx

@ -184,7 +184,7 @@ steps:
# - make diwansport-prod
# depends_on:
# - npm-install
#
# - name: deploy-diwansport
# image: amazon/aws-cli:latest
# environment:
@ -197,7 +197,9 @@ steps:
# AWS_MAX_ATTEMPTS: 10
# commands:
# - aws s3 sync build_insports-diwansport s3://insports-diwansport --delete
# - aws cloudfront create-invalidation --distribution-id E3LKAH6TR4O2JL --paths "/*"
# - 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

@ -130,6 +130,12 @@ india-build: clean
REACT_APP_CLIENT=india \
npm run build
tunisia-build: clean
REACT_APP_TYPE=ott \
REACT_APP_ENV=staging \
REACT_APP_CLIENT=tunisia \
npm run build
lff-build: clean
REACT_APP_TYPE=ott \
REACT_APP_ENV=staging \
@ -180,7 +186,16 @@ lff-prod:
BUILD_PATH=build_lff \
npm run build && cp -r .well-known build_lff
deploy-all: prod preprod facr-prod lff-prod
diwansport-prod:
rm -rf build_tunisia && \
REACT_APP_TYPE=ott \
REACT_APP_ENV=production \
REACT_APP_STRIPE_PK=pk_live_51J5TEYEDSxVnTgDW5XxhC6ntKZKddXgKHq5HOCDmJTdfSKluMYCdLHOcUA3Miuy8HesxG1eS4c0dQRQpMsEHRrQL00USpu5xIq \
REACT_APP_CLIENT=tunisia \
BUILD_PATH=build_tunisia \
npm run build && cp -r .well-known build_tunisia
deploy-all: prod preprod facr-prod lff-prod diwansport-prod india-prod
test:
npm test

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square70x70logo src="/mstile-70x70.png"/>
<square144x144logo src="/mstile-144x144.png"/>
<square150x150logo src="/mstile-150x150.png"/>
<square310x310logo src="/mstile-310x310.png"/>
<TileColor>#da532c</TileColor>
</tile>
</msapplication>
</browserconfig>

Binary file not shown.

After

Width:  |  Height:  |  Size: 477 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

@ -0,0 +1,19 @@
{
"name": "",
"short_name": "",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

@ -0,0 +1,18 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="700.000000pt" height="700.000000pt" viewBox="0 0 700.000000 700.000000" preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.14, written by Peter Selinger 2001-2017
</metadata>
<g transform="translate(0.000000,700.000000) scale(0.100000,-0.100000)" fill="#000000" stroke="none">
<path d="M1499 6996 c-2 -2 -59 -6 -125 -9 -247 -12 -462 -57 -614 -129 -64
-30 -206 -123 -265 -173 -105 -89 -173 -164 -247 -270 -153 -219 -210 -411
-235 -790 -11 -161 -10 -4130 0 -4270 12 -158 20 -222 43 -331 60 -297 246
-573 515 -766 182 -130 345 -193 584 -225 22 -2 51 -6 65 -8 124 -17 518 -20
2260 -20 1773 0 2220 4 2295 19 11 2 45 7 75 10 75 9 120 17 190 36 121 32
186 61 300 129 87 53 77 46 155 109 140 114 277 283 353 437 83 166 119 330
139 630 11 160 10 4107 0 4260 -29 420 -108 642 -311 880 -175 205 -390 346
-626 412 -47 13 -107 26 -135 29 -27 4 -52 8 -55 9 -3 2 -44 6 -90 10 -47 4
-96 9 -110 13 -26 6 -4154 14 -4161 8z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

@ -0,0 +1,29 @@
<svg width="102" height="75" viewBox="0 0 102 75" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_8_12573)">
<path d="M87.7871 0H14.2129C6.36333 0 0 6.37899 0 14.2479V47.1045C0 54.9734 6.36333 61.3524 14.2129 61.3524H87.7871C95.6367 61.3524 102 54.9734 102 47.1045V14.2479C102 6.37899 95.6367 0 87.7871 0Z" fill="#0B2E4D"/>
<path d="M88.6677 33.2715H13.3323C5.96907 33.2715 0 39.2553 0 46.6366V61.626C0 69.0074 5.96907 74.9911 13.3323 74.9911H88.6677C96.0309 74.9911 102 69.0074 102 61.626V46.6366C102 39.2553 96.0309 33.2715 88.6677 33.2715Z" fill="url(#paint0_linear_8_12573)"/>
<path d="M26.3565 21.1689C26.3565 26.5538 23.838 29.2551 18.801 29.2551C14.169 29.2551 11.853 26.8805 11.853 22.1223C11.853 20.8511 12.038 19.5182 12.4078 18.1146L17.1895 17.2583C16.7139 18.8031 16.4762 20.2773 16.4762 21.681C16.4762 24.3204 17.348 25.6358 19.1004 25.6358C20.0338 25.6358 20.6943 25.3444 21.0905 24.753C21.5044 24.1262 21.707 23.0404 21.707 21.4867V12.1559H26.3477V21.1689H26.3565ZM17.031 15.5545C16.5995 15.122 16.3881 14.6011 16.3881 13.992C16.3881 13.3829 16.5995 12.8621 17.031 12.4295C17.4536 12.0058 17.9644 11.7939 18.5808 11.7939C19.1972 11.7939 19.708 12.0058 20.1395 12.4295C20.571 12.8621 20.7823 13.3829 20.7823 13.992C20.7823 14.6011 20.571 15.122 20.1395 15.5545C19.708 15.9783 19.1884 16.1901 18.5808 16.1901C17.9732 16.1901 17.4536 15.9783 17.031 15.5545Z" fill="white"/>
<path d="M29.3945 6.42676H34.0177V23.6407H29.3945V6.42676Z" fill="white"/>
<path d="M36.7301 29.5023L36.9679 25.8035C38.0862 26.0154 39.3103 26.1213 40.64 26.1213C43.0088 26.1213 44.1976 25.3003 44.1976 23.6496V23.6231H43.0792C38.6322 23.6231 36.4043 21.7604 36.4043 18.0352C36.4043 16.2608 36.9327 14.8131 37.9982 13.6919C39.2134 12.4207 40.9746 11.7852 43.2818 11.7852C45.404 11.7852 47.2093 12.0676 48.6799 12.6326V20.0126H50.626V23.6231H48.6535C48.5302 25.5563 47.7817 27.0394 46.4167 28.0811C44.9902 29.1757 42.9472 29.723 40.2789 29.723C39.1077 29.723 37.9189 29.6436 36.7213 29.4847L36.7301 29.5023ZM44.1976 15.6958C43.8366 15.5016 43.3875 15.4133 42.8415 15.4133C42.2515 15.4133 41.7936 15.634 41.4501 16.0842C41.1419 16.4991 40.9834 17.0111 40.9834 17.6379C40.9834 19.2357 41.82 20.0302 43.4931 20.0302H44.1976V15.7046V15.6958Z" fill="white"/>
<path d="M50.2646 20.0303H55.3545V23.6408H50.2646V20.0303Z" fill="white"/>
<path d="M54.8613 20.0303H59.9512V23.6408H54.8613V20.0303Z" fill="white"/>
<path d="M59.4673 20.0303H64.5572V23.6408H59.4673V20.0303Z" fill="white"/>
<path d="M64.0728 20.0303H69.1626V23.6408H64.0728V20.0303Z" fill="white"/>
<path d="M68.6694 20.0305H72.8083V12.1562H77.4314V23.6322H68.6694V20.0217V20.0305ZM72.2359 28.8406C71.8308 29.2643 71.3288 29.4762 70.7388 29.4762C70.1488 29.4762 69.6645 29.2643 69.2682 28.8406C68.872 28.4168 68.6694 27.9048 68.6694 27.3046C68.6694 26.7043 68.8632 26.2099 69.2682 25.795C69.6733 25.3713 70.1665 25.1594 70.7388 25.1594C71.3112 25.1594 71.8308 25.3713 72.2359 25.795C72.6321 26.2187 72.8347 26.7219 72.8347 27.3046C72.8347 27.8872 72.6321 28.4168 72.2359 28.8406ZM76.9119 28.8406C76.5156 29.2643 76.0224 29.4762 75.4412 29.4762C74.8601 29.4762 74.3581 29.2643 73.953 28.8406C73.548 28.4168 73.3454 27.9048 73.3454 27.3046C73.3454 26.7043 73.548 26.2099 73.953 25.795C74.3581 25.3713 74.8512 25.1594 75.4412 25.1594C76.0313 25.1594 76.5156 25.3713 76.9119 25.795C77.3081 26.2187 77.5107 26.7219 77.5107 27.3046C77.5107 27.8872 77.3081 28.4168 76.9119 28.8406Z" fill="white"/>
<path d="M79.6855 20.0299H86.0435C85.9202 18.8028 85.4183 17.7788 84.5465 16.9402C83.6306 16.0574 82.3978 15.4925 80.8744 15.2364L81.9487 11.4141C87.699 12.5705 90.5698 15.9162 90.5698 21.4511V23.6404H79.6855V20.0299Z" fill="white"/>
<path d="M20.7294 63.4183C19.0651 64.8484 16.9604 65.5634 14.4067 65.5634C12.3373 65.5634 10.5761 65.378 9.10546 65.0161L9.61621 59.384C11.2189 60.0638 12.8568 60.408 14.53 60.408C15.9037 60.408 16.5906 59.9049 16.5906 58.8897C16.5906 58.2188 16.1767 57.6715 15.3401 57.2566C15.0583 57.1153 14.6356 56.9299 14.072 56.7092C13.35 56.4532 12.8568 56.2679 12.6014 56.1531C9.93322 55.0232 8.60352 53.0634 8.60352 50.265C8.60352 48.1111 9.38725 46.4073 10.9459 45.1538C12.5398 43.8915 14.7237 43.2559 17.5152 43.2559C18.9154 43.2559 20.2274 43.3971 21.4515 43.6708L20.9583 48.782C19.7519 48.3583 18.5279 48.1464 17.3039 48.1464C15.7452 48.1464 14.9615 48.6319 14.9615 49.5941C14.9615 50.1679 15.3929 50.6623 16.2471 51.1037C16.5289 51.2361 16.9604 51.4303 17.5592 51.6775L19.0739 52.2954C21.8213 53.5489 23.1951 55.4822 23.1951 58.104C23.1951 60.2403 22.3761 62.0059 20.7294 63.4183Z" fill="white"/>
<path d="M38.4733 56.3913C36.853 58.0068 34.581 58.8101 31.6574 58.8101C31.358 58.8101 31.0938 58.8013 30.8649 58.7748V65.1395H24.9648V43.6794C27.0783 43.5647 29.3767 43.5117 31.8423 43.5117C37.7512 43.5117 40.7012 45.8864 40.7012 50.6357C40.7012 52.9838 39.9615 54.8994 38.4733 56.3825V56.3913ZM31.6926 48.3669C31.4637 48.3669 31.1907 48.3758 30.8737 48.4023V53.8401C31.1731 53.9019 31.5253 53.9372 31.9304 53.9372C33.7268 53.9372 34.625 53.0015 34.625 51.1388C34.625 49.2762 33.6476 48.3758 31.7014 48.3758L31.6926 48.3669Z" fill="white"/>
<path d="M59.3964 62.4296C57.3446 64.5394 54.7732 65.5988 51.6999 65.5988C48.3977 65.5988 45.888 64.6454 44.1708 62.7298C42.5065 60.876 41.6787 58.2453 41.6787 54.8466C41.6787 51.448 42.7442 48.5878 44.8665 46.3986C46.9183 44.2976 49.4808 43.2471 52.5453 43.2471C55.8476 43.2471 58.3661 44.2005 60.0921 46.1161C61.7564 47.9611 62.5842 50.5829 62.5842 53.9904C62.5842 57.3978 61.5186 60.2668 59.3964 62.4385V62.4296ZM52.1755 48.6408C50.8722 48.6408 49.8507 49.1263 49.0934 50.0974C48.3361 51.0949 47.9662 52.4808 47.9662 54.2728C47.9662 58.1835 49.3399 60.1433 52.0874 60.1433C53.3907 60.1433 54.4122 59.6666 55.1519 58.7132C55.918 57.7333 56.2967 56.3474 56.2967 54.5553C56.2967 50.6094 54.9229 48.6408 52.1755 48.6408Z" fill="white"/>
<path d="M74.6221 65.1395L70.6594 57.3182H70.3776V65.1395H64.4775V43.6794C66.1419 43.5647 68.5811 43.5117 71.8041 43.5117C77.4752 43.5117 80.3107 45.7451 80.3107 50.2208C80.3107 51.5273 79.9673 52.719 79.2892 53.796C78.5848 54.8994 77.6513 55.6763 76.4713 56.1088C77.1054 57.0622 77.6161 57.892 78.0212 58.5894L81.799 65.1395H74.6309H74.6221ZM71.4959 48.3846C71.0116 48.3846 70.6417 48.4023 70.3776 48.4464V53.0544C70.677 53.0986 71.0028 53.1162 71.355 53.1162C73.1867 53.1162 74.0937 52.2953 74.0937 50.6621C74.0937 49.1438 73.2307 48.3758 71.4959 48.3758V48.3846Z" fill="white"/>
<path d="M91.6619 48.7644V65.1397H85.7618V48.7644H81.1299V43.6885H96.2938V48.7644H91.6619Z" fill="white"/>
</g>
<defs>
<linearGradient id="paint0_linear_8_12573" x1="0" y1="54.1401" x2="102" y2="54.1401" gradientUnits="userSpaceOnUse">
<stop stop-color="#005D6B"/>
<stop offset="1" stop-color="#1DB9AB"/>
</linearGradient>
<clipPath id="clip0_8_12573">
<rect width="102" height="75" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 6.7 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 1.4 MiB

@ -5,7 +5,7 @@ import { instat } from './instat'
import { lff } from './lff'
import { insports } from './insports'
import { india } from './india'
import { tunis } from './tunis'
import { tunisia } from './tunisia'
export const currentClient = process.env.REACT_APP_CLIENT || 'insports'
@ -14,7 +14,7 @@ export const isInSportsClient = currentClient === 'insports'
export const isInstatClient = currentClient === 'instat'
export const isFacrClient = currentClient === 'facr'
export const isIndiaClient = currentClient === 'india'
export const isTunisClient = currentClient === 'tunis'
export const isTunisClient = currentClient === 'tunisia'
const clients = {
facr,
@ -22,7 +22,7 @@ const clients = {
insports,
instat,
lff,
tunis,
tunisia,
}
export const client: ClientConfig = clients[currentClient]

@ -11,6 +11,7 @@ export const lff: ClientConfig = {
},
defaultLanguage: 'lv',
description: 'Live sports streaming platform. Football, basketball, ice hockey and more. Access to various player playlists and game highlights. Multiple subscription options. Available across all devices.',
disabledHighlights: true,
disabledPreferences: true,
name: ClientNames.Lff,
privacyLink: '/clients/instat/terms-and-conditions.html',

@ -1,57 +0,0 @@
import { css } from 'styled-components/macro'
import {
ClientConfig,
ClientIds,
ClientNames,
} from './types'
const randomHash = () => (
(Math.random() ** Math.random()) * 9999999999999999
)
export const tunis: ClientConfig = {
auth: {
clientId: ClientIds.Tunis,
metaDataUrlParams: `?hash=${randomHash()}`,
},
defaultLanguage: 'fr',
description: 'Live sports streaming platform. All matches playing under the auspices of Czech Republic FA. Access to full matches, various player playlists, and highlights. Free access in the Czech Republic. Available across all devices',
disabledPreferences: false,
name: ClientNames.Tunis,
privacyLink: '/privacy-policy-and-statement',
showSearch: false,
styles: {
background: '',
homePageHeader: css`
background: radial-gradient(
160.34% 257.27% at -7.45% 162.22%,
#2AB7AA 3.27%,
#02505C 43.69%, #0B2E4D 100%);
`,
logo: 'tunis-logo.svg',
logoHeight: 6.3,
logoLeft: 1.1,
logoTop: 1.74,
logoWidth: 8.25,
matchLogoHeight: 3.4,
matchLogoTopMargin: 0.9,
matchLogoWidth: 4.5,
matchPageMobileHeaderLogo: css`
width: 35px;
height: 25px;
top: 2px;
`,
mobileHeaderLogo: css`
width: 48px;
height: 37px;
`,
userAccountLogo: css`
width: 4.56rem;
height: 3.488rem;
`,
},
termsLink: '/terms-and-conditions?client_id=facr-ott-web',
title: 'FACR.TV - The home of Czech football streaming',
userAccountLinksDisabled: true,
}

@ -0,0 +1,58 @@
import { css } from 'styled-components/macro'
import {
ClientConfig,
ClientIds,
ClientNames,
} from './types'
const randomHash = () => (
(Math.random() ** Math.random()) * 9999999999999999
)
export const tunisia: ClientConfig = {
auth: {
clientId: ClientIds.Tunisia,
metaDataUrlParams: `?hash=${randomHash()}`,
},
defaultLanguage: 'fr',
description: '',
disabledFilters: true,
disabledHighlights: true,
disabledPreferences: true,
name: ClientNames.Tunisia,
privacyLink: '/privacy-policy-and-statement?client_id=insports-ott-web',
showSearch: true,
styles: {
background: '',
homePageHeader: css`
background: radial-gradient(
160.34% 257.27% at -7.45% 162.22%,
#2AB7AA 3.27%,
#02505C 43.69%, #0B2E4D 100%);
`,
logo: 'tunis-logo.svg',
logoHeight: 1.922,
logoLeft: 1.1,
logoTop: 1.74,
logoWidth: 9,
matchLogoHeight: 1.922,
matchLogoTopMargin: 1,
matchLogoWidth: 9,
matchPageMobileHeaderLogo: css`
width: 100px;
height: 21px;
top: 5px;
`,
mobileHeaderLogo: css`
width: 100px;
height: 21px;
`,
userAccountLogo: css`
width: 9rem;
height: 1.922rem;
`,
},
termsLink: '/terms-and-conditions?client_id=insports-ott-web',
title: 'Diwan Sport - The home of Tunisian Ligue Professionnelle 1',
}

@ -10,16 +10,17 @@ export enum ClientIds {
Insports = 'insports-ott-web',
Instat = 'ott-web',
Lff = 'lff-ott-web',
Tunis = 'tunis-ott-web',
Tunisia = 'tunis-ott-web',
}
export enum ClientNames {
Brasil = 'brasil',
Facr = 'facr',
India = 'india',
Insports = 'insports',
Instat = 'instat',
Lff = 'lff',
Tunis = 'tunis',
Tunisia = 'tunisia'
}
export type ClientConfig = {
@ -30,6 +31,8 @@ export type ClientConfig = {
},
defaultLanguage: string,
description: string,
disabledFilters?: boolean,
disabledHighlights?: boolean,
disabledPreferences?: boolean,
name: ClientNames,
privacyLink: string,

@ -12,5 +12,6 @@ export const currencySymbols = {
KZT: '₸',
MDL: 'L',
RUB: '₽',
TND: 'TND',
USD: '$',
} as const

@ -1,4 +1,8 @@
export const joinMatchLexics = {
diwan_desc: 20035,
diwan_join: 20037,
diwan_season: 19983,
diwan_title: 20036,
join_insports_tv: 15420,
join_now: 15422,
promo_text: 15421,

@ -19,6 +19,7 @@ export const paymentLexics = {
error_empty_name: 15290,
error_empty_state: 19821,
error_payment_unsuccessful: 14446,
failed_paymee: 20046,
if_you_cancel: 18189,
is_gpay: 20045,
next_payment: 18183,
@ -27,6 +28,7 @@ export const paymentLexics = {
payment_date: 15603,
payment_method: 2010,
pb_instat: 18274,
processing: 722,
save_sub: 18190,
state: 12932,
still_cancel: 2646,

@ -1,5 +1,6 @@
export const PAGES = {
about_the_project: 'https://instatsport.com/InStatTV/ott_platform',
failedPaymee: '/failed-paymee',
highlights: '/highlights',
home: '/',
mailings: '/useraccount/mailings',

@ -0,0 +1,22 @@
import { ClientNames } from './clients/types'
export enum PaymentSystem {
PagBrazil = 'pag_brasil',
Paymee = 'paymee',
Paytm = 'paytm',
Stripe = 'stripe'
}
type PaymentsType = {
[key in ClientNames]: PaymentSystem
}
export const payments: PaymentsType = {
[ClientNames.Tunisia]: PaymentSystem.Paymee,
brasil: PaymentSystem.PagBrazil,
[ClientNames.India]: PaymentSystem.Paytm,
[ClientNames.Insports]: PaymentSystem.Stripe,
[ClientNames.Instat]: PaymentSystem.Stripe,
[ClientNames.Facr]: PaymentSystem.Stripe,
[ClientNames.Lff]: PaymentSystem.Stripe,
}

@ -40,6 +40,7 @@ const HighlightsPage = lazy(() => import('pages/HighlightsPage'))
const ThanksPage = lazy(() => import('pages/ThanksPage'))
const Mailings = lazy(() => import('pages/Mailings'))
const FailedPaymeePage = lazy(() => import('pages/FailedPaymeePage'))
export const AuthenticatedApp = () => {
useLexicsConfig(indexLexics)
@ -66,6 +67,9 @@ export const AuthenticatedApp = () => {
<Route path={PAGES.mailings}>
<Mailings />
</Route>
<Route path={PAGES.failedPaymee}>
<FailedPaymeePage />
</Route>
<Route path={PAGES.useraccount}>
<UserAccount />
</Route>

@ -5,7 +5,7 @@ import { insports } from './insports'
import { instat } from './instat'
import { lff } from './lff'
import { india } from './india'
import { tunis } from './tunis'
import { tunisia } from './tunisia'
const clients = {
[ClientIds.Facr]: facr,
@ -13,7 +13,7 @@ const clients = {
[ClientIds.Lff]: lff,
[ClientIds.Insports]: insports,
[ClientIds.India]: india,
[ClientIds.Tunis]: tunis,
[ClientIds.Tunisia]: tunisia,
}
const params = new URLSearchParams(window.location.search)

@ -1,6 +1,6 @@
import styled, { css } from 'styled-components/macro'
import { tunis as platformTunis } from 'config/clients/tunis'
import { tunisia as platformTunis } from 'config/clients/tunisia'
import { isMobileDevice } from 'config/userAgent'
import type { ClientConfig } from './types'
@ -16,7 +16,7 @@ const Background = styled.div`
radial-gradient(152.89% 271.81% at 0% 96.71%, #2AB7AA 3.27%, #02505C 43.69%, #0B2E4D 100%);
`
export const tunis: ClientConfig = {
export const tunisia: ClientConfig = {
...platformTunis,
background: Background,
styles: {
@ -49,9 +49,10 @@ export const tunis: ClientConfig = {
margin-bottom: 1.82rem;
${isMobileDevice ? css`
background-image: url(/images/tunis_auth_logo_mobile.svg);
margin-bottom: 20px;
width: 130px;
height: 100px;
width: 102px;
height: 75px;
` : ''}
`,
popupApplyButton: css`

@ -22,11 +22,11 @@ export interface Settings extends UserManagerSettings {
export const getClientNameByRedirectUri = () => {
switch (client.name) {
case ClientNames.Lff:
return 'lff.instat'
return 'lff.insports'
case ClientNames.India:
return 'india.insports'
case ClientNames.Tunis:
return ClientNames.Tunis
case ClientNames.Tunisia:
return 'diwan.insports'
case ClientNames.Facr:
return ClientNames.Facr
case ClientNames.Instat:
@ -44,7 +44,7 @@ const redirectUrl = () => {
|| client.name === 'lff'
|| client.name === 'facr'
|| client.name === 'india'
|| client.name === 'tunis'
|| client.name === 'tunisia'
):
return `${window.origin}/redirect`
case (ENV === 'staging' || ENV === 'preproduction'):

@ -1,101 +0,0 @@
import {
useEffect,
useState,
MouseEvent,
} from 'react'
import { useHistory } from 'react-router-dom'
import { ProfileTypes } from 'config'
import isNumber from 'lodash/isNumber'
import { useLexicsStore } from 'features/LexicsStore'
import { useBuyMatchPopupStore } from 'features/BuyMatchPopup/store'
import { getProfileUrl } from 'features/ProfileLink/helpers'
import { getMatchInfo } from 'requests/getMatchInfo'
import { getBrazilPaymentUrl } from 'requests/getBrazilPaymentUrl'
import type { Props } from './index'
type ResponsePayment = {
url: string,
}
type ResponsePaymentArray = ResponsePayment | null
export const useBrazilPayment = ({
match,
open,
selectedPackage,
setIsOpenBrasilian,
}: Props) => {
const history = useHistory()
const { close } = useBuyMatchPopupStore()
const [src, setSrc] = useState('')
const [error, setError] = useState('')
const { translate } = useLexicsStore()
const { id, sportType } = match
const {
name,
nameLexic,
originalObject,
pass,
} = selectedPackage
const teams = isNumber(nameLexic) ? translate(String(nameLexic)) : name
const pack = translate(String(pass))
const matchLink = getProfileUrl({
id,
profileType: ProfileTypes.MATCHES,
sportType,
})
const closePopup = async (e?: MouseEvent) => {
e?.stopPropagation()
setIsOpenBrasilian(false)
setError('')
const accessMatch = await getMatchInfo(sportType, id)
if (accessMatch?.access) {
close()
history.push(matchLink)
}
}
// eslint-disable-next-line
window.onmessage = function (event) {
if (event.data === 'close') {
closePopup()
}
}
useEffect(() => {
if (open) {
(async () => {
try {
const json: ResponsePaymentArray = await getBrazilPaymentUrl({
action: pass === 'pass_match_access' ? 'one_payment' : 'create_subscription',
item: originalObject,
product_name: `${pack} ${teams}`,
})
setSrc(json?.url || '')
} catch (err) {
setError('error_payment_unsuccessful')
}
})()
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedPackage, open])
return {
closePopup,
error,
matchLink,
src,
}
}

@ -17,13 +17,13 @@ export const ErrorStep = () => {
} = useBuyMatchPopupStore()
return (
<Wrapper height={278} width={369}>
<Wrapper width={369}>
<Header height={24}>
<HeaderTitle>
<T9n t='payment' />
</HeaderTitle>
</Header>
<Body marginTop={30} marginBottom={40}>
<Body marginTop={30}>
<ResultText>
{paymentError || <T9n t='error_payment_unsuccessful' />}
</ResultText>

@ -0,0 +1,173 @@
import {
MouseEvent,
useCallback,
useEffect,
useState,
} from 'react'
import { PAGES, ProfileTypes } from 'config'
import { ClientNames } from 'config/clients/types'
import { payments, PaymentSystem } from 'config/payments'
import isNumber from 'lodash/isNumber'
import { useLexicsStore } from 'features/LexicsStore'
import { useBuyMatchPopupStore } from 'features/BuyMatchPopup/store'
import { getProfileUrl } from 'features/ProfileLink/helpers'
import { getMatchInfo } from 'requests/getMatchInfo'
import { getPaymentUrl } from 'requests/getPaymentUrl'
import { redirectToUrl } from 'helpers'
import type { Props } from './index'
type ResponsePayment = {
url: string,
}
type ResponsePaymentArray = ResponsePayment | null
export const useIframePayment = ({
match,
open,
paymentSystem,
selectedPackage,
setIsOpenIframe,
}: Props) => {
const { close } = useBuyMatchPopupStore()
const [src, setSrc] = useState('')
const [error, setError] = useState('')
const [isPaymentProcessing, setIsPaymentProcessing] = useState(false)
const { translate } = useLexicsStore()
const { id, sportType } = match
const {
name,
nameLexic,
originalObject,
pass,
} = selectedPackage
const teams = isNumber(nameLexic) ? translate(String(nameLexic)) : name
const pack = translate(String(pass))
const matchLink = getProfileUrl({
id,
profileType: ProfileTypes.MATCHES,
sportType,
})
const closePopup = useCallback(async (e?: MouseEvent) => {
e?.stopPropagation()
if (error) {
setIsOpenIframe(false)
setError('')
}
const accessMatch = await getMatchInfo(sportType, id)
if (accessMatch?.access) {
setIsPaymentProcessing(false)
setIsOpenIframe(false)
setError('')
close()
redirectToUrl(matchLink)
}
}, [close, error, id, matchLink, setIsOpenIframe, sportType])
const paymentRequest = async () => {
let url_cancel
let url_return
let action: Parameters<typeof getPaymentUrl>[0]['action']
switch (paymentSystem) {
case PaymentSystem.Paymee:
url_cancel = `${window.origin}/failed-paymee`
url_return = null
// paymee не умеет работать с подписками
action = 'one_payment'
break
default:
url_return = `${window.location.origin}${PAGES.thanksForSubscribe}`
action = pass === 'pass_match_access' ? 'one_payment' : 'create_subscription'
break
}
const payment: ResponsePaymentArray = await getPaymentUrl({
action,
item: originalObject,
product_name: `${pack} ${teams}`,
service: paymentSystem,
url_cancel,
url_return,
})
setSrc(payment?.url || '')
}
if (paymentSystem === payments[ClientNames.Brasil]) {
// eslint-disable-next-line
window.onmessage = function (event) {
if (event.data === 'close') {
closePopup()
}
}
}
useEffect(() => {
let interval: ReturnType<typeof setInterval>
let timeout: ReturnType<typeof setTimeout>
const paymentCallback = (event: MessageEvent<{ event_id: string }>) => {
if (event.data.event_id === 'paymee.complete') {
setIsPaymentProcessing(true)
interval = setInterval(() => closePopup(), 2000)
timeout = setTimeout(() => {
clearInterval(interval)
setIsPaymentProcessing(false)
setError('failed_paymee')
setSrc('')
}, 60000)
}
}
if (paymentSystem === payments[ClientNames.Tunisia]) {
window.addEventListener(
'message',
paymentCallback,
false,
)
}
return () => {
window.removeEventListener(
'message',
paymentCallback,
false,
)
clearInterval(interval)
clearTimeout(timeout)
}
}, [closePopup, paymentSystem])
useEffect(() => {
if (open) {
(async () => {
try {
await paymentRequest()
} catch (err) {
setError('error_payment_unsuccessful')
}
})()
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedPackage, open])
return {
closePopup,
error,
isPaymentProcessing,
matchLink,
src,
}
}

@ -2,7 +2,10 @@ import { Loader } from 'features/Loader'
import { MatchPackage, Match } from 'features/BuyMatchPopup/types'
import { T9n } from 'features/T9n'
import { useBrazilPayment } from './hooks'
import { PaymentSystem } from 'config/payments'
import { isMobileDevice } from 'config'
import { useIframePayment } from './hooks'
import {
LoaderWrapper,
@ -12,35 +15,38 @@ import {
export type Props = {
match: Match,
open: boolean,
paymentSystem: PaymentSystem,
selectedPackage: MatchPackage,
setIsOpenBrasilian: (open: boolean) => void,
setIsOpenIframe: (open: boolean) => void,
}
export const BrazilPayment = ({
export const IframePayment = ({
match,
open,
paymentSystem,
selectedPackage,
setIsOpenBrasilian,
setIsOpenIframe,
}: Props) => {
const {
closePopup,
error,
isPaymentProcessing,
src,
} = useBrazilPayment({
} = useIframePayment({
match,
open,
paymentSystem,
selectedPackage,
setIsOpenBrasilian,
setIsOpenIframe,
})
return (
<ScModal isOpen={open} withCloseButton close={closePopup}>
<ScModal isOpen={open} withCloseButton close={() => setIsOpenIframe(false)}>
{src && open ? (
<iframe
title='BrazilPayment'
title='Payment'
frameBorder='0'
src={src}
height={600}
height={isMobileDevice ? 450 : 600}
width='100%'
/>
) : (
@ -54,6 +60,14 @@ export const BrazilPayment = ({
)}
</>
)}
{
isPaymentProcessing && (
<LoaderWrapper>
<Loader color='#515151' />
<T9n t='processing' />
</LoaderWrapper>
)
}
</ScModal>
)
}

@ -17,6 +17,8 @@ export const ScModal = styled(BaseModal)`
${isMobileDevice
? css`
text-align: center;
font-size: 16px;
padding: 50px 0px;
width: calc(100vw - 30px);
@media screen and (orientation: landscape){
@ -30,7 +32,7 @@ export const ScModal = styled(BaseModal)`
`
export const LoaderWrapper = styled.div`
position: absolute;
position: fixed;
top: 0;
left: 0;
width: 100%;
@ -38,4 +40,6 @@ export const LoaderWrapper = styled.div`
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
z-index: 20;
`

@ -3,11 +3,14 @@ import {
useEffect,
useState,
MouseEvent,
useMemo,
} from 'react'
import isNull from 'lodash/isNull'
import { MDASH } from 'config'
import { payments } from 'config/payments'
import { client } from 'config/clients'
import { CountryCodeType, getCountryCode } from 'requests/getCountryCode'
@ -18,7 +21,7 @@ import { useCardsStore } from 'features/CardsStore'
import { ArrowLoader } from 'features/ArrowLoader'
import { Arrow } from 'features/HeaderFilters/components/DateFilter/styled'
import { BrazilPayment } from '../BrazilPayment'
import { IframePayment } from '../IframePayment'
import { useBuyMatchPopupStore } from '../../store'
import { SelectedCard } from '../SelectedCard'
@ -38,7 +41,7 @@ export const PackageSelectionStep = () => {
cards,
fetchCards,
} = useCardsStore()
const [isOpenBrasilian, setIsOpenBrasilian] = useState(false)
const [isOpenIframe, setIsOpenIframe] = useState(false)
const [countryCode, setCountryCode] = useState<CountryCodeType | null>(null)
const {
@ -63,9 +66,28 @@ export const PackageSelectionStep = () => {
}
}, [cards, fetchCards])
if (!match) return null
const paymentSystem = useMemo(() => {
switch (countryCode?.country_code) {
case 'BR':
return payments.brasil
case 'TN':
return payments.tunisia
default:
return payments[client.name]
}
}, [countryCode])
const isBrasil = countryCode?.country_code === 'BR'
const isIframePayment = useMemo(() => {
switch (countryCode?.country_code) {
case 'BR':
case 'TN':
return true
default:
return false
}
}, [countryCode])
if (!match) return null
const getUserCountry = () => {
getCountryCode().then(setCountryCode)
@ -75,8 +97,8 @@ export const PackageSelectionStep = () => {
cards?.length
&& lastSelectedPackage === selectedPackage?.id
&& setDisabledBuyBtn(true)
if (isBrasil) {
setIsOpenBrasilian(true)
if (isIframePayment) {
setIsOpenIframe(true)
} else {
onBuyClick(e)
}
@ -110,7 +132,7 @@ export const PackageSelectionStep = () => {
</Header>
<Body marginTop={20}>
<Packages />
{isBrasil ? null : <SelectedCard />}
{!isIframePayment && <SelectedCard />}
</Body>
<Footer>
{loader ? (
@ -124,12 +146,13 @@ export const PackageSelectionStep = () => {
</Button>
)}
</Footer>
{selectedPackage && isOpenBrasilian && (
<BrazilPayment
{selectedPackage && isIframePayment && (
<IframePayment
match={match}
open={isOpenBrasilian}
open={isOpenIframe}
paymentSystem={paymentSystem}
selectedPackage={selectedPackage}
setIsOpenBrasilian={setIsOpenBrasilian}
setIsOpenIframe={setIsOpenIframe}
/>
)}
</Wrapper>

@ -25,13 +25,13 @@ export const SuccessStep = () => {
const { closeAfterPayment } = useSuccessStep()
return (
<Wrapper height={253} width={369}>
<Wrapper width={369}>
<Header height={24}>
<HeaderTitle>
<T9n t='payment' />
</HeaderTitle>
</Header>
<Body marginTop={30} marginBottom={40}>
<Body marginTop={30}>
<ResultText>
<T9n t='success_subscription' />
</ResultText>

@ -85,7 +85,7 @@ export const Wrapper = styled.div<WrapperProps>`
position: relative;
height: ${({ height }) => (height ? `${height}px` : 'auto')};
width: ${({ width }) => (width ? `${width}px` : '830px')};
padding: 40px 0;
padding: 40px 10px;
@media (max-width: 750px){
width: 100%;

@ -39,7 +39,7 @@ export const CompanyInfo = ({
</CompanyInfoText>
</Fragment>
)
case ClientNames.Tunis:
case ClientNames.Tunisia:
return ''
case ClientNames.Lff:
return (

@ -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 (client.name === 'lff') {
if (['lff', 'tunis'].includes(client.name)) {
return client.styles.homePageHeader
}

@ -20,6 +20,7 @@ import { useHomePage } from './hooks'
import { Header } from './components/Header'
import { HeaderMobile } from '../HeaderMobile'
import { HeaderFilters } from './components/HeaderFilters'
// import { client } from '../../config/clients'
const Home = () => {
usePageLogger(PAGES.home)

@ -1,5 +1,3 @@
import format from 'date-fns/format'
import { joinMatchLexics } from 'config/lexics/joinMatch'
import { usePageParams } from 'hooks/usePageParams'
@ -8,6 +6,8 @@ import { T9n } from 'features/T9n'
import { Name } from 'features/Name'
import { useLexicsConfig } from 'features/LexicsStore'
import { getCurrentYear } from 'helpers'
import { useUnauthenticatedMatch } from './hooks'
import {
@ -45,7 +45,7 @@ export const JoinMatchPage = () => {
onJoinClick,
} = useUnauthenticatedMatch()
const currentYear = format(new Date(), 'Y')
const currentYear = getCurrentYear()
return (
<Wrapper>

@ -1,11 +1,12 @@
import { useEffect } from 'react'
import format from 'date-fns/format'
import { joinMatchLexics } from 'config/lexics/joinMatch'
import { T9n } from 'features/T9n'
import { useLexicsConfig, useLexicsStore } from 'features/LexicsStore'
import { getCurrentYear } from 'helpers'
import { useUnauthenticatedMatch } from './hooks'
import {
@ -40,7 +41,7 @@ export const JoinMatchPageRFEF = () => {
onJoinClick,
} = useUnauthenticatedMatch()
const currentYear = format(new Date(), 'Y')
const currentYear = getCurrentYear()
const { changeLang } = useLexicsStore()

@ -31,7 +31,6 @@ export const LiveMatch = () => {
resume,
streamUrl,
} = useLiveMatch()
return (
<Fragment>
<Container>

@ -62,7 +62,6 @@ export const HeaderTitle = styled.h2`
${isMobileDevice
? css`
font-size: 16px;
line-height: 52px;
position: relative;
width: 100%;
text-overflow: ellipsis;

@ -98,7 +98,7 @@ export const ProfileCard = ({ profile }: ProfileType) => {
<StarIcon isFavorite={isFavorite} />
<T9n t='add_to_favorites' />
</FavoriteButton>
{!isLffClient && isPlayerPage && isGetHighLightShown && (
{!client.disabledHighlights && isPlayerPage && isGetHighLightShown && (
<Link to={PAGES.highlights}>
<SсGetHighlightBtn
onClick={() => setPlayerHighlight({

@ -4,6 +4,7 @@ import isUndefined from 'lodash/isUndefined'
import { client } from 'config/clients'
import { isMobileDevice } from 'config/userAgent'
import { ClientNames } from 'config/clients/types'
import { Logo } from 'features/Logo'
import { ScoreSwitch } from 'features/MatchSwitches'
@ -13,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 (client.name === 'lff') {
if ([ClientNames.Lff, ClientNames.Tunisia, ClientNames.Facr].includes(client.name)) {
return client.styles.homePageHeader
}
@ -32,7 +33,8 @@ export const defaultHeaderStyles = (
z-index: 10;
`
}
return client.name === 'facr' ? client.styles.homePageHeader : css`
return css`
background: linear-gradient(
187deg,
${color} -4.49%,

@ -7,8 +7,6 @@ import { STRIPE_PUBLIC_KEY } from 'config/env'
import { useLexicsStore } from 'features/LexicsStore'
const stripe = loadStripe(STRIPE_PUBLIC_KEY)
type Props = {
children: ReactNode,
}
@ -16,6 +14,10 @@ type Props = {
export const StripeElements = ({ children }: Props) => {
const { lang } = useLexicsStore()
const stripe = loadStripe(STRIPE_PUBLIC_KEY, {
locale: lang as StripeElementLocale,
})
return (
<Elements
key={lang}

@ -82,6 +82,19 @@ export const facrTheme: CustomTheme = {
name: 'facr',
}
type Name = 'light' | 'dark' | 'lff' | 'facr'
export const tunisTheme: CustomTheme = {
...defaultTheme,
colors: {
...defaultTheme.colors,
background: '#1D1D1D',
button: '#0E8F84',
buttonHover: '#09aa9d',
dateFilter: '#ffffff80',
inputs: '#3A4849',
},
name: 'tunis',
}
type Name = 'light' | 'dark' | 'lff' | 'facr' | 'tunis'
export type CustomTheme = typeof lightTheme

@ -13,6 +13,7 @@ import {
defaultTheme,
facrTheme,
lffTheme,
tunisTheme,
} from './config'
import { ClientNames } from '../../config/clients/types'
@ -31,6 +32,9 @@ export const Theme = ({ children }: Props) => {
case ClientNames.Facr:
setTheme(facrTheme)
break
case ClientNames.Tunisia:
setTheme(tunisTheme)
break
default:
setTheme(defaultTheme)
break

@ -61,28 +61,25 @@ export const PageSubscriptions = () => {
<Wrapper>
{subscribes?.map((subscribe: Subscribe) => {
const {
access_to,
card,
is_active,
iso,
lexic,
name,
option_sys_name,
price,
purchase_type,
sub_id,
ts_payment,
} = subscribe
const hideCancel = selectedSubscribe.sub_id === sub_id && isSubCanceled
return (
<ScSubscribe key={`${access_to}${name}`}>
<ScSubscribe key={ts_payment}>
<ScItem>
<T9n t='subscription_plan' className='payment_title' />
<ScText
isActive={is_active}
className='payment_plan'
>
<T9n t={lexic} />
<ScText isActive={is_active}>
{option_sys_name} {name}
</ScText>
</ScItem>
<ScItemPaymentSum>
@ -108,7 +105,7 @@ export const PageSubscriptions = () => {
className='payment_title'
/>
<ScText isActive={is_active}>
{is_active && !hideCancel ? format(new Date(access_to), 'd MMM yyyy') : '—'}
{is_active && !hideCancel ? format(new Date(ts_payment), 'd MMM yyyy') : '—'}
</ScText>
</ScItem>
</ScItemPaymentSum>

@ -86,15 +86,12 @@ export const ScItem = styled.div`
display: flex;
flex-direction: row;
}
.payment_plan {
text-transform: none;
}
`
export const ScText = styled.span<({ isActive?: boolean })>`
color: ${({ isActive }) => (isActive ? '#FFFFFF' : 'rgba(255, 255, 255, 0.6)')};
max-width: 560px;
text-transform: capitalize;
${isMobileDevice
? css`

@ -85,7 +85,7 @@ const UserAccount = () => {
</Fragment>
)}
<ScoreSwitch />
{!isLffClient && (
{!client.disabledHighlights && (
<Link to={`${PAGES.highlights}`}>
<ScButtonGetHighlight>
<T9n t='get_highlights' />

@ -0,0 +1,3 @@
import format from 'date-fns/format'
export const getCurrentYear = () => format(new Date(), 'Y')

@ -8,3 +8,4 @@ export * from './secondsToHms'
export * from './redirectToUrl'
export * from './getRandomString'
export * from './selectedApi'
export * from './getCurrentYear'

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

@ -0,0 +1,78 @@
import { Fragment } from 'react'
import format from 'date-fns/format'
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 {
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 = format(new Date(), 'Y')
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>
)
}

@ -0,0 +1,302 @@
import styled, { css } from 'styled-components/macro'
import { devices } from 'config'
import { isMobileDevice } from 'config/userAgent'
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;
`
: ''};
`

@ -0,0 +1,13 @@
import { T9n } from 'features/T9n'
import { FailedPaymeeWrapper } from './styled'
// эта страница рассчитана на открытие во фрейме
// при неудачной оплате paymee
const FailedPaymeePage = () => (
<FailedPaymeeWrapper>
<T9n t='failed_paymee' />
</FailedPaymeeWrapper>
)
export default FailedPaymeePage

@ -0,0 +1,11 @@
import styled from 'styled-components/macro'
export const FailedPaymeeWrapper = styled.div`
color: #FFFFFF;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
font-size: 22px;
text-align: center;
`

@ -2,8 +2,6 @@ import { useState } from 'react'
import { Link } from 'react-router-dom'
import { format } from 'date-fns'
import { PAGES } from 'config'
import { saveUserInfo } from 'requests'
@ -11,6 +9,8 @@ import { saveUserInfo } from 'requests'
import { T9n } from 'features/T9n'
import { useAuthStore } from 'features/AuthStore'
import { getCurrentYear } from 'helpers'
import {
Body,
ButtonsBlock,
@ -35,7 +35,7 @@ const Mailings = () => {
if (!userInfo) return null
const currentYear = format(new Date(), 'Y')
const currentYear = getCurrentYear()
const onUnsubscribe = async (isUnsubscribed: boolean) => {
if (!isUnsubscribed) {

@ -3,7 +3,7 @@
declare namespace NodeJS {
export interface ProcessEnv {
REACT_APP_CLIENT: 'instat' | 'facr' | 'lff' | 'insports' | 'india' | 'tunis',
REACT_APP_CLIENT: 'instat' | 'facr' | 'lff' | 'insports' | 'india' | 'tunisia',
REACT_APP_ENV: 'production' | 'preproduction' | 'staging',
REACT_APP_STAGE: 'staging' | 'test-a' | 'test-b' | 'test-c' | 'test-d' | 'test-e' | 'test-f' | 'test-g' | 'test-h' | 'test-i' | 'test-j' | 'test',
REACT_APP_TYPE: 'auth-service' | 'ott',

@ -1,5 +1,4 @@
import { AUTH_SERVICE } from 'config'
import { callApi } from 'helpers'
export type GeoInfoType = {

@ -1,4 +1,4 @@
import { API_ROOT, PAGES } from 'config'
import { API_ROOT } from 'config'
import { callApi } from 'helpers'
@ -8,21 +8,28 @@ type Props = {
action: 'one_payment' | 'create_subscription',
item: SubscriptionResponse,
product_name: string,
service: string,
url_cancel?: string,
url_return?: string | null,
}
export const getBrazilPaymentUrl = async ({
export const getPaymentUrl = async ({
action,
item,
product_name,
service,
url_cancel,
url_return,
}: Props) => {
const config = {
body: {
action,
data: {
item: { ...item, product_name },
url_return: `${window.location.origin}${PAGES.thanksForSubscribe}`,
url_cancel,
url_return,
},
service: 'pag_brasil',
service,
},
}
Loading…
Cancel
Save