diff --git a/.eslintrc b/.eslintrc index 48fef2e1..1dbe0edb 100644 --- a/.eslintrc +++ b/.eslintrc @@ -11,6 +11,7 @@ "postro4no" ], "rules": { + "@typescript-eslint/no-explicit-any": "warn", "@typescript-eslint/array-type": [ "warn", { "default" : "generic" } diff --git a/package-lock.json b/package-lock.json index 7fe9d720..5134195b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "react": "^17.0.2", "react-datepicker": "^3.1.3", "react-dom": "^17.0.2", + "react-query": "^3.39.3", "react-router": "^5.2.0", "react-router-dom": "^5.2.0", "react-scripts": "^5.0.1", @@ -15819,8 +15820,6 @@ "version": "1.6.51", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", - "dev": true, - "optional": true, "engines": { "node": ">=0.6" } @@ -16079,6 +16078,21 @@ "node": ">=8" } }, + "node_modules/broadcast-channel": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/broadcast-channel/-/broadcast-channel-3.7.0.tgz", + "integrity": "sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg==", + "dependencies": { + "@babel/runtime": "^7.7.2", + "detect-node": "^2.1.0", + "js-sha3": "0.8.0", + "microseconds": "0.2.0", + "nano-time": "1.0.0", + "oblivious-set": "1.0.0", + "rimraf": "3.0.2", + "unload": "2.2.0" + } + }, "node_modules/brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", @@ -26209,6 +26223,11 @@ "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==" }, + "node_modules/js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" + }, "node_modules/js-string-escape": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", @@ -27281,6 +27300,15 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/match-sorter": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/match-sorter/-/match-sorter-6.3.1.tgz", + "integrity": "sha512-mxybbo3pPNuA+ZuCUhm5bwNkXrJTbsk5VWbR5wiwz/GC6LIiegBGn2w3O08UG/jdbYLinw51fSQ5xNU1U3MgBw==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "remove-accents": "0.4.2" + } + }, "node_modules/mathml-tag-names": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", @@ -27601,6 +27629,11 @@ "node": ">=8.6" } }, + "node_modules/microseconds": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/microseconds/-/microseconds-0.2.0.tgz", + "integrity": "sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA==" + }, "node_modules/miller-rabin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", @@ -28049,6 +28082,14 @@ "dev": true, "optional": true }, + "node_modules/nano-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/nano-time/-/nano-time-1.0.0.tgz", + "integrity": "sha512-flnngywOoQ0lLQOTRNexn2gGSNuM9bKj9RZAWSzhQ+UJYaAFG9bac4DW9VHjUAzrOaIcajHybCTHe/bkvozQqA==", + "dependencies": { + "big-integer": "^1.6.16" + } + }, "node_modules/nanoid": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", @@ -28606,6 +28647,11 @@ "integrity": "sha512-eJJDYkhJFFbBBAxeh8xW+weHlkI28n2ZdQV/J/DNfWfSKlGEf2xcfAbZTv3riEXHAhL9SVOTs2pRmXiSTf78xg==", "dev": true }, + "node_modules/oblivious-set": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/oblivious-set/-/oblivious-set-1.0.0.tgz", + "integrity": "sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw==" + }, "node_modules/obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", @@ -31820,6 +31866,31 @@ "react": "0.14.x || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, + "node_modules/react-query": { + "version": "3.39.3", + "resolved": "https://registry.npmjs.org/react-query/-/react-query-3.39.3.tgz", + "integrity": "sha512-nLfLz7GiohKTJDuT4us4X3h/8unOh+00MLb2yJoGTPjxKs2bc1iDhkNx2bd5MKklXnOD3NrVZ+J2UXujA5In4g==", + "dependencies": { + "@babel/runtime": "^7.5.5", + "broadcast-channel": "^3.4.1", + "match-sorter": "^6.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, "node_modules/react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", @@ -32723,6 +32794,11 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/remove-accents": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz", + "integrity": "sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==" + }, "node_modules/remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -36571,6 +36647,15 @@ "node": ">= 10.0.0" } }, + "node_modules/unload": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unload/-/unload-2.2.0.tgz", + "integrity": "sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==", + "dependencies": { + "@babel/runtime": "^7.6.2", + "detect-node": "^2.0.4" + } + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -50498,9 +50583,7 @@ "big-integer": { "version": "1.6.51", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", - "dev": true, - "optional": true + "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==" }, "big.js": { "version": "5.2.2", @@ -50705,6 +50788,21 @@ "fill-range": "^7.0.1" } }, + "broadcast-channel": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/broadcast-channel/-/broadcast-channel-3.7.0.tgz", + "integrity": "sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg==", + "requires": { + "@babel/runtime": "^7.7.2", + "detect-node": "^2.1.0", + "js-sha3": "0.8.0", + "microseconds": "0.2.0", + "nano-time": "1.0.0", + "oblivious-set": "1.0.0", + "rimraf": "3.0.2", + "unload": "2.2.0" + } + }, "brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", @@ -58413,6 +58511,11 @@ "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==" }, + "js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" + }, "js-string-escape": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", @@ -59249,6 +59352,15 @@ "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==", "dev": true }, + "match-sorter": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/match-sorter/-/match-sorter-6.3.1.tgz", + "integrity": "sha512-mxybbo3pPNuA+ZuCUhm5bwNkXrJTbsk5VWbR5wiwz/GC6LIiegBGn2w3O08UG/jdbYLinw51fSQ5xNU1U3MgBw==", + "requires": { + "@babel/runtime": "^7.12.5", + "remove-accents": "0.4.2" + } + }, "mathml-tag-names": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", @@ -59504,6 +59616,11 @@ "picomatch": "^2.3.1" } }, + "microseconds": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/microseconds/-/microseconds-0.2.0.tgz", + "integrity": "sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA==" + }, "miller-rabin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", @@ -59871,6 +59988,14 @@ "dev": true, "optional": true }, + "nano-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/nano-time/-/nano-time-1.0.0.tgz", + "integrity": "sha512-flnngywOoQ0lLQOTRNexn2gGSNuM9bKj9RZAWSzhQ+UJYaAFG9bac4DW9VHjUAzrOaIcajHybCTHe/bkvozQqA==", + "requires": { + "big-integer": "^1.6.16" + } + }, "nanoid": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", @@ -60321,6 +60446,11 @@ "integrity": "sha512-eJJDYkhJFFbBBAxeh8xW+weHlkI28n2ZdQV/J/DNfWfSKlGEf2xcfAbZTv3riEXHAhL9SVOTs2pRmXiSTf78xg==", "dev": true }, + "oblivious-set": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/oblivious-set/-/oblivious-set-1.0.0.tgz", + "integrity": "sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw==" + }, "obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", @@ -62534,6 +62664,16 @@ "warning": "^4.0.2" } }, + "react-query": { + "version": "3.39.3", + "resolved": "https://registry.npmjs.org/react-query/-/react-query-3.39.3.tgz", + "integrity": "sha512-nLfLz7GiohKTJDuT4us4X3h/8unOh+00MLb2yJoGTPjxKs2bc1iDhkNx2bd5MKklXnOD3NrVZ+J2UXujA5In4g==", + "requires": { + "@babel/runtime": "^7.5.5", + "broadcast-channel": "^3.4.1", + "match-sorter": "^6.0.2" + } + }, "react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", @@ -63224,6 +63364,11 @@ "mdast-util-to-markdown": "^0.6.0" } }, + "remove-accents": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz", + "integrity": "sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==" + }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -66161,6 +66306,15 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" }, + "unload": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unload/-/unload-2.2.0.tgz", + "integrity": "sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==", + "requires": { + "@babel/runtime": "^7.6.2", + "detect-node": "^2.0.4" + } + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", diff --git a/package.json b/package.json index aab73c3d..ef91e0f2 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "react": "^17.0.2", "react-datepicker": "^3.1.3", "react-dom": "^17.0.2", + "react-query": "^3.39.3", "react-router": "^5.2.0", "react-router-dom": "^5.2.0", "react-scripts": "^5.0.1", diff --git a/src/components/ItemInfo/ItemInfo.tsx b/src/components/ItemInfo/ItemInfo.tsx index e5814204..36f04847 100644 --- a/src/components/ItemInfo/ItemInfo.tsx +++ b/src/components/ItemInfo/ItemInfo.tsx @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ import { ProfileTypes, PROFILE_NAMES, diff --git a/src/config/clients/types.tsx b/src/config/clients/types.tsx index 88a59a2d..fc31fa6e 100644 --- a/src/config/clients/types.tsx +++ b/src/config/clients/types.tsx @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ import { css } from 'styled-components/macro' type ProcedureName = string diff --git a/src/config/index.tsx b/src/config/index.tsx index 87f53711..357bcd8f 100644 --- a/src/config/index.tsx +++ b/src/config/index.tsx @@ -10,3 +10,4 @@ export * from './currencies' export * from './dashes' export * from './env' export * from './userAgent' +export * from './queries' diff --git a/src/config/queries.tsx b/src/config/queries.tsx new file mode 100644 index 00000000..c90d0f0f --- /dev/null +++ b/src/config/queries.tsx @@ -0,0 +1,4 @@ +export const querieKeys = { + liveMatchScores: 'liveMatchScores', + matchScore: 'matchScore', +} diff --git a/src/features/AirPlay/index.tsx b/src/features/AirPlay/index.tsx index 13d9459e..627fe641 100644 --- a/src/features/AirPlay/index.tsx +++ b/src/features/AirPlay/index.tsx @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ import { useEffect } from 'react' import includes from 'lodash/includes' diff --git a/src/features/App/index.tsx b/src/features/App/index.tsx index 94a6a8b1..71bbf677 100644 --- a/src/features/App/index.tsx +++ b/src/features/App/index.tsx @@ -4,6 +4,8 @@ import { useState, } from 'react' import { Router } from 'react-router-dom' +import { QueryClient, QueryClientProvider } from 'react-query' +import { ReactQueryDevtools } from 'react-query/devtools' import { history } from 'config/history' import { client } from 'config/clients' @@ -11,6 +13,8 @@ import { isAvailable } from 'config/env' import { readToken } from 'helpers' +import { isLocalhost } from 'serviceWorker' + import { setClientTitleAndDescription } from 'helpers/setClientHeads' import { GlobalStores } from 'features/GlobalStores' @@ -28,13 +32,19 @@ setClientTitleAndDescription(client.title, client.description) const Main = () => { const [isToken, setIsToken] = useState(false) const { userInfo } = useAuthStore() + const queryClient = new QueryClient() useEffect(() => { readToken() && setIsToken(true) }, [userInfo]) // имеется действующий токен - return isToken ? : null + return isToken ? ( + + + + + ) : null } const date = new Date() diff --git a/src/features/ChromeCast/index.tsx b/src/features/ChromeCast/index.tsx index ec632b8e..0a038712 100644 --- a/src/features/ChromeCast/index.tsx +++ b/src/features/ChromeCast/index.tsx @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ import { Fragment, memo, diff --git a/src/features/Combobox/helpers/index.tsx b/src/features/Combobox/helpers/index.tsx index e891445b..4233601d 100644 --- a/src/features/Combobox/helpers/index.tsx +++ b/src/features/Combobox/helpers/index.tsx @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ import startsWith from 'lodash/startsWith' import orderBy from 'lodash/orderBy' import toLower from 'lodash/toLower' diff --git a/src/features/HeaderFilters/store/hooks/index.tsx b/src/features/HeaderFilters/store/hooks/index.tsx index 524cf521..f2089981 100644 --- a/src/features/HeaderFilters/store/hooks/index.tsx +++ b/src/features/HeaderFilters/store/hooks/index.tsx @@ -34,7 +34,7 @@ export const useFilters = () => { const [selectedFilters, setSelectedFilters] = useState>([]) const [isShowTournament, setIsShowTournament] = useState(true) const [selectTournament, setSelectTournament] = useState() - const [sportIds, setSportIds] = useState() + const [sportIds, setSportIds] = useState>([]) const isTodaySelected = isToday(selectedDate) const compareSport = useCallback((match: Match, sportNames: Array) => { diff --git a/src/features/Icon/index.tsx b/src/features/Icon/index.tsx index 9cfc61dc..d6fd2300 100644 --- a/src/features/Icon/index.tsx +++ b/src/features/Icon/index.tsx @@ -1,4 +1,5 @@ -import React from 'react' +/* eslint-disable @typescript-eslint/no-explicit-any */ +import React, { CSSProperties } from 'react' import * as icons from '../../libs/index' export type IconProps = { @@ -8,7 +9,7 @@ export type IconProps = { onClick?: () => void, refIcon: any, size?: number | string, - styles?: any, + styles?: CSSProperties, } export const Icon: React.FC = ({ diff --git a/src/features/MatchCard/CardFrontside/MatchCardMobile/index.tsx b/src/features/MatchCard/CardFrontside/MatchCardMobile/index.tsx index 00b5037c..6034f830 100644 --- a/src/features/MatchCard/CardFrontside/MatchCardMobile/index.tsx +++ b/src/features/MatchCard/CardFrontside/MatchCardMobile/index.tsx @@ -12,8 +12,11 @@ import { useName } from 'features/Name' import { T9n } from 'features/T9n' import { MatchAccess } from 'features/Matches/helpers/getMatchClickAction' import { useUserFavoritesStore } from 'features/UserFavorites/store' + import { getCardColor } from 'helpers/getCardColor' +import type { LiveScore } from 'requests' + import { NoAccessMessage } from '../../NoAccessMessage' import { getPrepareTimeFormat } from '../../helpers' import { getPrepareDateFormat } from '../../helpers/getPrepareDateFormat' @@ -50,6 +53,7 @@ type Props = { match: Match, onClick: () => void, onKeyPress: (e: KeyboardEvent) => void, + score?: LiveScore, } export const CardFrontsideMobile = ({ @@ -58,6 +62,7 @@ export const CardFrontsideMobile = ({ match, onClick, onKeyPress, + score, }: Props) => { const location = useLocation() const { @@ -150,14 +155,14 @@ export const CardFrontsideMobile = ({ {team1InFavorites && } - {showScore && {team1.score}} + {showScore && {score?.team1.score ?? team1.score}} {team2InFavorites && } - {showScore && {team2.score}} + {showScore && {score?.team2.score ?? team2.score}} diff --git a/src/features/MatchCard/CardFrontside/index.tsx b/src/features/MatchCard/CardFrontside/index.tsx index 85dcc363..78445d08 100644 --- a/src/features/MatchCard/CardFrontside/index.tsx +++ b/src/features/MatchCard/CardFrontside/index.tsx @@ -6,7 +6,10 @@ import getUnixTime from 'date-fns/getUnixTime' import { ProfileTypes, PAGES } from 'config' import { isLffClient } from 'config/clients' +import type { LiveScore } from 'requests' + import { getCardColor } from 'helpers/getCardColor' + import type { Match } from 'features/Matches' import { useMatchSwitchesStore } from 'features/MatchSwitches' import { useName } from 'features/Name' @@ -47,6 +50,7 @@ type Props = { match: Match, onClick: () => void, onKeyPress: (e: KeyboardEvent) => void, + score?: LiveScore, } export const CardFrontside = ({ @@ -54,6 +58,7 @@ export const CardFrontside = ({ match, onClick, onKeyPress, + score, }: Props) => { const location = useLocation() const { @@ -165,14 +170,14 @@ export const CardFrontside = ({ {team1InFavorites && } - {showScore && {team1.score}} + {showScore && {score?.team1.score ?? team1.score}} {team2InFavorites && } - {showScore && {team2.score}} + {showScore && {score?.team2.score ?? team2.score}} {!isMatchPage && ( diff --git a/src/features/MatchCard/index.tsx b/src/features/MatchCard/index.tsx index 567285d6..db334df0 100644 --- a/src/features/MatchCard/index.tsx +++ b/src/features/MatchCard/index.tsx @@ -2,15 +2,18 @@ import type { Match } from 'features/Matches' import { isMobileDevice } from 'config/userAgent' +import { LiveScore } from 'requests/getLiveScores' + import { CardFrontside } from './CardFrontside' import { CardFrontsideMobile } from './CardFrontside/MatchCardMobile' import { useCard } from './hooks' type Props = { match: Match, + score?: LiveScore, } -export const MatchCard = ({ match }: Props) => { +export const MatchCard = ({ match, score }: Props) => { const { isNeedFormatTimeChanged, isOwnedMatches, @@ -27,6 +30,7 @@ export const MatchCard = ({ match }: Props) => { onKeyPress={onKeyPress} isNeedFormatTimeChanged={isNeedFormatTimeChanged} isOwnedMatches={isOwnedMatches} + score={score} /> ) } diff --git a/src/features/MatchPage/components/FavouriteTeam/hooks.tsx b/src/features/MatchPage/components/FavouriteTeam/hooks.tsx index b65e2688..e336acfe 100644 --- a/src/features/MatchPage/components/FavouriteTeam/hooks.tsx +++ b/src/features/MatchPage/components/FavouriteTeam/hooks.tsx @@ -13,14 +13,15 @@ export const useFavouriteTeam = () => { const [group1, setGroup1] = useState>([]) const [group2, setGroup2] = useState>([]) - const sortTeam = (teams: Array) => teams.sort((n1:FavouriteTeams, n2: FavouriteTeams) => { - if (n1.name_en > n2.name_en) { - return 1 - } if (n1.name_en < n2.name_en) { - return -1 - } - return 0 - }) + const sortTeam = (teams: Array) => ( + teams.sort((n1:FavouriteTeams, n2: FavouriteTeams) => { + if (n1.name_en > n2.name_en) { + return 1 + } if (n1.name_en < n2.name_en) { + return -1 + } + return 0 + })) const changeActive = (team: FavouriteTeams) => { setActiveId((prev) => (prev === team.id ? null : team.id)) } diff --git a/src/features/MatchPage/components/MatchDescription/index.tsx b/src/features/MatchPage/components/MatchDescription/index.tsx index 91ef4164..cc69648e 100644 --- a/src/features/MatchPage/components/MatchDescription/index.tsx +++ b/src/features/MatchPage/components/MatchDescription/index.tsx @@ -1,5 +1,7 @@ import { useCallback } from 'react' +import { useQuery } from 'react-query' + import { format } from 'date-fns' import includes from 'lodash/includes' @@ -16,11 +18,16 @@ import { useMatchPageStore } from 'features/MatchPage/store' import { parseDate } from 'helpers/parseDate' -import { ProfileTypes } from 'config' -import { isMobileDevice } from 'config/userAgent' +import { + ProfileTypes, + querieKeys, + isMobileDevice, +} from 'config' import { usePageParams } from 'hooks/usePageParams' +import { getMatchScore } from 'requests' + import { Description, DescriptionInnerBlock, @@ -33,7 +40,10 @@ import { } from './styled' export const MatchDescription = () => { - const { sportType } = usePageParams() + const { + profileId, + sportType, + } = usePageParams() const { user } = useAuthStore() const { isScoreHidden } = useMatchSwitchesStore() const { suffix } = useLexicsStore() @@ -45,6 +55,19 @@ export const MatchDescription = () => { : ), [suffix]) + const { data: queryScore } = useQuery({ + queryFn: async () => { + if (profile?.live && !isScoreHidden) { + const score = await getMatchScore({ profileId, sportType }) + return score + } + + return null + }, + queryKey: querieKeys.matchScore, + refetchInterval: 5000, + }) + if (!profile) return const { @@ -77,7 +100,8 @@ export const MatchDescription = () => { { isScoreHidden || isNil(team1.score) || isNil(team2.score) ? '-' - : `${team1.score} - ${team2.score}` + : `${queryScore?.team1.score ?? team1.score} - ${queryScore?.team2.score ?? team2.score}` + } , @@ -16,6 +22,7 @@ type MatchesGridProps = { export const MatchesGrid = memo(({ matches }: MatchesGridProps) => { const isHomePage = useRouteMatch(PAGES.home)?.isExact + const { isScoreHidden } = useMatchSwitchesStore() const { compareSport, @@ -48,19 +55,39 @@ export const MatchesGrid = memo(({ matches }: MatchesGridProps) => { return matches } + const { data: liveMatchScores } = useQuery({ + queryFn: async () => { + if (!isScoreHidden && matches.filter(({ live }) => live)?.length > 0) { + const scores = await getLiveScores() + return scores + } + return [] + }, + queryKey: querieKeys.liveMatchScores, + refetchInterval: 5000, + }) + useEffect(() => { if (!isHomePage) return updateSportIds(matches) // eslint-disable-next-line react-hooks/exhaustive-deps }, [selectedDate, matches]) - return ( {isHomePage && isShowTournament ? ( ) : ( - filteredMatches().map((match) => ) + filteredMatches().map((match) => ( + match_id === match.id + && sport_id === match.sportType, + )} + /> + )) )} ) diff --git a/src/features/MultiSourcePlayer/components/ProgressBar/hooks.tsx b/src/features/MultiSourcePlayer/components/ProgressBar/hooks.tsx index b080af87..0a63ff12 100644 --- a/src/features/MultiSourcePlayer/components/ProgressBar/hooks.tsx +++ b/src/features/MultiSourcePlayer/components/ProgressBar/hooks.tsx @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ import { useMemo } from 'react' import { secondsToHms } from 'helpers' diff --git a/src/features/Name/index.tsx b/src/features/Name/index.tsx index a93bc2ce..a2099b82 100644 --- a/src/features/Name/index.tsx +++ b/src/features/Name/index.tsx @@ -1,3 +1,5 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ + import styled from 'styled-components/macro' import { useLexicsStore } from 'features/LexicsStore' diff --git a/src/features/SportsFilter/components/SelectSportPopup/index.tsx b/src/features/SportsFilter/components/SelectSportPopup/index.tsx index 9545543b..a57fea77 100644 --- a/src/features/SportsFilter/components/SelectSportPopup/index.tsx +++ b/src/features/SportsFilter/components/SelectSportPopup/index.tsx @@ -19,7 +19,7 @@ type Props = { onModalClose: () => void, onSportClick: (sport: string) => void, selectedSport: Array, - sportIds: Array, + sportIds: Array, sports: SportsType, } export const SelectSportPopup = ({ diff --git a/src/features/StreamPlayer/components/ProgressBar/hooks.tsx b/src/features/StreamPlayer/components/ProgressBar/hooks.tsx index 5fced27e..43b2b41c 100644 --- a/src/features/StreamPlayer/components/ProgressBar/hooks.tsx +++ b/src/features/StreamPlayer/components/ProgressBar/hooks.tsx @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ import { useMemo, RefObject } from 'react' import { secondsToHms } from 'helpers' diff --git a/src/features/StreamPlayer/hooks/useSlider.tsx b/src/features/StreamPlayer/hooks/useSlider.tsx index 8c3971e9..873bb68a 100644 --- a/src/features/StreamPlayer/hooks/useSlider.tsx +++ b/src/features/StreamPlayer/hooks/useSlider.tsx @@ -1,3 +1,5 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ + import { useRef } from 'react' import { useEventListener, useToggle } from 'hooks' diff --git a/src/features/UserAccount/components/PageSubscriptions/hooks.tsx b/src/features/UserAccount/components/PageSubscriptions/hooks.tsx index b43eee04..9f34704e 100644 --- a/src/features/UserAccount/components/PageSubscriptions/hooks.tsx +++ b/src/features/UserAccount/components/PageSubscriptions/hooks.tsx @@ -1,6 +1,10 @@ import { useEffect, useState } from 'react' -import { getUserSubscribes, Subscribe } from 'requests/getUserSubscribes' +import { + getUserSubscribes, + Subscribe, + Subscribes, +} from 'requests/getUserSubscribes' import { cancelSubscribe } from 'requests/cancelSubscribe' import { useLexicsStore } from 'features/LexicsStore' @@ -10,7 +14,7 @@ export const useUserSubscribes = () => { const { addLexicsConfig } = useLexicsStore() const [selectedSubscribe, setSelectedSubscribe] = useState({} as Subscribe) - const [subscribes, setSubscribes] = useState([]) + const [subscribes, setSubscribes] = useState([]) const [isCancelPopupOpen, setIsCancelPopupOpen] = useState(false) const [changeCardPopupOpen, setChangeCardPopupOpen] = useState(false) const [isSubCanceled, setSubCanceled] = useState(false) diff --git a/src/helpers/callApi/types.tsx b/src/helpers/callApi/types.tsx index 446b630e..c1ee90ad 100644 --- a/src/helpers/callApi/types.tsx +++ b/src/helpers/callApi/types.tsx @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ export type RequestConfig = { body?: any, headers?: Headers, diff --git a/src/hooks/useEventListener.tsx b/src/hooks/useEventListener.tsx index ad34bfc2..3d0e4680 100644 --- a/src/hooks/useEventListener.tsx +++ b/src/hooks/useEventListener.tsx @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ import type { RefObject } from 'react' import { useEffect, useRef } from 'react' diff --git a/src/hooks/useLocalStorage.tsx b/src/hooks/useLocalStorage.tsx deleted file mode 100644 index b583164f..00000000 --- a/src/hooks/useLocalStorage.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { useState } from 'react' - -export const useLocalStorage = (keyName: string, defaultValue?: any) => { - const [storedValue, setStoredValue] = useState(() => { - try { - const value = localStorage.getItem(keyName) - - if (value) { - return JSON.parse(value) - } - localStorage.setItem(keyName, JSON.stringify(defaultValue)) - return defaultValue - } catch (err) { - return defaultValue - } - }) - - const setValue = (newValue: any) => { - try { - localStorage.setItem(keyName, JSON.stringify(newValue)) - } catch (err) { - /* eslint-disable-next-line */ - console.log(err) - } - setStoredValue(newValue) - } - - return [storedValue, setValue] -} diff --git a/src/hooks/useObjectState.tsx b/src/hooks/useObjectState.tsx index 6b46897e..db256368 100644 --- a/src/hooks/useObjectState.tsx +++ b/src/hooks/useObjectState.tsx @@ -1,3 +1,5 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ + import type { Dispatch } from 'react' import { useCallback, useState } from 'react' diff --git a/src/hooks/useRequest.tsx b/src/hooks/useRequest.tsx index cf091a2c..4dabde22 100644 --- a/src/hooks/useRequest.tsx +++ b/src/hooks/useRequest.tsx @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ import { useState, useCallback } from 'react' /** diff --git a/src/hooks/useStorage/index.tsx b/src/hooks/useStorage/index.tsx index 96fe4a6a..e28fae3e 100644 --- a/src/hooks/useStorage/index.tsx +++ b/src/hooks/useStorage/index.tsx @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ import { useState, useEffect } from 'react' import { queryParamStorage } from 'features/QueryParamsStorage' diff --git a/src/pages/HighlightsPage/components/FormHighlights/hooks.tsx b/src/pages/HighlightsPage/components/FormHighlights/hooks.tsx index a83b35cf..3428f2c6 100644 --- a/src/pages/HighlightsPage/components/FormHighlights/hooks.tsx +++ b/src/pages/HighlightsPage/components/FormHighlights/hooks.tsx @@ -123,7 +123,7 @@ export const useHighlightsForm = () => { const { playerHighlight } = useUserFavoritesStore() const [sports, setSports] = useState>([]) - const [sounds, setSounds] = useState([]) + const [sounds, setSounds] = useState>([]) const [isFetchingTeams, setIsFetchingTeams] = useState(false) const [teams, setTeams] = useState>([]) const [playersData, setPlayersData] = useState>([]) @@ -301,6 +301,8 @@ export const useHighlightsForm = () => { useEffect(() => { if (playerHighlight?.sportType && playerHighlight?.profile) { + // TODO: исправить any + // eslint-disable-next-line setFormState((state: any) => ({ ...state, selectedPlayer: { diff --git a/src/requests/getLiveScores.tsx b/src/requests/getLiveScores.tsx new file mode 100644 index 00000000..e7e72e23 --- /dev/null +++ b/src/requests/getLiveScores.tsx @@ -0,0 +1,28 @@ +import { callApi } from 'helpers' + +import { API_ROOT } from 'config' + +type ScoreTeam = { + id: number, + score: number | null, +} + +export type LiveScore = { + match_id: number, + sport_id: number, + team1:ScoreTeam, + team2: ScoreTeam, +} + +export const getLiveScores = (): Promise> => { + const url = `${API_ROOT}/v1/matches/live/scores` + + const config = { + method: 'GET', + } + + return callApi({ + config, + url, + }) +} diff --git a/src/requests/getMatchInfo.tsx b/src/requests/getMatchInfo.tsx index 30e8df28..6c492a80 100644 --- a/src/requests/getMatchInfo.tsx +++ b/src/requests/getMatchInfo.tsx @@ -19,6 +19,13 @@ export type Team = { score: number, } +export type MatchTournament = { + id: number, + name_eng: string, + name_rus: string, + sportType: SportTypes, +} + export type VideoBound = { e: string, h: string, @@ -42,12 +49,7 @@ export type MatchInfo = { sub: boolean, team1: Team, team2: Team, - tournament: { - id: number, - name_eng: string, - name_rus: string, - sportType: SportTypes, - }, + tournament: MatchTournament, video_bounds?: VideoBounds, youtube_link?: string, } | null diff --git a/src/requests/getMatchScore.tsx b/src/requests/getMatchScore.tsx new file mode 100644 index 00000000..d46a5dff --- /dev/null +++ b/src/requests/getMatchScore.tsx @@ -0,0 +1,33 @@ +import { callApi } from 'helpers' + +import { API_ROOT } from 'config' + +import type { Team, MatchTournament } from 'requests/getMatchInfo' + +type Params = { + profileId: number, + sportType: number, +} + +type Response = { + match_date: string, + match_date_utc: string, + match_id: number, + sport_id: number, + team1: Team, + team2: Team, + tournament: MatchTournament, +} + +export const getMatchScore = ({ profileId, sportType }: Params): Promise => { + const url = `${API_ROOT}/v1/matches/${sportType}/${profileId}/scores` + + const config = { + method: 'GET', + } + + return callApi({ + config, + url, + }) +} diff --git a/src/requests/getSound.tsx b/src/requests/getSound.tsx index 318ff00b..df5ff02d 100644 --- a/src/requests/getSound.tsx +++ b/src/requests/getSound.tsx @@ -3,6 +3,8 @@ import { API_ROOT } from 'config' type ResponseSound = { asset: string, + id: number, + name: string, } export const getSound = async (id: number | string): Promise => { diff --git a/src/requests/getSounds.tsx b/src/requests/getSounds.tsx index b1110a57..92b19ae4 100644 --- a/src/requests/getSounds.tsx +++ b/src/requests/getSounds.tsx @@ -3,6 +3,7 @@ import { API_ROOT } from 'config' type ResponseSound = { asset: string, + id: number, name: string, } diff --git a/src/requests/getUserSubscribes.tsx b/src/requests/getUserSubscribes.tsx index 3154e129..9c0aee8b 100644 --- a/src/requests/getUserSubscribes.tsx +++ b/src/requests/getUserSubscribes.tsx @@ -35,7 +35,7 @@ type Team = { name_ru: string, } -type Subscribes = Array +export type Subscribes = Array export const getUserSubscribes = ( _p_email: string, diff --git a/src/requests/index.tsx b/src/requests/index.tsx index fd1e81e3..347d9f29 100644 --- a/src/requests/index.tsx +++ b/src/requests/index.tsx @@ -27,3 +27,5 @@ export * from './buySubscription' export * from './saveMatchStats' export * from './getGeoInfo' export * from './getTokenVirtualUser' +export * from './getMatchScore' +export * from './getLiveScores' diff --git a/src/serviceWorker.ts b/src/serviceWorker.ts index 3fd94404..e3a8cd5e 100644 --- a/src/serviceWorker.ts +++ b/src/serviceWorker.ts @@ -10,7 +10,7 @@ // To learn more about the benefits of this model and instructions on how to // opt-in, read https://cra.link/PWA /* eslint-disable no-console */ -const isLocalhost = Boolean( +export const isLocalhost = Boolean( window.location.hostname === 'localhost' // [::1] is the IPv6 localhost address. || window.location.hostname === '[::1]'