= props => {\n const { authUser, authAcademy } = props;\n const { data, loading } = authAcademy;\n const status = data?.status;\n const isAcademyActive = !loading && status === EAcademyStatus.Active;\n const { id } = authUser.data || {};\n const [showGuide, setShowGuide] = useState(false);\n const lang = getCurrentLang();\n const isShowGuide = showGuide && isAcademyActive;\n\n useEffect(() => {\n if (id) {\n const isFirstLogin = localStorage.getItem(`isFirstLogin_${id}`);\n\n if (!isFirstLogin && isAcademyActive) {\n setShowGuide(true);\n localStorage.setItem(`isFirstLogin_${id}`, 'true');\n }\n }\n }, [id]);\n\n // console.log('ProductFruits work status:', isShowGuide, 'lang:', lang);\n return isShowGuide ? (\n \n ) : null;\n};\nexport const ProductFruitsLayout = communicationAuth.injector(ProductFruitsLayoutComponent);\n","import React from 'react';\nimport Button from 'antd/es/button';\nimport Typography from 'antd/es/typography';\nimport SearchOutlined from '@ant-design/icons/SearchOutlined';\n\nconst { Title, Text } = Typography;\n\nexport const ButtonsComponent: React.FC = () => (\n <>\n Buttons \n Type Primary \n \n \n Primary\n \n \n Disabled\n \n } className=\"mr-2\">\n Search\n \n } className=\"mr-2\" />\n } size=\"small\" className=\"mr-2\">\n Small\n \n } size=\"large\" className=\"mr-2\">\n Large\n \n
\n Type Default \n \n \n Default\n \n \n Disabled\n \n } className=\"mr-2\">\n Search\n \n } className=\"mr-2\" />\n } size=\"small\" className=\"mr-2\">\n Small\n \n } size=\"large\" className=\"mr-2\">\n Large\n \n
\n Type Dashed \n \n \n Dashed\n \n \n Disabled\n \n } className=\"mr-2\">\n Search\n \n } className=\"mr-2\" />\n } size=\"small\" className=\"mr-2\">\n Small\n \n } size=\"large\" className=\"mr-2\">\n Large\n \n
\n Link \n \n \n Link\n \n \n Disabled\n \n } className=\"mr-2\">\n Search\n \n } className=\"mr-2\" />\n } size=\"small\" className=\"mr-2\">\n Small\n \n } size=\"large\" className=\"mr-2\">\n Large\n \n
\n Text \n \n \n Text\n \n \n Disabled\n \n } className=\"mr-2\">\n Search\n \n } className=\"mr-2\" />\n } size=\"small\" className=\"mr-2\">\n Small\n \n } size=\"large\" className=\"mr-2\">\n Large\n \n
\n Danger \n \n \n Primary\n \n \n Default\n \n \n Dashed\n \n \n Danger\n \n \n Danger\n \n
\n >\n);\n","import React from 'react';\nimport Input from 'antd/es/input';\nimport InputNumber from 'antd/es/input-number';\nimport Typography from 'antd/es/typography';\n\nconst { Title, Text } = Typography;\nconst { TextArea } = Input;\n\nexport const InputsComponent: React.FC = () => (\n <>\n Inputs \n \n \n Size large \n \n Textarea \n \n InputNumber \n \n
\n >\n);\n","import React from 'react';\nimport Checkbox from 'antd/es/checkbox';\nimport Typography from 'antd/es/typography';\nimport { TagsCheckbox } from 'common/components/TagsCheckbox/TagsCheckbox';\n\nconst { Title } = Typography;\n\nexport const CheckboxComponent: React.FC = () => {\n const [value, setValue] = React.useState<{ id: string }[]>([{ id: '0-10' }]);\n\n const onChange = (element: { id: string }[]) => {\n setValue(element);\n };\n\n return (\n <>\n Checkbox \n \n \n
\n \n \n
\n >\n );\n};\n","import React from 'react';\nimport Typography from 'antd/es/typography';\n\nconst { Title, Text, Paragraph, Link } = Typography;\n\nexport const TypographyComponent: React.FC = () => (\n \n
Typography \n
Title Level 1 (38px) \n
Title Level 2 (30px) \n
Title Level 3 (24px) \n
Title Level 4 (20px) \n
Title Level 5 (16px) \n
Text (14px) \n
\n Text strong (14px)\n \n
\n Text underline (14px)\n \n
\n Text type secondary (Medium) (14px)\n \n
Link 14px underline\n
Paragraph (Description) (12px) \n
\n);\n","import React from 'react';\nimport Select from 'antd/es/select';\nimport Typography from 'antd/es/typography';\n\nconst { Title } = Typography;\nconst { Option } = Select;\n\nexport const SelectComponent: React.FC = () => (\n \n
Select \n
\n \n \n Option 1\n \n \n Option 2\n \n \n
\n
\n);\n","import React from 'react';\nimport Radio from 'antd/es/radio';\nimport Typography from 'antd/es/typography';\n\nconst { Title, Text } = Typography;\n\nexport const RadioButtonsComponent: React.FC = () => (\n <>\n Radio Buttons \n Outlined \n \n \n Test1 \n Test2 \n Test3 \n \n Test4\n \n \n
\n Solid \n \n \n Test1 \n Test2 \n Test3 \n \n Test4\n \n \n
\n >\n);\n","import React from 'react';\nimport Tabs from 'antd/es/tabs';\nimport Typography from 'antd/es/typography';\n\nconst { Title, Text } = Typography;\nconst { TabPane } = Tabs;\n\nexport const TabsComponent: React.FC = () => (\n <>\n Tab \n Horizontal \n \n \n \n Content of Tab Pane 1\n \n \n Content of Tab Pane 2\n \n \n Content of Tab Pane 3\n \n \n
\n Vertical \n \n \n \n Content of Tab Pane 1\n \n \n Content of Tab Pane 2\n \n \n Content of Tab Pane 3\n \n \n
\n Card \n \n \n \n Content of Tab Pane 1\n \n \n Content of Tab Pane 2\n \n \n Content of Tab Pane 3\n \n \n
\n >\n);\n","import React from 'react';\nimport Typography from 'antd/es/typography';\nimport { ButtonsComponent } from 'common/components/ComponentsPage/Buttons';\nimport { InputsComponent } from 'common/components/ComponentsPage/Inputs';\nimport { CheckboxComponent } from 'common/components/ComponentsPage/Checkbox';\nimport { TypographyComponent } from 'common/components/ComponentsPage/Typography';\nimport { SelectComponent } from 'common/components/ComponentsPage/Select';\nimport { RadioButtonsComponent } from 'common/components/ComponentsPage/RadioButtons';\nimport { TabsComponent } from 'common/components/ComponentsPage/Tabs';\n\nconst { Title } = Typography;\n\nconst ComponentsPageComponent: React.FC = () => {\n return (\n \n
Components Page \n \n \n \n \n \n \n \n \n );\n};\n\nexport default ComponentsPageComponent;\n","import React, { ReactElement } from 'react';\nimport { LoadingSpin } from 'common/components/LoadingSpin';\nimport { communicationAuth, IAuthConnectedProps } from 'entities/Auth/Auth.communication';\nimport { EAcademyStatus } from 'entities/Academy/Academy.models';\n\ninterface IComponentProps {\n activeStatusRoutes: ReactElement;\n notActiveStatusRoutes: ReactElement;\n}\ntype AllProps = IAuthConnectedProps & IComponentProps;\n\nconst AcademyStatusLayoutComponent: React.FC = props => {\n const { authAcademy, activeStatusRoutes, notActiveStatusRoutes } = props;\n const { data, loading } = authAcademy;\n const status = data?.status;\n const isAcademyActive = status === EAcademyStatus.Active;\n\n if (loading || !status) {\n return ;\n }\n\n return isAcademyActive ? activeStatusRoutes : notActiveStatusRoutes;\n};\n\nexport const AcademyStatusLayout = communicationAuth.injector(AcademyStatusLayoutComponent);\n","import React from 'react';\nimport Col from 'antd/es/col';\nimport Row from 'antd/es/row';\n\nexport const CenteredWithLogoLayout: React.FC = props => {\n return (\n \n \n \n {props.children}\n
\n \n
\n );\n};\n","import React, { SyntheticEvent, useCallback, useMemo, useState } from 'react';\nimport { useHistory } from 'react-router';\nimport MessageOutlined from '@ant-design/icons/MessageOutlined';\nimport CloseOutlined from '@ant-design/icons/CloseOutlined';\nimport Dropdown from 'antd/es/dropdown';\nimport Menu from 'antd/es/menu';\nimport Button from 'antd/es/button';\nimport { options } from 'options';\nimport Typography from 'antd/es/typography';\nimport { ERoutesPublic } from 'common/models/routesModel';\nimport TgIcon from 'app/assets/icons/telegram.svg';\nimport WaIcon from 'app/assets/icons/whatsapp.svg';\n\nconst ICON_SIZE = 26;\nconst TRIGGER = ['click'] as ['click'];\nconst ITEM_NAME = 'junistat-help-button-closed';\nconst HIDDEN_VALUE = JSON.stringify(true);\nconst isButtonHidden = localStorage.getItem(ITEM_NAME) === HIDDEN_VALUE;\n\nconst Component: React.FC = () => {\n const [isHidden, setIsHidden] = useState(isButtonHidden);\n const history = useHistory();\n const isPlayerViewPage = history.location.pathname.includes(ERoutesPublic.PlayerView);\n\n const menu = useMemo(\n () => (\n \n \n \n \n Telegram\n \n \n \n \n \n WhatsApp\n \n \n \n ),\n []\n );\n\n const onRemoveButton = useCallback((e: SyntheticEvent) => {\n e.stopPropagation();\n localStorage.setItem(ITEM_NAME, HIDDEN_VALUE);\n setIsHidden(true);\n }, []);\n\n if (isHidden || isPlayerViewPage) {\n return null;\n }\n\n return (\n \n \n \n );\n};\n\nexport const HelpButton = Component;\n","import React from 'react';\nimport Col from 'antd/es/col';\nimport Row from 'antd/es/row';\nimport classNames from 'classnames';\n\ninterface IComponentProps {\n className?: string;\n rowClassName?: string;\n isSmall?: boolean;\n isMedium?: boolean;\n id?: string;\n}\n\nexport const LayoutContent: React.FC = props => {\n const { children, className = '', id, isSmall = false, isMedium, rowClassName = '' } = props;\n\n return (\n \n \n {children}\n \n
\n );\n};\n","import React from 'react';\nimport i18n from 'i18next';\n\ninterface IComponentProps {\n label?: string;\n}\n\ntype AllProps = IComponentProps;\n\nclass ItemsNotFoundComponent extends React.PureComponent {\n render() {\n const { label } = this.props;\n\n return {label || i18n.t('No Data')} ;\n }\n}\n\nexport const ItemsNotFound = ItemsNotFoundComponent;\n","export class Queue {\n queue: {\n promiseGenerator: () => Promise;\n resolve: (value: void) => void | PromiseLike;\n reject: (value: void) => void | PromiseLike;\n }[] = [];\n pendingPromise = false;\n stop = false;\n workingOnPromise = false;\n\n enqueue(promiseGenerator: () => Promise) {\n return new Promise((resolve, reject) => {\n this.queue.push({\n promiseGenerator,\n resolve,\n reject\n });\n this.dequeue();\n });\n }\n\n dequeue() {\n if (this.workingOnPromise) {\n return false;\n }\n if (this.stop) {\n this.queue = [];\n this.stop = false;\n return;\n }\n const item = this.queue.shift();\n if (!item) {\n return false;\n }\n try {\n this.workingOnPromise = true;\n item\n .promiseGenerator()\n .then(item.resolve)\n .catch(item.reject)\n .finally(() => {\n this.workingOnPromise = false;\n this.dequeue();\n });\n } catch (err) {\n this.workingOnPromise = false;\n item.reject(err);\n this.dequeue();\n }\n return true;\n }\n\n clear() {\n this.queue = [];\n }\n}\n","import React from 'react';\nimport List from 'antd/es/list';\nimport Table from 'antd/es/table';\nimport InfiniteScroll from 'react-infinite-scroller';\nimport { StoreBranch } from '@axmit/redux-communications';\nimport { IBaseFilterModel } from '@axmit/client-models';\nimport { LoadingSpin } from 'common/components/LoadingSpin';\nimport { ItemsNotFound } from 'common/components/Text/ItemsNotFound';\nimport { clearFromUndefinedFields } from 'common/helpers/filters.helper';\nimport { Queue } from 'common/helpers/queue.helper';\n\ninterface IComponentProps {\n elementId: string;\n bordered?: boolean;\n filter?: Filter;\n pageSize?: number;\n isReverse?: boolean;\n threshold?: number;\n isTable?: boolean;\n columns?: object[];\n className?: string;\n grid?: object;\n hasPlaceholder?: boolean;\n}\n\ninterface IComponentState {\n pageIndex: number;\n isForce?: boolean;\n}\n\nconst DEFAULT_PAGE_SIZE = 20;\n\nabstract class InfiniteListComponent<\n Collection extends { data: Model[]; meta: { count?: number } },\n Model extends object,\n IProps,\n Filter = undefined,\n Params = any\n> extends React.PureComponent & IProps, IComponentState> {\n mounted = true;\n queue = new Queue();\n\n constructor(props: IComponentProps & IProps) {\n super(props);\n this.state = { pageIndex: 0 };\n }\n\n componentDidMount(): void {\n this.addLoadRequestToQueue();\n }\n\n componentWillUnmount(): void {\n this.mounted = false;\n this.queue.clear();\n this.clearCollection();\n }\n\n componentDidUpdate(prevProps: Readonly & IProps>) {\n const prevFilter = clearFromUndefinedFields(prevProps.filter);\n const nextFilter = clearFromUndefinedFields(this.props.filter);\n\n if (JSON.stringify(prevFilter) !== JSON.stringify(nextFilter)) {\n this.addLoadRequestToQueue(true);\n }\n }\n\n render() {\n const {\n elementId,\n isReverse,\n threshold = 250,\n isTable = false,\n columns,\n grid,\n bordered = true,\n className = '',\n hasPlaceholder\n } = this.props;\n const collection = this.getCollection();\n const { data: collectionData, loading } = collection;\n const items = collectionData?.data || [];\n const count = collectionData?.meta?.count || 0;\n const hasMore = !loading && items.length < count;\n\n return (\n this.addLoadRequestToQueue()}\n hasMore={hasMore}\n useWindow={false}\n isReverse={isReverse}\n threshold={threshold}\n getScrollParent={() => document.getElementById(elementId)}\n >\n {loading && isReverse && }\n {isTable && columns ? (\n \n ) : (\n (collectionData || hasPlaceholder || !loading) && (\n
: this.renderNoData() || }}\n />\n )\n )}\n {loading && !isReverse && !isTable && }\n \n );\n }\n\n addLoadRequestToQueue = (clear?: boolean) => {\n if (clear) {\n this.queue.clear();\n this.queue.enqueue(async () => {\n this.mounted && (await new Promise(resolve => this.setState(() => ({ pageIndex: 0, isForce: true }), resolve)));\n });\n }\n this.queue.enqueue(() => this.loadData());\n };\n\n loadData = async () => {\n const collection = this.getCollection();\n const { pageSize = DEFAULT_PAGE_SIZE } = this.props;\n const { pageIndex, isForce } = this.state;\n\n const { data: collectionData } = collection;\n const count = collectionData?.meta?.count || 0;\n const hasMore = collectionData?.meta?.count === undefined || count > pageSize * pageIndex || isForce;\n\n if (hasMore) {\n const params: IBaseFilterModel = {\n limit: pageSize,\n offset: pageSize * pageIndex\n };\n\n if (params.offset === 0) {\n await this.clearCollection();\n }\n\n await this.loadCollection(params);\n this.mounted &&\n (await new Promise(resolve => this.setState(state => ({ pageIndex: state.pageIndex + 1, isForce: false }), resolve)));\n }\n };\n\n renderNoData: () => JSX.Element | void = () => undefined;\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n clearCollection: () => void = () => {};\n abstract getCollection: () => StoreBranch;\n abstract loadCollection: (params: IBaseFilterModel) => Promise;\n abstract renderListItem: (model: Model) => JSX.Element;\n}\n\nexport const InfiniteList = InfiniteListComponent;\n","/* eslint-disable no-bitwise */\n\nexport interface IDecodeGiftcardInterface {\n period?: number;\n isGiftcardOk: boolean;\n}\n\nconst crc4 = (data: string): number => {\n const POLY = 0xc;\n const INIT = 0;\n const XOROUT = 0;\n let crc = INIT;\n\n for (let i = 0; i < data.length; i++) {\n crc = crc ^ data.charCodeAt(i);\n for (let j = 0; j < 8; j++) {\n crc = crc & 1 ? (crc >>> 1) ^ POLY : crc >>> 1;\n }\n }\n return (crc ^ XOROUT) & 0xf;\n};\n\nfunction decodeGiftcardNumberDig16(number: string): IDecodeGiftcardInterface {\n const rand = number.substr(0, 13);\n const suffix = number.substr(13);\n const amount = ((+suffix & 0b111110000) >>> 4) + 1;\n const crc = crc4(`${rand}${amount}`);\n\n return {\n isGiftcardOk: crc === (+suffix & 0b1111),\n period: amount\n };\n}\n\nfunction decodeGiftcardNumberDig6(number: string): IDecodeGiftcardInterface {\n const _number = Number.parseInt(number, 36);\n const amount = (_number & 0b1111) + 1;\n return {\n isGiftcardOk: true,\n period: amount\n };\n}\n\nexport const decodeGiftcardNumber = (number: string): IDecodeGiftcardInterface => {\n if (!number) {\n return { isGiftcardOk: true };\n }\n\n if (number.length === 16) {\n return decodeGiftcardNumberDig16(number);\n } else if (number.length === 6) {\n return decodeGiftcardNumberDig6(number);\n }\n\n return { isGiftcardOk: false };\n};\n","import message from 'antd/es/message';\nimport i18n from 'common/helpers/i18n';\nimport { ESubscriptionStatus } from 'entities/Subscription/Subscription.models';\n\nexport interface ILocationModel extends Components.Schemas.AddressDto {}\n\nexport enum ELocationType {\n Country = 'country',\n Political = 'political',\n Address = 'address',\n City = 'locality',\n Street = 'route',\n Cities = '(cities)',\n Regions = '(regions)',\n HouseNumber = 'street_number',\n RegionLevelOne = 'administrative_area_level_1',\n RegionLevelTwo = 'administrative_area_level_2',\n RegionLevelThree = 'administrative_area_level_3',\n RegionLevelFour = 'administrative_area_level_4',\n RegionLevelFive = 'administrative_area_level_5'\n}\n\nexport function parseLocation(location: any, type: ELocationType) {\n if (!location.address_components) {\n message.error('Incorrect request!');\n }\n\n const locationArr = location.address_components.filter((item: any) => item.types?.includes(type));\n\n return locationArr.length !== 0 ? locationArr[0].long_name : undefined;\n}\n\nexport function parseLocationCountryCode(location: any) {\n if (!location.address_components) {\n message.error('Incorrect request!');\n }\n\n const locationArr = location.address_components.filter((item: any) => item.types?.includes(ELocationType.Country));\n\n return locationArr.length !== 0 ? locationArr[0].short_name : undefined;\n}\n\nexport function locationFormatter(location?: Partial) {\n const { city, region, country } = location ?? {};\n return location ? `${city || ''} ${region && region !== city ? region : ''} ${country || ''}` : undefined;\n}\n\nexport const getSubscriptionStatus = (status?: string, subscriptionExpiredDate?: string) => {\n if (status === ESubscriptionStatus.Expired && !subscriptionExpiredDate) {\n return i18n.t(`${ESubscriptionStatus.New}`);\n }\n return i18n.t(`${status}`);\n};\n\nconst COUNTRY_ISO_MAP: any = {\n ABH: 'AB',\n AFG: 'AF',\n ALB: 'AL',\n DZA: 'DZ',\n ASM: 'AS',\n AND: 'AD',\n AGO: 'AO',\n AIA: 'AI',\n ATA: 'AQ',\n ATG: 'AG',\n ARG: 'AR',\n ARM: 'AM',\n ABW: 'AW',\n AUS: 'AU',\n AUT: 'AT',\n AZE: 'AZ',\n BHS: 'BS',\n BHR: 'BH',\n BGD: 'BD',\n BRB: 'BB',\n BLR: 'BY',\n BEL: 'BE',\n BLZ: 'BZ',\n BEN: 'BJ',\n BMU: 'BM',\n BTN: 'BT',\n BOL: 'BO',\n BES: 'BQ',\n BIH: 'BA',\n BWA: 'BW',\n BVT: 'BV',\n BRA: 'BR',\n IOT: 'IO',\n BRN: 'BN',\n BGR: 'BG',\n BFA: 'BF',\n BDI: 'BI',\n CPV: 'CV',\n KHM: 'KH',\n CMR: 'CM',\n CAN: 'CA',\n CYM: 'KY',\n CAF: 'CF',\n TCD: 'TD',\n CHL: 'CL',\n CHN: 'CN',\n CXR: 'CX',\n CCK: 'CC',\n COL: 'CO',\n COM: 'KM',\n COD: 'CD',\n COG: 'CG',\n COK: 'CK',\n CRI: 'CR',\n HRV: 'HR',\n CUB: 'CU',\n CUW: 'CW',\n CYP: 'CY',\n CZE: 'CZ',\n CIV: 'CI',\n DNK: 'DK',\n DJI: 'DJ',\n DMA: 'DM',\n DOM: 'DO',\n ECU: 'EC',\n EGY: 'EG',\n SLV: 'SV',\n GNQ: 'GQ',\n ERI: 'ER',\n EST: 'EE',\n SWZ: 'SZ',\n ETH: 'ET',\n FLK: 'FK',\n FRO: 'FO',\n FJI: 'FJ',\n FIN: 'FI',\n FRA: 'FR',\n GUF: 'GF',\n PYF: 'PF',\n ATF: 'TF',\n GAB: 'GA',\n GMB: 'GM',\n GEO: 'GE',\n DEU: 'DE',\n GHA: 'GH',\n GIB: 'GI',\n GRC: 'GR',\n GRL: 'GL',\n GRD: 'GD',\n GLP: 'GP',\n GUM: 'GU',\n GTM: 'GT',\n GGY: 'GG',\n GIN: 'GN',\n GNB: 'GW',\n GUY: 'GY',\n HTI: 'HT',\n HMD: 'HM',\n VAT: 'VA',\n HND: 'HN',\n HKG: 'HK',\n HUN: 'HU',\n ISL: 'IS',\n IND: 'IN',\n IDN: 'ID',\n IRN: 'IR',\n IRQ: 'IQ',\n IRL: 'IE',\n IMN: 'IM',\n ISR: 'IL',\n ITA: 'IT',\n JAM: 'JM',\n JPN: 'JP',\n JEY: 'JE',\n JOR: 'JO',\n KAZ: 'KZ',\n KEN: 'KE',\n KIR: 'KI',\n PRK: 'KP',\n KOR: 'KR',\n KWT: 'KW',\n KGZ: 'KG',\n LAO: 'LA',\n LVA: 'LV',\n LBN: 'LB',\n LSO: 'LS',\n LBR: 'LR',\n LBY: 'LY',\n LIE: 'LI',\n LTU: 'LT',\n LUX: 'LU',\n MAC: 'MO',\n MDG: 'MG',\n MWI: 'MW',\n MYS: 'MY',\n MDV: 'MV',\n MLI: 'ML',\n MLT: 'MT',\n MHL: 'MH',\n MTQ: 'MQ',\n MRT: 'MR',\n MUS: 'MU',\n MYT: 'YT',\n MEX: 'MX',\n FSM: 'FM',\n MDA: 'MD',\n MCO: 'MC',\n MNG: 'MN',\n MNE: 'ME',\n MSR: 'MS',\n MAR: 'MA',\n MOZ: 'MZ',\n MMR: 'MM',\n NAM: 'NA',\n NRU: 'NR',\n NPL: 'NP',\n NLD: 'NL',\n NCL: 'NC',\n NZL: 'NZ',\n NIC: 'NI',\n NER: 'NE',\n NGA: 'NG',\n NIU: 'NU',\n NFK: 'NF',\n MNP: 'MP',\n NOR: 'NO',\n OMN: 'OM',\n PAK: 'PK',\n PLW: 'PW',\n PSE: 'PS',\n PAN: 'PA',\n PNG: 'PG',\n PRY: 'PY',\n PER: 'PE',\n PHL: 'PH',\n PCN: 'PN',\n POL: 'PL',\n PRT: 'PT',\n PRI: 'PR',\n QAT: 'QA',\n MKD: 'MK',\n ROU: 'RO',\n RUS: 'RU',\n RWA: 'RW',\n REU: 'RE',\n BLM: 'BL',\n SHN: 'SH',\n KNA: 'KN',\n LCA: 'LC',\n MAF: 'MF',\n SPM: 'PM',\n VCT: 'VC',\n WSM: 'WS',\n SMR: 'SM',\n STP: 'ST',\n SAU: 'SA',\n SEN: 'SN',\n SRB: 'RS',\n SYC: 'SC',\n SLE: 'SL',\n SGP: 'SG',\n SXM: 'SX',\n SVK: 'SK',\n SVN: 'SI',\n SLB: 'SB',\n SOM: 'SO',\n ZAF: 'ZA',\n SGS: 'GS',\n SSD: 'SS',\n ESP: 'ES',\n LKA: 'LK',\n SDN: 'SD',\n SUR: 'SR',\n SJM: 'SJ',\n SWE: 'SE',\n CHE: 'CH',\n SYR: 'SY',\n TWN: 'TW',\n TJK: 'TJ',\n TZA: 'TZ',\n THA: 'TH',\n TLS: 'TL',\n TGO: 'TG',\n TKL: 'TK',\n TON: 'TO',\n TTO: 'TT',\n TUN: 'TN',\n TUR: 'TR',\n TKM: 'TM',\n TCA: 'TC',\n TUV: 'TV',\n UGA: 'UG',\n UKR: 'UA',\n ARE: 'AE',\n GBR: 'GB',\n UMI: 'UM',\n USA: 'US',\n URY: 'UY',\n UZB: 'UZ',\n VUT: 'VU',\n VEN: 'VE',\n VNM: 'VN',\n VGB: 'VG',\n VIR: 'VI',\n WLF: 'WF',\n ESH: 'EH',\n YEM: 'YE',\n ZMB: 'ZM',\n ZWE: 'ZW',\n ALA: 'AX'\n};\n\nexport const countryCodeToIso = (code: string) => COUNTRY_ISO_MAP[code] ?? code;\n","import { RuleObject } from 'antd/es/form';\nimport i18n from 'common/helpers/i18n';\nimport { decodeGiftcardNumber } from 'common/helpers/giftcard.helper';\n\nexport const requiredField = () => ({ required: true, message: i18n.t('Field is required') });\n\nexport const commonStringRules = () => [\n {\n min: 2,\n message: i18n.t('Minimum value', { value: 2 })\n },\n {\n max: 64,\n message: i18n.t('Maximum value', { value: 64 })\n },\n {\n pattern: /.*[^\\s]$/,\n message: i18n.t('Invalid field value')\n }\n];\n\nexport const passwordRules = () => ({\n validator(rule: RuleObject, value: string) {\n if (value) {\n if (/[^a-zA-Z0-9!\"#$%&'()*+,\\-./:;<=>?@[\\\\\\]^_`{|}]/.test(value)) {\n return Promise.reject(i18n.t('Only latin characters is allowed'));\n }\n if (value?.length < 8) {\n return Promise.reject(i18n.t('Password needs 8 or more characters'));\n }\n if (value?.length > 64) {\n return Promise.reject(i18n.t('Password needs 64 or less characters'));\n }\n if (!/[a-z]/.test(value)) {\n return Promise.reject(i18n.t('Password needs at least one lowercase'));\n }\n if (!/[A-Z]/.test(value)) {\n return Promise.reject(i18n.t('Password needs at least one uppercase'));\n }\n if (!/[0-9]/.test(value)) {\n return Promise.reject(i18n.t('Password needs at least one number'));\n }\n }\n return Promise.resolve();\n }\n});\nexport const externalIdRules = () => ({\n validator(rule: RuleObject, value: string) {\n if (!/^[a-zA-Z0-9-_]{2,128}$/.test(value)) {\n return Promise.reject(i18n.t('Invalid field value'));\n }\n return Promise.resolve();\n }\n});\n\nexport const phoneRule = () => ({\n validator(rule: RuleObject, value: string) {\n if (!value || /^\\d+$/g.test(value?.replace('+', ''))) {\n return Promise.resolve();\n }\n return Promise.reject(i18n.t('Phone mask'));\n }\n});\n\nexport const maxLengthRule = (maxLength: number) => ({\n max: maxLength,\n message: i18n.t('Maximum characters', { count: maxLength })\n});\n\nexport const maxNumberRule = (maxNumber: number) => ({\n validator(rule: RuleObject, value: number) {\n if (value === undefined || value === null || value <= maxNumber) {\n return Promise.resolve();\n }\n return Promise.reject(i18n.t('Maximum value', { value: maxNumber }));\n }\n});\n\nexport const minNumberRule = (minNumber: number) => ({\n validator(rule: RuleObject, value: number) {\n if (value === undefined || value === null || value >= minNumber) {\n return Promise.resolve();\n }\n return Promise.reject(i18n.t('Minimum value', { value: minNumber }));\n }\n});\n\nexport const maxArrayLengthRule = (maxLength: number) => ({\n validator(rule: RuleObject, value: string) {\n if (!value || value?.length <= maxLength) {\n return Promise.resolve();\n }\n return Promise.reject(i18n.t('Maximum number of values', { value: maxLength }));\n }\n});\n\nexport const validateGiftcard = () => ({\n validator(rule: RuleObject, value: string) {\n const giftcard = value?.replace(/ /g, '');\n const { isGiftcardOk } = decodeGiftcardNumber(giftcard);\n if (isGiftcardOk) {\n return Promise.resolve();\n }\n return Promise.reject(i18n.t('Wrong giftcard'));\n }\n});\n","import { useFormMapper } from '@axmit/antd4-helpers';\nimport React from 'react';\nimport Button from 'antd/es/button';\nimport Form from 'antd/es/form';\nimport Input from 'antd/es/input';\nimport Typography from 'antd/es/typography';\nimport { useTranslation } from 'react-i18next';\nimport { requiredField } from 'common/helpers/filed-rules';\nimport { communicationMentorRequest, IMentorRequestConnectedProps } from 'entities/MentorRequest/MentorRequest.communication';\nimport { IMentorRequestCreateParams } from 'entities/MentorRequest/MentorRequest.models';\n\ninterface IComponentProps {\n onClose: () => void;\n}\ntype AllProps = IMentorRequestConnectedProps & IComponentProps;\n\nconst MentorRequestCreateFormComponent: React.FC = props => {\n const { t } = useTranslation();\n const { mentorRequestModel, addMentorRequestModel } = props;\n const { params, errors, loading } = mentorRequestModel;\n const { fields } = useFormMapper(['email'], null, params, errors);\n\n const addMentorRequest = (values: any) => {\n const { email } = values;\n const body: IMentorRequestCreateParams = {\n email\n };\n\n addMentorRequestModel(body);\n };\n\n return (\n \n \n \n \n {t('Player must confirm the change of representative in his application')}\n \n \n \n {t('Send request')}\n \n \n \n );\n};\n\nexport const MentorRequestCreateForm = communicationMentorRequest.injector(MentorRequestCreateFormComponent);\n","import i18n from 'common/helpers/i18n';\n\nexport const nameBuilder = (firstName?: string | null, lastName?: string | null, replace?: string): string =>\n firstName && lastName ? `${lastName} ${firstName}` : replace || i18n.t('Unknown name');\n\nexport const getPlayerName = (player?: { firstName?: string; lastName?: string } | null): string => {\n if (!player) {\n return i18n.t('Unknown name');\n }\n return nameBuilder(player.firstName, player.lastName);\n};\n","import React, { useCallback, useContext, useMemo } from 'react';\nimport Typography from 'antd/es/typography';\nimport Popover from 'antd/es/popover';\nimport Row from 'antd/es/row';\nimport InfoCircleOutlined from '@ant-design/icons/InfoCircleOutlined';\nimport { useTranslation } from 'react-i18next';\nimport classNames from 'classnames';\nimport { formatDateFromServer } from 'common/helpers/date.helper';\nimport { clientDateFullMonthFormat } from 'common/models/dateModels';\nimport { StripeContext } from 'common/components/Stripe/StripeProvider';\nimport {\n EProcessings,\n ESubscriptionsEngines,\n ESubscriptionStatus,\n ISubscriptionModel\n} from 'entities/Subscription/Subscription.models';\nimport { communicationSubscription, ISubscriptionConnectedProps } from 'entities/Subscription/Subscription.communication';\nimport { getSubscriptionInfoTextClass } from 'entities/Subscription/helpers/subscription.helper';\nimport { IAuthConnectedProps, communicationAuth } from 'entities/Auth/Auth.communication';\nimport { IUIConnectedProps, communicationUI } from 'entities/UI/UI.communication';\nimport { EModalStripePaymentType } from 'entities/UI/UI.models';\n\ninterface IProps {\n subscription?: ISubscriptionModel | null;\n size?: 'large' | 'middle' | 'small';\n block?: boolean;\n}\n\ntype AllProps = IProps & ISubscriptionConnectedProps & IAuthConnectedProps & IUIConnectedProps;\n\nconst POPOVER_TEXT_STYLE = { maxWidth: 400 };\nconst Z_INDEX = 9997;\n\nconst Component: React.FC = props => {\n const { t } = useTranslation();\n const { lastSavedPaymentMethod } = useContext(StripeContext);\n const {\n subscription,\n subscriptionModel,\n updateSubscriptionModel,\n size,\n block,\n addSubscriptionActivityModel,\n authUser,\n openUIStripePaymentModal,\n closeUIStripePaymentModal\n } = props;\n const { loading: subscriptionLoading } = subscriptionModel;\n const userStripePaymentMethod = authUser?.data?.stripePaymentMethod;\n\n const isStripe = useMemo(() => subscription?.engine === ESubscriptionsEngines.Stripe, [subscription?.engine]);\n\n const paidTill = useMemo(() => formatDateFromServer(subscription?.prepaidTo, clientDateFullMonthFormat), [subscription]);\n\n const hasPaymentMethod = useMemo(() => {\n if (!isStripe) {\n return subscription?.hasSavedPaymentMethod;\n }\n\n return Boolean(userStripePaymentMethod || lastSavedPaymentMethod?.card);\n }, [userStripePaymentMethod, isStripe, lastSavedPaymentMethod]);\n\n const onCancelDelayedCancellation = useCallback(() => {\n if (subscription?.id) {\n updateSubscriptionModel({\n id: subscription.id,\n status: ESubscriptionStatus.Active,\n engine: subscription.engine as ESubscriptionsEngines\n });\n }\n }, [subscription]);\n\n const infoTextClass = useMemo(() => getSubscriptionInfoTextClass(size, block), [size, block]);\n\n const onTestPaymentClick = useCallback(() => {\n if (subscription?.id) {\n if (isStripe) {\n openUIStripePaymentModal({\n withCardDetails: true,\n withCoupon: false,\n title: t('Card adding'),\n cardDetailBtnText: t('Add'),\n subscription: subscription.id,\n type: EModalStripePaymentType.ReactivateSubscription\n });\n } else {\n onCancelDelayedCancellation();\n addSubscriptionActivityModel({\n isTest: true,\n subscriptionId: subscription.id,\n processing: EProcessings.Yookassa\n });\n }\n }\n }, [subscription, isStripe, closeUIStripePaymentModal, onCancelDelayedCancellation]);\n\n const preventDefault = useCallback((e: React.MouseEvent) => {\n e.stopPropagation();\n }, []);\n\n return (\n \n \n {t('Subscription cancelled')}\n \n \n {t('subscription-delay-info', { date: paidTill })}\n {hasPaymentMethod && (\n \n {t('Restore')}\n \n )}\n \n {!hasPaymentMethod && (\n \n {t(`need-pay-first${isStripe ? '-stripe' : ''}`)}\n \n {t('Restore')}\n \n \n )}\n >\n }\n >\n \n \n \n
\n );\n};\n\nexport const SubscriptionDelayedCancellation = communicationUI.injector(\n communicationAuth.injector(communicationSubscription.injector(Component))\n);\n","import React, { ReactElement, useCallback, useMemo } from 'react';\nimport Button from 'antd/es/button';\nimport Popconfirm from 'antd/es/popconfirm';\nimport Popover from 'antd/es/popover';\nimport Typography from 'antd/es/typography';\nimport InfoCircleOutlined from '@ant-design/icons/InfoCircleOutlined';\nimport { useTranslation } from 'react-i18next';\nimport { useHistory } from 'react-router';\nimport { stripeSettingsPageRoute } from 'common/models/routesModel';\nimport {\n EPaymentActivitiesStatus,\n EProcessings,\n ESubscriptionsEngines,\n ESubscriptionStatus,\n ISubscriptionModel\n} from 'entities/Subscription/Subscription.models';\nimport { communicationSubscription, ISubscriptionConnectedProps } from 'entities/Subscription/Subscription.communication';\nimport { communicationUI, IUIConnectedProps } from 'entities/UI/UI.communication';\nimport { SubscriptionDelayedCancellation } from 'entities/Subscription/components/SubscriptionDelayedCancellation';\nimport { getSubscriptionInfoTextClass } from 'entities/Subscription/helpers/subscription.helper';\n\ninterface IProps {\n subscription?: ISubscriptionModel;\n mentorRequestId: string | undefined;\n playerId?: string;\n mentorRequestSubscriptionEngine: ESubscriptionsEngines;\n onUnsubscribeClick?: () => void;\n onSubscribeClick?: () => void;\n onPayClick?: () => void;\n hideTariffs?: boolean;\n isPaid?: boolean;\n hideUnsubscribeBtn?: boolean;\n hideActiveStatus?: boolean;\n unsubscribeElement?: ReactElement;\n block?: boolean;\n size?: 'large' | 'middle' | 'small';\n}\n\ntype AllProps = IProps & ISubscriptionConnectedProps & IUIConnectedProps;\n\nconst SubscriptionButtonComponent: React.FC = props => {\n const { t } = useTranslation();\n const history = useHistory();\n const {\n onSubscribeClick,\n subscription,\n mentorRequestId,\n updateSubscriptionModel,\n onUnsubscribeClick,\n hideUnsubscribeBtn,\n unsubscribeElement,\n block,\n size = 'middle',\n openUIPaymentRequirementsModal,\n subscriptionModel,\n mentorRequestSubscriptionEngine,\n playerId,\n isPaid,\n hideTariffs,\n hideActiveStatus\n } = props;\n const { loading: subscriptionLoading } = subscriptionModel;\n\n const isSubscriptionActive = useMemo(() => subscription && subscription.status === ESubscriptionStatus.Active, [subscription]);\n\n const isDelayedCancellation = useMemo(() => subscription && subscription.delayedCancellation, [subscription]);\n\n const linkToPay = useMemo(() => {\n if (subscription && subscription.lastActivity?.confirmationUrl) {\n return subscription.lastActivity.confirmationUrl;\n }\n return '';\n }, [subscription]);\n\n const isCheckingLastPayment = useMemo(() => {\n if (subscription && subscription.lastActivity && subscription?.engine !== ESubscriptionsEngines.Stripe) {\n return (\n subscription.lastActivity.status === EPaymentActivitiesStatus.New || subscription.lastActivity.isApplied === undefined\n );\n }\n\n return false;\n }, [subscription]);\n\n const label = useMemo(() => {\n switch (subscription?.status) {\n case ESubscriptionStatus.Active: {\n return t('Unsubscribe');\n }\n case ESubscriptionStatus.Expired: {\n return t('Pay for a Subscription');\n }\n default: {\n return t('Subscribe');\n }\n }\n }, [subscription]);\n\n const getInfoTextClass = useMemo(() => getSubscriptionInfoTextClass(size, block), [size, block]);\n\n const btnType = useMemo(() => {\n if (isSubscriptionActive) {\n return 'default';\n }\n return 'primary';\n }, [subscription]);\n\n const onUnsubscribe = () => {\n if (subscription?.id) {\n updateSubscriptionModel({\n id: subscription.id,\n status: ESubscriptionStatus.Canceled\n });\n if (onUnsubscribeClick) {\n onUnsubscribeClick();\n }\n }\n };\n\n const onClickHandler = useCallback(\n e => {\n e?.stopPropagation();\n if (subscription?.status !== ESubscriptionStatus.Active) {\n if (mentorRequestSubscriptionEngine === ESubscriptionsEngines.Yookassa) {\n const body =\n subscription?.status === ESubscriptionStatus.Expired\n ? {\n subscriptionId: subscription.id,\n processing: EProcessings.Yookassa\n }\n : {\n mentorRequestId\n };\n openUIPaymentRequirementsModal(body);\n }\n if (mentorRequestSubscriptionEngine === ESubscriptionsEngines.Stripe && playerId) {\n history.push(stripeSettingsPageRoute(playerId));\n }\n onSubscribeClick && onSubscribeClick();\n }\n },\n [subscription, playerId, mentorRequestSubscriptionEngine]\n );\n\n const preventDefault = useCallback((e: React.MouseEvent) => {\n e.stopPropagation();\n }, []);\n\n switch (true) {\n case isDelayedCancellation:\n return ;\n case isCheckingLastPayment:\n return (\n \n
\n {t('Payment is verifying')}\n {mentorRequestSubscriptionEngine === ESubscriptionsEngines.Yookassa && (\n \n {t(\"If you didn't pay\")}\n \n {t('click here')}\n \n \n }\n >\n
\n \n )}\n \n
\n );\n case isPaid:\n case hideTariffs: {\n return !hideActiveStatus ? (\n {t('active')} \n ) : null;\n }\n case isSubscriptionActive: {\n if (hideUnsubscribeBtn) {\n return null;\n }\n if (unsubscribeElement) {\n return unsubscribeElement;\n }\n return {t('active')} ;\n }\n default:\n return (\n \n \n {label}\n \n \n );\n }\n};\n\nexport const SubscriptionButton = communicationUI.injector(communicationSubscription.injector(SubscriptionButtonComponent));\n","import React, { useCallback, useMemo } from 'react';\nimport Button from 'antd/es/button';\nimport Row from 'antd/es/row';\nimport Typography from 'antd/es/typography';\nimport List from 'antd/es/list';\nimport Card from 'antd/es/card';\nimport Col from 'antd/es/col';\nimport moment from 'moment';\nimport Popconfirm from 'antd/es/popconfirm';\nimport CameraOutlined from '@ant-design/icons/CameraOutlined';\nimport { useTranslation } from 'react-i18next';\nimport { nameBuilder } from 'common/helpers/name.helper';\nimport { locationFormatter } from 'common/helpers/location.helper';\nimport { ImagePrivate } from 'common/components/Image/ImagePrivate';\nimport { IMentorRequestModel, EMentorRequestStatus, EMentorRequestAcceptSide } from 'entities/MentorRequest/MentorRequest.models';\nimport { communicationMentorRequest, IMentorRequestConnectedProps } from 'entities/MentorRequest/MentorRequest.communication';\nimport { SubscriptionButton } from 'entities/Subscription/components/SubscriptionButton';\nimport { ESubscriptionsEngines } from 'entities/Subscription/Subscription.models';\nimport { isAcademyHideTariffs } from 'entities/Subscription/helpers/subscription.helper';\nimport { communicationUI, IUIConnectedProps } from 'entities/UI/UI.communication';\n\ntype AllProps = IComponentProps & IMentorRequestConnectedProps & IUIConnectedProps;\n\ninterface IComponentProps {\n item: IMentorRequestModel;\n onClick: (itemModel: IMentorRequestModel) => void;\n}\n\nconst avatarSize = 48;\nconst defaultAvatarStyle = { width: avatarSize, height: avatarSize, fontSize: avatarSize / 2 };\n\nconst MentorRequestListItemComponent = ({\n item,\n onClick,\n updateMentorRequestModel,\n mentorRequestModel,\n openUIPlayerEmailEditModal\n}: AllProps) => {\n const { loading, params } = mentorRequestModel;\n const { t } = useTranslation();\n const { id, player, status, subscription, acceptSide, subscriptionEngine } = item;\n const {\n firstName,\n lastName,\n ageGroup,\n rating,\n image,\n email,\n phone,\n isPaid,\n id: playerId,\n birthday,\n academyLink,\n address\n } = player;\n const hideTariffs = useMemo(() => isAcademyHideTariffs(player), [player]);\n const playerName = nameBuilder(firstName, lastName);\n const fullAddress = locationFormatter(address) ?? t('Unknown address');\n const playerAcademy = academyLink?.academy;\n\n const paramsId = useMemo(() => {\n if (params) {\n if (typeof params === 'string') {\n return params;\n }\n\n if ('id' in params) {\n return params.id;\n }\n }\n\n return undefined;\n }, [params]);\n const disabled = useMemo(() => (paramsId ? paramsId === id && loading : loading), [paramsId, id, loading]);\n\n const onItemClick = useCallback(() => {\n if (status === EMentorRequestStatus.Accepted) {\n onClick(item);\n }\n }, [id, status]);\n\n const onRemoveRequest = useCallback(() => {\n updateMentorRequestModel({\n status: EMentorRequestStatus.Aborted,\n id\n });\n }, [id]);\n\n const onAcceptRequest = useCallback(async () => {\n await updateMentorRequestModel({\n status: EMentorRequestStatus.Accepted,\n id\n });\n }, [id]);\n\n const onDeclineRequest = useCallback(() => {\n updateMentorRequestModel({\n status: EMentorRequestStatus.Declined,\n id\n });\n }, [id]);\n\n const actionItem = useMemo(() => {\n switch (true) {\n case status === EMentorRequestStatus.New && acceptSide === EMentorRequestAcceptSide.Mentor: {\n return (\n \n \n openUIPlayerEmailEditModal({ playerId, mentorRequestId: id, needAcceptRequest: true })\n }\n block\n type=\"primary\"\n >\n {t('Accept')}\n \n \n \n \n \n \n {t('Decline')}\n
\n \n \n \n
\n );\n }\n case status === EMentorRequestStatus.New: {\n return (\n \n \n \n {t(`status-player-card.${status}`)}\n \n \n
\n );\n }\n\n default: {\n return (\n \n \n \n \n
\n \n {!email && (\n \n {\n e.stopPropagation();\n e.preventDefault();\n openUIPlayerEmailEditModal({ playerId, mentorRequestId: id });\n }}\n >\n \n {t('Connect JuniStat')}\n
\n \n \n )}\n
\n );\n }\n }\n }, [status, subscription, id, disabled, acceptSide, email]);\n\n return (\n \n \n \n \n \n \n \n \n \n \n \n {rating ?? '-'}\n \n \n \n \n {ageGroup}\n \n \n
\n \n \n \n {moment(birthday).year()}\n \n \n
\n \n \n {image?.id ? (\n \n ) : (\n \n \n
\n )}\n {playerAcademy?.image?.id && (\n \n )}\n \n \n \n \n \n {firstName || lastName ? playerName : email ? email : phone ? phone : t('Unknown player')}\n \n \n \n \n {fullAddress}\n \n \n {playerAcademy?.name && (\n \n \n {playerAcademy.name}\n \n \n )}\n
\n \n
\n \n {actionItem}\n
\n \n \n );\n};\n\nexport const MentorRequestListItem = communicationUI.injector(\n communicationMentorRequest.injector(MentorRequestListItemComponent)\n);\n","import React from 'react';\nimport Button from 'antd/es/button';\nimport Row from 'antd/es/row';\nimport Typography from 'antd/es/typography';\nimport Col from 'antd/es/col';\nimport { useTranslation } from 'react-i18next';\nimport AircraftIcon from 'app/assets/icons/aircraft.svg';\nimport { communicationMentorRequest, IMentorRequestConnectedProps } from 'entities/MentorRequest/MentorRequest.communication';\n\ninterface IComponentProps {\n onClose: () => void;\n}\ntype AllProps = IMentorRequestConnectedProps & IComponentProps;\n\nconst MentorRequestModal: React.FC = ({ onClose }) => {\n const { t } = useTranslation();\n return (\n \n \n \n \n \n \n {t('Request has been sent')}\n \n \n \n {t('after-send-player-message')} \n \n \n \n {t('Understand')}\n \n \n
\n );\n};\n\nexport const MentorRequestModalFinal = communicationMentorRequest.injector(MentorRequestModal);\n","import React from 'react';\nimport Button from 'antd/es/button';\nimport Row from 'antd/es/row';\nimport Typography from 'antd/es/typography';\nimport Col from 'antd/es/col';\nimport { useTranslation } from 'react-i18next';\nimport LampIcon from 'app/assets/icons/lamp.svg';\nimport { communicationMentorRequest, IMentorRequestConnectedProps } from 'entities/MentorRequest/MentorRequest.communication';\nimport { communicationPlayer, IPlayerConnectedProps } from 'entities/Player/Player.communication';\nimport { IMentorRequestCreateParams } from 'entities/MentorRequest/MentorRequest.models';\n\ninterface IComponentProps {\n onClose: () => void;\n}\ntype AllProps = IMentorRequestConnectedProps & IPlayerConnectedProps & IComponentProps;\n\nconst MentorRequestModal: React.FC = props => {\n const { onClose, mentorRequestModel, sendPlayerInvite, playerInvite } = props;\n const { params = {} } = mentorRequestModel;\n const { loading } = playerInvite;\n\n const { t } = useTranslation();\n\n const onSend = React.useCallback(() => {\n const { email } = params as IMentorRequestCreateParams;\n if (email) {\n sendPlayerInvite({ email });\n }\n }, [params]);\n\n return (\n \n \n \n \n \n \n {t('Player not exist')}\n \n \n \n {t('invite-player-mentor-message')} \n \n \n \n {t('Send request')}\n \n \n \n \n {t('Revoke')}\n \n \n
\n );\n};\n\nexport const MentorRequestModalInvite = communicationPlayer.injector(communicationMentorRequest.injector(MentorRequestModal));\n","import React from 'react';\nimport i18n from 'i18next';\nimport Modal from 'antd/es/modal/Modal';\nimport { communicationUI, IUIConnectedProps } from 'entities/UI/UI.communication';\nimport { EMentorRequestModalType } from 'entities/UI/UI.models';\nimport { MentorRequestCreateForm } from 'entities/MentorRequest/components/MentorRequestCreateForm';\nimport { MentorRequestModalFinal } from 'entities/MentorRequest/components/MentorRequestModalFinal';\nimport { MentorRequestModalInvite } from 'entities/MentorRequest/components/MentorRequestModalInvite';\nimport { communicationMentorRequest, IMentorRequestConnectedProps } from 'entities/MentorRequest/MentorRequest.communication';\n\ntype AllProps = IUIConnectedProps & IMentorRequestConnectedProps;\n\nclass MentorRequestModalComponent extends React.PureComponent {\n render() {\n const { UIMentorRequestModal } = this.props;\n const isVisible = UIMentorRequestModal.data?.isVisible;\n const modalType = UIMentorRequestModal.data?.modalType;\n const isAddModal = modalType === EMentorRequestModalType.AddPlayer;\n const isAfterAddModal = modalType === EMentorRequestModalType.AfterAddPlayer;\n const isInviteModal = modalType === EMentorRequestModalType.InvitePlayer;\n return (\n \n {isAddModal && }\n {isAfterAddModal && }\n {isInviteModal && }\n \n );\n }\n\n closeModal = () => {\n const { closeUIMentorRequestModal, clearMentorRequestModel } = this.props;\n clearMentorRequestModel();\n closeUIMentorRequestModal();\n };\n}\n\nexport const MentorRequestModal = communicationMentorRequest.injector(communicationUI.injector(MentorRequestModalComponent));\n","function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\nimport React from \"react\";\n\nvar _ref2 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"M64 128C99.3462 128 128 99.3462 128 64C128 28.6538 99.3462 0 64 0C28.6538 0 0 28.6538 0 64C0 99.3462 28.6538 128 64 128Z\",\n fill: \"url(#paint0_linear)\"\n});\n\nvar _ref3 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"M82.75 41.5C82.75 31.1613 74.3387 22.75 64 22.75C53.6613 22.75 45.25 31.1613 45.25 41.5C45.25 51.8387 53.6613 60.25 64 60.25C74.3387 60.25 82.75 51.8387 82.75 41.5ZM64 60.25C45.3902 60.25 30.25 75.3903 30.25 94V97.5145C30.25 98.5805 30.7035 99.596 31.4975 100.307C40.632 108.492 52.175 113 64 113C75.8252 113 87.3683 108.492 96.5025 100.307C97.2965 99.596 97.75 98.5803 97.75 97.5145V94C97.75 75.3903 82.6097 60.25 64 60.25Z\",\n fill: \"url(#paint1_linear)\"\n});\n\nvar _ref4 = /*#__PURE__*/React.createElement(\"defs\", null, /*#__PURE__*/React.createElement(\"linearGradient\", {\n id: \"paint0_linear\",\n x1: 64,\n y1: 128,\n x2: 64,\n y2: 0,\n gradientUnits: \"userSpaceOnUse\"\n}, /*#__PURE__*/React.createElement(\"stop\", {\n stopColor: \"#5558FF\"\n}), /*#__PURE__*/React.createElement(\"stop\", {\n offset: 1,\n stopColor: \"#00C0FF\"\n})), /*#__PURE__*/React.createElement(\"linearGradient\", {\n id: \"paint1_linear\",\n x1: 64,\n y1: 113,\n x2: 64,\n y2: 22.75,\n gradientUnits: \"userSpaceOnUse\"\n}, /*#__PURE__*/React.createElement(\"stop\", {\n stopColor: \"#ADDCFF\"\n}), /*#__PURE__*/React.createElement(\"stop\", {\n offset: 0.5028,\n stopColor: \"#EAF6FF\"\n}), /*#__PURE__*/React.createElement(\"stop\", {\n offset: 1,\n stopColor: \"#EAF6FF\"\n})));\n\nvar SvgFullHuman = function SvgFullHuman(_ref) {\n var svgRef = _ref.svgRef,\n title = _ref.title,\n props = _objectWithoutProperties(_ref, [\"svgRef\", \"title\"]);\n\n return /*#__PURE__*/React.createElement(\"svg\", _extends({\n width: 128,\n height: 128,\n viewBox: \"0 0 128 128\",\n fill: \"none\",\n ref: svgRef\n }, props), title ? /*#__PURE__*/React.createElement(\"title\", null, title) : null, _ref2, _ref3, _ref4);\n};\n\nvar ForwardRef = /*#__PURE__*/React.forwardRef(function (props, ref) {\n return /*#__PURE__*/React.createElement(SvgFullHuman, _extends({\n svgRef: ref\n }, props));\n});\nexport default __webpack_public_path__ + \"static/media/full-human.d191938a.svg\";\nexport { ForwardRef as ReactComponent };","import React from 'react';\nimport Button from 'antd/es/button';\nimport Row from 'antd/es/row';\nimport Icon from '@ant-design/icons/es/components/Icon';\nimport { useTranslation } from 'react-i18next';\nimport { ReactComponent as HumanIcon } from 'app/assets/icons/full-human.svg';\nimport { EMentorRequestModalType } from 'entities/UI/UI.models';\nimport { communicationUI, IUIConnectedProps } from 'entities/UI/UI.communication';\n\ntype AllProps = IUIConnectedProps;\n\nconst MentorRequestListNoDataComponent = (props: AllProps) => {\n const { t } = useTranslation();\n\n const onClick = () => {\n const { openUIMentorRequestModal } = props;\n openUIMentorRequestModal({ modalType: EMentorRequestModalType.AddPlayer });\n };\n\n return (\n \n \n \n {t('Add player')}\n \n
\n );\n};\n\nexport const MentorRequestListNoData = communicationUI.injector(MentorRequestListNoDataComponent);\n","import React from 'react';\nimport { InfiniteList } from 'common/components/InfiniteList';\nimport { IBaseFilterModel } from 'common/models/requestModels';\nimport {\n EMentorRequestStatus,\n IMentorRequestCollection,\n IMentorRequestCollectionFilter,\n IMentorRequestModel\n} from 'entities/MentorRequest/MentorRequest.models';\nimport { communicationMentorRequest, IMentorRequestConnectedProps } from 'entities/MentorRequest/MentorRequest.communication';\nimport { MentorRequestListItem, MentorRequestListNoData } from 'entities/MentorRequest/components';\n\ninterface IComponentProps {\n onItemClick: (itemModel: IMentorRequestModel) => void;\n}\n\ntype AllProps = IComponentProps & IMentorRequestConnectedProps;\n\nclass MentorRequestListComponent extends InfiniteList<\n IMentorRequestCollection,\n IMentorRequestModel,\n AllProps,\n IMentorRequestCollectionFilter\n> {\n loadCollection = async (params: IBaseFilterModel) => {\n const { getMentorRequestCollection } = this.props;\n const filters = {\n ...params,\n regComplete: true\n };\n return getMentorRequestCollection({\n ...filters,\n statuses: [EMentorRequestStatus.New, EMentorRequestStatus.Accepted]\n });\n };\n\n renderListItem = (item: IMentorRequestModel) => {\n const { onItemClick } = this.props;\n return ;\n };\n\n renderNoData = () => {\n return ;\n };\n\n getCollection = () => {\n return this.props.mentorRequestCollection;\n };\n}\n\nexport const MentorRequestList = communicationMentorRequest.injector(MentorRequestListComponent);\n","function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\nimport React from \"react\";\n\nvar _ref2 = /*#__PURE__*/React.createElement(\"rect\", {\n width: 24,\n height: 24,\n fill: \"#FF651D\"\n});\n\nvar _ref3 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"M6.148 16.144C5.508 16.144 4.956 16.036 4.492 15.82C4.028 15.604 3.668 15.292 3.412 14.884L4.696 13.66C4.864 13.94 5.072 14.16 5.32 14.32C5.568 14.472 5.852 14.548 6.172 14.548C6.54 14.548 6.84 14.444 7.072 14.236C7.312 14.028 7.476 13.696 7.564 13.24L8.368 9.16H5.416L5.74 7.6H10.612L9.496 13.144C9.352 13.88 9.132 14.468 8.836 14.908C8.548 15.34 8.18 15.656 7.732 15.856C7.284 16.048 6.756 16.144 6.148 16.144ZM15.2562 16.144C14.4002 16.144 13.6602 15.992 13.0362 15.688C12.4202 15.376 11.9442 14.948 11.6082 14.404C11.2722 13.852 11.1042 13.216 11.1042 12.496C11.1042 11.784 11.2282 11.12 11.4762 10.504C11.7322 9.888 12.0882 9.356 12.5442 8.908C13.0082 8.452 13.5562 8.096 14.1882 7.84C14.8282 7.584 15.5402 7.456 16.3242 7.456C17.0762 7.456 17.7402 7.584 18.3162 7.84C18.8922 8.096 19.3282 8.464 19.6242 8.944L18.2202 10.096C18.0042 9.776 17.7282 9.532 17.3922 9.364C17.0562 9.196 16.6562 9.112 16.1922 9.112C15.7202 9.112 15.2922 9.196 14.9082 9.364C14.5242 9.524 14.1922 9.756 13.9122 10.06C13.6402 10.356 13.4322 10.704 13.2882 11.104C13.1442 11.504 13.0722 11.928 13.0722 12.376C13.0722 12.8 13.1642 13.172 13.3482 13.492C13.5322 13.804 13.8002 14.048 14.1522 14.224C14.5042 14.4 14.9282 14.488 15.4242 14.488C15.8562 14.488 16.2602 14.412 16.6362 14.26C17.0122 14.1 17.3522 13.852 17.6562 13.516L18.8082 14.692C18.3682 15.204 17.8442 15.576 17.2362 15.808C16.6362 16.032 15.9762 16.144 15.2562 16.144Z\",\n fill: \"white\"\n});\n\nvar SvgJcSmall = function SvgJcSmall(_ref) {\n var svgRef = _ref.svgRef,\n title = _ref.title,\n props = _objectWithoutProperties(_ref, [\"svgRef\", \"title\"]);\n\n return /*#__PURE__*/React.createElement(\"svg\", _extends({\n width: 24,\n height: 24,\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n ref: svgRef\n }, props), title ? /*#__PURE__*/React.createElement(\"title\", null, title) : null, _ref2, _ref3);\n};\n\nvar ForwardRef = /*#__PURE__*/React.forwardRef(function (props, ref) {\n return /*#__PURE__*/React.createElement(SvgJcSmall, _extends({\n svgRef: ref\n }, props));\n});\nexport default __webpack_public_path__ + \"static/media/JCSmall.0dbd081c.svg\";\nexport { ForwardRef as ReactComponent };","function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\nimport React from \"react\";\n\nvar _ref2 = /*#__PURE__*/React.createElement(\"rect\", {\n width: 24,\n height: 24,\n fill: \"#FFE83F\"\n});\n\nvar _ref3 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"M7.148 17.144C6.508 17.144 5.956 17.036 5.492 16.82C5.028 16.604 4.668 16.292 4.412 15.884L5.696 14.66C5.864 14.94 6.072 15.16 6.32 15.32C6.568 15.472 6.852 15.548 7.172 15.548C7.54 15.548 7.84 15.444 8.072 15.236C8.312 15.028 8.476 14.696 8.564 14.24L9.368 10.16H6.416L6.74 8.6H11.612L10.496 14.144C10.352 14.88 10.132 15.468 9.836 15.908C9.548 16.34 9.18 16.656 8.732 16.856C8.284 17.048 7.756 17.144 7.148 17.144ZM14.7682 17.144C14.3122 17.144 13.8682 17.1 13.4362 17.012C13.0122 16.932 12.6242 16.82 12.2722 16.676C11.9282 16.532 11.6362 16.376 11.3962 16.208L12.1882 14.708C12.4522 14.892 12.7322 15.052 13.0282 15.188C13.3322 15.316 13.6482 15.416 13.9762 15.488C14.3042 15.552 14.6322 15.584 14.9602 15.584C15.3202 15.584 15.6282 15.544 15.8842 15.464C16.1482 15.384 16.3482 15.272 16.4842 15.128C16.6282 14.984 16.7002 14.808 16.7002 14.6C16.7002 14.408 16.6242 14.252 16.4722 14.132C16.3202 14.012 16.1202 13.912 15.8722 13.832C15.6322 13.744 15.3642 13.66 15.0682 13.58C14.7722 13.5 14.4722 13.408 14.1682 13.304C13.8722 13.192 13.6002 13.056 13.3522 12.896C13.1122 12.728 12.9162 12.516 12.7642 12.26C12.6122 12.004 12.5362 11.684 12.5362 11.3C12.5362 10.724 12.6922 10.224 13.0042 9.8C13.3242 9.376 13.7722 9.048 14.3482 8.816C14.9242 8.576 15.6002 8.456 16.3762 8.456C16.9442 8.456 17.4802 8.52 17.9842 8.648C18.4882 8.768 18.9202 8.944 19.2802 9.176L18.5482 10.664C18.2282 10.448 17.8722 10.288 17.4802 10.184C17.0882 10.072 16.6842 10.016 16.2682 10.016C15.8922 10.016 15.5682 10.06 15.2962 10.148C15.0322 10.236 14.8282 10.36 14.6842 10.52C14.5482 10.672 14.4802 10.848 14.4802 11.048C14.4802 11.248 14.5522 11.412 14.6962 11.54C14.8482 11.66 15.0482 11.764 15.2962 11.852C15.5442 11.932 15.8162 12.012 16.1122 12.092C16.4082 12.172 16.7042 12.264 17.0002 12.368C17.2962 12.472 17.5682 12.604 17.8162 12.764C18.0642 12.924 18.2642 13.128 18.4162 13.376C18.5682 13.616 18.6442 13.92 18.6442 14.288C18.6442 14.864 18.4842 15.368 18.1642 15.8C17.8442 16.224 17.3922 16.556 16.8082 16.796C16.2322 17.028 15.5522 17.144 14.7682 17.144Z\",\n fill: \"black\"\n});\n\nvar SvgJsSmall = function SvgJsSmall(_ref) {\n var svgRef = _ref.svgRef,\n title = _ref.title,\n props = _objectWithoutProperties(_ref, [\"svgRef\", \"title\"]);\n\n return /*#__PURE__*/React.createElement(\"svg\", _extends({\n width: 24,\n height: 24,\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n ref: svgRef\n }, props), title ? /*#__PURE__*/React.createElement(\"title\", null, title) : null, _ref2, _ref3);\n};\n\nvar ForwardRef = /*#__PURE__*/React.forwardRef(function (props, ref) {\n return /*#__PURE__*/React.createElement(SvgJsSmall, _extends({\n svgRef: ref\n }, props));\n});\nexport default __webpack_public_path__ + \"static/media/JSSmall.d2778e47.svg\";\nexport { ForwardRef as ReactComponent };","import { IPlayerModel } from 'entities/Player/Player.models';\nimport { ESubscriptionStatus } from 'entities/Subscription/Subscription.models';\nimport { IAcademyModel } from 'entities/Academy/Academy.models';\nimport { EUserRole, IUserModel } from 'entities/User/User.models';\n\nexport enum EPermissionType {\n ShowPlayerDataForAcademy = 'showPlayerDataForAcademy',\n ShowDataForMentor = 'showDataForMentor',\n ShowDataForAcademy = 'showDataForAcademy',\n ShowDataForPlayerAcademy = 'showDataForPlayerAcademy',\n ShowDataForAllMentors = 'showDataForAllMentors',\n ShowDataForMentorAcademyTestConfig = 'showDataForMentorAcademyTestConfig',\n ShowDataForMentorSubActive = 'showDataForMentorSubActive'\n}\n\nexport const permissionHelper = (\n type: EPermissionType,\n authUserModel?: IUserModel | null,\n playerModel?: IPlayerModel | null,\n academyModel?: IAcademyModel | null\n): boolean => {\n const isMentorSubActive = playerModel?.mentorRequest?.subscription?.status === ESubscriptionStatus.Active;\n\n // const visibilityForAll = playerModel?.mentorRequest?.playerVisibility === EMentorRequestPlayerVisibility.All;\n // const visibilityForSubAcademy = playerModel?.mentorRequest?.playerVisibility === EMentorRequestPlayerVisibility.Subscribed;\n // const academyRequest = playerModel?.academyRequests;\n // const academyRequestAccepted = academyRequest ? academyRequest[0]?.status === EAcademyRequestStatus.Accepted : false;\n\n const showPlayerData = !!(playerModel?.firstName || playerModel?.lastName);\n const isAuthUserMentorPlayer = playerModel?.mentorRequest?.mentor.id === authUserModel?.id;\n\n const showTestConfig = academyModel?.showTestConfig;\n const isMentor = authUserModel?.role === EUserRole.Mentor;\n const isAcademyWorker = authUserModel?.role === EUserRole.AcademyWorker;\n\n switch (type) {\n case EPermissionType.ShowDataForMentor: {\n return isMentor ? isAuthUserMentorPlayer : false;\n }\n case EPermissionType.ShowDataForMentorAcademyTestConfig: {\n return isMentor ? isMentorSubActive && !!showTestConfig : false;\n }\n case EPermissionType.ShowDataForMentorSubActive: {\n return isMentor ? isMentorSubActive : false;\n }\n case EPermissionType.ShowDataForAllMentors: {\n return isMentor;\n }\n case EPermissionType.ShowDataForAcademy: {\n return isAcademyWorker;\n }\n case EPermissionType.ShowPlayerDataForAcademy: {\n // return isMentorSubActive && isAcademyWorker\n // ? visibilityForAll || (visibilityForSubAcademy && academyRequestAccepted)\n // : false;\n return isAcademyWorker && showPlayerData;\n }\n case EPermissionType.ShowDataForPlayerAcademy: {\n return isAcademyWorker && authUserModel?.academyWorker?.academy?.id === playerModel?.academyLink?.academy?.id;\n }\n\n default: {\n return false;\n }\n }\n};\n\nexport const isAcademyWorkerHelper = (authUserModel?: IUserModel | null) => {\n return authUserModel?.role === EUserRole.AcademyWorker;\n};\n","import React from 'react';\nimport { Select } from 'antd';\nimport { SelectProps } from 'antd/es/select';\nimport debounce from 'lodash.debounce';\nimport { ItemsNotFound } from 'common/components/Text/ItemsNotFound';\n\ninterface IComponentProps {\n onChange?: (item?: Model) => void;\n placeholder?: string;\n disabled?: boolean;\n mode?: 'tags' | 'multiple';\n isTags?: boolean;\n size?: 'large' | 'middle' | 'small';\n}\n\ntype AllProps = SelectProps & IComponentProps;\n\ninterface IComponentState {\n data: Model[];\n value: Model | Model[] | undefined;\n}\n\nexport abstract class AbstractSearchableSelector extends React.PureComponent<\n AllProps & IProps\n> {\n state: IComponentState = {\n data: [],\n value: this.props.value\n };\n\n readonly searchDebounced: any;\n\n mounted: boolean = false;\n\n protected constructor(props: AllProps & IProps) {\n super(props);\n this.searchDebounced = debounce(this.handleSearch, 200);\n }\n\n static getDerivedStateFromProps(props: AllProps & IProps, state: IComponentState) {\n if (Array.isArray(props.value)) {\n if (!props.value?.length && state.value) {\n return { value: undefined };\n }\n\n if (props.value.length && (!state.value || (Array.isArray(state.value) && !state.value?.length))) {\n return { value: props.value };\n }\n } else {\n if (!props.value?.id && state.value) {\n return { value: undefined };\n }\n\n if (props.value && !state.value) {\n return { value: props.value };\n }\n }\n\n return null;\n }\n\n async componentDidMount() {\n this.mounted = true;\n await this.getCollection();\n }\n\n updateState(data: Model[]) {\n if (this.mounted) {\n this.setState({ data });\n }\n }\n\n getCollection = async () => {\n const { data } = await this.loadData();\n this.updateState(data);\n };\n\n handleSearch = async (value?: string) => {\n const { data } = await this.loadData(value);\n\n this.updateState(data);\n };\n\n handleChange = async (data: string | number | string[] | number[]) => {\n const { onChange, mode } = this.props;\n let value: any;\n\n if (mode && Array.isArray(data)) {\n value = (data as any[]).map((id: string | number) => this.state.data.find(el => el.id === id) || { name: id });\n this.handleSearch(undefined);\n } else {\n value = this.state.data.find(el => el.id === data);\n }\n\n this.setState({ value }, () => onChange && onChange(value));\n };\n\n get value() {\n const { value } = this.state;\n\n return Array.isArray(value)\n ? value.reduce((acc: string[], el: Model) => {\n const itemValue = el?.id || el?.name;\n if (itemValue) {\n return [...acc, itemValue];\n }\n return acc;\n }, [])\n : value?.id;\n }\n\n get data() {\n const { value, data } = this.state;\n\n if (value) {\n if (Array.isArray(value)) {\n const nonExistsValues = value.reduce((acc: Model[], valueEl: Model) => {\n const exist = data.find(el => el?.id === valueEl?.id);\n\n if (!exist && valueEl) {\n return [...acc, valueEl];\n }\n\n return acc;\n }, []);\n\n if (nonExistsValues.length) {\n data.unshift(...nonExistsValues);\n }\n } else {\n const exist = data.find(el => el.id === value?.id);\n if (!exist && value) {\n data.unshift(value);\n }\n }\n }\n\n return data;\n }\n\n render() {\n const { placeholder, disabled, mode, size, className } = this.props;\n\n const options = this.data\n .filter(item => item.id || item.name)\n .map(option => (\n \n {this.getItemLabel(option)}\n \n ));\n\n return this.data ? (\n this.searchDebounced('')}\n onSearch={this.searchDebounced}\n onChange={this.handleChange}\n notFoundContent={ }\n getPopupContainer={triggerNode => triggerNode as HTMLElement}\n >\n {options}\n \n ) : (\n
\n );\n }\n\n componentWillUnmount() {\n this.mounted = false;\n }\n\n abstract getItemLabel: (item: Model) => string;\n abstract loadData: (value?: string) => Promise<{ data: Model[] }>;\n}\n","import { AbstractSearchableSelector } from 'common/components/Input/AbstractSearchableSelector';\nimport { getPlayerName } from 'common/helpers/name.helper';\nimport { EPrivatePlayerSearchCollectionFilterSorters } from 'entities/PrivatePlayer/PrivatePlayer.models';\nimport { IPlayerSearchCollectionFilter, IPlayerSearchModel } from 'entities/Player/Player.models';\nimport { playerTransport } from 'entities/Player/Player.transport';\n\ninterface IComponentProps {\n academyId?: string | string[];\n excludeTrainer?: string;\n excludeTeam?: string;\n orderField?: EPrivatePlayerSearchCollectionFilterSorters;\n playerType?: 'target' | 'source';\n}\n\nexport class PrivatePlayerSelector extends AbstractSearchableSelector {\n getItemLabel = (item: IPlayerSearchModel): string => {\n return getPlayerName(item);\n };\n\n loadData = (value?: string): Promise<{ data: IPlayerSearchModel[] }> => {\n const { academyId, excludeTrainer, excludeTeam, orderField, playerType } = this.props;\n const filter: IPlayerSearchCollectionFilter = {};\n\n if (value) {\n filter.name = value;\n }\n if (playerType !== undefined) {\n filter.merged = false;\n filter.regComplete = true;\n filter.juniCoach = playerType === 'target';\n }\n if (orderField) {\n filter.orderField = orderField;\n }\n if (academyId) {\n filter.academiesIds = Array.isArray(academyId) ? academyId : [academyId];\n }\n if (excludeTrainer) {\n filter.excludeTrainerId = excludeTrainer;\n }\n if (excludeTeam) {\n filter.excludeTeamId = excludeTeam;\n }\n\n return playerTransport.getPlayerSearchCollection(filter);\n };\n}\n","import React, { useEffect, useState } from 'react';\nimport Modal from 'antd/es/modal/Modal';\nimport Typography from 'antd/es/typography';\nimport { useTranslation } from 'react-i18next';\nimport Alert from 'antd/lib/alert';\nimport Popconfirm from 'antd/es/popconfirm';\nimport Col from 'antd/es/col';\nimport message from 'antd/es/message';\nimport Row from 'antd/es/row';\nimport Button from 'antd/es/button';\nimport Divider from 'antd/es/divider';\nimport CameraOutlined from '@ant-design/icons/CameraOutlined';\nimport { ImagePrivate } from 'common/components/Image/ImagePrivate';\nimport { ReactComponent as JCSmallIcon } from 'app/assets/images/JCSmall.svg';\nimport { ReactComponent as JSSmallIcon } from 'app/assets/images/JSSmall.svg';\nimport { PrivatePlayerSelector } from 'entities/PrivatePlayer/components/Selectors/PrivatePlayerSelector';\nimport { IPlayerModel, IPlayerSearchModel } from 'entities/Player/Player.models';\nimport { playerTransport } from 'entities/Player/Player.transport';\nimport { EMentorRequestStatus, IMentorRequestCollectionFilter } from 'entities/MentorRequest/MentorRequest.models';\nimport { communicationMentorRequest, IMentorRequestConnectedProps } from 'entities/MentorRequest/MentorRequest.communication';\nimport { communicationUI, IUIConnectedProps } from 'entities/UI/UI.communication';\n\ntype AllProps = IMentorRequestConnectedProps & IUIConnectedProps;\n\nconst avatarSize = 88;\n\nconst PlayerMergeModalComponent: React.FC = props => {\n const { getMentorRequestCollection, UIPlayerMergeModal, closeUIPlayerMergeModal } = props;\n const { isVisible, sourceId: sourceIdPlayer, targetId: targetIdPlayer } = UIPlayerMergeModal?.data || {};\n const [targetPlayerData, setTargetPlayerData] = useState | undefined>(undefined);\n const [sourcePlayerData, setSourcePlayerData] = useState | undefined>(undefined);\n const { imageId: sourceImageId, id: sourceId } = sourcePlayerData || {};\n const { imageId: targetImageId, id: targetId } = targetPlayerData || {};\n const [isLoading, setLoading] = useState(false);\n const disable = !sourceId || !targetId || isLoading;\n\n const { t } = useTranslation();\n const mergePlayer = async () => {\n if (sourceId && targetId) {\n try {\n setLoading(true);\n const player: IPlayerModel = await playerTransport.mergePlayers({ source: sourceId, target: targetId });\n\n if (player) {\n message.success(t('Players merge request has been successfully sent'));\n const filters: IMentorRequestCollectionFilter = {\n limit: 20,\n offset: 0,\n statuses: [EMentorRequestStatus.New, EMentorRequestStatus.Accepted],\n regComplete: true\n };\n await getMentorRequestCollection(filters);\n setLoading(false);\n closeUIPlayerMergeModal();\n }\n } catch (e) {\n if (e?.data?.code === 'error.subscriptionActiveException') {\n message.warning(t('subscriptionActiveException'));\n } else {\n message.warning(t('An error occurred while merging profiles. Contact support team.'));\n }\n setLoading(false);\n }\n }\n };\n\n useEffect(() => {\n (async () => {\n if (sourceIdPlayer && targetIdPlayer) {\n setLoading(true);\n const sourcePlayer = await playerTransport.getPlayerModel(sourceIdPlayer);\n const targetPlayer = await playerTransport.getPlayerModel(targetIdPlayer);\n setSourcePlayerData(sourcePlayer);\n setTargetPlayerData(targetPlayer);\n setLoading(false);\n }\n })();\n }, [sourceIdPlayer, targetIdPlayer]);\n useEffect(() => {\n if (!isVisible && (sourcePlayerData || targetPlayerData)) {\n setSourcePlayerData(undefined);\n setTargetPlayerData(undefined);\n }\n }, [isVisible, sourcePlayerData, targetPlayerData]);\n\n return (\n {\n e?.stopPropagation();\n e?.preventDefault();\n closeUIPlayerMergeModal();\n }}\n footer={false}\n title={t('Merge player profiles')}\n >\n {t('Merging player profiles description')} \n \n {t('Player’s subscription will be saved')} \n \n {t('Profile cannot be split back')} \n \n {t('Profile cannot be deleted without confirmation by the academy/school')} \n >\n }\n type=\"warning\"\n showIcon\n />\n \n \n \n \n \n \n JuniStat \n
\n \n {sourceId && (\n \n \n \n
\n \n )}\n \n \n \n \n JuniCoach \n
\n \n {targetId && (\n \n \n \n
\n \n )}\n \n
\n \n \n \n \n {\n e?.preventDefault();\n e?.stopPropagation();\n closeUIPlayerMergeModal();\n }}\n >\n {t('Close')}\n \n \n \n {t('Merge')}\n \n \n
\n \n \n );\n};\n\nexport const PlayerMergeModal = communicationUI.injector(communicationMentorRequest.injector(PlayerMergeModalComponent));\n","import React, { useCallback, useState } from 'react';\nimport Modal from 'antd/es/modal/Modal';\nimport Typography from 'antd/es/typography';\nimport { useTranslation } from 'react-i18next';\nimport Col from 'antd/es/col';\nimport message from 'antd/es/message';\nimport Row from 'antd/es/row';\nimport Button from 'antd/es/button';\nimport Form from 'antd/es/form';\nimport Input from 'antd/es/input';\nimport { useFormMapper } from '@axmit/antd4-helpers';\nimport { translateErrors } from 'common/helpers/translate.helper';\nimport { requiredField } from 'common/helpers/filed-rules';\nimport { playerTransport } from 'entities/Player/Player.transport';\nimport { EMentorRequestStatus } from 'entities/MentorRequest/MentorRequest.models';\nimport { communicationMentorRequest, IMentorRequestConnectedProps } from 'entities/MentorRequest/MentorRequest.communication';\nimport { communicationUI, IUIConnectedProps } from 'entities/UI/UI.communication';\n\ntype AllProps = IMentorRequestConnectedProps & IUIConnectedProps;\n\nconst PlayerEmailEditModalComponent: React.FC = props => {\n const {\n UIPlayerEmailEditModal,\n closeUIPlayerEmailEditModal,\n updateMentorRequestModel,\n mentorRequestModel,\n openUIPlayerMergeModal,\n mentorRequestCollection,\n getMentorRequestCollection\n } = props;\n const { isVisible, mentorRequestId: id, playerId, needAcceptRequest } = UIPlayerEmailEditModal?.data || {};\n const [isLoading, setLoading] = useState(false);\n const loading = mentorRequestModel.loading || isLoading;\n const { params } = mentorRequestCollection;\n const { t } = useTranslation();\n const { fields } = useFormMapper(['email'], null);\n\n const onAcceptRequest = useCallback(async () => {\n if (id && needAcceptRequest) {\n setLoading(true);\n await updateMentorRequestModel({\n status: EMentorRequestStatus.Accepted,\n id\n });\n setLoading(false);\n }\n }, [id]);\n\n const onSubmit = useCallback(\n async (values: any) => {\n const { email: emailValue } = values;\n await onAcceptRequest();\n\n if (playerId && emailValue) {\n try {\n setLoading(true);\n await playerTransport.setPlayerEmail({ id: playerId, email: emailValue });\n getMentorRequestCollection({ ...params, offset: 0, limit: 100 });\n } catch (e) {\n if (e?.data?.code === 'error.playerWithEmailAlreadyLinkedException') {\n const { sourceCanMerge, targetCanMerge, targetId, sourceId } = e?.data || {};\n if (sourceCanMerge && targetCanMerge) {\n openUIPlayerMergeModal({ sourceId, targetId });\n } else {\n message.warning(translateErrors('Merging accounts is not possible'));\n }\n }\n } finally {\n setLoading(false);\n }\n }\n closeUIPlayerEmailEditModal();\n },\n [id, status]\n );\n\n return (\n {\n e?.stopPropagation();\n e?.preventDefault();\n closeUIPlayerEmailEditModal();\n }}\n footer={false}\n title={t('Player email')}\n >\n value.trimStart()} rules={[requiredField]} name=\"email\" className=\"mb-5\">\n \n \n \n {t('Enter the player email that will be used to log into the JuniStat app')}\n \n \n \n \n \n {t('Save')}\n \n \n \n \n {\n closeUIPlayerEmailEditModal();\n onAcceptRequest();\n }}\n loading={loading}\n disabled={loading}\n >\n {t('Skip')}\n \n \n
\n \n \n );\n};\n\nexport const PlayerEmailEditModal = communicationUI.injector(communicationMentorRequest.injector(PlayerEmailEditModalComponent));\n","import React, { useEffect } from 'react';\nimport Button from 'antd/es/button';\nimport Row from 'antd/es/row';\nimport Col from 'antd/es/col';\nimport { useTranslation } from 'react-i18next';\nimport Typography from 'antd/es/typography';\nimport { RouteComponentProps, useHistory, withRouter } from 'react-router';\nimport AsyncStorage from '@react-native-async-storage/async-storage';\nimport { queryToObject } from 'common/helpers/filters.helper';\nimport { LayoutContent } from 'common/components/Layouts/ContentLayout';\nimport { ERoutesMentor } from 'common/models/routesModel';\nimport { IMentorRequestModel, gridMentorRequestConfig, EMentorRequestStatus } from 'entities/MentorRequest/MentorRequest.models';\nimport { communicationUI, IUIConnectedProps } from 'entities/UI/UI.communication';\nimport { MentorRequestList } from 'entities/MentorRequest/components/MentorRequestList';\nimport { MentorRequestModal } from 'entities/MentorRequest/components/MentorRequestModal';\nimport { EMentorRequestModalType } from 'entities/UI/UI.models';\nimport { communicationMentorRequest, IMentorRequestConnectedProps } from 'entities/MentorRequest/MentorRequest.communication';\nimport { PlayerMergeModal } from 'entities/Player/components/Modal/PlayerMergeModal';\nimport { PlayerEmailEditModal } from 'entities/Player/components/Modal/PlayerEmailEditModal';\nimport { EUserRole } from 'entities/User/User.models';\nimport { communicationAuth, IAuthConnectedProps } from 'entities/Auth/Auth.communication';\n// Hidden in JS-4319\n// import { SubscriptionsCompare } from 'common/components/SubsriptionsCompare';\n\ninterface IQuery {\n playerIdRedirect?: string;\n}\n\ntype AllProps = IUIConnectedProps & IMentorRequestConnectedProps & IAuthConnectedProps & RouteComponentProps;\n\nconst MentorRequestPageComponent: React.FC = props => {\n const { mentorRequestCollection, openUIPlayerMergeModal, openUIMentorRequestModal, authUser } = props;\n const { data, loading } = mentorRequestCollection;\n const { t } = useTranslation();\n const history = useHistory();\n const { playerIdRedirect } = queryToObject({ playerIdRedirect: undefined }) as IQuery;\n\n const showPlayerPage = (itemModel: IMentorRequestModel) => {\n const playerId = itemModel.player.id;\n\n history.push(`${ERoutesMentor.Player}/${playerId}`);\n };\n\n useEffect(() => {\n if (playerIdRedirect && !!data?.data.length) {\n const mentorRequest = data?.data.find(item => item?.player?.id === playerIdRedirect);\n\n if (mentorRequest) {\n showPlayerPage(mentorRequest);\n }\n }\n }, [playerIdRedirect, data]);\n\n useEffect(() => {\n const redirectMentor = async () => {\n const firstMentorRequest = data?.data[0];\n\n if (data?.meta.count === 1 && firstMentorRequest?.status === EMentorRequestStatus.Accepted) {\n const authUserId = authUser?.data?.id;\n const authUserRole = authUser?.data?.role;\n const mentorId = await AsyncStorage.getItem('mentorIdOpenPlayer');\n\n if ((!mentorId || mentorId !== authUserId) && authUserRole === EUserRole.Mentor) {\n await AsyncStorage.setItem('mentorIdOpenPlayer', authUserId || '');\n showPlayerPage(firstMentorRequest);\n }\n }\n };\n redirectMentor();\n }, [data, loading]);\n\n const showAddPlayerModal = () => {\n openUIMentorRequestModal({ modalType: EMentorRequestModalType.AddPlayer });\n };\n return (\n \n \n \n \n {t('My footballers')}\n \n \n {!!data?.data?.length && (\n \n \n \n openUIPlayerMergeModal()}>\n {t('Merge profiles')}\n \n \n \n \n {t('Add player')}\n \n \n
\n \n )}\n
\n \n \n {/* Hidden in JS-4319 */}\n {/* {!!data?.data?.length && }*/}\n
\n \n \n \n \n );\n};\n\nexport const MentorRequestPage = communicationAuth.injector(\n communicationUI.injector(communicationMentorRequest.injector(withRouter(MentorRequestPageComponent)))\n);\n","import { IBasePathParams } from 'common/models/requestModels';\n\nexport interface IAcademyRequestModel extends Components.Schemas.AcademyRequestDto {}\nexport interface IAcademyRequestLiteModel extends Components.Schemas.AcademyRequestForPlayerLiteDto {}\nexport interface IAcademyRequestUpdateParams\n extends Components.Schemas.UpdateAcademyRequestStatusDto,\n Paths.AcademyRequestControllerSetStatus.PathParameters {\n modelsToUpdate?: EAcademyRequestSuccessUpdateModels[];\n playerId?: string;\n optimisticUpdate?: boolean;\n}\n\nexport interface IAcademyRequestAcademyToPlayerParams extends Components.Schemas.CreateAcademyRequestFromAcademyToPlayerDto {\n modelsToUpdate?: EAcademyRequestSuccessUpdateModels[];\n optimisticUpdate?: boolean;\n}\nexport interface IAcademyRequestPlayerToAcademyParams extends Components.Schemas.CreateAcademyRequestFromPlayerToAcademyDto {}\n\nexport interface IAcademyRequestCollection extends Components.Schemas.AcademyRequestCollectionDto {}\nexport interface IAcademyRequestCollectionFilter extends Paths.AcademyRequestControllerList.QueryParameters {\n address?: string;\n name?: string;\n ageGroup?: string;\n}\n\nexport interface IAcademyRequestModelParams\n extends IAcademyRequestUpdateParams,\n // IAcademyRequestAcademyToPlayerParams, // conflicts with IAcademyRequestPlayerToAcademyParams\n IAcademyRequestPlayerToAcademyParams,\n IBasePathParams {}\n\nexport enum EAcademyRequestStatus {\n New = 'new',\n Declined = 'declined',\n Aborted = 'aborted',\n Accepted = 'accepted'\n}\n\nexport enum EAcademyRequestSuccessUpdateModels {\n Profile = 'profile',\n Profiles = 'profiles',\n Player = 'player',\n Players = 'players'\n}\n","import React, { useMemo } from 'react';\nimport Row from 'antd/es/row';\nimport Typography from 'antd/es/typography';\nimport { useTranslation } from 'react-i18next';\nimport AcademyRequestImg from 'app/assets/icons/academy-request.svg';\nimport { ESubscriptionsEngines } from 'entities/Subscription/Subscription.models';\nimport { communicationPlayer, IPlayerConnectedProps } from 'entities/Player/Player.communication';\nimport { SubscriptionButton } from 'entities/Subscription/components/SubscriptionButton';\nimport { isAcademyHideTariffs } from 'entities/Subscription/helpers/subscription.helper';\n\ntype AllProps = IPlayerConnectedProps;\n\nconst MentorRequestToAcademyWithoutSubComponent: React.FC = props => {\n const { playerModel } = props;\n const { t } = useTranslation();\n const { data: playerData } = playerModel || {};\n const mentorRequestId = playerData?.mentorRequest?.id;\n const mentorRequestSubscriptionEngine = playerData?.mentorRequest?.subscriptionEngine;\n const subscription = playerData?.mentorRequest?.subscription;\n const modalTitle = t('Player without subscription');\n const { isPaid, id } = playerData || {};\n const hideTariffs = useMemo(() => isAcademyHideTariffs(playerData), [playerData]);\n\n return (\n <>\n \n \n
\n \n {modalTitle}\n \n \n {t('Modal subscription description_1')}\n \n \n {t('Modal subscription description_2')}\n \n \n \n
\n >\n );\n};\n\nexport const MentorRequestToAcademyWithoutSub = communicationPlayer.injector(MentorRequestToAcademyWithoutSubComponent);\n","import React from 'react';\nimport Button from 'antd/es/button';\nimport Row from 'antd/es/row';\nimport Typography from 'antd/es/typography';\nimport { useTranslation } from 'react-i18next';\nimport AcademyRequestSuccessImg from 'app/assets/icons/academy-request-success.svg';\n\ninterface IComponentProps {\n onClose: () => void;\n}\ntype AllProps = IComponentProps;\n\nconst MentorRequestToAcademySuccessComponent: React.FC = props => {\n const { onClose } = props;\n const { t } = useTranslation();\n const modalTitle = t('Modal success');\n\n return (\n <>\n \n \n
\n \n {modalTitle}\n \n \n {t('Modal success description')}\n \n \n \n {t('Continue')}\n \n
\n >\n );\n};\n\nexport const MentorRequestToAcademySuccess = MentorRequestToAcademySuccessComponent;\n","import React from 'react';\nimport Modal from 'antd/es/modal/Modal';\nimport { communicationUI, IUIConnectedProps } from 'entities/UI/UI.communication';\nimport { EMentorRequestToAcademyModalType } from 'entities/UI/UI.models';\nimport { MentorRequestToAcademyWithoutSub } from 'entities/AcademyRequest/components/Modal/MentorRequestToAcademyWithoutSub';\nimport { MentorRequestToAcademySuccess } from 'entities/AcademyRequest/components/Modal/MentorToAcademyRequestSuccess';\n\ntype AllProps = IUIConnectedProps;\n\nconst MentorRequestToAcademyModalComponent: React.FC = props => {\n const { UIMentorRequestToAcademyModal, closeUIMentorRequestToAcademyModal } = props;\n const isVisible = UIMentorRequestToAcademyModal.data?.isVisible;\n const modalType = UIMentorRequestToAcademyModal.data?.modalType;\n const isAddSubModal = modalType === EMentorRequestToAcademyModalType.AddSub;\n const isSuccessModal = modalType === EMentorRequestToAcademyModalType.Success;\n\n const closeModal = () => {\n closeUIMentorRequestToAcademyModal();\n };\n\n return (\n \n {isAddSubModal && }\n {isSuccessModal && }\n \n );\n};\n\nexport const MentorRequestToAcademyModal = communicationUI.injector(MentorRequestToAcademyModalComponent);\n","import React, { useEffect } from 'react';\nimport Button from 'antd/es/button';\nimport Card from 'antd/es/card';\nimport Col from 'antd/es/col';\nimport Row from 'antd/es/row';\nimport Skeleton from 'antd/es/skeleton';\nimport Typography from 'antd/es/typography';\nimport Spin from 'antd/es/spin';\nimport { useParams } from 'react-router';\nimport { useMediaPredicate } from 'react-media-hook';\nimport { Link } from 'react-router-dom';\nimport { useTranslation } from 'react-i18next';\nimport ArrowLeftOutlined from '@ant-design/icons/ArrowLeftOutlined';\nimport EnvironmentOutlined from '@ant-design/icons/EnvironmentOutlined';\nimport classNames from 'classnames';\nimport { locationFormatter } from 'common/helpers/location.helper';\nimport { ERoutesMentor } from 'common/models/routesModel';\nimport { MEDIA_DESKTOP, SCREEN_LG } from 'common/const/config.const';\nimport { ImagePrivate } from 'common/components/Image/ImagePrivate';\n// import { AgeGroupSelector } from 'common/components/Selector/AgeGroupSelector';\nimport { communicationAcademy, IAcademyConnectedProps } from 'entities/Academy/Academy.communication';\nimport { MentorRequestToAcademyModal } from 'entities/AcademyRequest/components/Modal/MentorToAcademyRequestModal';\nimport { communicationUI, IUIConnectedProps } from 'entities/UI/UI.communication';\nimport { EMentorRequestToAcademyModalType } from 'entities/UI/UI.models';\nimport { communicationPlayer, IPlayerConnectedProps } from 'entities/Player/Player.communication';\nimport { communicationAcademyRequest, IAcademyRequestConnectedProps } from 'entities/AcademyRequest/AcademyRequest.communication';\nimport { ESubscriptionStatus } from 'entities/Subscription/Subscription.models';\nimport { EAcademyStatus } from 'entities/Academy/Academy.models';\nimport { EAcademyRequestStatus } from 'entities/AcademyRequest/AcademyRequest.models';\nimport { communicationAuth, IAuthConnectedProps } from 'entities/Auth/Auth.communication';\nimport { EPlayerTabKeys } from 'entities/Player/Player.models';\n\nconst AVATAR_DESKTOP_SIZE = 144;\nconst AVATAR_MOBILE_SIZE = 112;\n\ntype AllProps = IAcademyConnectedProps &\n IUIConnectedProps &\n IPlayerConnectedProps &\n IAcademyRequestConnectedProps &\n IAuthConnectedProps;\n\nconst MentorAcademyPageComponent: React.FC = props => {\n const {\n getForPlayerAcademyModel,\n academyModel,\n clearAcademyModel,\n openUIMentorRequestToAcademyModal,\n playerModel,\n playerToAcademyRequestModel,\n updateAcademyRequestModel,\n // authUser,\n academyRequestModel\n } = props;\n const { academyId } = useParams();\n const isDesktop: boolean = useMediaPredicate(`(min-width: ${MEDIA_DESKTOP})`);\n const { t } = useTranslation();\n const { data: academyData, loading: academyLoading } = academyModel;\n const academyName = academyData?.name || t('Unknown name');\n const location = locationFormatter(academyData?.address) || t('Unknown address');\n const descriptionValue = academyData?.description || t('No description');\n const imageId = academyData?.image?.id;\n // const totalResultsCount = academyData?.totalResultsCount;\n const academyStatusActive = academyData?.status === EAcademyStatus.Active;\n const playerId = playerModel.data?.id;\n // const ageGroups = playerModel.data?.ageGroup;\n const playerToAcademyRequest = academyData?.playerToAcademyRequest;\n // const academyAgeGroups = academyData?.ageGroups;\n const isSubscriptionActive = playerModel.data?.mentorRequest?.subscription?.status === ESubscriptionStatus.Active;\n // const [ageGroupValue, setAgeGroupValue] = useState(ageGroups);\n // const [testList, setTestList] = useState(\n // academyData?.tests?.find(item => item.ageGroup === ageGroups)?.tests\n // );\n // const [passedResultCount, setPassedResultCount] = useState(\n // academyData?.tests?.find(item => item.ageGroup === ageGroups)?.passedResultCount\n // );\n\n const { loading } = academyRequestModel;\n // const { data: authUserData } = authUser;\n // const isMentorSubActive = permissionHelper(\n // EPermissionType.ShowDataForMentorSubActive,\n // authUserData,\n // playerModel?.data,\n // academyData\n // );\n // const showTestConfig = permissionHelper(\n // EPermissionType.ShowDataForMentorAcademyTestConfig,\n // authUserData,\n // playerModel?.data,\n // academyData\n // );\n\n useEffect(() => {\n if (!!playerId && !!academyId) {\n getForPlayerAcademyModel({ academyId, playerId });\n }\n return () => clearAcademyModel();\n }, [academyId, playerId]);\n\n // useEffect(() => {\n // const findAgeGroupTests = academyData?.tests?.find(item => item.ageGroup === ageGroupValue);\n // setTestList(findAgeGroupTests?.tests);\n // setPassedResultCount(findAgeGroupTests?.passedResultCount);\n // }, [ageGroupValue, academyData]);\n\n const onClickAcademyButton = () => {\n if (playerId && isSubscriptionActive) {\n playerToAcademyRequestModel({ player: playerId, academy: academyId });\n } else {\n openUIMentorRequestToAcademyModal({ modalType: EMentorRequestToAcademyModalType.AddSub });\n }\n };\n const cancelAcademyRequest = () => {\n if (playerToAcademyRequest) {\n const requestId = playerToAcademyRequest?.id;\n if (requestId) {\n updateAcademyRequestModel({ id: requestId, status: EAcademyRequestStatus.Aborted });\n }\n }\n };\n\n const isLg: boolean = useMediaPredicate(`(min-width: ${SCREEN_LG})`);\n\n // const getPassedPlayerTest = (academyBaseResultsArray: IAcademyBaseResultWithPlayerValue[]) => {\n // const academyTestsCount = academyBaseResultsArray?.length || 0;\n // const playersPassedTestsCount =\n // academyBaseResultsArray?.reduce((acc: number, item: IAcademyBaseResultWithPlayerValue) => {\n // if (item.isPassed) {\n // return acc + 1;\n // }\n // return acc;\n // }, 0) || 0;\n // return { academyTests: academyTestsCount, playerTestsResult: playersPassedTestsCount };\n // };\n\n // const isAcademyAcceptsThatAge = useMemo(() => ageGroupValue && academyAgeGroups?.includes(ageGroupValue), [ageGroupValue]);\n\n // const renderBaseResult = (academyBaseResultsArray: IAcademyBaseResultWithPlayerValue[]) =>\n // academyBaseResultsArray.map(item => {\n // const { playerValue, value, baseResult, id, isPassed } = item;\n //\n // const title = t(baseResult.tag);\n // const unit = notExistTranslationWrapper(baseResult.units);\n // const label = unit.length ? `${title}, ${unit}` : title;\n //\n // return (\n // \n // \n // \n // \n // {label}\n // \n // \n // \n // \n // \n // \n // {normalizeTestValue(baseResult.tag, playerValue)}\n // \n // \n // \n // \n // {showTestConfig ? `${t(`${baseResult.ranging}`)} ${normalize(value)}` : }\n // \n // \n //
\n // \n // \n // \n // {t('Result')}\n // \n // \n // \n // \n // {t('Requirement')}\n // \n // \n //
\n // \n //
\n // \n // );\n // });\n\n // const renderPanelItems = (baseResults: IPlayerTestBaseResult[]) =>\n // baseResults?.map(resultItem => {\n // const { id, video, academyBaseResults, firstImage, secondImage } = resultItem;\n // const videoId = video?.id;\n // const videoPreview = video?.image?.id;\n // const imagePreview = firstImage?.id || secondImage?.id;\n // const { academyTests, playerTestsResult } = getPassedPlayerTest(academyBaseResults);\n // const { title } = translateTestData(resultItem);\n //\n // return (\n // \n // \n // {title}\n // \n // \n // {playerTestsResult}/{academyTests}\n // \n // \n // }\n // key={id}\n // >\n // \n // {videoId ? (\n // \n // ) : (\n // \n // )}\n // \n // {renderBaseResult(academyBaseResults)}
\n // \n //
\n // \n // );\n // });\n\n return (\n \n \n }\n title={t('Back to academy list')}\n >\n {t('Back to academy list')}\n \n \n \n \n \n {imageId ? (\n \n ) : (\n \n \n
\n )}\n
\n \n \n {academyName}\n \n
\n \n \n \n {location}\n \n
\n \n \n \n {/* */}\n {/* */}\n {/* */}\n {/* */}\n {/* */}\n {/* */}\n {/* */}\n {/* */}\n {/* {t(`Points out of points`, {*/}\n {/* result: passedResultCount || 0,*/}\n {/* count: totalResultsCount || 0*/}\n {/* })}*/}\n {/* */}\n {/* */}\n {/*
*/}\n {/* */}\n {/*
*/}\n {/* */}\n \n {playerToAcademyRequest ? (\n \n {t('Cancel request')}\n \n ) : (\n \n {t('Want to academy')}\n \n )}\n \n
\n \n
\n \n {/* */}\n {/* */}\n {/* {isMentorSubActive ? (*/}\n {/* testList?.length ? (*/}\n {/* <>*/}\n {/* {!showTestConfig && (*/}\n {/* */}\n {/* */}\n {/* {t('Academy hid test requirements')}*/}\n {/* */}\n {/*
*/}\n {/* )}*/}\n {/* */}\n {/* {renderPanelItems(testList)}*/}\n {/* */}\n {/* >*/}\n {/* ) : isAcademyAcceptsThatAge ? (*/}\n {/* {t('Requirements list empty')} */}\n {/* ) : (*/}\n {/* */}\n {/* {t('The Academy does not accept children of this age category')}*/}\n {/* */}\n {/* )*/}\n {/* ) : (*/}\n {/* */}\n {/* )}*/}\n {/* */}\n {/* */}\n {descriptionValue} \n {/* */}\n {/* */}\n
\n \n \n \n \n );\n};\n\nexport const MentorAcademyPage = communicationAuth.injector(\n communicationAcademyRequest.injector(\n communicationPlayer.injector(communicationUI.injector(communicationAcademy.injector(MentorAcademyPageComponent)))\n )\n);\n","import i18n from 'i18next';\nimport Row from 'antd/es/row';\nimport React from 'react';\nimport moment from 'moment';\nimport { IBasePathParams } from 'common/models/requestModels';\nimport DefaultAvatar from 'app/assets/images/pp-avatar-empty.svg';\nimport { EResultTypes } from 'entities/PlayerTest/PlayerTest.models';\nimport { getImageUrl } from 'entities/Image/Image.helper';\nimport { EPlayerAgeGroup, IPlayerItemModel } from 'entities/Player/Player.models';\nimport { ITrainerModel } from 'entities/Trainer/Trainer.models';\nimport { ITeamModel } from 'entities/Team/Team.models';\nimport { IAcademySearchModel } from 'entities/Academy/Academy.models';\nimport { EUserRole, TUserRole } from 'entities/User/User.models';\nimport { EImageSize } from 'entities/Image/Image.models';\n\nexport interface ITestModel extends Components.Schemas.TestDto {}\nexport interface ITestPureModel extends Components.Schemas.PlayerToTestPureTestDto {}\nexport interface ITestCollection extends Components.Schemas.TestCollectionDto {}\n\nexport interface ITestCollectionFilter extends Paths.TestControllerList.QueryParameters {}\nexport interface ITestUpdateData extends Components.Schemas.UpdateTestDto, ITestUpdateParams {}\nexport interface ITestUpdateParams extends Paths.TestControllerUpdate.PathParameters {}\n\nexport interface ITestBaseResultModel extends Components.Schemas.BaseResultDto {}\n\nexport interface ITestResultsHistoryPlayerTestModel extends Components.Schemas.TestResultsHistoryPlayerTestDto {}\n// export interface ITestResultsHistoryTeamModel extends Components.Schemas.TestResultsHistoryTeamDto {}\n// export interface ITestResultsHistoryTrainerItemModel extends Components.Schemas.TestResultsHistoryTrainerDto {}\nexport interface ITestResultsHistoryPlayerTestResultModel extends Components.Schemas.TestResultsHistoryPlayerTestResultDto {}\n\nexport interface ITestResultsHistoryModel extends Components.Schemas.TestResultsHistoryItemDto {}\nexport interface ITestResultsHistoryCollection extends Components.Schemas.TestResultsHistoryDto {}\nexport interface ITestResultsHistoryCollectionFilter\n extends Paths.TestControllerGetTestResultsHistory.QueryParameters,\n Paths.TestControllerGetTestResultsHistory.PathParameters {\n testTag?: TTestTag;\n pageIndex?: number;\n tags?: string[];\n trainer?: Partial;\n team?: Partial;\n academy?: Partial;\n teamListFilter?: Partial;\n teamId?: string;\n fromPlayerAcademy?: boolean;\n playerAcademyId?: string;\n}\n\nexport interface ITestTeamHistoryModel extends Components.Schemas.TeamTestsHistoryItemDto {}\nexport interface ITestTeamHistoryCollection extends Components.Schemas.TeamTestsHistoryDto {}\nexport interface ITestTeamHistoryCollectionFilter\n extends Paths.TeamControllerGetTeamTestsHistory.QueryParameters,\n Paths.TeamControllerGetTeamTestsHistory.PathParameters {}\n\nexport type TTestResultHistoryOrderField = Paths.TestControllerGetTestResultsHistory.Parameters.OrderField;\n\n// todo check after JS-4569\nexport interface ITestResultItemModel {\n units?: EResultTypes;\n value: number | null;\n isBest: boolean;\n}\n\nexport type TTestParamsModel = ITestUpdateData | IBasePathParams;\n\nexport enum ETestStatus {\n New = 'new',\n AI = 'aIModeration',\n Moderation = 'moderation',\n Accept = 'accept',\n Reject = 'reject'\n}\n\nexport enum ETestRanging {\n SB = 'SB',\n LB = 'LB'\n}\nexport enum ETestListTabs {\n Trainers = 'Trainers',\n Players = 'Players'\n}\n\nexport enum ETestListTabKeys {\n JuniStat = 'junistat',\n RFSList = 'rfs'\n}\nexport enum ETestListTabKeysText {\n JuniStat = 'JuniStat',\n RFSList = 'RFS'\n}\n\ninterface IPlayerTestRejectReasonText {\n [key: number]: string;\n}\n\nexport const initTestResultFilter: Partial = {\n pageIndex: 1,\n id: undefined,\n testTag: undefined,\n academies: undefined,\n ageGroups: undefined,\n from: moment()\n .subtract(6, 'month')\n .startOf('day')\n .toISOString(),\n to: moment()\n .endOf('day')\n .toISOString(),\n hasTeam: undefined,\n hasTrainer: undefined,\n name: undefined,\n orderDirection: 'DESC',\n orderField: 'date',\n teams: undefined,\n trainers: undefined,\n tags: undefined,\n trainer: undefined,\n team: undefined,\n teamId: undefined,\n academy: undefined,\n teamListFilter: undefined,\n years: undefined,\n uploaderType: undefined,\n fromPlayerAcademy: true,\n onlyMy: undefined\n};\n\nexport const EPlayerTestRejectReasonText: IPlayerTestRejectReasonText = {\n 1: 'Bad video quality',\n 2: 'Poor video lighting',\n 3: 'Video is too long',\n 4: 'Inappropriate video content',\n 5: 'AI was unable to rate the video',\n 6: 'Exceeded number of execution errors',\n 7: 'AI not support test',\n 8: 'Error while downloading video',\n 9: 'Execution of the exercise is wrong',\n 10: 'The camera must be stationary',\n 11: 'The player must be fully framed throughout the video',\n 12: 'Video upload error',\n 13: 'Incorrect job execution',\n 14: 'Failed to find chips/cones on video',\n 15: 'Camera installed incorrectly'\n};\n\nexport enum EComplexity {\n Low = 'low',\n Medium = 'medium',\n Pro = 'pro'\n}\n\nexport enum ETestResultFilter {\n PlayerName = 'playerName',\n AgeGroup = 'ageGroup',\n BirthYear = 'birthYear',\n TestDateRange = 'testDateRange',\n Academy = 'academy',\n MyAcademy = 'myAcademy',\n ShowAll = 'showAll',\n Coach = 'coach',\n Team = 'team',\n UploaderType = 'uploaderType',\n Download = 'download'\n}\n\nexport enum ETestUploaderType {\n Self = 'player',\n AtTheAcademy = 'trainer'\n}\n\nexport enum ETestUploaderTypeText {\n Self = 'Self',\n AtTheAcademy = 'At the academy'\n}\n\nconst renderItem = (item: string) => {\n return {item}
;\n};\n\nexport const tableTestResultConfig = (isDesktopValue?: boolean, role?: TUserRole) => {\n const isAcademyWorker = role === EUserRole.AcademyWorker;\n return [\n {\n title: i18n.t('Player'),\n dataIndex: 'img',\n key: 'img',\n fixed: true,\n ellipsis: true,\n colSpan: isDesktopValue ? 2 : 1,\n width: 70,\n // eslint-disable-next-line react/no-multi-comp\n render: (image: string) => {\n const imgUrl = getImageUrl(image, EImageSize.X56) || DefaultAvatar;\n return {\n props: { style: { background: '#ffffff' } },\n children: \n };\n }\n },\n {\n title: isDesktopValue ? '' : i18n.t('First name'),\n dataIndex: 'player',\n key: 'player',\n colSpan: isDesktopValue ? 0 : 1,\n width: isDesktopValue === undefined ? 300 : isDesktopValue ? 300 : 150,\n fixed: isDesktopValue,\n ellipsis: true,\n // eslint-disable-next-line react/no-multi-comp\n render: (renderItemValue: IPlayerItemModel) => {\n const { firstName, lastName } = renderItemValue || {};\n const isName = firstName && lastName;\n const firstNameValue = isName ? firstName : i18n.t('Is hidden');\n const lastNameValue = isName ? lastName : i18n.t('Player');\n\n return {\n props: { style: { background: '#ffffff' } },\n children: (\n \n \n {lastNameValue} \n {firstNameValue} \n
\n
\n )\n };\n }\n },\n {\n title: {i18n.t('Year of birth')} ,\n dataIndex: 'birthday',\n key: 'birthday',\n ellipsis: true,\n width: 120,\n sorter: true,\n render: renderItem\n },\n {\n title: i18n.t('Age group'),\n dataIndex: 'ageGroup',\n key: 'ageGroup',\n ellipsis: true,\n width: 90,\n sorter: true,\n render: (ageGroup: EPlayerAgeGroup) => renderItem(i18n.t(ageGroup))\n },\n {\n title: {i18n.t('Test date')} ,\n dataIndex: 'date',\n key: 'date',\n ellipsis: true,\n width: 150,\n sorter: true,\n render: renderItem\n },\n isAcademyWorker\n ? {\n title: i18n.t('Trainer'),\n dataIndex: 'trainer',\n key: 'trainer',\n ellipsis: false,\n sorter: true,\n width: 200,\n render: renderItem\n }\n : undefined,\n isAcademyWorker\n ? {\n title: i18n.t('Team'),\n dataIndex: 'team',\n key: 'team',\n ellipsis: false,\n sorter: true,\n width: 200,\n render: renderItem\n }\n : undefined\n ];\n};\n\nexport type TTestTag =\n | 'run10m'\n | 'run15m'\n | 'arrow'\n | 'arrowWithBallRight'\n | 'arrowWithBallLeft'\n | 'snake'\n | 'run15mStart'\n | 'runningRight15m'\n | 'runningLeft15m'\n | 'jump1'\n | 'jump2'\n | 'pushUps'\n | 'ladderForwardBackward'\n | 'ladderLeftRight'\n | 'braking'\n | 'sota1'\n | 'sota2'\n | 'rightLegStop'\n | 'leftLegStop'\n | 'gate'\n | 'shortPass'\n | 'longRightPass'\n | 'longLeftPass'\n | 'rightLegKick'\n | 'leftLegKick'\n | 'monsterKickRF'\n | 'monsterKickLF'\n | 'juggles'\n | 'freestyle'\n | 'freeKickRF'\n | 'freeKickLF'\n | 'run5mRfs'\n | 'run10mRfs'\n | 'run15mRfs'\n | 'run20mRfs'\n | 'jumpLongRfs'\n | 'jumpUpRfs'\n | 'jumpTripleLongRfs'\n | 'run30mRfs'\n | 'shuttleRun3x10mRfs'\n | 'dribblingRight10mRfs'\n | 'dribblingLeft10mRfs'\n | 'dribblingRight3x10mRfs'\n | 'dribblingLeft3x10mRfs'\n | 'dribblingWithDirectionRight10mRfs'\n | 'dribblingWithDirectionLeft10mRfs'\n | 'accuracyHitRightRfs'\n | 'accuracyHitLeftRfs'\n | 'passingLeftRfs'\n | 'passingRightRfs'\n | 'jugglingHeadRfs'\n | 'feints1x1WithTasksRfs'\n | 'dribblingGame1x1LineRfs'\n | 'strike1x1In2GateRfs'\n | 'receivingAndPassingGame2x1Rfs'\n | 'positionAndOpeningGame2x1Rfs';\n\nexport type TSkillTag =\n | 't1'\n | 'n2'\n | 't3'\n | 'n4'\n | 't5'\n | 't6'\n | 'v7'\n | 't8'\n | 'd9'\n | 't10'\n | 'v11'\n | 'v12'\n | 't13'\n | 't14'\n | 't15'\n | 'n16'\n | 'h17'\n | 'h18'\n | 'h19'\n | 'n20'\n | 'h21'\n | 'h22'\n | 'h23'\n | 'n24'\n | 't25'\n | 'r26'\n | 'l27'\n | 't28'\n | 'r29'\n | 'l30'\n | 't31'\n | 't32'\n | 't33'\n | 'n34'\n | 't35'\n | 't36'\n | 't37'\n | 'n38'\n | 'x39'\n | 'tz39'\n | 'n40'\n | 'x41'\n | 'n42'\n | 'x43'\n | 'n44'\n | 'pr45'\n | 'tr46'\n | 'r47'\n | 'pl48'\n | 'tl49'\n | 'l50'\n | 'pr51'\n | 'mr52'\n | 'tr53'\n | 'pl54'\n | 'ml55'\n | 'tl56'\n | '1dr57'\n | '2dr57'\n | '3dr57'\n | '4dr57'\n | '5dr57'\n | '1dl58'\n | '2dl58'\n | '3dl58'\n | '4dl58'\n | '5dl58'\n | '1dg59'\n | '2dg59'\n | '3dg59'\n | '4dg59'\n | '5dg59'\n | '1dr60'\n | '2dr60'\n | '3dr60'\n | '4dr60'\n | '5dr60'\n | '1t61'\n | '2t61'\n | '3t61'\n | '4t61'\n | '5t61'\n | '1r62'\n | '2r62'\n | '3r62'\n | '4r62'\n | '5r62'\n | '1dg63'\n | '2dg63'\n | '3dg63'\n | '4dg63'\n | '5dg63'\n | '1dl64'\n | '2dl64'\n | '3dl64'\n | '4dl64'\n | '5dl64'\n | '1t65'\n | '2t65'\n | '3t65'\n | '4t65'\n | '5t65'\n | '1l66'\n | '2l66'\n | '3l66'\n | '4l66'\n | '5l66'\n | 'f67'\n | 'j68'\n | 'ir_l69'\n | 'pp1'\n | 'pp2'\n | 'pp3'\n | 'pp5'\n | 'pp9'\n | 'pp10'\n | 'pp11'\n | 'pp14'\n | 'pp15'\n | 'pp17'\n | 'pp17_avg'\n | 'pp18'\n | 'pp21'\n | 'pp21_avg'\n | 'pp23'\n | 'pp28'\n | 'pp32'\n | 'pp33'\n | 'pp37'\n | 'pp38'\n | 'pp45'\n | 'pp47'\n | 'pp49'\n | 'pp50'\n | 'pp51'\n | 'pp52'\n | 'pp53'\n | 'pp54'\n | 'pp55'\n | 'pp56'\n | 'pp57'\n | 'pp57_avg'\n | 'pp58'\n | 'pp58_avg'\n | 'pp59'\n | 'pp60'\n | 'pp60_avg'\n | 'pp62'\n | 'pp63'\n | 'pp64'\n | 'pp64_avg'\n | 'pp66'\n | 'pp70'\n | 'pp71'\n | 'pp72'\n | 'pp73'\n | 'pp74'\n | 'pp75'\n | 'pp76'\n | 'pp77'\n | 'pp78'\n | 'pp79';\n","import React, { useContext } from 'react';\nimport List from 'antd/es/list';\nimport Row from 'antd/es/row';\nimport Tag from 'antd/es/tag';\nimport Typography from 'antd/es/typography';\nimport { useTranslation } from 'react-i18next';\nimport { translateTestData } from 'common/helpers/test.helper';\nimport { ImagePrivate } from 'common/components/Image/ImagePrivate';\nimport { MeasurementContext } from 'common/components/Provider/MeasurementContext';\nimport { EComplexity, ETestStatus, ITestModel } from 'entities/Test/Test.models';\n\nexport enum ESubtitleTypes {\n ShortDescription = 'shortDescription',\n TryCount = 'tryCount'\n}\n\ninterface IComponentProps {\n item: ITestModel;\n onItemClick: (itemModel: ITestModel) => void;\n subtitle?: ESubtitleTypes;\n hideComplexity?: boolean;\n smallSize?: boolean;\n}\ntype AllProps = IComponentProps;\n\nconst getColorByComplexity = (complexity: string) => {\n switch (complexity) {\n case EComplexity.Low: {\n return 'success';\n }\n case EComplexity.Medium: {\n return 'warning';\n }\n case EComplexity.Pro: {\n return 'error';\n }\n default: {\n return undefined;\n }\n }\n};\n\nconst TestListItemComponent: React.FC = props => {\n const { item, onItemClick, subtitle = ESubtitleTypes.TryCount, hideComplexity, smallSize = false } = props;\n const { t } = useTranslation();\n const { tryCount, firstImage, lastStatus, id, complexity, icon } = item;\n const showAppraisal = lastStatus === ETestStatus.AI || lastStatus === ETestStatus.Moderation || lastStatus === ETestStatus.New;\n const { measurementSystem } = useContext(MeasurementContext);\n const { title, skills } = translateTestData(item, measurementSystem);\n const imgWidth = smallSize ? 50 : 80;\n const itemStyle = smallSize ? 'p-2 mb-2' : 'p-4 mb-3';\n\n return (\n onItemClick(item)}\n >\n \n \n \n
\n \n \n {title}\n
\n {showAppraisal && (\n \n {t('Appraisal')}\n \n )}\n {subtitle === ESubtitleTypes.ShortDescription ? (\n \n {skills}\n \n ) : (\n \n {t('Try')} {tryCount} {t('Count')}\n \n )}\n {!hideComplexity && complexity && (\n \n {t(complexity)}\n \n )}\n
\n
\n \n );\n};\n\nexport const TestListItem = TestListItemComponent;\n","import React from 'react';\nimport Typography from 'antd/es/typography';\nimport i18n from 'common/helpers/i18n';\nimport { InfiniteList } from 'common/components/InfiniteList';\nimport { IBaseFilterModel } from 'common/models/requestModels';\nimport { ITestCollection, ITestCollectionFilter, ITestModel } from 'entities/Test/Test.models';\nimport { communicationTest, ITestConnectedProps } from 'entities/Test/Test.communication';\nimport { ESubtitleTypes, TestListItem } from 'entities/Test/components/List/TestListItem';\n\ninterface IComponentProps {\n playerId?: string;\n onItemClick?: (itemModel: ITestModel) => void;\n subtitle?: ESubtitleTypes;\n hideComplexity?: boolean;\n}\n\ntype AllProps = IComponentProps & ITestConnectedProps;\n\nclass TestListComponent extends InfiniteList {\n loadCollection = (params: IBaseFilterModel) => {\n const { getTestCollection, playerId, filter } = this.props;\n const body: ITestCollectionFilter = {\n ...params\n };\n\n if (playerId) {\n body.player = playerId;\n }\n if (filter?.isVisibleForTrainer) {\n body.isVisibleForTrainer = filter?.isVisibleForTrainer;\n body.isVisibleForRfs = false;\n body.isVisibleForPlayer = false;\n }\n if (filter?.isVisibleForPlayer) {\n body.isVisibleForPlayer = filter?.isVisibleForPlayer;\n body.isVisibleForTrainer = false;\n body.isVisibleForRfs = false;\n }\n if (filter?.isVisibleForRfs) {\n body.isVisibleForRfs = filter?.isVisibleForRfs;\n body.isVisibleForTrainer = true;\n body.isVisibleForPlayer = false;\n }\n\n return getTestCollection(body);\n };\n\n renderNoData = () => {\n return {i18n.t('Test list is empty')} ;\n };\n\n renderListItem = (item: ITestModel) => {\n const { onItemClick = () => null, subtitle, hideComplexity } = this.props;\n return ;\n };\n\n getCollection = () => {\n return this.props.testCollection;\n };\n\n clearCollection = () => {\n return this.props.clearTestCollection();\n };\n}\n\nexport const TestList = communicationTest.injector(TestListComponent);\n","import React from 'react';\nimport { store } from 'common/helpers/axios.helper';\nimport { isCurrentUserMentorForSomeoneElse } from 'common/helpers/player.helper';\nimport { EPermissionType, permissionHelper } from 'common/helpers/permission.helper';\nimport { communicationPlayer, IPlayerConnectedProps } from 'entities/Player/Player.communication';\nimport { communicationAuth, IAuthConnectedProps } from 'entities/Auth/Auth.communication';\nimport { EUserRole, IUserModel } from 'entities/User/User.models';\n\ntype TShowForFunction = (user: IUserModel) => boolean;\n\ntype TRole = EUserRole | EUserRole[] | TShowForFunction | EPermissionType;\n\ninterface IComponentProps {\n availableFor: TRole;\n alternative?: React.ReactElement;\n}\n\ntype AllProps = IAuthConnectedProps & IPlayerConnectedProps & IComponentProps;\n\nconst isAvailableForUser = (showFor: TRole, user: IUserModel | null) => {\n const { role } = user ?? {};\n\n if (!role) {\n return false;\n }\n\n switch (true) {\n case Array.isArray(showFor): {\n return (showFor as EUserRole[]).includes(role as EUserRole);\n }\n case typeof showFor === 'function': {\n return (showFor as TShowForFunction)(user as IUserModel);\n }\n case typeof showFor === 'string': {\n return showFor === role;\n }\n default: {\n return false;\n }\n }\n};\n\nconst PrivateContentComponent: React.FC = props => {\n const { availableFor, children, authUser, alternative, playerModel } = props;\n const { data } = authUser;\n const { data: playerData } = playerModel;\n const showDataForPlayerMentor = permissionHelper(EPermissionType.ShowDataForMentor, data, playerData);\n const showDataForAcademy = permissionHelper(EPermissionType.ShowDataForAcademy, data, playerData);\n const showDataForPlayerAcademy = permissionHelper(EPermissionType.ShowDataForPlayerAcademy, data, playerData);\n\n const isAvailable = React.useMemo(() => {\n return isAvailableForUser(availableFor, data);\n }, [availableFor, data]);\n\n if (availableFor === EPermissionType.ShowDataForMentor && showDataForPlayerMentor) {\n return children as React.ReactElement;\n }\n if (availableFor === EPermissionType.ShowDataForAcademy && showDataForAcademy) {\n return children as React.ReactElement;\n }\n if (availableFor === EPermissionType.ShowDataForPlayerAcademy && showDataForPlayerAcademy) {\n return children as React.ReactElement;\n }\n\n if (isAvailable) {\n return children as React.ReactElement;\n } else if (alternative) {\n return alternative;\n }\n\n return null;\n};\n\nexport const isAvailable = (role: TRole) => {\n const state = store.getState();\n const user = state.auth?.user?.data;\n return isAvailableForUser(role, user);\n};\n\nexport const isAvailableForPlayer = (role: EUserRole[]) => {\n const available = isAvailable(role);\n if (role.includes(EUserRole.Mentor)) {\n return available && !isCurrentUserMentorForSomeoneElse();\n }\n return available;\n};\n\nexport const PrivateContent = communicationPlayer.injector(communicationAuth.injector(PrivateContentComponent));\n","import { options } from 'options';\nimport message from 'antd/es/message';\nimport { getCreds, ICreds } from 'axios-patch-jwt';\nimport { RcFile } from 'antd/es/upload';\nimport moment from 'moment';\nimport Logger from 'common/helpers/logger';\nimport i18n from 'common/helpers/i18n';\nimport { videoApiRoute } from 'common/models/routesModel';\nimport { maxVideoTitleLength, maxVideoDescriptionLength } from 'entities/Video/Video.models';\n\nconst maxVideoDuration = 180; // seconds\n\nexport function getBase64(img: Blob, callback: { (): void; (arg0: string | ArrayBuffer | null): any }) {\n const reader = new FileReader();\n reader.addEventListener('load', () => callback(reader.result));\n reader.readAsDataURL(img);\n}\n\nexport async function downloadFile(linkUrl: string, token?: string) {\n const response = await fetch(\n linkUrl,\n token\n ? {\n headers: {\n Authorization: `Bearer ${token}`\n }\n }\n : undefined\n );\n\n if (response.status === 200) {\n const blob = await response.blob();\n const downloadUrl = window.URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = downloadUrl;\n document.body.appendChild(link);\n link.click();\n link.remove();\n }\n}\n\nexport function checkImage(file: { type: string; size: number }) {\n const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';\n if (!isJpgOrPng) {\n message.error(i18n.t('web-image-loader:Only JPG/PNG'));\n }\n const isLt2M = file.size / 1024 / 1024 < 15;\n if (!isLt2M) {\n message.error(i18n.t('web-image-loader:Size should be less than 15MB'));\n }\n return isJpgOrPng && isLt2M;\n}\n\nexport const getVideoLink = async (videoId: string, isPublic?: boolean): Promise => {\n const creds: ICreds = await getCreds();\n const token = creds?.access?.token || '';\n\n return `${videoApiRoute(videoId, isPublic)}${isPublic ? '' : `&token=${token}`}`;\n};\n\nexport const checkVideoDuration = async (source: RcFile, duration: number = maxVideoDuration): Promise =>\n new Promise(resolve => {\n window.URL = window.URL || window.webkitURL;\n\n const video = document.createElement('video');\n video.preload = 'metadata';\n\n video.onloadedmetadata = () => {\n window.URL.revokeObjectURL(video.src);\n const videoDuration = video.duration;\n const isVideoOk = videoDuration <= duration;\n if (!isVideoOk) {\n message.error(i18n.t('Video duration should be less than 3 minutes'));\n }\n resolve(isVideoOk);\n };\n\n video.onerror = (event: Event | string, sourceData?: string, lineno?: number, colno?: number, error?: Error) => {\n message.error(i18n.t('This format not accepted, try mp4'));\n console.error('An error occurred while processing video. Error: ', video?.error);\n Logger.err(\n ['VIDEOERROR', 'ONERROR'],\n `Video: ${JSON.stringify(video)} / Event: ${JSON.stringify(event)} / Source: ${JSON.stringify(\n sourceData\n )} / Lineno: ${JSON.stringify(lineno)} / Colno: ${JSON.stringify(colno)}`,\n JSON.stringify(error)\n );\n\n resolve(false);\n };\n\n video.src = URL.createObjectURL(source);\n });\n\nexport const checkVideo = async (file: RcFile) => {\n const { type, size } = file;\n const isVideo = type.search('video/') > -1;\n if (!isVideo) {\n message.error(i18n.t('Only video files'));\n }\n const isLt100M = size / 1024 / 1024 < 100;\n if (!isLt100M) {\n message.error(i18n.t('Size should be less than 100MB'));\n }\n\n return isVideo && isLt100M;\n};\n\nconst getYouTubeId = (url: string): string => {\n const arr = url.split(/(vi\\/|v%3D|v=|\\/v\\/|youtu\\.be\\/|\\/embed\\/)/);\n return arr[2] !== undefined ? arr[2].split(/[^\\w-]/i)[0] : arr[0];\n};\n\ninterface IGetYoutubeDataValue {\n title: string;\n description: string;\n youtubeId: string;\n preview: string;\n}\n\nexport const getYouTubeData = (url: string): Promise => {\n const youtubeId = getYouTubeId(url);\n return fetch(\n `https://www.googleapis.com/youtube/v3/videos?id=${youtubeId}&key=${options.googleApiKey}&part=snippet,contentDetails`\n )\n .then(res => res.json())\n .then((res = {}) => {\n const { items } = res;\n\n if (items && items.length) {\n const [videoDetails] = items;\n const duration = videoDetails?.contentDetails?.duration;\n const title = videoDetails?.snippet?.title || '';\n const description = videoDetails?.snippet?.description || '';\n const preview = videoDetails?.snippet?.thumbnails?.medium?.url || '';\n\n if (duration) {\n const durationInSeconds = moment.duration(duration).asSeconds();\n\n if (durationInSeconds > maxVideoDuration) {\n message.error(i18n.t('Video duration should be less than 3 minutes'));\n return false;\n }\n\n return {\n description: description.replace(/↵/g, '\\n').substr(0, maxVideoDescriptionLength),\n title: title.substr(0, maxVideoTitleLength),\n youtubeId,\n preview\n };\n }\n }\n message.error(i18n.t('Error while getting video information'));\n return false;\n })\n .catch(err => {\n console.error('Error while getting youtube video Info: ', err);\n message.error(i18n.t('Error while getting video information'));\n return false;\n });\n};\n","import React, { useEffect, useState, useRef, useCallback } from 'react';\nimport { Player, ControlBar } from 'video-react';\nimport { useTranslation } from 'react-i18next';\nimport YouTubePlayer from 'react-youtube';\nimport Skeleton from 'antd/es/skeleton';\nimport message from 'antd/es/message';\nimport { getVideoLink } from 'common/helpers/loader.helper';\n\ninterface IModalProps {\n videoId?: string | null;\n youtubeId?: string | null;\n isPublic?: boolean;\n}\n\ntype AllProps = IModalProps;\n\nenum EAutoPLay {\n 'Yes' = 1\n}\n\nconst playerOptions = {\n width: '100%',\n playerVars: {\n autoplay: EAutoPLay.Yes // Хак, на просто цифру ругается ts\n }\n};\n\nexport const VideoPrivateModalBody: React.FC = props => {\n const { videoId, youtubeId, isPublic } = props;\n const { t } = useTranslation();\n const [videoUrl, setVideoUrl] = useState('');\n const [useFallbackImg, setUseFallbackImg] = useState(false);\n const videoPlayerRef = useRef(null);\n\n const enableFallback = useCallback(() => {\n setUseFallbackImg(true);\n }, []);\n\n const onVideoPlayerStateChange = useCallback(state => {\n const { error } = state;\n if (error) {\n console.error('Error while playing video', error);\n message.error(t('An error occurred during playing video'));\n enableFallback();\n }\n }, []);\n\n useEffect(() => {\n if (videoId && !youtubeId) {\n const videoPlayer = videoPlayerRef.current;\n if (videoPlayer) {\n // @ts-ignore\n videoPlayer.subscribeToStateChange(onVideoPlayerStateChange);\n }\n }\n }, []);\n\n useEffect(() => {\n const getVideoUrl = async (id: string) => {\n const data = await getVideoLink(id, isPublic);\n setVideoUrl(data);\n };\n\n if (videoId && !youtubeId) {\n getVideoUrl(videoId);\n }\n }, [videoId]);\n\n return (\n \n {youtubeId ? (\n
\n ) : useFallbackImg ? (\n
\n ) : (\n
\n \n \n \n )}\n
\n );\n};\n","export interface IVideoModel extends Components.Schemas.VideoDto {}\nexport interface IVideoUploadModel extends Components.Schemas.VideoUploadDto {}\n\nexport const maxVideoTitleLength = 37;\nexport const maxVideoDescriptionLength = 140;\n","import React from 'react';\nimport Modal from 'antd/es/modal';\nimport { VideoPrivateModalBody } from 'common/components/Video/VideoPrivateModalBody';\n\ninterface IModalProps {\n visible: boolean;\n isPublic?: boolean;\n onCancel: () => void;\n videoId?: string | null;\n youtubeId?: string | null;\n}\n\ntype AllProps = IModalProps;\n\nexport const VideoPrivateModal: React.FC = props => {\n const { visible, onCancel, ...rest } = props;\n\n return (\n \n \n \n );\n};\n","import React, { useEffect, useState, useCallback, useMemo } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport Skeleton from 'antd/es/skeleton';\nimport { VideoPrivateModal } from 'common/components/Video/VideoPrivateModal';\nimport { getImageSize, getImageUrl } from 'entities/Image/Image.helper';\n\ninterface IComponentProps {\n width?: number | string;\n height: number | string;\n videoId?: string | null;\n youtubeId?: string | null;\n className?: string;\n previewClass?: string;\n preview?: string | null;\n youtubePreviewUrl?: string | null;\n isPublic?: boolean;\n}\ntype AllProps = IComponentProps;\n\nconst VideoPrivateComponent: React.FC = props => {\n const { width, height, videoId, className = '', preview = '', youtubeId, previewClass = '', isPublic } = props;\n const { t } = useTranslation();\n const [modalVisible, setModalVisible] = useState(false);\n const [previewUrl, setPreviewUrl] = useState(undefined);\n const [useFallbackImg, setUseFallbackImg] = useState(false);\n\n useEffect(() => {\n if (preview) {\n if (youtubeId) {\n setPreviewUrl(preview);\n } else {\n setPreviewUrl(getImageUrl(preview, getImageSize(Number(height), Number(width))));\n }\n }\n }, [previewUrl]);\n\n const previewStyle = useMemo(\n () => ({\n width: width ?? '100%',\n minWidth: width ?? '100%',\n maxWidth: width ?? '100%',\n height,\n minHeight: height,\n maxHeight: height\n }),\n [width, height]\n );\n\n const onImageLoadError = useCallback(() => {\n setUseFallbackImg(false);\n }, []);\n\n const openModal = useCallback(() => {\n setModalVisible(true);\n }, []);\n\n const closeModal = useCallback(() => {\n setModalVisible(false);\n }, []);\n\n return (\n \n
\n {useFallbackImg || !preview ? (\n
\n ) : (\n
\n )}\n
\n
\n
\n
\n );\n};\n\nexport const VideoPrivate = VideoPrivateComponent;\n","import React, { useCallback, useContext, useRef } from 'react';\nimport Button from 'antd/es/button';\nimport Carousel from 'antd/es/carousel';\nimport Row from 'antd/es/row';\nimport Typography from 'antd/es/typography';\nimport { CarouselRef } from 'antd/es/carousel';\nimport CaretLeftOutlined from '@ant-design/icons/CaretLeftOutlined';\nimport CaretRightOutlined from '@ant-design/icons/CaretRightOutlined';\nimport { useMediaPredicate } from 'react-media-hook';\nimport { translateTestData } from 'common/helpers/test.helper';\nimport { ImagePrivate } from 'common/components/Image/ImagePrivate';\nimport { VideoPrivate } from 'common/components/Video/VideoPrivate';\nimport { MEDIA_DESKTOP } from 'common/const/config.const';\nimport { MeasurementContext } from 'common/components/Provider/MeasurementContext';\nimport { ITestModel } from 'entities/Test/Test.models';\n\nconst sizeHeight = 320;\n\ninterface IComponent {\n item: ITestModel;\n}\n\nconst TestModalDescriptionComponent: React.FC = props => {\n const { item } = props;\n const carouselRef = useRef(null);\n const isDesktop: boolean = useMediaPredicate(`(min-width: ${MEDIA_DESKTOP})`);\n const { firstImage, secondImage, video } = item;\n const { measurementSystem } = useContext(MeasurementContext);\n const { description } = translateTestData(item, measurementSystem);\n\n const carouselNext = useCallback(() => {\n carouselRef?.current?.next();\n }, []);\n\n const carouselPrev = useCallback(() => {\n carouselRef?.current?.prev();\n }, []);\n\n return (\n <>\n \n {firstImage?.id && (\n \n )}\n {secondImage?.id && (\n \n )}\n {video?.id && }\n \n {isDesktop && (secondImage?.id || video?.id) && (\n \n \n \n \n \n \n \n
\n )}\n \n {description}\n \n >\n );\n};\n\nexport const TestModalDescription = TestModalDescriptionComponent;\n","import React, { Suspense } from 'react';\nimport Spin from 'antd/es/spin';\nimport Row from 'antd/es/row';\nimport Typography from 'antd/es/typography';\nimport { useTranslation } from 'react-i18next';\nimport ScrollContainer from 'react-indiana-drag-scroll';\nimport { ILineDataset } from 'common/models/lineChartModel';\nimport { communicationPlayer, IPlayerConnectedProps } from 'entities/Player/Player.communication';\nimport { IPlayerTestResultModel } from 'entities/PlayerTest/PlayerTest.models';\nimport { isAvailable } from 'entities/Auth/components/PrivateContent';\nimport { EUserRole } from 'entities/User/User.models';\n\nconst LineChart = React.lazy(() => import('common/components/LineChart/LineChart'));\n\ninterface IProps {\n playerId: string;\n testId: string;\n}\n\ninterface IDatasets {\n [key: string]: ReadonlyArray;\n}\n\ntype AllProps = IProps & IPlayerConnectedProps;\n\nconst PlayerTestResultsComponent: React.FC = props => {\n const { playerId, testId, getPlayerTestHistory, playerTestHistory } = props;\n const containerRef = React.useRef(null);\n const { t } = useTranslation();\n const { data, loading } = playerTestHistory;\n\n React.useEffect(() => {\n getPlayerTestHistory({\n playerId,\n testId,\n onlyBestOfDay: true\n });\n }, [playerId, testId]);\n\n const datasets = React.useMemo(() => {\n if (!data?.data) {\n return {};\n }\n\n return data.data.reduce((reducer: IDatasets, item: IPlayerTestResultModel) => {\n const { baseResult, createdAt, value, updatedAt } = item;\n const { tag } = baseResult;\n const tagValue = { date: createdAt, updateDate: updatedAt, value };\n\n if (reducer[tag]) {\n return {\n ...reducer,\n [tag]: [...reducer[tag], tagValue]\n };\n } else {\n return {\n ...reducer,\n [tag]: [tagValue]\n };\n }\n }, {});\n }, [data]);\n\n const refChartsCollection = React.useMemo(() => {\n return Object.keys(datasets)?.map(() => React.createRef());\n }, [datasets]);\n\n const onChartScroll = React.useCallback(\n index => (y: number) => {\n refChartsCollection.forEach((ref, refIndex) => {\n if (index !== refIndex && ref?.current?.scrollLeft !== undefined) {\n ref.current.scrollLeft = y;\n }\n });\n },\n [refChartsCollection]\n );\n\n if (loading) {\n return (\n \n \n
\n );\n }\n\n if (!loading && Object.keys(datasets).length === 0) {\n return (\n \n {isAvailable(EUserRole.AcademyWorker) ? (\n \n {t('The player has no grades for this test')}\n \n ) : (\n \n {t('Take tests to get grades')}\n \n )}\n
\n );\n }\n\n return (\n \n }>\n {Object.keys(datasets).map((tag, index) => (\n \n {t(`${tag}`)} \n \n
\n ))}\n \n \n );\n};\n\nexport const PlayerTestResults = communicationPlayer.injector(PlayerTestResultsComponent);\n","export const valueToPercent = (\n valueRaw: number | null | undefined,\n minValueRaw: number = 0,\n maxValueRaw: number = 0,\n ranging: 'SB' | 'LB' | undefined\n) => {\n const isSB = ranging === 'SB';\n if (valueRaw === null || valueRaw === undefined) {\n return null;\n }\n if (maxValueRaw - minValueRaw === 0) {\n return 100;\n }\n let value = valueRaw;\n let min = minValueRaw;\n let max = maxValueRaw;\n\n if (isSB) {\n min = maxValueRaw;\n max = minValueRaw;\n }\n\n if (value < minValueRaw) {\n value = minValueRaw;\n }\n if (value > maxValueRaw) {\n value = maxValueRaw;\n }\n\n const delta = ((max - min) / 100) * 10;\n min = min - delta;\n\n if (max >= min) {\n return (100 / (max - min)) * (value - min);\n } else {\n return 100 - (100 / (min - max)) * (value - max);\n }\n};\n","import { Tooltip } from 'antd';\nimport React, { useContext, useMemo } from 'react';\nimport Col from 'antd/es/col';\nimport Row from 'antd/es/row';\nimport Slider from 'antd/es/slider';\nimport { useTranslation } from 'react-i18next';\nimport Typography from 'antd/es/typography';\nimport { useMediaPredicate } from 'react-media-hook';\nimport { valueToPercent } from 'common/helpers/number.helper';\nimport { notExistTranslationWrapper } from 'common/helpers/translate.helper';\nimport { normalizeTestValue } from 'common/helpers/normalize.helper';\nimport { MEDIA_DESKTOP } from 'common/const/config.const';\nimport { MeasurementContext } from 'common/components/Provider/MeasurementContext';\nimport { EResultTypes } from 'entities/PlayerTest/PlayerTest.models';\nimport { IPlayerProfileMicroSkillModel } from 'entities/Player/Player.models';\n\ninterface IProps {\n result: Partial;\n isWrap?: boolean;\n}\n\nexport const PlayerTestResultAverage: React.FC = props => {\n const { result, isWrap } = props;\n const { t } = useTranslation();\n const isDesktop: boolean = useMediaPredicate(`(min-width: ${MEDIA_DESKTOP})`);\n const { tag, value, avgValue, maxValue, minValue, ranging, valuePercent, units } = result;\n const { measurementSystem } = useContext(MeasurementContext);\n const normalizedValue = normalizeTestValue(tag, value, units as EResultTypes, measurementSystem);\n const bestValue = ranging === 'LB' ? maxValue : minValue;\n const normalizedBestValue = normalizeTestValue(tag, bestValue, units as EResultTypes, measurementSystem);\n const resultTitle = notExistTranslationWrapper(tag, {}, measurementSystem);\n const valueOut = valuePercent || useMemo(() => valueToPercent(value, Number(minValue), Number(maxValue), ranging), []);\n const avgPercent = useMemo(() => valueToPercent(avgValue, Number(minValue), Number(maxValue), ranging), []);\n const hideAvg = avgValue === maxValue || avgPercent === minValue;\n const hideBar = units === EResultTypes.Bool;\n\n return isDesktop ? (\n \n \n \n \n \n {resultTitle}\n \n \n \n \n {normalizedValue} {notExistTranslationWrapper(result?.units, { count: normalizedValue - 0 }, measurementSystem)}\n \n \n
\n \n \n \n {!hideBar ? (\n \n {t('Average')} }\n }\n />\n \n ) : null}\n \n \n {normalizedBestValue}{' '}\n {notExistTranslationWrapper(result?.units, { count: normalizedBestValue - 0 }, measurementSystem)}\n \n \n
\n \n
\n ) : (\n \n \n \n \n \n \n {resultTitle}\n \n {t('Benchmark')} \n
\n \n \n \n \n {normalizedValue} {notExistTranslationWrapper(result?.units, { count: normalizedValue - 0 }, measurementSystem)}\n \n \n {normalizedBestValue}{' '}\n {notExistTranslationWrapper(result?.units, { count: normalizedBestValue - 0 }, measurementSystem)}\n \n
\n \n
\n \n {!hideBar ? (\n \n {t('Average')} }\n }\n />\n \n ) : null}\n
\n );\n};\n","import React from 'react';\nimport Col from 'antd/es/col';\nimport Collapse from 'antd/es/collapse';\nimport List from 'antd/es/list';\nimport Typography from 'antd/es/typography';\nimport Row from 'antd/es/row';\nimport { useTranslation } from 'react-i18next';\nimport { dateFormatter } from 'common/helpers/date.helper';\nimport { VideoPrivate } from 'common/components/Video/VideoPrivate';\nimport { PlayerTestResultAverage } from 'entities/PlayerTest/components/PlayerTestResultAverage';\nimport { EPlayerTestRejectReasonText, ETestStatus } from 'entities/Test/Test.models';\nimport { IPlayerTestModel, IPlayerTestResultPureModel } from 'entities/PlayerTest/PlayerTest.models';\n\ninterface IComponentProps {\n item: IPlayerTestModel;\n}\ntype AllProps = IComponentProps;\n\nconst TestModalEvaluationItemComponent: React.FC = props => {\n const { t } = useTranslation();\n const { item } = props;\n\n const testStatus = (\n status: ETestStatus,\n testResults?: IPlayerTestResultPureModel[],\n rejectCode?: number | null,\n rejectDetails?: string | null\n ) => {\n switch (status) {\n case ETestStatus.New:\n case ETestStatus.AI:\n case ETestStatus.Moderation:\n return {t('Waiting for evaluation')} ;\n\n case ETestStatus.Accept: {\n return testResults?.length ? (\n \n {testResults.map((testItem, index) => {\n return (\n \n \n \n );\n })}\n
\n ) : (\n {t('Test passed')} \n );\n }\n\n case ETestStatus.Reject:\n return (\n <>\n {t('Failed to evaluate test')} \n {rejectCode && (\n {t(`${EPlayerTestRejectReasonText[rejectCode]}`)} \n )}\n \n {rejectDetails && {rejectDetails} }\n >\n );\n default:\n return;\n }\n };\n\n const { id, createdAt, video, testResults, rejectCode, status, rejectDetails } = item;\n const videoId = video?.id;\n\n return (\n \n \n \n \n {!!videoId && (\n \n \n \n )}\n {testStatus(status as ETestStatus, testResults, rejectCode, rejectDetails)}\n
\n \n \n \n );\n};\n\nexport const TestModalEvaluationItem = TestModalEvaluationItemComponent;\n","import React from 'react';\nimport i18n from 'i18next';\nimport Typography from 'antd/es/typography';\nimport { InfiniteList } from 'common/components/InfiniteList';\nimport { IBaseFilterModel } from 'common/models/requestModels';\nimport { IPlayerTestCollection, IPlayerTestModel, IPlayerTestCollectionFilter } from 'entities/PlayerTest/PlayerTest.models';\nimport { TestModalEvaluationItem } from 'entities/Test/components/List/TestModalEvaluationItem';\nimport { communicationPlayerTest, IPlayerTestConnectedProps } from 'entities/PlayerTest/PlayerTest.communication';\n\ninterface IComponentProps {\n testId?: string;\n playerId?: string;\n}\n\ntype AllProps = IComponentProps & IPlayerTestConnectedProps;\n\nclass TestModalEvaluationListComponent extends InfiniteList<\n IPlayerTestCollection,\n IPlayerTestModel,\n AllProps,\n IPlayerTestCollectionFilter\n> {\n loadCollection = (params: IBaseFilterModel) => {\n const { getPlayerTestCollection, playerId, testId } = this.props;\n const body: IPlayerTestCollectionFilter = {\n ...params\n };\n\n if (playerId) {\n body.player = playerId;\n }\n\n if (testId) {\n body.test = testId;\n }\n\n return getPlayerTestCollection(body);\n };\n\n renderNoData = () => {\n return {i18n.t('The player has no grades for this test')} ;\n };\n\n renderListItem = (item: IPlayerTestModel) => {\n return ;\n };\n\n getCollection = () => {\n return this.props.playerTestCollection;\n };\n\n clearCollection = () => {\n return this.props.clearPlayerTestCollection();\n };\n}\n\nexport const TestModalEvaluationList = communicationPlayerTest.injector(TestModalEvaluationListComponent);\n","import React, { useContext } from 'react';\nimport Modal from 'antd/es/modal';\nimport Tabs from 'antd/es/tabs';\nimport Typography from 'antd/es/typography';\nimport { useTranslation } from 'react-i18next';\nimport { useMediaPredicate } from 'react-media-hook';\nimport { translateTestData } from 'common/helpers/test.helper';\nimport { MEDIA_DESKTOP } from 'common/const/config.const';\nimport { MeasurementContext } from 'common/components/Provider/MeasurementContext';\nimport { ITestModel } from 'entities/Test/Test.models';\nimport { communicationPlayerTest, IPlayerTestConnectedProps } from 'entities/PlayerTest/PlayerTest.communication';\nimport { communicationPlayer, IPlayerConnectedProps } from 'entities/Player/Player.communication';\nimport { isAvailable } from 'entities/Auth/components/PrivateContent';\nimport { EUserRole } from 'entities/User/User.models';\nimport { TestModalDescription } from 'entities/Test/components/Modal/TestModalDescription';\nimport { PlayerTestResults } from 'entities/PlayerTest/components/PlayerTestResults';\nimport { TestModalEvaluationList } from 'entities/Test/components/List/TestModalEvaluationList';\n\ninterface IComponentProps {\n item: ITestModel;\n visible: boolean;\n onCancel: () => void;\n playerId?: string;\n testId?: string;\n}\n\ntype AllProps = IComponentProps & IPlayerTestConnectedProps & IPlayerConnectedProps;\n\nconst TestModalComponent: React.FC = props => {\n const { item, visible, onCancel, playerId, testId, playerTestCollection } = props;\n const { t } = useTranslation();\n const isDesktop: boolean = useMediaPredicate(`(min-width: ${MEDIA_DESKTOP})`);\n const { id: testItemId } = item;\n const { data } = playerTestCollection;\n const resultsArray = data?.data ?? [];\n const { measurementSystem } = useContext(MeasurementContext);\n const { title, skills } = translateTestData(item, measurementSystem);\n\n return (\n \n \n {title}\n \n {skills && (\n \n {skills}\n \n )}\n >\n }\n >\n \n {isAvailable(EUserRole.AcademyWorker) ? (\n <>\n \n \n \n
\n \n \n \n \n \n \n \n >\n ) : (\n <>\n \n \n \n \n \n \n
\n \n >\n )}\n \n \n );\n};\n\nexport const TestModal = communicationPlayerTest.injector(communicationPlayer.injector(TestModalComponent));\n","function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\nimport React from \"react\";\n\nvar _ref2 = /*#__PURE__*/React.createElement(\"g\", {\n clipPath: \"url(#clip0_2877_24292)\"\n}, /*#__PURE__*/React.createElement(\"path\", {\n d: \"M18.1276 0.824087C17.9292 0.831082 17.737 0.898868 17.5736 1.0194L11.961 5.02764L10.1108 6.28307L8.29692 6.38833H1.5562C1.41878 6.38624 1.28235 6.41344 1.15482 6.46834C1.0273 6.52325 0.911236 6.60476 0.813368 6.70814C0.715504 6.81153 0.637793 6.93472 0.584751 7.07056C0.531709 7.2064 0.504394 7.35219 0.504395 7.49944C0.504395 7.64669 0.531709 7.79247 0.584751 7.92831C0.637793 8.06415 0.715504 8.18734 0.813368 8.29073C0.911236 8.39409 1.0273 8.47559 1.15482 8.5305C1.28235 8.58542 1.41878 8.61267 1.5562 8.61059H1.62203L8.29692 9.26917V14.4439V14.9702V23.055C8.29498 23.2023 8.32041 23.3484 8.37167 23.485C8.42284 23.6217 8.49899 23.746 8.59543 23.8509C8.69195 23.9558 8.80691 24.039 8.93369 24.0958C9.06047 24.1527 9.19658 24.1819 9.33401 24.1819C9.47144 24.1819 9.60748 24.1527 9.73426 24.0958C9.86103 24.039 9.97599 23.9558 10.0725 23.8509C10.169 23.746 10.2451 23.6217 10.2964 23.485C10.3476 23.3484 10.373 23.2023 10.371 23.055V22.4192L10.9118 15.2762L19.8836 13.5943C20.1426 13.5496 20.3761 13.4013 20.5372 13.1795C20.6983 12.9577 20.7749 12.6787 20.7516 12.3988C20.7284 12.1188 20.607 11.8587 20.412 11.6708C20.2168 11.4829 19.9626 11.3812 19.7003 11.3862C19.6415 11.387 19.5829 11.3932 19.5251 11.4046L19.119 11.4806L12.8401 11.8343L12.594 7.75768L18.6167 2.94539L18.724 2.86836C18.9146 2.73657 19.0596 2.54147 19.1368 2.31295C19.214 2.08443 19.2192 1.83509 19.1515 1.60313C19.0838 1.37117 18.947 1.16938 18.7621 1.02868C18.5771 0.887968 18.3542 0.8161 18.1276 0.824087ZM14.0007 16.1117C13.4506 16.1117 12.923 16.3458 12.534 16.7625C12.1451 17.1793 11.9266 17.7445 11.9266 18.3338C11.9266 18.9233 12.1451 19.4884 12.534 19.9052C12.923 20.3219 13.4506 20.5561 14.0007 20.5561C14.5507 20.5561 15.0783 20.3219 15.4673 19.9052C15.8562 19.4884 16.0747 18.9233 16.0747 18.3338C16.0747 17.7445 15.8562 17.1793 15.4673 16.7625C15.0783 16.3458 14.5507 16.1117 14.0007 16.1117Z\",\n fill: \"black\"\n}));\n\nvar _ref3 = /*#__PURE__*/React.createElement(\"defs\", null, /*#__PURE__*/React.createElement(\"clipPath\", {\n id: \"clip0_2877_24292\"\n}, /*#__PURE__*/React.createElement(\"rect\", {\n width: 21,\n height: 25,\n fill: \"white\"\n})));\n\nvar SvgAgilityIcon = function SvgAgilityIcon(_ref) {\n var svgRef = _ref.svgRef,\n title = _ref.title,\n props = _objectWithoutProperties(_ref, [\"svgRef\", \"title\"]);\n\n return /*#__PURE__*/React.createElement(\"svg\", _extends({\n width: 21,\n height: 25,\n viewBox: \"0 0 21 25\",\n fill: \"none\",\n ref: svgRef\n }, props), title ? /*#__PURE__*/React.createElement(\"title\", null, title) : null, _ref2, _ref3);\n};\n\nvar ForwardRef = /*#__PURE__*/React.forwardRef(function (props, ref) {\n return /*#__PURE__*/React.createElement(SvgAgilityIcon, _extends({\n svgRef: ref\n }, props));\n});\nexport default __webpack_public_path__ + \"static/media/AgilityIcon.01e12092.svg\";\nexport { ForwardRef as ReactComponent };","function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\nimport React from \"react\";\n\nvar _ref2 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"M13.9906 3.11655e-05C13.7617 0.00165414 13.537 0.0621909 13.3383 0.175812L8.6716 2.84248C8.51597 2.92742 8.37884 3.04255 8.26823 3.18113C8.15763 3.31971 8.07577 3.47895 8.02745 3.64955C7.97912 3.82014 7.96531 3.99866 7.98681 4.17466C8.00831 4.35066 8.06469 4.5206 8.15266 4.67455C8.24063 4.82849 8.35842 4.96335 8.49913 5.07122C8.63985 5.1791 8.80066 5.25783 8.97217 5.30281C9.14367 5.34779 9.32243 5.35811 9.49797 5.33317C9.67352 5.30824 9.84232 5.24854 9.99452 5.15758L13.8031 2.9805L15.3969 5.21227L10.9724 8.71748C10.1936 9.18305 9.6664 10.0265 9.6664 10.9987C9.6664 11.6844 9.93305 12.3034 10.3578 12.7761L10.3513 12.7839L10.4216 12.8542C10.4407 12.8739 10.4605 12.8924 10.4802 12.9115L13.2445 15.6667H8.99973C8.82305 15.6642 8.64763 15.6968 8.48367 15.7627C8.31971 15.8286 8.17049 15.9264 8.04466 16.0505C7.91883 16.1745 7.81892 16.3224 7.75072 16.4854C7.68252 16.6484 7.64741 16.8233 7.64741 17C7.64741 17.1767 7.68252 17.3517 7.75072 17.5147C7.81892 17.6777 7.91883 17.8255 8.04466 17.9496C8.17049 18.0736 8.31971 18.1715 8.48367 18.2373C8.64763 18.3032 8.82305 18.3359 8.99973 18.3334H16.6664C16.8996 18.3333 17.1288 18.272 17.3309 18.1557C17.5331 18.0393 17.7012 17.872 17.8185 17.6704C17.9358 17.4688 17.9981 17.2399 17.9993 17.0067C18.0005 16.7734 17.9405 16.544 17.8253 16.3412L15.3213 11.9349L18.7016 9.65238L20.7432 12.4649L20.7992 12.5808C20.9084 12.8063 21.0789 12.9966 21.2912 13.1297C21.5036 13.2628 21.7491 13.3334 21.9997 13.3334H26.6664C26.8431 13.3359 27.0185 13.3032 27.1825 13.2373C27.3464 13.1715 27.4956 13.0736 27.6215 12.9496C27.7473 12.8255 27.8472 12.6777 27.9154 12.5147C27.9836 12.3517 28.0187 12.1767 28.0187 12C28.0187 11.8233 27.9836 11.6484 27.9154 11.4854C27.8472 11.3224 27.7473 11.1745 27.6215 11.0505C27.4956 10.9264 27.3464 10.8286 27.1825 10.7627C27.0185 10.6968 26.8431 10.6642 26.6664 10.6667H22.8357L20.3695 5.57555C20.3528 5.54048 20.3346 5.50616 20.3148 5.47269C19.9748 4.90294 19.5697 4.53312 19.0297 4.00654C18.4897 3.47997 17.8508 2.90001 17.2341 2.3542C16.0007 1.26257 14.8513 0.307323 14.8513 0.307323C14.6096 0.10671 14.3047 -0.00211564 13.9906 3.11655e-05ZM22.9984 0.333364C21.5264 0.333364 20.3331 1.52806 20.3331 2.99873C20.3331 4.47206 21.5264 5.6667 22.9984 5.6667C24.4738 5.6667 25.6664 4.47206 25.6664 2.99873C25.6664 1.52806 24.4738 0.333364 22.9984 0.333364ZM3.6664 6.33336C3.57805 6.33212 3.49035 6.34844 3.40837 6.38138C3.32639 6.41432 3.25177 6.46323 3.18886 6.52526C3.12595 6.58729 3.07599 6.6612 3.04189 6.74271C3.00779 6.82421 2.99023 6.91168 2.99023 7.00003C2.99023 7.08838 3.00779 7.17585 3.04189 7.25736C3.07599 7.33886 3.12595 7.41278 3.18886 7.4748C3.25177 7.53683 3.32639 7.58574 3.40837 7.61868C3.49035 7.65163 3.57805 7.66795 3.6664 7.6667H8.33306C8.4214 7.66795 8.50911 7.65163 8.59109 7.61868C8.67307 7.58574 8.74768 7.53683 8.8106 7.4748C8.87351 7.41278 8.92347 7.33886 8.95757 7.25736C8.99166 7.17585 9.00922 7.08838 9.00922 7.00003C9.00922 6.91168 8.99166 6.82421 8.95757 6.74271C8.92347 6.6612 8.87351 6.58729 8.8106 6.52526C8.74768 6.46323 8.67307 6.41432 8.59109 6.38138C8.50911 6.34844 8.4214 6.33212 8.33306 6.33336H3.6664ZM1.6664 9.6667C1.57805 9.66545 1.49035 9.68177 1.40837 9.71471C1.32639 9.74765 1.25177 9.79656 1.18886 9.85859C1.12595 9.92062 1.07599 9.99454 1.04189 10.076C1.00779 10.1575 0.990234 10.245 0.990234 10.3334C0.990234 10.4217 1.00779 10.5092 1.04189 10.5907C1.07599 10.6722 1.12595 10.7461 1.18886 10.8081C1.25177 10.8702 1.32639 10.9191 1.40837 10.952C1.49035 10.985 1.57805 11.0013 1.6664 11H6.33306C6.4214 11.0013 6.50911 10.985 6.59109 10.952C6.67307 10.9191 6.74768 10.8702 6.8106 10.8081C6.87351 10.7461 6.92347 10.6722 6.95757 10.5907C6.99166 10.5092 7.00922 10.4217 7.00922 10.3334C7.00922 10.245 6.99166 10.1575 6.95757 10.076C6.92347 9.99454 6.87351 9.92062 6.8106 9.85859C6.74768 9.79656 6.67307 9.74765 6.59109 9.71471C6.50911 9.68177 6.4214 9.66545 6.33306 9.6667H1.6664ZM2.33306 13C2.24472 12.9988 2.15701 13.0151 2.07503 13.048C1.99306 13.081 1.91844 13.1299 1.85553 13.1919C1.79261 13.254 1.74266 13.3279 1.70856 13.4094C1.67446 13.4909 1.6569 13.5783 1.6569 13.6667C1.6569 13.755 1.67446 13.8425 1.70856 13.924C1.74266 14.0055 1.79261 14.0794 1.85553 14.1415C1.91844 14.2035 1.99306 14.2524 2.07503 14.2854C2.15701 14.3183 2.24472 14.3346 2.33306 14.3334H6.99973C7.08807 14.3346 7.17578 14.3183 7.25776 14.2854C7.33974 14.2524 7.41435 14.2035 7.47726 14.1415C7.54018 14.0794 7.59013 14.0055 7.62423 13.924C7.65833 13.8425 7.67589 13.755 7.67589 13.6667C7.67589 13.5783 7.65833 13.4909 7.62423 13.4094C7.59013 13.3279 7.54018 13.254 7.47726 13.1919C7.41435 13.1299 7.33974 13.081 7.25776 13.048C7.17578 13.0151 7.08807 12.9988 6.99973 13H2.33306ZM12.5831 19.6667L10.9333 21.8672C10.4913 22.4566 10.6116 23.2918 11.2003 23.7331C11.4403 23.9138 11.7198 24 11.9984 24C12.4038 24 12.8048 23.8155 13.0674 23.4662L15.9177 19.6667H12.5831Z\",\n fill: \"black\"\n});\n\nvar SvgPaceIcon = function SvgPaceIcon(_ref) {\n var svgRef = _ref.svgRef,\n title = _ref.title,\n props = _objectWithoutProperties(_ref, [\"svgRef\", \"title\"]);\n\n return /*#__PURE__*/React.createElement(\"svg\", _extends({\n width: 29,\n height: 24,\n viewBox: \"0 0 29 24\",\n fill: \"none\",\n ref: svgRef\n }, props), title ? /*#__PURE__*/React.createElement(\"title\", null, title) : null, _ref2);\n};\n\nvar ForwardRef = /*#__PURE__*/React.forwardRef(function (props, ref) {\n return /*#__PURE__*/React.createElement(SvgPaceIcon, _extends({\n svgRef: ref\n }, props));\n});\nexport default __webpack_public_path__ + \"static/media/PaceIcon.af8c8c59.svg\";\nexport { ForwardRef as ReactComponent };","function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\nimport React from \"react\";\n\nvar _ref2 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"M7.571 15.3592L8.26602 13.6713L11.384 16.0097L9.98409 18.1732C9.4949 18.9292 8.83767 19.562 8.06366 20.0222L3.22558 22.8989C2.55957 23.2949 1.69942 23.0901 1.28342 22.4363L1.19525 22.2978C0.886024 21.8119 0.955784 21.1764 1.36306 20.7691C1.4179 20.7143 1.47781 20.6647 1.54198 20.6212L5.44781 17.9708C6.39625 17.3272 7.13459 16.419 7.571 15.3592Z\",\n fill: \"black\"\n});\n\nvar _ref3 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"M13.2906 2.61449L16.2218 3.59156C16.5024 3.68511 16.7963 3.7328 17.0921 3.7328H17.2734C17.7513 3.7328 18.2163 3.88781 18.5986 4.17455C19.2027 4.62765 19.5335 5.35799 19.4756 6.11094L19.4408 6.56367C19.3969 7.13323 19.1933 7.67887 18.8533 8.13789L16.0016 11.9877C15.712 12.3786 15.7961 12.9306 16.1889 13.2177L19.2013 15.419C19.9128 15.939 20.0058 16.9657 19.3992 17.605L14.2471 23.0356C13.7383 23.572 12.8947 23.6053 12.3451 23.1106C11.8062 22.6256 11.7409 21.8037 12.1964 21.2397L14.8934 17.9006C15.2099 17.5088 15.132 16.9315 14.723 16.6375L9.96705 13.2192C9.56813 12.9325 9.48255 12.374 9.77732 11.981L13.6936 6.75922C14.074 6.25201 13.8071 5.52117 13.1893 5.3786L12.8867 5.30878C12.2813 5.16907 11.6534 5.15752 11.0433 5.27484L8.0672 5.84717C7.41352 5.97288 6.77556 5.56584 6.61411 4.92005C6.44904 4.25976 6.84091 3.58836 7.49702 3.40736L10.6253 2.5444C11.501 2.30282 12.4288 2.32722 13.2906 2.61449Z\",\n fill: \"black\"\n});\n\nvar _ref4 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"M20.7135 8.89707L20.5429 8.21485L18.9443 10.2131C18.5088 10.7575 18.4968 11.5276 18.9151 12.0854C19.2038 12.4703 19.6569 12.6969 20.1381 12.6969H23.7583C24.5655 12.6969 25.2199 12.0426 25.2199 11.2354C25.2199 10.4282 24.5655 9.77383 23.7583 9.77383H21.8364C21.3053 9.77383 20.8423 9.41235 20.7135 8.89707Z\",\n fill: \"black\"\n});\n\nvar _ref5 = /*#__PURE__*/React.createElement(\"ellipse\", {\n cx: 21.9987,\n cy: 2.66667,\n rx: 2.66667,\n ry: 2.66667,\n fill: \"black\"\n});\n\nvar _ref6 = /*#__PURE__*/React.createElement(\"ellipse\", {\n cx: 25.9987,\n cy: 21.3327,\n rx: 2.66667,\n ry: 2.66667,\n fill: \"black\"\n});\n\nvar SvgDribblingIcon = function SvgDribblingIcon(_ref) {\n var svgRef = _ref.svgRef,\n title = _ref.title,\n props = _objectWithoutProperties(_ref, [\"svgRef\", \"title\"]);\n\n return /*#__PURE__*/React.createElement(\"svg\", _extends({\n width: 29,\n height: 24,\n viewBox: \"0 0 29 24\",\n fill: \"none\",\n ref: svgRef\n }, props), title ? /*#__PURE__*/React.createElement(\"title\", null, title) : null, _ref2, _ref3, _ref4, _ref5, _ref6);\n};\n\nvar ForwardRef = /*#__PURE__*/React.forwardRef(function (props, ref) {\n return /*#__PURE__*/React.createElement(SvgDribblingIcon, _extends({\n svgRef: ref\n }, props));\n});\nexport default __webpack_public_path__ + \"static/media/DribblingIcon.18a5e5cf.svg\";\nexport { ForwardRef as ReactComponent };","function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\nimport React from \"react\";\n\nvar _ref2 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"M14.9893 0.550859C14.8198 0.553509 14.6582 0.623308 14.5401 0.744936C14.422 0.866564 14.357 1.03008 14.3593 1.19961V5.03961C14.3581 5.12442 14.3738 5.20862 14.4054 5.28732C14.437 5.36602 14.484 5.43765 14.5435 5.49804C14.6031 5.55844 14.674 5.6064 14.7523 5.63913C14.8305 5.67187 14.9145 5.68872 14.9993 5.68872C15.0841 5.68872 15.1681 5.67187 15.2463 5.63913C15.3246 5.6064 15.3955 5.55844 15.4551 5.49804C15.5146 5.43765 15.5616 5.36602 15.5932 5.28732C15.6248 5.20862 15.6405 5.12442 15.6393 5.03961V1.19961C15.6405 1.11398 15.6244 1.02899 15.5922 0.949672C15.5599 0.87035 15.5121 0.79831 15.4514 0.737816C15.3908 0.677323 15.3187 0.629606 15.2393 0.597493C15.1599 0.565379 15.0749 0.549522 14.9893 0.550859ZM9.2393 1.19086C9.13368 1.19038 9.02958 1.21604 8.93628 1.26556C8.84299 1.31508 8.7634 1.38691 8.70461 1.47466C8.64582 1.56241 8.60967 1.66334 8.59936 1.76846C8.58905 1.87358 8.60492 1.97961 8.64555 2.07711L9.92555 5.27711C9.95418 5.35856 9.999 5.43338 10.0573 5.49706C10.1156 5.56073 10.1862 5.61196 10.2648 5.64764C10.3434 5.68333 10.4285 5.70274 10.5148 5.70471C10.6011 5.70668 10.6869 5.69116 10.7671 5.6591C10.8473 5.62703 10.9201 5.57908 10.9813 5.51812C11.0424 5.45717 11.0906 5.38447 11.1229 5.30441C11.1552 5.22435 11.171 5.13858 11.1693 5.05225C11.1676 4.96593 11.1485 4.88084 11.113 4.80211L9.83305 1.60211C9.78698 1.48176 9.70566 1.37811 9.59972 1.30473C9.49378 1.23136 9.36816 1.19167 9.2393 1.19086ZM20.7405 1.19211C20.6151 1.19651 20.4936 1.23773 20.3914 1.31063C20.2891 1.38353 20.2106 1.4849 20.1655 1.60211L18.8855 4.80211C18.8501 4.88084 18.831 4.96593 18.8293 5.05225C18.8276 5.13858 18.8434 5.22435 18.8757 5.30441C18.908 5.38447 18.9562 5.45717 19.0173 5.51812C19.0785 5.57908 19.1513 5.62703 19.2315 5.6591C19.3117 5.69116 19.3975 5.70668 19.4838 5.70471C19.5701 5.70274 19.6551 5.68333 19.7338 5.64764C19.8124 5.61196 19.883 5.56073 19.9413 5.49706C19.9996 5.43338 20.0444 5.35856 20.073 5.27711L21.353 2.07711C21.3941 1.97819 21.4097 1.87056 21.3983 1.76406C21.387 1.65757 21.3491 1.55563 21.2882 1.46757C21.2272 1.3795 21.1451 1.30814 21.0495 1.26002C20.9538 1.21189 20.8476 1.18854 20.7405 1.19211ZM5.3993 5.03961C4.6921 5.03961 4.1193 5.61241 4.1193 6.31961V20.3996C4.1193 21.1068 4.6921 21.6796 5.3993 21.6796C6.1065 21.6796 6.6793 21.1068 6.6793 20.3996V14.6396H8.5993H9.8793V12.0796H6.6793V6.31961C6.6793 5.61241 6.1065 5.03961 5.3993 5.03961ZM25.2393 5.03961C24.5321 5.03961 23.9593 5.61241 23.9593 6.31961V12.0796H21.3993V14.6396H23.9593V20.3996C23.9593 21.1068 24.5321 21.6796 25.2393 21.6796C25.9465 21.6796 26.5193 21.1068 26.5193 20.3996V6.31961C26.5193 5.61241 25.9465 5.03961 25.2393 5.03961ZM1.5593 7.59961C0.852097 7.59961 0.279297 8.17241 0.279297 8.87961V17.8396C0.279297 18.5468 0.852097 19.1196 1.5593 19.1196C2.2665 19.1196 2.8393 18.5468 2.8393 17.8396V8.87961C2.8393 8.17241 2.2665 7.59961 1.5593 7.59961ZM14.3593 7.59961C13.6521 7.59961 13.0793 8.17241 13.0793 8.87961V9.51961C13.0793 8.81241 12.5065 8.23961 11.7993 8.23961C11.0921 8.23961 10.5193 8.81241 10.5193 9.51961V9.83961V12.0796V15.5996C10.5193 15.7762 10.3759 15.9196 10.1993 15.9196C10.0227 15.9196 9.8793 15.7769 9.8793 15.5996V15.2796H8.60805C8.69445 16.774 9.82298 19.2963 11.7993 19.6784L11.1593 27.4396H19.4793L18.8393 19.5471C19.9619 19.1081 20.7593 17.382 20.7593 16.1046V14.6396V12.0796V10.4796V10.1596C20.7593 9.45241 20.1865 8.87961 19.4793 8.87961C18.7721 8.87961 18.1993 9.45241 18.1993 10.1596V9.51961C18.1993 8.81241 17.6265 8.23961 16.9193 8.23961C16.2121 8.23961 15.6393 8.81241 15.6393 9.51961V8.87961C15.6393 8.17241 15.0665 7.59961 14.3593 7.59961ZM29.0793 7.59961C28.3721 7.59961 27.7993 8.17241 27.7993 8.87961V17.8396C27.7993 18.5468 28.3721 19.1196 29.0793 19.1196C29.7865 19.1196 30.3593 18.5468 30.3593 17.8396V8.87961C30.3593 8.17241 29.7865 7.59961 29.0793 7.59961Z\",\n fill: \"black\"\n});\n\nvar SvgPhysicalIcon = function SvgPhysicalIcon(_ref) {\n var svgRef = _ref.svgRef,\n title = _ref.title,\n props = _objectWithoutProperties(_ref, [\"svgRef\", \"title\"]);\n\n return /*#__PURE__*/React.createElement(\"svg\", _extends({\n width: 31,\n height: 28,\n viewBox: \"0 0 31 28\",\n fill: \"none\",\n ref: svgRef\n }, props), title ? /*#__PURE__*/React.createElement(\"title\", null, title) : null, _ref2);\n};\n\nvar ForwardRef = /*#__PURE__*/React.forwardRef(function (props, ref) {\n return /*#__PURE__*/React.createElement(SvgPhysicalIcon, _extends({\n svgRef: ref\n }, props));\n});\nexport default __webpack_public_path__ + \"static/media/PhysicalIcon.116abe06.svg\";\nexport { ForwardRef as ReactComponent };","function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\nimport React from \"react\";\n\nvar _ref2 = /*#__PURE__*/React.createElement(\"path\", {\n fillRule: \"evenodd\",\n clipRule: \"evenodd\",\n d: \"M8.43375 6.88869C7.62902 6.97052 6.81828 7.24307 6.02977 7.41376C3.75073 7.90692 3.66828 7.92999 3.39078 8.15172C2.82717 8.60201 0.779847 10.704 0.645368 10.9705C0.473717 11.3106 0.465895 11.6238 0.620682 11.9537C0.853258 12.4489 1.44987 12.6794 1.95141 12.4675C2.09335 12.4076 2.71609 11.8738 3.33531 11.2814C3.9546 10.689 4.56004 10.1416 4.68082 10.065C4.92746 9.90878 5.87168 9.66166 6.22546 9.66079C6.88282 9.6591 6.62086 10.657 6.57687 11.0233C6.51121 11.5702 6.40996 12.5293 6.35176 13.1547C6.29363 13.7801 6.21599 14.5145 6.17925 14.7867C6.04821 15.7581 6.01205 16.7954 6.09801 17.1179C6.25732 17.7161 6.89068 18.2225 7.6085 18.3258C7.78611 18.3514 8.41581 18.4497 9.00783 18.5444C9.59985 18.6392 10.6816 18.8026 11.4118 18.9075C13.2476 19.1716 13.3192 19.1888 14.1498 19.5661C14.5551 19.7502 15.1947 20.0255 15.5712 20.1778C15.9476 20.3301 16.4817 20.559 16.758 20.6864C17.6852 21.1139 18.5086 21.4107 18.7674 21.4107C19.4606 21.4107 20.0948 20.7274 20.0948 19.9806C20.0948 19.3316 19.6777 18.8038 18.9524 18.5352C18.7716 18.4683 18.4623 18.342 18.2649 18.2546C17.6763 17.9937 16.6167 17.5365 15.3516 16.9974C14.0837 16.4572 13.7358 16.3703 11.8231 16.1166C10.7624 15.9759 10.5119 15.875 10.4328 15.5565C10.38 15.3438 10.6321 12.445 10.8194 11.1109C10.8838 10.6521 10.9385 9.85242 10.9409 9.3338C10.9451 8.44831 10.9337 8.3686 10.7544 8.02529C10.5239 7.58385 10.0187 7.09628 9.68353 6.99169C9.41392 6.90762 8.77052 6.8546 8.43375 6.88869ZM12.1724 9.59899C12.0677 10.2704 11.9823 12.0348 12.0462 12.2048C12.5977 13.6704 16.2197 13.6133 17.3397 13.4358C17.9419 13.3404 17.9759 12.6629 17.886 12.1092C17.7435 11.2318 17.4493 11.4471 15.8251 11.1907C13.6088 10.8408 13.7912 10.9113 12.9435 10.0776L12.2102 9.35651L12.1724 9.59899ZM5.11482 18.3824C5.07557 18.4323 4.80123 18.9834 4.50522 19.6071C3.89152 20.9002 3.73379 21.1472 3.00363 21.9596C2.71429 22.2815 2.17085 22.8987 1.7959 23.3313C1.42095 23.7638 0.910379 24.3418 0.661227 24.6157C0.412074 24.8896 0.161846 25.2261 0.105083 25.3633C-0.149021 25.978 0.0741539 26.7775 0.597359 27.1275C0.974317 27.3796 1.69451 27.4035 2.07067 27.1763C2.20214 27.097 2.91257 26.3496 3.6494 25.5154C6.25409 22.5671 6.10167 22.7722 6.86076 21.196C7.23463 20.4196 7.52555 19.7451 7.50732 19.697C7.48909 19.6489 7.30251 19.5735 7.09283 19.5294C6.58685 19.4231 6.07168 19.1167 5.63609 18.6628C5.25095 18.2615 5.22218 18.246 5.11482 18.3824Z\",\n fill: \"black\"\n});\n\nvar _ref3 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"M7.03442 3.49483C7.03442 1.93252 8.28742 0.666016 9.83307 0.666016C11.3787 0.666016 12.6317 1.93252 12.6317 3.49483C12.6317 5.05715 11.3787 6.32365 9.83307 6.32365C8.28742 6.32365 7.03442 5.05715 7.03442 3.49483Z\",\n fill: \"black\"\n});\n\nvar _ref4 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"M20.5971 17.1312C20.5971 15.8092 21.6574 14.7376 22.9652 14.7376C24.2731 14.7376 25.3333 15.8092 25.3333 17.1312C25.3333 18.4531 24.2731 19.5248 22.9652 19.5248C21.6574 19.5248 20.5971 18.4531 20.5971 17.1312Z\",\n fill: \"black\"\n});\n\nvar SvgShootingIcon = function SvgShootingIcon(_ref) {\n var svgRef = _ref.svgRef,\n title = _ref.title,\n props = _objectWithoutProperties(_ref, [\"svgRef\", \"title\"]);\n\n return /*#__PURE__*/React.createElement(\"svg\", _extends({\n width: 26,\n height: 28,\n viewBox: \"0 0 26 28\",\n fill: \"none\",\n ref: svgRef\n }, props), title ? /*#__PURE__*/React.createElement(\"title\", null, title) : null, _ref2, _ref3, _ref4);\n};\n\nvar ForwardRef = /*#__PURE__*/React.forwardRef(function (props, ref) {\n return /*#__PURE__*/React.createElement(SvgShootingIcon, _extends({\n svgRef: ref\n }, props));\n});\nexport default __webpack_public_path__ + \"static/media/ShootingIcon.aeec7dc9.svg\";\nexport { ForwardRef as ReactComponent };","import i18n from 'i18next';\nimport { ITariffModel } from 'entities/Tariff/Tariff.models';\n\nenum TranslationKeys {\n Title = 'Title',\n SaleDescription1 = 'Sale description 1 line',\n SaleDescription2 = 'Sale description 2 line'\n}\n\nexport const translateTariffData = (\n item: Partial | null | undefined\n): { title: string; saleDescription1: string; saleDescription2: string } => {\n const tag = item?.localizationTag;\n const unknownTitle = i18n.t('Unknown title');\n\n if (tag) {\n const title = i18n.exists(`${tag}.${TranslationKeys.Title}`) ? i18n.t(`${tag}.${TranslationKeys.Title}`) : tag;\n const saleDescription1 = i18n.exists(`${tag}.${TranslationKeys.SaleDescription1}`)\n ? i18n.t(`${tag}.${TranslationKeys.SaleDescription1}`)\n : '';\n const saleDescription2 = i18n.exists(`${tag}.${TranslationKeys.SaleDescription2}`)\n ? i18n.t(`${tag}.${TranslationKeys.SaleDescription2}`)\n : '';\n return { title, saleDescription1, saleDescription2 };\n }\n\n return { title: unknownTitle, saleDescription1: '', saleDescription2: '' };\n};\n\nexport const getCurrencySign = (currency: string) => {\n if (currency) {\n return (0)\n .toLocaleString(undefined, { style: 'currency', currency, minimumFractionDigits: 0, maximumFractionDigits: 0 })\n .replace(/\\d/g, '')\n .trim();\n }\n\n return '';\n};\n\nexport const getTariffAmountAndCurrency = (item: Partial | null | undefined) => {\n const { currency, currentPrice, amount } = item || {};\n\n const tariffAmount = currentPrice?.amount || amount;\n const tariffCurrency = currentPrice?.currency || currency;\n\n return { tariffAmount, tariffCurrency };\n};\n","import React, { useEffect, useMemo } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport Card from 'antd/lib/card';\nimport Row from 'antd/es/row';\nimport Col from 'antd/es/col';\nimport Divider from 'antd/es/divider';\nimport { useMediaPredicate } from 'react-media-hook';\nimport { MEDIA_DESKTOP } from 'common/const/config.const';\nimport { LoadingSpin } from 'common/components/LoadingSpin';\nimport { ReactComponent as AgilityIcon } from 'app/assets/icons/AgilityIcon.svg';\nimport { ReactComponent as PaceIcon } from 'app/assets/icons/PaceIcon.svg';\nimport { ReactComponent as DribblingIcon } from 'app/assets/icons/DribblingIcon.svg';\nimport { ReactComponent as PhysicalIcon } from 'app/assets/icons/PhysicalIcon.svg';\nimport { ReactComponent as ShootingIcon } from 'app/assets/icons/ShootingIcon.svg';\nimport { ITestCollectionFilter, ITestModel } from 'entities/Test/Test.models';\nimport { ESubtitleTypes, TestListItem } from 'entities/Test/components/List/TestListItem';\nimport { communicationTest, ITestConnectedProps } from 'entities/Test/Test.communication';\n\ninterface IComponentProps {\n playerId?: string;\n onItemClick?: (itemModel: ITestModel) => void;\n subtitle?: ESubtitleTypes;\n hideComplexity?: boolean;\n isRFS?: boolean;\n}\ninterface IItem {\n [skill: string]: ITestModel[];\n}\nconst cardConfigRFSDesktop = [\n [{ title: 'Physical training', icon: }],\n [{ title: 'Technical training', icon: }]\n];\nconst cardConfigRFSMob = [\n [\n { title: 'Physical training', icon: },\n { title: 'Technical training', icon: }\n ]\n];\nconst cardConfigDesktop = [\n [\n { title: 'agility', icon: },\n { title: 'physical', icon: }\n ],\n\n [\n { title: 'pace', icon: },\n { title: 'shooting', icon: }\n ],\n [{ title: 'dribbling', icon: }]\n];\nconst cardConfigMob = [\n [\n { title: 'agility', icon: },\n { title: 'physical', icon: },\n { title: 'pace', icon: },\n { title: 'shooting', icon: },\n { title: 'dribbling', icon: }\n ]\n];\n\ntype AllProps = ITestConnectedProps & IComponentProps;\n\nconst TestSkillCardListComponent: React.FC = props => {\n const { getTestCollection, playerId, testCollection, onItemClick, subtitle, hideComplexity, isRFS } = props;\n const { data: testCollectionData, loading } = testCollection;\n const { t } = useTranslation();\n const isDesktop: boolean = useMediaPredicate(`(min-width: ${MEDIA_DESKTOP})`);\n const configDefault = useMemo(() => (isDesktop ? cardConfigDesktop : cardConfigMob), [isDesktop]);\n const configRfs = useMemo(() => (isDesktop ? cardConfigRFSDesktop : cardConfigRFSMob), [isDesktop]);\n const config = isRFS ? configRfs : configDefault;\n\n const testsBySkill = useMemo(\n () =>\n testCollectionData?.data\n .sort((a, b) => a.displayPointCloud - b.displayPointCloud)\n .reduce((acc: IItem, el: ITestModel) => {\n const skillArray = isRFS ? [el.typeOfTraining] : el.skillsDependencies;\n if (!skillArray) {\n return acc;\n }\n skillArray?.forEach(item => {\n if (!acc[item]) {\n acc[item] = [el];\n } else {\n acc[item].push(el);\n }\n });\n return acc;\n }, {}),\n [testCollectionData]\n );\n\n useEffect(() => {\n const body: ITestCollectionFilter = {\n offset: 0,\n limit: 100\n };\n\n if (playerId) {\n body.player = playerId;\n }\n\n body.isVisibleForRfs = !!isRFS;\n body.isVisibleForTrainer = true;\n body.isVisibleForPlayer = false;\n\n getTestCollection(body);\n }, [getTestCollection]);\n\n if (loading) {\n return ;\n }\n\n return (\n \n \n {config.map((cardItem, index) => (\n \n \n {cardItem?.map(item => (\n \n \n \n {item.icon} {t(item.title)} \n
\n {testsBySkill && !!testsBySkill[item?.title]?.length\n ? testsBySkill[item?.title]?.map(testItem =>\n testItem && onItemClick ? (\n \n ) : null\n )\n : null}\n \n \n ))}\n
\n \n ))}\n
\n \n );\n};\n\nexport const TestSkillCardList = communicationTest.injector(TestSkillCardListComponent);\n","import React, { useState } from 'react';\nimport { useParams } from 'react-router';\nimport Col from 'antd/es/col';\nimport Row from 'antd/es/row';\nimport { isAcademyWorkerHelper } from 'common/helpers/permission.helper';\nimport { TestList } from 'entities/Test/components/List/TestList';\nimport { ITestModel } from 'entities/Test/Test.models';\nimport { TestModal } from 'entities/Test/components/Modal/TestModal';\nimport { IAuthConnectedProps, communicationAuth } from 'entities/Auth/Auth.communication';\nimport { TestSkillCardList } from 'entities/Test/components/List/TestSkillCardList';\n\ninterface IParams {\n id: string;\n}\n\ninterface IProps {\n hideComplexity?: boolean;\n isRFS?: boolean;\n}\n\ntype AllProps = IAuthConnectedProps & IProps;\n\nconst PlayerTestTabComponent: React.FC = props => {\n const { id: playerId } = useParams();\n const { hideComplexity, authUser, isRFS } = props;\n const isAcademyWorker = isAcademyWorkerHelper(authUser?.data);\n const [showModal, setShowModal] = useState(false);\n const [testItem, setTestItem] = useState();\n const testId = testItem?.id;\n const isHideComplexity = typeof hideComplexity === 'boolean' ? hideComplexity : isAcademyWorker;\n\n const openModal = (item: ITestModel) => {\n setShowModal(true);\n setTestItem(item);\n };\n const onClose = () => {\n setShowModal(false);\n setTestItem(undefined);\n };\n\n return (\n \n \n {isRFS ? (\n \n ) : (\n \n )}\n {testItem && }\n \n
\n );\n};\n\nexport const PlayerTestTab = communicationAuth.injector(PlayerTestTabComponent);\n","import React, { useEffect, useMemo, useState } from 'react';\nimport { useHistory, useParams } from 'react-router';\nimport axios from 'axios';\nimport { StoreBranch } from '@axmit/redux-communications';\nimport { IError } from 'fe-error-helper';\nimport { LoadingSpin } from 'common/components/LoadingSpin';\nimport { queryToObject } from 'common/helpers/filters.helper';\nimport { EErrorStatus } from 'common/models/requestModels';\nimport { ERoutesCommon, ERoutesPublic } from 'common/models/routesModel';\nimport { setHeaders } from 'common/helpers/axios.helper';\nimport { IPlayerModel, IPlayerParamsModel, IPlayerProfileModel } from 'entities/Player/Player.models';\nimport { communicationPlayer, IPlayerConnectedProps } from 'entities/Player/Player.communication';\nimport { playerTransport } from 'entities/Player/Player.transport';\nimport { EUserRole } from 'entities/User/User.models';\nimport { communicationAuth, IAuthConnectedProps } from 'entities/Auth/Auth.communication';\n\nexport interface IPlayerProfileProviderContext {\n profile?: StoreBranch | null;\n playerId?: string;\n isUserAcademyPlayer?: boolean;\n}\n\nexport interface IPlayerProviderContext {\n player?: StoreBranch | null;\n}\n\ninterface IProps {\n children?: React.ReactNode;\n}\n\nconst ACCESS_PROFILE_TOKEN = 'profile_token';\nexport const PlayerProviderContext = React.createContext({});\nexport const PlayerProfileProviderContext = React.createContext({});\n\ntype AllProps = IPlayerConnectedProps & IProps & IAuthConnectedProps;\n\nconst PlayerProfileProviderComponent: React.FC = (props: AllProps) => {\n const {\n children,\n getPlayerProfile,\n playerProfile,\n clearPlayerProfile,\n playerModel,\n getPlayerModel,\n clearPlayerModel,\n authUser\n } = props;\n const { id } = useParams();\n const history = useHistory();\n const { data, errors } = playerProfile;\n const playerModelValue = useMemo(() => playerModel, [playerModel]);\n const playerMentorId = data?.mentor?.mentorId;\n const playerAcademyId = data?.academy?.academyId;\n const authUserId = authUser?.data?.id;\n const isAuthUserAcademy = authUser?.data?.role === EUserRole.AcademyWorker;\n const isAuthUserMentor = authUser?.data?.role === EUserRole.Mentor;\n const authUserAcademyId = authUser?.data?.academyWorker?.academy?.id;\n const isAcademyPlayer = !!authUserAcademyId && !!playerAcademyId && authUserAcademyId === playerAcademyId;\n const isMentorPlayer = !!authUserId && !!playerMentorId && authUserId === playerMentorId;\n const canGetPlayerModel = useMemo(\n () => !!data && !!authUser && (isAuthUserAcademy ? isAcademyPlayer : isAuthUserMentor ? isMentorPlayer : false),\n [data, authUser, isAuthUserAcademy, isAcademyPlayer, isMentorPlayer]\n );\n const [loading, setLoading] = useState(true);\n const [authProfileToken, setAuthProfileToken] = useState();\n const { token, auth: authToken } = queryToObject<{ token?: string; auth?: string }>({ token: undefined, auth: undefined }) as {\n token: string | undefined;\n auth: string | undefined;\n };\n const isPlayerViewPage = history.location.pathname.includes(ERoutesPublic.PlayerView);\n\n useEffect(() => {\n if (authToken && isPlayerViewPage) {\n localStorage.setItem(ACCESS_PROFILE_TOKEN, authToken);\n }\n }, [authToken, isPlayerViewPage]);\n\n useEffect(() => {\n if (isPlayerViewPage) {\n const authProfileTokenStorage = localStorage.getItem(ACCESS_PROFILE_TOKEN);\n if (authProfileTokenStorage) {\n setAuthProfileToken(authProfileTokenStorage);\n }\n }\n }, [isPlayerViewPage]);\n\n useEffect(() => {\n if (authProfileToken && isPlayerViewPage) {\n axios.defaults.headers.common['Authorization'] = `Bearer ${authProfileToken}`;\n setHeaders('coachWebView');\n getPlayerProfile({ playerId: id });\n }\n return () => clearPlayerProfile();\n }, [id, authProfileToken, isPlayerViewPage]);\n\n useEffect(() => {\n const checkToken = async () => {\n if (token) {\n try {\n await playerTransport.checkShareToken({ playerId: id, token });\n\n await getPlayerProfile({ playerId: id, token });\n } catch (e) {\n await getPlayerProfile({ playerId: id });\n }\n } else {\n await getPlayerProfile({ playerId: id });\n }\n };\n\n if (!isPlayerViewPage) {\n checkToken();\n }\n\n return () => clearPlayerProfile();\n }, [id, token]);\n\n useEffect(() => {\n (async () => {\n if (canGetPlayerModel) {\n await getPlayerModel(id);\n }\n data && setLoading(false);\n })();\n\n return () => clearPlayerModel();\n }, [canGetPlayerModel, data, id]);\n\n useEffect(() => {\n const status = errors?.status;\n\n if (status && [EErrorStatus.NotFound, EErrorStatus.Forbidden].includes(status) && !isPlayerViewPage) {\n history.replace(ERoutesCommon.Root);\n }\n }, [errors]);\n\n if (loading) {\n return ;\n }\n\n return (\n \n {children} \n \n );\n};\n\nexport const PlayerProvider = communicationAuth.injector(communicationPlayer.injector(PlayerProfileProviderComponent));\n","export enum ERequestType {\n PlayerToAcademy = 'playerToAcademy',\n AcademyToPlayer = 'academyToPlayer'\n}\n\nexport interface IBaseUserDto {\n id: string;\n firstName?: string;\n lastName?: string;\n}\n","import React, { useCallback } from 'react';\nimport Popconfirm from 'antd/es/popconfirm';\nimport Button from 'antd/es/button';\nimport { useTranslation } from 'react-i18next';\nimport { useHistory } from 'react-router';\nimport { ERoutesCommon } from 'common/models/routesModel';\nimport { EMentorRequestStatus } from 'entities/MentorRequest/MentorRequest.models';\nimport { communicationMentorRequest, IMentorRequestConnectedProps } from 'entities/MentorRequest/MentorRequest.communication';\n\ninterface IProps {\n mentorRequestId: string;\n disabled?: boolean;\n}\n\ntype AllProps = IProps & IMentorRequestConnectedProps;\n\nconst Component: React.FC = props => {\n const { t } = useTranslation();\n const history = useHistory();\n const { mentorRequestId, updateMentorRequestModel, mentorRequestModel, disabled } = props;\n const { loading } = mentorRequestModel;\n\n const onUnlink = useCallback(async () => {\n if (mentorRequestId) {\n await updateMentorRequestModel({\n id: mentorRequestId,\n status: EMentorRequestStatus.Aborted\n });\n history.push(ERoutesCommon.Root);\n }\n }, [mentorRequestId, history]);\n\n return (\n \n \n {t('Unlink player')}\n \n \n );\n};\n\nexport const PlayerUnlink = communicationMentorRequest.injector(Component);\n","import React, { useCallback, useMemo } from 'react';\nimport Card from 'antd/es/card';\nimport Col from 'antd/es/col';\nimport Radio from 'antd/es/radio';\nimport Row from 'antd/es/row';\nimport Typography from 'antd/es/typography';\nimport Space from 'antd/es/space';\nimport { useTranslation } from 'react-i18next';\nimport { RadioChangeEvent } from 'antd/es/radio/interface';\nimport { communicationPlayer, IPlayerConnectedProps } from 'entities/Player/Player.communication';\nimport {\n EPlayersVisibilityModeFromSettings,\n EPlayerVisibilityMode,\n EPlayerVisibilityModeText,\n EPlayerVisibilitySettingsValues\n} from 'entities/Player/Player.models';\n\ninterface IComponentProps {\n isDesktop: boolean;\n}\n\ntype AllProps = IComponentProps & IPlayerConnectedProps;\n\nexport const PlayerVisibilityComponent: React.FC = props => {\n const { t } = useTranslation();\n const { playerModel, updateMentorRequestPlayerSetting } = props;\n const { data: playerData } = playerModel;\n const isPlayerHideFromJuniCoach = playerData?.juniCoachModule ? !playerData?.juniCoachPublicity : false;\n\n const playerVisibility = useMemo(() => {\n switch (true) {\n case playerData?.juniStatVisibility === EPlayerVisibilityMode.Public:\n return EPlayerVisibilitySettingsValues.Public;\n case playerData?.juniStatVisibility === EPlayerVisibilityMode.Protected:\n return EPlayerVisibilitySettingsValues.Protected;\n case playerData?.juniStatPublicity:\n return EPlayerVisibilitySettingsValues.Private;\n default:\n return EPlayerVisibilitySettingsValues.Hidden;\n }\n }, [playerData]);\n\n const viewSettings = React.useMemo(() => {\n return [\n EPlayerVisibilitySettingsValues.Public,\n EPlayerVisibilitySettingsValues.Protected,\n EPlayerVisibilitySettingsValues.Private,\n EPlayerVisibilitySettingsValues.Hidden\n ];\n }, []);\n\n const onChangeVisibility = useCallback(\n (e: RadioChangeEvent) => {\n if (playerData?.id) {\n const radioValue = e.target.value as EPlayerVisibilitySettingsValues;\n updateMentorRequestPlayerSetting({\n id: playerData.id,\n juniStatVisibility: EPlayersVisibilityModeFromSettings[radioValue] as EPlayerVisibilityMode,\n juniStatPublicity: radioValue !== EPlayerVisibilitySettingsValues.Hidden\n });\n }\n },\n [playerData]\n );\n\n return (\n \n \n {t('Who sees the player profile')} \n \n \n {viewSettings.map(item => (\n \n \n {t(`view-settings-${EPlayerVisibilityModeText[item]}-title`)} \n \n {t(`view-settings-${EPlayerVisibilityModeText[item]}-label`)}\n \n
\n \n ))}\n \n \n {isPlayerHideFromJuniCoach && (\n \n \n {t('Attention')}.\n \n {t('The academy hid the player with its privacy settings')} \n
\n )}\n \n \n );\n};\n\nexport const PlayerVisibility = communicationPlayer.injector(PlayerVisibilityComponent);\n","import React, { useCallback, useMemo } from 'react';\nimport Card from 'antd/es/card';\nimport Col from 'antd/es/col';\nimport Button from 'antd/es/button';\nimport Row from 'antd/es/row';\nimport Typography from 'antd/es/typography';\nimport Space from 'antd/es/space';\nimport Modal from 'antd/es/modal';\nimport Popconfirm from 'antd/es/popconfirm';\nimport message from 'antd/es/message';\nimport { useTranslation } from 'react-i18next';\nimport moment from 'moment';\nimport { formatDateFromServer } from 'common/helpers/date.helper';\nimport { clientDateFormat, clientDateFullMonthFormat } from 'common/models/dateModels';\nimport { translateTariffData } from 'common/helpers/tariff-helper';\nimport StopIcon from 'app/assets/icons/stop.svg';\nimport { PlayerUnlink } from 'entities/Player/components/ActionButtons/PlayerUnlink';\nimport { communicationPlayer, IPlayerConnectedProps } from 'entities/Player/Player.communication';\nimport { communicationSubscription, ISubscriptionConnectedProps } from 'entities/Subscription/Subscription.communication';\nimport { communicationMentorRequest, IMentorRequestConnectedProps } from 'entities/MentorRequest/MentorRequest.communication';\nimport { EPaymentActivitiesStatus, ESubscriptionsEngines, ESubscriptionStatus } from 'entities/Subscription/Subscription.models';\nimport { SubscriptionButton } from 'entities/Subscription/components/SubscriptionButton';\nimport { communicationUI, IUIConnectedProps } from 'entities/UI/UI.communication';\nimport { ETariffStatus } from 'entities/Tariff/Tariff.models';\nimport { isAcademyHideTariffs, isPrepaymentDisabled } from 'entities/Subscription/helpers/subscription.helper';\nimport { PlayerVisibility } from 'entities/Player/components/PlayerVisibility';\n\ninterface IComponentProps {\n isDesktop: boolean;\n}\n\ntype AllProps = IComponentProps &\n IPlayerConnectedProps &\n ISubscriptionConnectedProps &\n IMentorRequestConnectedProps &\n IUIConnectedProps;\n\nexport const PlayerSettingTabComponent: React.FC = props => {\n const { t } = useTranslation();\n const [isOpenDialog, setOpenDialog] = React.useState(false);\n const {\n playerModel,\n updateSubscriptionModel,\n openUIPaymentRequirementsModal,\n openUIChangeTariffModal,\n subscriptionModel,\n deleteSubscriptionActivityModel,\n isDesktop\n } = props;\n const { data: playerData } = playerModel;\n const { loading: subscriptionLoading } = subscriptionModel;\n const mentorRequestId = playerData?.mentorRequest?.id;\n const subscription = playerData?.mentorRequest?.subscription;\n const tariffId = subscription?.tariff?.id;\n const tariffData = translateTariffData(subscription?.tariff);\n const isPaid = playerData?.isPaid;\n const hideTariffs = useMemo(() => isAcademyHideTariffs(playerData), [playerData]);\n\n const paidTill = useMemo(() => formatDateFromServer(subscription?.prepaidTo, clientDateFullMonthFormat), [subscription]);\n\n const isSubscriptionActive = useMemo(() => subscription && subscription.status === ESubscriptionStatus.Active, [subscription]);\n\n const isSubscriptionExpired = useMemo(() => subscription && subscription.status === ESubscriptionStatus.Expired, [\n subscription\n ]);\n\n const isCheckingLastPayment = useMemo(() => {\n if (subscription && subscription.lastActivity) {\n return (\n subscription.lastActivity.status === EPaymentActivitiesStatus.New || subscription.lastActivity.isApplied === undefined\n );\n }\n\n return false;\n }, [subscription]);\n\n const onUnsubscribe = useCallback(() => {\n if (subscription?.id) {\n updateSubscriptionModel({\n id: subscription.id,\n status: ESubscriptionStatus.Canceled\n });\n setOpenDialog(false);\n }\n }, [subscription]);\n\n const isNewSubscription = useMemo(() => {\n return isSubscriptionExpired && !subscription?.prepaidTo;\n }, [subscription]);\n\n const subscriptionStatusLabel = useMemo(() => {\n if (isNewSubscription) {\n return t('New');\n }\n if (isSubscriptionExpired && subscription?.lastActivity?.status === EPaymentActivitiesStatus.New) {\n return t('Not active');\n }\n return t(`status-player-card.${subscription?.status || 'not-active'}`);\n }, [subscription]);\n\n const onPayClick = useCallback(() => {\n if (isPrepaymentDisabled(subscription)) {\n message.error(t('prepaymentRestrictedException'));\n } else if (subscription?.id) {\n openUIPaymentRequirementsModal({\n subscriptionId: subscription.id\n });\n }\n }, [subscription]);\n\n const isAbleToRemoveCardData = useMemo(\n () => subscription?.hasSavedPaymentMethod && (subscription?.delayedCancellation || isSubscriptionExpired),\n [subscription]\n );\n\n const isTariffArchived = useMemo(() => subscription?.tariff?.status === ETariffStatus.Archived, [subscription]);\n\n const deletePaymentsData = useCallback(() => {\n if (subscription?.id) {\n deleteSubscriptionActivityModel(subscription?.id);\n }\n }, [subscription]);\n\n const onChangeTariff = useCallback(() => {\n if (subscription?.id) {\n openUIChangeTariffModal({\n subscriptionId: subscription?.id,\n tariffId\n });\n }\n }, [subscription]);\n\n const whenArchiveText = useMemo(\n () =>\n (!isTariffArchived &&\n subscription?.tariff?.activeTo &&\n t('archive-will-be', { date: moment(subscription.tariff.activeTo).format(clientDateFormat) })) ||\n '',\n [isTariffArchived, subscription]\n );\n\n return (\n \n \n {!isPaid && !hideTariffs && (\n \n \n \n {t('Subscription')}\n \n \n {subscriptionStatusLabel} \n {isSubscriptionActive && !subscription?.delayedCancellation && (\n <>\n \n {t('next-payment', {\n date: paidTill,\n cost: `${subscription?.tariff?.currentPrice?.amount ||\n subscription?.tariffAmount?.amount ||\n 0} ${subscription?.tariff?.currentPrice?.currency || subscription?.tariffAmount?.currency || ''}`\n })}\n
\n \n {t('tariff-info', {\n tariff: tariffData.title,\n isArchived: isTariffArchived ? t('Archived') : '',\n whenArchive: whenArchiveText\n })}\n
\n >\n )}\n {(isNewSubscription || isSubscriptionExpired || subscription?.delayedCancellation) &&\n tariffData.title &&\n t('Chosen tariff', {\n name: tariffData.title,\n cost: `${subscription?.tariff?.currentPrice?.amount || subscription?.tariffAmount?.amount || 0} ${subscription\n ?.tariff?.currentPrice?.currency ||\n subscription?.tariffAmount?.currency ||\n ''}`,\n isArchived: isTariffArchived ? t('Archived') : '',\n whenArchive: whenArchiveText\n })}\n \n \n \n setOpenDialog(true)}>\n {t('Unsubscribe')}\n \n }\n />\n \n {subscription && (\n \n {t('Change tariff')}\n \n )}\n
\n \n \n )}\n {isSubscriptionActive &&\n !subscription?.delayedCancellation &&\n !isCheckingLastPayment &&\n !isTariffArchived &&\n !isPaid &&\n !hideTariffs && (\n \n \n \n {t('Payment')}\n \n \n {t('payment-description')}\n \n \n {t('Pay for a Subscription')}\n \n \n \n )}\n \n \n \n {t('Unlink player')}\n \n \n {t('unlink-description')}\n \n \n \n \n {isAbleToRemoveCardData && (\n \n \n \n {t('Payment data')}\n \n \n {t('payments-data-remove-description')}\n \n \n {t('Delete')} \n \n \n \n )}\n setOpenDialog(false)}\n footer={false}\n title={
}\n visible={isOpenDialog}\n >\n \n \n \n {t('Unsubscribe?')} \n \n {t('unsubscribe-description', { date: paidTill })}\n \n \n {t('Unsubscribe')}\n \n setOpenDialog(false)} className=\"width-full\" block type=\"primary\" size=\"large\">\n {t('Leave')}\n \n \n
\n \n
\n );\n};\n\nexport const PlayerSettingTabYookassa = communicationUI.injector(\n communicationMentorRequest.injector(communicationSubscription.injector(communicationPlayer.injector(PlayerSettingTabComponent)))\n);\n","import React, { useContext } from 'react';\nimport Row from 'antd/es/row';\nimport Card from 'antd/es/card';\nimport Typography from 'antd/es/typography';\nimport { useTranslation } from 'react-i18next';\nimport Col from 'antd/es/col';\nimport { PlayerVisibility } from 'entities/Player/components/PlayerVisibility';\nimport { PlayerUnlink } from 'entities/Player/components/ActionButtons/PlayerUnlink';\nimport { PlayerProviderContext } from 'entities/Player/components/PlayerProvider';\n\ninterface IProps {\n isDesktop: boolean;\n}\n\ntype AllProps = IProps;\n\nconst PlayerSettingTabStripeProfileComponent: React.FC = props => {\n const { t } = useTranslation();\n const { player } = useContext(PlayerProviderContext);\n const { isDesktop } = props;\n const mentorRequestId = player?.data?.mentorRequest?.id;\n\n return (\n \n \n \n \n \n {t('Unlink player')}\n \n \n {t('unlink-description')}\n \n \n \n \n
\n );\n};\n\nexport const PlayerSettingTabStripeProfile = PlayerSettingTabStripeProfileComponent;\n","import classNames from 'classnames';\nimport React, { FC } from 'react';\n\ninterface IPaperProps {\n className?: string;\n onClick?(): void;\n}\n\nexport const Paper: FC = props => {\n const { children, onClick = () => undefined, className = '' } = props;\n\n return (\n \n {children}\n
\n );\n};\n","import React, { useMemo } from 'react';\nimport Col from 'antd/es/col';\nimport Row from 'antd/es/row';\nimport Typography from 'antd/es/typography';\nimport { useTranslation } from 'react-i18next';\nimport Button from 'antd/es/button';\nimport classNames from 'classnames';\nimport { getCurrencySign, getTariffAmountAndCurrency, translateTariffData } from 'common/helpers/tariff-helper';\nimport { normalize } from 'common/helpers/normalize.helper';\nimport { ITariffModel } from 'entities/Tariff/Tariff.models';\n\ninterface IProps {\n item: Partial;\n selectedTariffId?: string;\n onSelect(tariffId: string): void;\n disabled?: boolean;\n tariffEnd?: string;\n nextTariff?: string;\n nextTariffStart?: string;\n}\n\ntype AllProps = IProps;\n\nconst Component: React.FC = props => {\n const { t } = useTranslation();\n const { item, selectedTariffId, onSelect, disabled, tariffEnd, nextTariff, nextTariffStart } = props;\n const { period } = item;\n const { title, saleDescription1, saleDescription2 } = translateTariffData(item);\n const { tariffCurrency, tariffAmount } = getTariffAmountAndCurrency(item);\n\n const isTariffSelected = useMemo(() => item.id === selectedTariffId, [item.id, selectedTariffId]);\n const isNextTariff = useMemo(() => item.id === nextTariff, [item.id, nextTariff]);\n const isFree = useMemo(() => Number(tariffAmount) === 0, [tariffAmount]);\n\n const periodText = useMemo(() => {\n switch (true) {\n case period === 1:\n return t('mon');\n case period === 12:\n return t('year');\n default:\n return `${period}\\u00A0${t('mon')}`;\n }\n }, [period]);\n\n const onTariffSelectCallback = () => {\n if (item.id) {\n onSelect(item.id);\n }\n };\n\n return (\n \n \n \n \n {title}\n \n\n \n {t(isTariffSelected ? 'Active' : 'Connect')}\n \n \n \n \n \n {isFree ? t('Free') : `${getCurrencySign(tariffCurrency as string)}\\u00A0${normalize(Number(tariffAmount))}`}\n \n {!isFree && /{periodText} }\n
\n \n
\n {isTariffSelected && tariffEnd && (\n \n {t('Valid until', { date: tariffEnd })} \n
\n )}\n {isNextTariff && nextTariffStart && (\n \n {t('Activated from', { date: nextTariffStart })} \n
\n )}\n {saleDescription1 && (\n \n \n {saleDescription1}\n \n
\n )}\n {saleDescription2 && (\n \n \n {saleDescription2}\n \n
\n )}\n \n );\n};\n\nexport const TariffStripeComponentItem = Component;\n","import React, { useEffect, useMemo } from 'react';\nimport Spin from 'antd/es/spin';\nimport List from 'antd/es/list';\nimport {\n CANCEL_SUBSCRIPTION_TARIFF_ID,\n ETariffStatus,\n ITariffCollectionFilter,\n ITariffModel\n} from 'entities/Tariff/Tariff.models';\nimport { communicationTariff, ITariffConnectedProps } from 'entities/Tariff/Tariff.communication';\nimport { TariffStripeComponentItem } from 'entities/Tariff/components/TariffsStripe/TariffsStripeComponentItem';\n\ninterface IProps {\n onSelectTariff(tariffId: string | undefined): void;\n mentorId?: string;\n playerId?: string;\n isTrialPhaseNow?: boolean;\n tariffEnd?: string;\n subscriptionId?: string;\n selectedTariffId?: string;\n disabled?: boolean;\n nextTariff?: string;\n nextTariffStart?: string;\n hidden?: boolean;\n}\n\ntype AllProps = IProps & ITariffConnectedProps;\n\nconst LIST_GRID = {\n gutter: 16,\n column: 3,\n xs: 1,\n sm: 1,\n md: 2,\n lg: 2,\n xl: 3\n};\n\nconst Component: React.FC = props => {\n const {\n tariffCollection,\n getTariffCollection,\n clearTariffCollection,\n mentorId,\n playerId,\n subscriptionId,\n selectedTariffId,\n onSelectTariff,\n disabled,\n tariffEnd,\n nextTariff,\n nextTariffStart,\n isTrialPhaseNow,\n hidden\n } = props;\n const { data, loading } = tariffCollection;\n const tariffs = data?.data;\n\n useEffect(() => {\n const filter: ITariffCollectionFilter = {\n limit: 100,\n orderField: 'status',\n orderDirection: 'ASC',\n statuses: [ETariffStatus.Active]\n };\n\n if (!mentorId && !playerId && !subscriptionId) {\n return;\n }\n\n if (mentorId) {\n filter.forMentor = mentorId;\n }\n\n if (playerId) {\n filter.forPlayer = playerId;\n }\n\n if (subscriptionId) {\n filter.forSubscription = subscriptionId;\n }\n\n getTariffCollection(filter);\n }, [mentorId, playerId, subscriptionId]);\n\n useEffect(() => {\n return () => clearTariffCollection();\n }, []);\n\n const dataSource: Partial[] = useMemo(\n () => [\n {\n id: CANCEL_SUBSCRIPTION_TARIFF_ID,\n localizationTag: isTrialPhaseNow ? 'Trial' : 'Initial',\n currentPrice: { amount: '0', currency: 'RUB', country: '' }\n },\n ...(tariffs || [])\n ],\n [tariffs, isTrialPhaseNow]\n );\n\n if (hidden) {\n return null;\n }\n\n return (\n \n (\n \n \n \n )}\n />\n
\n );\n};\n\nexport const TariffsStripeComponent = communicationTariff.injector(Component);\n","import React, { useCallback, useContext, useMemo } from 'react';\nimport Typography from 'antd/es/typography';\nimport { useTranslation } from 'react-i18next';\nimport Col from 'antd/es/col';\nimport Row from 'antd/es/row';\nimport Popconfirm from 'antd/es/popconfirm';\nimport { StripeContext } from 'common/components/Stripe/StripeProvider';\nimport { PlayerProviderContext } from 'entities/Player/components/PlayerProvider';\nimport { IUIConnectedProps, communicationUI } from 'entities/UI/UI.communication';\nimport { IUserPaymentMethod } from 'entities/User/User.models';\nimport { IUserConnectedProps, communicationUser } from 'entities/User/User.communication';\n\ninterface IProps {\n userPaymentMethod?: IUserPaymentMethod;\n}\n\ntype AllProps = IProps & IUIConnectedProps & IUserConnectedProps;\n\nconst Component: React.FC = React.memo(props => {\n const { lastSavedPaymentMethod, clearSavedPaymentMethod } = useContext(StripeContext);\n const { player } = useContext(PlayerProviderContext);\n const { t } = useTranslation();\n const { openUIStripePaymentModal, userPaymentMethod, updateUserModel } = props;\n const subscriptionId = player?.data?.mentorRequest?.subscription?.id;\n const mentorId = player?.data?.mentorRequest?.mentor?.id;\n\n const paymentMethod: IUserPaymentMethod | undefined = useMemo(() => {\n if (lastSavedPaymentMethod?.card) {\n return {\n brand: lastSavedPaymentMethod?.card?.brand,\n expMonth: lastSavedPaymentMethod?.card?.exp_month,\n expYear: lastSavedPaymentMethod?.card?.exp_year,\n last4: lastSavedPaymentMethod?.card?.last4\n };\n }\n\n return userPaymentMethod;\n }, [lastSavedPaymentMethod, userPaymentMethod]);\n\n const onAddClickCallback = useCallback(() => {\n openUIStripePaymentModal({\n withCardDetails: true,\n withCoupon: false,\n title: t('Card adding'),\n cardDetailBtnText: t('Add'),\n subscription: subscriptionId\n });\n }, [openUIStripePaymentModal, subscriptionId]);\n\n const onChangeClickCallback = useCallback(() => {\n openUIStripePaymentModal({\n withCardDetails: true,\n withCoupon: false,\n title: t('Change card'),\n cardDetailBtnText: t('Change'),\n subscription: subscriptionId\n });\n }, [openUIStripePaymentModal, subscriptionId]);\n\n const onRemovePaymentDataCallback = useCallback(() => {\n if (mentorId) {\n updateUserModel({\n stripePaymentMethodToken: null,\n id: mentorId\n });\n }\n clearSavedPaymentMethod?.();\n }, [updateUserModel, mentorId, clearSavedPaymentMethod]);\n\n return (\n \n \n \n {t('Used card')}\n \n
\n {!paymentMethod ? (\n <>\n \n \n {t('Not connected')}\n \n
\n {subscriptionId && (\n \n \n {t('Add')}\n \n
\n )}\n >\n ) : (\n <>\n \n \n **** **** **** {paymentMethod.last4}\n \n
\n \n \n \n {t('Change')}\n \n \n \n \n {t('Delete')} \n \n \n
\n >\n )}\n \n );\n});\n\nexport const StripeSavedPaymentMethodCard = communicationUser.injector(communicationUI.injector(Component));\n","import React, { ChangeEvent, useCallback, useEffect, useMemo, useState } from 'react';\nimport Form from 'antd/es/form';\nimport { useTranslation } from 'react-i18next';\nimport CheckCircleFilled from '@ant-design/icons/CheckCircleFilled';\nimport ExclamationCircleFilled from '@ant-design/icons/ExclamationCircleFilled';\nimport MaskedInput from 'antd-mask-input';\nimport Row from 'antd/es/row';\nimport Col from 'antd/es/col';\nimport Button from 'antd/es/button';\nimport { decodeGiftcardNumber, IDecodeGiftcardInterface } from 'common/helpers/giftcard.helper';\nimport { getErrorMessageByCode } from 'common/helpers/translate.helper';\nimport { validateGiftcard } from 'common/helpers/filed-rules';\nimport { ESubscriptionsEngines } from 'entities/Subscription/Subscription.models';\nimport { communicationSubscription, ISubscriptionConnectedProps } from 'entities/Subscription/Subscription.communication';\n\nconst giftcardFieldName = 'giftcard';\nconst giftcardFormName = 'giftcardForm';\nconst INITIAL_STATE = { isGiftcardOk: true };\n\nexport interface IGiftcardChangeEvent extends IDecodeGiftcardInterface {\n number?: string;\n}\n\ninterface IProps {\n errors?: any;\n loading?: boolean;\n subscriptionId?: string;\n showApplyButton?: boolean;\n engine?: ESubscriptionsEngines;\n mentorRequest?: string;\n onGiftcardChanged?(giftcard: IGiftcardChangeEvent): void;\n size?: 'small' | 'middle' | 'large';\n}\n\ntype AllProps = IProps & ISubscriptionConnectedProps;\n\nconst getValueFromMask = (value?: string) => value?.replace(/ /g, '');\n\nconst Component: React.FC = props => {\n const {\n errors,\n loading,\n subscriptionId,\n applyGiftcardSubscriptionActivityModel,\n addSubscriptionModel,\n showApplyButton,\n onGiftcardChanged,\n size = 'middle',\n mentorRequest,\n engine\n } = props;\n const { t, i18n } = useTranslation(['web-subscription-button', 'common-fields-rules']);\n const [giftcardForm] = Form.useForm();\n const [giftcardMessage, setGiftcardMessage] = useState('');\n const [giftcard, setGiftcard] = useState(INITIAL_STATE);\n\n useEffect(() => {\n const errorMessage: any = errors;\n if (errorMessage && errorMessage?.data?.errors?.['.giftcard']?.length) {\n const [errorData] = errorMessage?.data?.errors?.['.giftcard'];\n if (errorData?.message) {\n setGiftcardMessage(\n i18n.exists(errorData.message)\n ? t(errorData.message)\n : (getErrorMessageByCode(errorData.code, { _property: t('giftcard') }) as string)\n );\n setGiftcard({ isGiftcardOk: false });\n giftcardForm.setFields([{ name: giftcardFieldName, errors: [errorData.message] }]);\n }\n }\n }, [errors]);\n\n const clearGiftcardState = useCallback(() => {\n setGiftcardMessage('');\n setGiftcard(INITIAL_STATE);\n }, [giftcardForm, setGiftcardMessage, setGiftcard]);\n\n const sendChangeEvent = useCallback(() => {\n const giftcardValue = giftcardForm.getFieldValue(giftcardFieldName);\n const number = getValueFromMask(giftcardValue);\n\n if (engine === ESubscriptionsEngines.Stripe && !giftcardValue) {\n clearGiftcardState();\n }\n\n onGiftcardChanged?.({ ...giftcard, number });\n }, [giftcard, engine, clearGiftcardState]);\n\n useEffect(() => {\n sendChangeEvent();\n }, [giftcard]);\n\n const giftcardBtnDisabled = useMemo(() => loading || !giftcard.isGiftcardOk || (!subscriptionId && !mentorRequest), [\n loading,\n giftcard,\n subscriptionId,\n mentorRequest\n ]);\n\n const getGiftcardInfo = useCallback(\n (e: ChangeEvent) => {\n const number = getValueFromMask(e?.target?.value);\n\n if (number) {\n const giftcardValue = decodeGiftcardNumber(number);\n setGiftcard(giftcardValue);\n if (giftcardValue.isGiftcardOk) {\n if (giftcardValue?.period) {\n setGiftcardMessage(t('promocode-amount', { period: giftcardValue?.period }));\n } else {\n setGiftcardMessage('');\n }\n } else {\n setGiftcardMessage(t('common-fields-rules:Wrong giftcard'));\n }\n }\n },\n [setGiftcardMessage]\n );\n\n const giftcardIcon = useMemo(() => {\n const { isGiftcardOk } = giftcard;\n const number = giftcardForm.getFieldValue(giftcardFieldName);\n\n if (!number) {\n return ;\n }\n\n return isGiftcardOk ? (\n \n ) : (\n \n );\n }, [giftcard]);\n\n const onResetForm = useCallback(() => {\n giftcardForm.resetFields();\n clearGiftcardState();\n }, [giftcardForm, clearGiftcardState]);\n\n const onApplyGiftcard = useCallback(() => {\n const giftcardValue = giftcardForm.getFieldValue(giftcardFieldName);\n const number = getValueFromMask(giftcardValue);\n\n if (engine && number && giftcard.isGiftcardOk) {\n if (subscriptionId) {\n applyGiftcardSubscriptionActivityModel({\n subscriptionId,\n giftcard: number,\n engine,\n onSuccess: onResetForm\n });\n } else if (mentorRequest) {\n addSubscriptionModel({\n giftcard: number,\n engine,\n mentorRequest,\n onSuccess: onResetForm\n });\n }\n }\n }, [applyGiftcardSubscriptionActivityModel, giftcard, subscriptionId, mentorRequest, engine, onResetForm]);\n\n return (\n \n \n \n /[A-Za-z0-9]/.test(char)\n }\n }}\n size={size}\n suffix={giftcardIcon}\n placeholder={t('Giftcard, if any')}\n onChange={getGiftcardInfo}\n />\n \n \n \n {showApplyButton && (\n \n \n {t('Apply')}\n \n \n )}\n
\n );\n};\n\nexport const GiftcardForm = communicationSubscription.injector(Component);\n","import { Col, Row } from 'antd';\nimport React from 'react';\nimport Typography from 'antd/es/typography';\nimport { useTranslation } from 'react-i18next';\nimport { ISubscriptionConnectedProps, communicationSubscription } from 'entities/Subscription/Subscription.communication';\nimport { GiftcardForm } from 'entities/Subscription/components/GiftcardForm';\nimport { ESubscriptionsEngines } from 'entities/Subscription/Subscription.models';\n\ninterface IProps {\n subscriptionId?: string;\n mentorRequestId?: string;\n}\n\ntype AllProps = IProps & ISubscriptionConnectedProps;\n\nconst Component: React.FC = props => {\n const { subscriptionModel, subscriptionId, mentorRequestId } = props;\n const { t } = useTranslation();\n const { errors, loading } = subscriptionModel;\n\n return (\n \n \n \n {t('giftcard')}\n \n \n \n \n \n
\n );\n};\n\nexport const StripeGiftcardCard = communicationSubscription.injector(Component);\n","import { Table } from 'antd';\nimport React, { useCallback, useEffect, useMemo, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useHistory, useLocation } from 'react-router';\nimport queryString from 'query-string';\nimport Typography from 'antd/es/typography';\nimport { nameBuilder } from 'common/helpers/name.helper';\nimport { normalizeDateFirstMouth } from 'common/helpers/normalize.helper';\nimport { getStripePaymentIncludingDiscount } from 'entities/Subscription/helpers/subscription.helper';\nimport {\n EPaymentActivitiesTypes,\n ESubscriptionInvoiceType,\n ESubscriptionsEngines,\n ISubscriptionActivityModel\n} from 'entities/Subscription/Subscription.models';\nimport { communicationSubscription, ISubscriptionConnectedProps } from 'entities/Subscription/Subscription.communication';\n\nexport interface IPaymentsHistoryProps {\n subscriptionId?: string;\n className?: string;\n isEmpty?: boolean;\n}\n\nexport interface IPaymentsTableState {\n current?: number;\n pageSize?: number;\n total?: number;\n}\n\ntype AllProps = IPaymentsHistoryProps & ISubscriptionConnectedProps;\n\nconst PaymentsHistoryComponent: React.FC = props => {\n const { search } = useLocation();\n const { push } = useHistory();\n const { t } = useTranslation(['web-payment-and-subscription-page', 'web-payment-statuses']);\n const {\n subscriptionId,\n getSubscriptionActivityCollection,\n clearSubscriptionActivityCollection,\n subscriptionActivityCollection,\n isEmpty,\n className\n } = props;\n const [state, setState] = useState(\n queryString.parse(search, { parseNumbers: true }) ?? { current: 1, pageSize: 10 }\n );\n const { data, loading } = subscriptionActivityCollection;\n const { data: datasets, meta } = data ?? {};\n\n const [dataSource, setDataSource] = useState([]);\n\n useEffect(() => {\n if (datasets) {\n setDataSource(datasets);\n return;\n }\n if (isEmpty) {\n setDataSource([]);\n }\n }, [datasets, loading]);\n\n useEffect(() => {\n const { pageSize = 10, current = 1 } = state;\n if (isEmpty) {\n return;\n }\n getSubscriptionActivityCollection({\n subscription: subscriptionId,\n limit: pageSize,\n offset: pageSize * (current - 1)\n });\n return () => {\n clearSubscriptionActivityCollection();\n };\n }, [subscriptionId, state]);\n\n const columns = useMemo(\n () => [\n {\n title: t('Date'),\n dataIndex: 'createdAt',\n key: 'createdAt',\n width: 120,\n ellipsis: true,\n render: normalizeDateFirstMouth\n },\n {\n title: t('Description'),\n dataIndex: 'id',\n key: 'id',\n width: 240,\n ellipsis: true,\n render: (value: string, row: ISubscriptionActivityModel) => {\n const { type, subscription } = row;\n const isGiftCardUsed = type === EPaymentActivitiesTypes.Giftcard;\n const firstName = subscription?.mentorRequest?.player?.firstName;\n const lastName = subscription?.mentorRequest?.player?.lastName;\n const playerName = nameBuilder(firstName, lastName);\n return `${t('Subscription to', { playerName })} ${isGiftCardUsed ? t('by giftcard') : ''}`;\n }\n },\n {\n title: t('Amount'),\n dataIndex: 'amountValue',\n key: 'amountValue',\n width: 80,\n ellipsis: true,\n render: (value: number, row: ISubscriptionActivityModel) => {\n let currency = row.amountCurrency;\n let amount = row?.amountValue ?? '0.00';\n\n if (row.processing === ESubscriptionsEngines.Stripe && row.invoice?.type === ESubscriptionInvoiceType.Payment) {\n const paymentAmount = getStripePaymentIncludingDiscount(row.invoice.amount, row.invoice.discountAmount);\n\n if (paymentAmount !== undefined) {\n amount = paymentAmount;\n }\n if (row.invoice.currency) {\n currency = row.invoice.currency;\n }\n }\n\n return currency ? `${currency} ${amount}` : `-`;\n }\n },\n {\n title: t('Status'),\n dataIndex: 'status',\n key: 'status',\n width: 120,\n ellipsis: true,\n // eslint-disable-next-line react/no-multi-comp\n render: (value: string, activityModel: ISubscriptionActivityModel) => {\n const label = activityModel.isApplied === undefined ? 'Awaiting' : activityModel.isApplied ? 'Successful' : 'Failed';\n\n return (\n \n {t(label)}\n {activityModel.isApplied === undefined &&\n activityModel.processing === ESubscriptionsEngines.Stripe &&\n activityModel?.invoice?.url && (\n \n {' '}\n (\n \n {t('Pay')}\n \n )\n \n )}\n {activityModel.invoice?.urlPdf ? (\n \n {' '}\n (\n \n {t('Download PDF')}\n \n )\n \n ) : (\n ''\n )}\n \n );\n }\n }\n ],\n []\n );\n\n useEffect(() => {\n push({\n search: queryString.stringify(state)\n });\n }, [state]);\n\n const onChange = useCallback(event => {\n setState({\n current: event.current,\n pageSize: event.pageSize,\n total: event.total\n });\n }, []);\n\n return (\n \n );\n};\n\nexport const PaymentsHistory = communicationSubscription.injector(PaymentsHistoryComponent);\n","import React, { ReactElement } from 'react';\nimport Row from 'antd/es/row';\n\ninterface IProps {\n children: ReactElement;\n}\n\nconst Component: React.FC = props => {\n const { children } = props;\n\n return (\n \n {children}\n
\n );\n};\n\nexport const StripeSubscriptionInfoCardCenteredLayout = Component;\n","import { Col, Row, Typography } from 'antd';\nimport React from 'react';\nimport classNames from 'classnames';\nimport { useTranslation } from 'react-i18next';\nimport { getCurrencySign } from 'common/helpers/tariff-helper';\nimport { IStripeNextWithdrawal } from 'entities/Subscription/Subscription.models';\n\ninterface IProps extends IStripeNextWithdrawal {\n className?: string;\n}\n\nconst Component: React.FC = props => {\n const { amount, currency, date, className } = props;\n const { t } = useTranslation();\n\n return (\n \n \n \n {t('Next withdrawal')}\n \n \n \n \n {amount ? `${getCurrencySign(currency as string)}${amount} ${currency} • ${date}` : date}\n \n \n
\n );\n};\n\nexport const StripeSubscriptionInfoCardNextWithdrawal = Component;\n","import React, { useCallback, useMemo } from 'react';\nimport moment from 'moment';\nimport Col from 'antd/es/col';\nimport Row from 'antd/es/row';\nimport Spin from 'antd/es/spin';\nimport Typography from 'antd/es/typography';\nimport { useTranslation } from 'react-i18next';\nimport Popconfirm from 'antd/es/popconfirm';\nimport { translateTariffData } from 'common/helpers/tariff-helper';\nimport { clientDateFormat } from 'common/models/dateModels';\nimport { communicationSubscription, ISubscriptionConnectedProps } from 'entities/Subscription/Subscription.communication';\nimport { communicationTariff, ITariffConnectedProps } from 'entities/Tariff/Tariff.communication';\nimport { SubscriptionDelayedCancellation } from 'entities/Subscription/components/SubscriptionDelayedCancellation';\nimport {\n ESubscriptionsEngines,\n ESubscriptionStatus,\n IStripeNextWithdrawal,\n ISubscriptionModel\n} from 'entities/Subscription/Subscription.models';\nimport { IMentorRequestModel } from 'entities/MentorRequest/MentorRequest.models';\nimport {\n getStripeNextWithdrawal,\n getStripeSubscriptionAllGiftcards,\n getStripeSubscriptionNextTariff,\n isStripeCurrentPhaseGiftcard,\n isStripeTrialVersion\n} from 'entities/Subscription/helpers/subscription.helper';\nimport { StripeSubscriptionInfoCardCenteredLayout } from 'entities/Subscription/components/StripeSubscriptionInfoCard/StripeSubscriptionInfoCardCenteredLayout';\nimport { StripeSubscriptionInfoCardNextWithdrawal } from 'entities/Subscription/components/StripeSubscriptionInfoCard/StripeSubscriptionInfoCardNextWithdrawal';\n\ninterface IProps {\n subscription?: ISubscriptionModel | null;\n mentorRequest?: IMentorRequestModel | null;\n}\n\ntype AllProps = IProps & ISubscriptionConnectedProps & ITariffConnectedProps;\n\nconst Component: React.FC = props => {\n const {\n subscription,\n mentorRequest,\n tariffCollection,\n changeTariffSubscriptionModel,\n subscriptionModel,\n updateSubscriptionModel\n } = props;\n const { t } = useTranslation();\n const { loading } = subscriptionModel;\n const isDelayedCancellation = useMemo(() => subscription && subscription.delayedCancellation, [subscription]);\n const nextTariff = useMemo(() => getStripeSubscriptionNextTariff(subscription), [subscription]);\n const allGiftcards = useMemo(() => getStripeSubscriptionAllGiftcards(subscription), [subscription]);\n const nextWithdrawal = useMemo(() => getStripeNextWithdrawal(subscription), [subscription]);\n const isGiftcardPhaseNow = useMemo(() => isStripeCurrentPhaseGiftcard(subscription), [subscription]);\n const isTrialPhaseNow = useMemo(() => isStripeTrialVersion(subscription), [subscription]);\n const nextTariffData = useMemo(() => tariffCollection?.data?.data?.find(tariff => tariff.id === nextTariff?.id), [\n tariffCollection?.data,\n nextTariff\n ]);\n const { title: nextTariffTitle } = translateTariffData(nextTariffData);\n\n const onCancelNextTariffCallback = useCallback(() => {\n if (subscription) {\n if (isGiftcardPhaseNow) {\n updateSubscriptionModel({\n engine: ESubscriptionsEngines.Stripe,\n id: subscription.id,\n status: ESubscriptionStatus.Canceled\n });\n } else {\n changeTariffSubscriptionModel({\n engine: ESubscriptionsEngines.Stripe,\n subscriptionId: subscription.id,\n tariff: subscription.currentPhase?.tariffId || subscription.tariff.id,\n isSameTariff: true\n });\n }\n }\n }, [subscription, isGiftcardPhaseNow]);\n\n const Element = useMemo(() => {\n switch (true) {\n case loading: {\n return (\n \n \n \n );\n }\n case subscription?.status === ESubscriptionStatus.Expired:\n return (\n \n {t('Awaiting payment')} \n \n );\n case subscription?.status === ESubscriptionStatus.Canceled:\n return (\n \n {t('Subscription cancelled')} \n \n );\n case isDelayedCancellation:\n return (\n \n \n \n );\n case Boolean(nextTariff?.id): {\n return (\n \n \n \n {t('Next tariff', { title: nextTariffTitle })}{' '}\n \n ({t('Revoke')} )\n \n \n
\n );\n }\n case Boolean(nextWithdrawal): {\n return ;\n }\n case isTrialPhaseNow: {\n return (\n \n {t('Trial version')} \n \n );\n }\n case isGiftcardPhaseNow: {\n return (\n \n {t('Gift card applied')} \n \n );\n }\n case subscription?.status === ESubscriptionStatus.Active: {\n return (\n \n {t('Subscription active')} \n \n );\n }\n default:\n return (\n \n {t('Subscription not registered')} \n \n );\n }\n }, [\n isDelayedCancellation,\n mentorRequest,\n nextTariffTitle,\n subscription,\n nextTariff?.id,\n onCancelNextTariffCallback,\n nextWithdrawal,\n loading,\n isGiftcardPhaseNow,\n isTrialPhaseNow\n ]);\n\n return (\n \n {Element}\n {!!allGiftcards?.length && (\n <>\n \n {t('Gift cards')}\n \n {allGiftcards?.map(phase => (\n \n {phase.giftcardNumber} \n \n {moment(phase.periodStart).format(clientDateFormat)} - {moment(phase.periodEnd).format(clientDateFormat)}\n \n
\n ))}\n >\n )}\n \n );\n};\n\nexport const StripeSubscriptionInfoCard = communicationTariff.injector(communicationSubscription.injector(Component));\n","import React, { useCallback, useContext, useEffect, useMemo } from 'react';\nimport Row from 'antd/es/row';\nimport Spin from 'antd/es/spin';\nimport Typography from 'antd/es/typography';\nimport { useTranslation } from 'react-i18next';\nimport Col from 'antd/es/col';\nimport classNames from 'classnames';\nimport { Paper } from 'common/components/Paper/Paper';\nimport { StripeContext } from 'common/components/Stripe/StripeProvider';\nimport { formatDateFromServer } from 'common/helpers/date.helper';\nimport { clientDateFullMonthFormat } from 'common/models/dateModels';\nimport {\n getStripeSubscriptionCurrentTariffEndDate,\n getStripeSubscriptionNextTariff,\n getStripeSubscriptionTariffId,\n isAcademyHideTariffs,\n isStripeTrialVersion\n} from 'entities/Subscription/helpers/subscription.helper';\nimport { TariffsStripeComponent } from 'entities/Tariff/components/TariffsStripe/TariffsStripeComponent';\nimport { PlayerProviderContext } from 'entities/Player/components/PlayerProvider';\nimport { communicationMentorRequest, IMentorRequestConnectedProps } from 'entities/MentorRequest/MentorRequest.communication';\nimport { communicationSubscription, ISubscriptionConnectedProps } from 'entities/Subscription/Subscription.communication';\nimport { IUIConnectedProps, communicationUI } from 'entities/UI/UI.communication';\nimport { StripeSavedPaymentMethodCard } from 'entities/Subscription/components/StripeSavedPaymentMethodCard';\nimport { StripeGiftcardCard } from 'entities/Subscription/components/StripeGiftcardCard';\nimport { PaymentsHistory } from 'entities/Subscription/components/PaymentAndSubscriptions/PaymentsHistory';\nimport { StripeSubscriptionInfoCard } from 'entities/Subscription/components/StripeSubscriptionInfoCard/StripeSubscriptionInfoCard';\nimport { CANCEL_SUBSCRIPTION_TARIFF_ID } from 'entities/Tariff/Tariff.models';\nimport { IAuthConnectedProps, communicationAuth } from 'entities/Auth/Auth.communication';\n\ninterface IProps {\n isDesktop: boolean;\n}\n\ntype AllProps = IProps & IMentorRequestConnectedProps & ISubscriptionConnectedProps & IUIConnectedProps & IAuthConnectedProps;\n\nconst PlayerSettingTabStripeSubscriptionComponent: React.FC = props => {\n const { t } = useTranslation();\n const {\n authUser,\n mentorRequestModel,\n subscriptionModel,\n getMentorRequestModel,\n getSubscriptionModel,\n openUIStripePaymentModal,\n openUIStripeCancelSubscriptionModal\n } = props;\n const { player } = useContext(PlayerProviderContext);\n const { lastSavedPaymentMethod } = useContext(StripeContext);\n const { data: mentorRequest, loading: mentorRequestLoading } = mentorRequestModel;\n const { data: subscription, loading: subscriptionLoading } = subscriptionModel;\n const userPaymentMethod = authUser?.data?.stripePaymentMethod;\n const mentorRequestId = player?.data?.mentorRequest?.id;\n const playerId = player?.data?.id;\n const isPaid = player?.data?.isPaid;\n const mentorId = mentorRequest?.mentor?.id;\n const subscriptionId = mentorRequest?.subscription?.id;\n\n const hideTariffs = useMemo(() => isAcademyHideTariffs(player?.data), [player]);\n const selectedTariffId = useMemo(() => getStripeSubscriptionTariffId(subscription), [subscription]);\n const tariffEnd = useMemo(() => {\n const date = getStripeSubscriptionCurrentTariffEndDate(subscription);\n\n return date ? formatDateFromServer(date, clientDateFullMonthFormat) : undefined;\n }, [subscription]);\n const nextTariff = useMemo(() => getStripeSubscriptionNextTariff(subscription), [subscription]);\n const isTrialPhaseNow = useMemo(() => isStripeTrialVersion(subscription), [subscription]);\n\n const commonLoading = useMemo(() => mentorRequestLoading || subscriptionLoading, [mentorRequestLoading, subscriptionLoading]);\n\n const paymentMethod = useMemo(() => lastSavedPaymentMethod?.card || userPaymentMethod, [\n userPaymentMethod,\n lastSavedPaymentMethod\n ]);\n\n useEffect(() => {\n if (mentorRequestId && mentorRequestId !== mentorRequest?.id) {\n getMentorRequestModel(mentorRequestId);\n }\n }, [mentorRequestId, mentorRequest, mentorRequestLoading]);\n\n useEffect(() => {\n if (subscriptionId) {\n getSubscriptionModel(subscriptionId);\n }\n }, [subscriptionId]);\n\n const onTariffSelectCallback = useCallback(\n tariffId => {\n if (tariffId) {\n if (tariffId === CANCEL_SUBSCRIPTION_TARIFF_ID) {\n openUIStripeCancelSubscriptionModal({\n subscription: subscriptionId\n });\n } else {\n openUIStripePaymentModal({\n tariff: tariffId,\n title: t('Subscription payment'),\n withCoupon: true,\n withCardDetails: !paymentMethod,\n mentorRequest: mentorRequestId,\n subscription: subscriptionId\n });\n }\n }\n },\n [openUIStripePaymentModal, paymentMethod, mentorRequestId, subscriptionId]\n );\n\n return (\n \n \n \n {!hideTariffs && !isPaid && (\n \n \n {t('Player subscription')}\n \n
\n )}\n \n \n \n \n
\n
\n \n \n \n {t('Payment')}\n \n
\n \n \n \n \n {!hideTariffs && !isPaid && (\n \n \n \n )}\n \n \n \n
\n
\n {!hideTariffs && !isPaid && (\n \n \n \n {t('Bills')}\n \n
\n \n \n
\n
\n )}\n \n \n );\n};\n\nexport const PlayerSettingTabStripeSubscription = communicationAuth.injector(\n communicationSubscription.injector(\n communicationMentorRequest.injector(communicationUI.injector(PlayerSettingTabStripeSubscriptionComponent))\n )\n);\n","import React, { useEffect, useState, useContext, useMemo } from 'react';\nimport Row from 'antd/es/row';\nimport Tabs from 'antd/es/tabs';\nimport { useTranslation } from 'react-i18next';\nimport { Switch, Route, useHistory, useLocation, useRouteMatch, useParams } from 'react-router';\nimport Col from 'antd/es/col';\nimport { EPlayerSettingsTabKeys } from 'entities/Player/Player.models';\nimport { PlayerProviderContext } from 'entities/Player/components/PlayerProvider';\nimport { PlayerSettingTabStripeProfile } from 'entities/Player/components/Tabs/PlayerSettingTab/PlayerSettingTabStripe/PlayerSettingTabStripeProfile';\nimport { PlayerSettingTabStripeSubscription } from 'entities/Player/components/Tabs/PlayerSettingTab/PlayerSettingTabStripe/PlayerSettingTabStripeSubscription';\nimport { isAcademyHideTariffs } from 'entities/Subscription/helpers/subscription.helper';\n\ninterface IProps {\n isDesktop: boolean;\n}\n\ntype AllProps = IProps;\n\nconst PlayerSettingTabStripeTabsComponent: React.FC = props => {\n const { isDesktop } = props;\n const { t } = useTranslation();\n const history = useHistory();\n const { player } = useContext(PlayerProviderContext);\n const { stripeTab: tabKey } = useParams();\n const { search } = useLocation();\n const { path, url } = useRouteMatch();\n const [searchValue, setSearchValue] = useState(search);\n const [tabValue, setTabValue] = useState(tabKey || EPlayerSettingsTabKeys.Profile);\n const { isPaid } = player?.data || {};\n const hideTariffs = useMemo(() => isAcademyHideTariffs(player?.data), [player]);\n\n const selectTab = (key: string): EPlayerSettingsTabKeys => {\n if (isPaid || hideTariffs) {\n return EPlayerSettingsTabKeys.Profile;\n }\n\n switch (key) {\n case EPlayerSettingsTabKeys.Profile:\n return EPlayerSettingsTabKeys.Profile;\n case EPlayerSettingsTabKeys.Subscription:\n return EPlayerSettingsTabKeys.Subscription;\n\n default:\n return EPlayerSettingsTabKeys.Profile;\n }\n };\n\n useEffect(() => {\n replace(selectTab(tabKey));\n setTabValue(selectTab(tabKey));\n }, [tabKey]);\n\n const changeUrl = (newTab: string, saveSearch?: boolean) => {\n const newPathname = tabKey ? url?.replace(tabKey, newTab) : `${url}/${newTab}`;\n history.push({ pathname: newPathname, search: saveSearch ? searchValue : undefined });\n };\n\n const onTabChange = (tab: string) => {\n const selectedTab = selectTab(tab);\n setSearchValue(undefined);\n setTabValue(selectedTab);\n changeUrl(tab);\n };\n\n const replace = (tab: string) => {\n changeUrl(selectTab(tab), true);\n };\n\n return (\n \n \n \n \n {!isPaid && !hideTariffs && }\n \n \n \n \n \n {!isPaid && !hideTariffs && (\n \n \n \n )}\n \n \n \n \n \n
\n );\n};\n\nexport const PlayerSettingTabStripeTabs = PlayerSettingTabStripeTabsComponent;\n","import React, { useContext, useEffect } from 'react';\nimport { LoadingSpin } from 'common/components/LoadingSpin';\nimport { PlayerProviderContext } from 'entities/Player/components/PlayerProvider';\nimport { communicationMentorRequest, IMentorRequestConnectedProps } from 'entities/MentorRequest/MentorRequest.communication';\nimport { PlayerSettingTabYookassa } from 'entities/Player/components/Tabs/PlayerSettingTab/PlayerSettingTabYookassa';\nimport { PlayerSettingTabStripeTabs } from 'entities/Player/components/Tabs/PlayerSettingTab/PlayerSettingTabStripe/PlayerSettingTabStripeTabs';\nimport { ESubscriptionsEngines } from 'entities/Subscription/Subscription.models';\n\ninterface IProps {\n isDesktop: boolean;\n}\n\ntype AllProps = IProps & IMentorRequestConnectedProps;\n\nconst Component: React.FC = props => {\n const { player } = useContext(PlayerProviderContext);\n const { getMentorRequestModel, mentorRequestModel, isDesktop } = props;\n const { data: mentorRequest, loading } = mentorRequestModel;\n const mentorRequestId = player?.data?.mentorRequest?.id;\n\n useEffect(() => {\n if (mentorRequestId && mentorRequestId !== mentorRequest?.id) {\n getMentorRequestModel(mentorRequestId);\n }\n }, [mentorRequestId, mentorRequest]);\n\n if (loading || !mentorRequest) {\n return ;\n }\n\n if (mentorRequest?.subscriptionEngine === ESubscriptionsEngines.Stripe) {\n return ;\n }\n\n return ;\n};\n\nexport const PlayerSettingTab = communicationMentorRequest.injector(Component);\n","import React from 'react';\nimport Card from 'antd/es/card';\nimport Col from 'antd/es/col';\nimport Row from 'antd/es/row';\nimport Typography from 'antd/es/typography';\nimport List from 'antd/es/list';\nimport { Link } from 'react-router-dom';\nimport { useRouteMatch } from 'react-router';\nimport { useTranslation } from 'react-i18next';\nimport { useMediaPredicate } from 'react-media-hook';\nimport EnvironmentOutlined from '@ant-design/icons/EnvironmentOutlined';\nimport { locationFormatter } from 'common/helpers/location.helper';\nimport { MEDIA_DESKTOP } from 'common/const/config.const';\nimport { ImagePrivate } from 'common/components/Image/ImagePrivate';\nimport { IAcademyModel } from 'entities/Academy/Academy.models';\n\ninterface IComponentProps {\n item: IAcademyModel;\n}\n\ntype AllProps = IComponentProps;\n\nconst avatarWidth = 56;\nconst avatarHeight = 56;\n\nexport const AcademyListItemComponent: React.FC = props => {\n const { item } = props;\n const { t } = useTranslation();\n const { url } = useRouteMatch();\n const { address, name = t('Unknown name'), id, image } = item;\n // const { address, name = t('Unknown name'), id, image, passedResultsCount, totalResultsCount } = item;\n // const count = `${passedResultsCount}/${totalResultsCount}`;\n const location = locationFormatter(address) || t('Unknown address');\n const isDesktop: boolean = useMediaPredicate(`(min-width: ${MEDIA_DESKTOP})`);\n const imgId = image?.id;\n\n return (\n \n \n \n \n \n \n \n \n
\n \n {name}\n
\n
\n
\n \n {location}\n \n
\n \n \n {/* */}\n {/* {count} */}\n {/* */}\n {/*
*/}\n {/* */}\n
\n
\n \n \n \n );\n};\n\nexport const AcademyListItem = AcademyListItemComponent;\n","function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\nimport React from \"react\";\n\nvar _ref2 = /*#__PURE__*/React.createElement(\"g\", {\n clipPath: \"url(#clip0)\"\n}, /*#__PURE__*/React.createElement(\"path\", {\n d: \"M83.4977 11.25C64.8869 11.25 49.7477 26.3892 49.7477 45C49.7477 63.6107 64.8869 78.75 83.4977 78.75C102.108 78.75 117.248 63.6107 117.248 45C117.248 26.3892 102.108 11.25 83.4977 11.25ZM51.6922 71.5027L34.3447 88.8503C32.8799 90.315 32.8799 92.6882 34.3447 94.153C35.8094 95.6178 38.1824 95.6178 39.6474 94.153L56.9949 76.8055C58.4597 75.3407 58.4597 72.9675 56.9949 71.5027C55.5302 70.038 53.1572 70.0377 51.6922 71.5027Z\",\n fill: \"url(#paint0_linear)\"\n}), /*#__PURE__*/React.createElement(\"path\", {\n d: \"M75.9942 45C78.0945 45 79.7442 43.3498 79.7442 41.25V37.5C79.7442 35.3997 78.0945 33.75 75.9942 33.75C73.894 33.75 72.2442 35.3997 72.2442 37.5V41.25C72.2442 43.3498 73.894 45 75.9942 45ZM90.9942 45C93.0945 45 94.7442 43.3498 94.7442 41.25V37.5C94.7442 35.3997 93.0945 33.75 90.9942 33.75C88.894 33.75 87.2442 35.3997 87.2442 37.5V41.25C87.2442 43.3498 88.894 45 90.9942 45ZM83.4942 0C58.6692 0 38.4942 20.175 38.4942 45C38.4942 69.825 58.6692 90 83.4942 90C108.319 90 128.494 69.825 128.494 45C128.494 20.175 108.319 0 83.4942 0ZM83.4942 75C66.919 75 53.4942 61.5748 53.4942 45C53.4942 28.4247 66.919 15 83.4942 15C100.069 15 113.494 28.4247 113.494 45C113.494 61.5748 100.069 75 83.4942 75ZM72.9195 53.6247C71.4195 55.0497 71.4195 57.4497 72.9195 58.8747C74.3445 60.3747 76.7442 60.3747 78.1692 58.8747C81.0192 56.0247 85.9695 56.0247 88.8197 58.8747C89.4942 59.6252 90.4692 60 91.4442 60C92.4192 60 93.3942 59.625 94.0692 58.8747C95.5692 57.4497 95.5692 55.0497 94.0692 53.6247C88.444 47.925 78.5445 47.925 72.9195 53.6247ZM34.3415 83.5475C32.8767 82.0827 30.5035 82.0827 29.0387 83.5475L3.78223 108.803C-0.601266 113.187 -0.601265 120.321 3.77848 124.712C3.78223 124.712 3.78223 124.711 3.78223 124.715C8.16973 129.095 15.3132 129.096 19.6905 124.712L44.9467 99.4557C46.4115 97.991 46.4115 95.6178 44.9467 94.153L34.3415 83.5475Z\",\n fill: \"url(#paint1_linear)\"\n}));\n\nvar _ref3 = /*#__PURE__*/React.createElement(\"defs\", null, /*#__PURE__*/React.createElement(\"linearGradient\", {\n id: \"paint0_linear\",\n x1: 75.2469,\n y1: 95.2515,\n x2: 75.2469,\n y2: 11.25,\n gradientUnits: \"userSpaceOnUse\"\n}, /*#__PURE__*/React.createElement(\"stop\", {\n stopColor: \"#ADDCFF\"\n}), /*#__PURE__*/React.createElement(\"stop\", {\n offset: 0.5028,\n stopColor: \"#EAF6FF\"\n}), /*#__PURE__*/React.createElement(\"stop\", {\n offset: 1,\n stopColor: \"#EAF6FF\"\n})), /*#__PURE__*/React.createElement(\"linearGradient\", {\n id: \"paint1_linear\",\n x1: 64.4942,\n y1: 128,\n x2: 64.4942,\n y2: 0,\n gradientUnits: \"userSpaceOnUse\"\n}, /*#__PURE__*/React.createElement(\"stop\", {\n stopColor: \"#5558FF\"\n}), /*#__PURE__*/React.createElement(\"stop\", {\n offset: 1,\n stopColor: \"#00C0FF\"\n})), /*#__PURE__*/React.createElement(\"clipPath\", {\n id: \"clip0\"\n}, /*#__PURE__*/React.createElement(\"rect\", {\n width: 128,\n height: 128,\n fill: \"white\",\n transform: \"translate(0.5)\"\n})));\n\nvar SvgNodataMagnifier = function SvgNodataMagnifier(_ref) {\n var svgRef = _ref.svgRef,\n title = _ref.title,\n props = _objectWithoutProperties(_ref, [\"svgRef\", \"title\"]);\n\n return /*#__PURE__*/React.createElement(\"svg\", _extends({\n width: 129,\n height: 128,\n viewBox: \"0 0 129 128\",\n fill: \"none\",\n ref: svgRef\n }, props), title ? /*#__PURE__*/React.createElement(\"title\", null, title) : null, _ref2, _ref3);\n};\n\nvar ForwardRef = /*#__PURE__*/React.forwardRef(function (props, ref) {\n return /*#__PURE__*/React.createElement(SvgNodataMagnifier, _extends({\n svgRef: ref\n }, props));\n});\nexport default __webpack_public_path__ + \"static/media/nodata-magnifier.335dbbbe.svg\";\nexport { ForwardRef as ReactComponent };","import React, { useCallback, useState, useMemo } from 'react';\nimport Typography from 'antd/es/typography';\nimport Tabs from 'antd/es/tabs';\nimport Upload from 'antd/es/upload';\nimport Input from 'antd/es/input';\nimport Spin from 'antd/es/spin';\nimport Row from 'antd/es/row';\nimport Button from 'antd/es/button';\nimport message from 'antd/es/message';\nimport { useTranslation } from 'react-i18next';\nimport InboxOutlined from '@ant-design/icons/InboxOutlined';\nimport DeleteOutlined from '@ant-design/icons/DeleteOutlined';\nimport { RcFile } from 'antd/es/upload/interface';\nimport { EErrorStatus } from 'common/models/requestModels';\nimport { getYouTubeData, checkVideo } from 'common/helpers/loader.helper';\nimport { uploadVideo } from 'entities/Video/Video.transport';\nimport { IAddPlayerVideoParams } from 'entities/Player/Player.models';\nimport { maxVideoTitleLength } from 'entities/Video/Video.models';\n\nconst { Dragger } = Upload;\n\nenum EUploadType {\n fromFile = 'fromFile',\n fromYoutube = 'fromYoutube'\n}\n\ninterface IComponentProps {\n onCancel: () => void;\n setUploadData: (data: Partial) => void;\n isDesktop: boolean;\n}\n\ninterface IVideoFileData {\n title: string;\n}\n\ntype AllProps = IComponentProps;\n\nconst PlayerVideosModalBodyUploadComponent: React.FC = props => {\n const { t } = useTranslation();\n const { onCancel, setUploadData, isDesktop } = props;\n const [activeTab, setActiveTab] = useState(EUploadType.fromFile);\n const [youtubeLink, setYoutubeLink] = useState('');\n const [videoFile, setVideoFile] = useState();\n const [loading, setLoading] = useState(false);\n const [videoFileData, setVideoFileData] = useState({ title: '' });\n\n const onChangeTab = useCallback(newActiveTab => {\n setActiveTab(newActiveTab);\n }, []);\n\n const isUploadButtonDisabled = useMemo(() => {\n if (activeTab === EUploadType.fromFile) {\n return !videoFile;\n } else {\n return !youtubeLink;\n }\n }, [videoFile, youtubeLink, activeTab]);\n\n const onBeforeUpload = useCallback(async (file: RcFile): Promise => {\n setLoading(true);\n const isVideoOk = await checkVideo(file);\n if (isVideoOk) {\n setVideoFile(file);\n const videoTitle = file.name || '';\n setVideoFileData({ title: videoTitle.substr(0, maxVideoTitleLength) });\n }\n setLoading(false);\n return Promise.reject();\n }, []);\n\n const onRemoveFile = useCallback(() => {\n setVideoFile(undefined);\n setVideoFileData({ title: '' });\n }, [videoFile]);\n\n const onChangeYouTubeLink = useCallback((e: React.ChangeEvent) => {\n setYoutubeLink(e?.target?.value);\n }, []);\n\n const onUpload = useCallback(async () => {\n setLoading(true);\n let videoData: Partial = { title: '' };\n\n if (activeTab === EUploadType.fromYoutube) {\n const data = await getYouTubeData(youtubeLink);\n if (typeof data === 'object') {\n videoData = { ...videoData, ...data };\n }\n } else if (videoFile) {\n try {\n const { id } = await uploadVideo(videoFile, videoFileData.title);\n videoData = { ...videoData, ...videoFileData, video: id };\n } catch (e) {\n switch (e.status) {\n case EErrorStatus.PayloadTooLarge: {\n message.error(t('Size should be less than 100MB'));\n break;\n }\n case EErrorStatus.UnsupportedMediaType: {\n message.error(t('Only video files'));\n break;\n }\n\n default: {\n message.error(t('Error while uploading video'));\n break;\n }\n }\n }\n }\n\n setLoading(false);\n\n if (videoData?.title) {\n setUploadData(videoData);\n }\n }, [activeTab, youtubeLink, videoFileData, videoFile]);\n\n return (\n \n
\n \n \n {videoFileData.title ? (\n \n {videoFileData.title} \n \n
\n ) : (\n \n \n \n
\n \n {t('Click or drag file to this area to upload')}\n \n \n )}\n \n \n {t('Link on video from YouTube')} \n \n \n \n \n \n {t('Cancel')}\n \n \n {t('Upload')}\n \n
\n \n
\n );\n};\n\nexport const PlayerVideosModalBodyUpload = PlayerVideosModalBodyUploadComponent;\n","import React, { useCallback } from 'react';\nimport Button from 'antd/es/button';\nimport Col from 'antd/es/col';\nimport Row from 'antd/es/row';\nimport Typography from 'antd/es/typography';\nimport { useHistory } from 'react-router';\nimport queryString from 'query-string';\nimport Icon from '@ant-design/icons/es/components/Icon';\nimport { useTranslation } from 'react-i18next';\nimport { ReactComponent as NoDataIcon } from 'app/assets/icons/nodata-magnifier.svg';\nimport { EPlayerAcademyTabKeys, EPlayerTabKeys } from 'entities/Player/Player.models';\n\ninterface IComponentProps {\n showClearFilterButton: boolean;\n clearFilter: (tab: EPlayerAcademyTabKeys) => void;\n}\n\nconst PlayerAcademyTabListNoDataComponent: React.FC = props => {\n const { showClearFilterButton, clearFilter } = props;\n const history = useHistory();\n const listType = queryString.parse(history.location.search).tab as any;\n const isSearch = listType === EPlayerAcademyTabKeys.Search;\n const isMyRequests = listType === EPlayerAcademyTabKeys.MyRequests;\n const isFollow = listType === EPlayerAcademyTabKeys.Follow;\n const { t } = useTranslation();\n\n const redirectFromList = useCallback(\n (needClear?: boolean) => {\n if (needClear) {\n clearFilter && clearFilter(listType);\n // window.location.replace(`${EPlayerTabKeys.Academy}?tab=${listType}`);\n } else {\n if (listType === EPlayerAcademyTabKeys.Follow) {\n // window.location.replace(EPlayerTabKeys.Tests);\n history.push(EPlayerTabKeys.Tests);\n } else {\n clearFilter && clearFilter(EPlayerAcademyTabKeys.Search);\n // window.location.replace(`${EPlayerTabKeys.Academy}?tab=${EPlayerAcademyTabKeys.Search}`);\n }\n }\n },\n [listType, clearFilter, history]\n );\n\n return (\n \n \n \n \n \n {t('No academies found')} \n \n {isSearch && t('empty-search-description')}\n {isFollow && t('empty-follow-description')}\n {isMyRequests && t('empty-request-description')}\n \n \n {showClearFilterButton || isSearch ? (\n redirectFromList(true)} className=\"mt-9\" size=\"large\" type=\"primary\">\n {t('Clear filter')}\n \n ) : (\n redirectFromList(false)} className=\"mt-9\" size=\"large\" type=\"primary\">\n {isMyRequests && t('Back to academy list')}\n {isFollow && t('Do tests')}\n \n )}\n \n \n
\n );\n};\n\nexport const PlayerAcademyTabListNoData = PlayerAcademyTabListNoDataComponent;\n","import React from 'react';\nimport { InfiniteList } from 'common/components/InfiniteList';\nimport { IBaseFilterModel } from 'common/models/requestModels';\nimport { LoadingSpin } from 'common/components/LoadingSpin';\nimport { IAcademyCollection, IAcademyModel } from 'entities/Academy/Academy.models';\nimport { communicationAcademy, IAcademyConnectedProps } from 'entities/Academy/Academy.communication';\nimport { AcademyListItem } from 'entities/Academy/components/List/AcademyListItem';\nimport { PlayerAcademyTabListNoData } from 'entities/Player/components/Tabs/PlayerAcademyTabNoData';\nimport { EPlayerAcademyTabKeys, IPlayerAcademyCollectionFilter } from 'entities/Player/Player.models';\n\ninterface IComponentProps {\n clearFilter: (tab: EPlayerAcademyTabKeys) => void;\n}\ntype AllProps = IAcademyConnectedProps & IComponentProps;\n\nclass AcademyListComponent extends InfiniteList<\n IAcademyCollection,\n IAcademyModel,\n AllProps,\n Partial\n> {\n loadCollection = async (params: IBaseFilterModel) => {\n const { getAcademyCollectionForPlayer, filter } = this.props;\n const { location, resultRangesValue, ...clearedFilter } = filter || {};\n const resultRanges = resultRangesValue?.map(item => item.id);\n\n if (filter?.playerId) {\n const newFilter: IPlayerAcademyCollectionFilter = {\n ...clearedFilter,\n ...params,\n ...location,\n resultRanges,\n playerId: filter?.playerId\n };\n\n if (filter?.ageGroup) {\n newFilter.ageGroup = filter?.ageGroup;\n }\n\n return getAcademyCollectionForPlayer(newFilter);\n }\n };\n\n renderListItem = (item: IAcademyModel) => {\n return ;\n };\n\n getCollection = () => {\n return this.props.academyCollectionForPlayer;\n };\n clearCollection = () => {\n return this.props.clearAcademyCollectionForPlayer();\n };\n renderNoData = () => {\n const { filter, academyCollectionForPlayer, clearFilter } = this.props;\n const { loading, data } = academyCollectionForPlayer;\n const showClearFilterButton = !!(filter?.name || filter?.location || filter?.resultRangesValue || filter?.ageGroup);\n\n return !loading && data?.data.length === 0 ? (\n \n ) : (\n \n );\n };\n}\n\nexport const AcademyList = communicationAcademy.injector(AcademyListComponent);\n","import { options } from 'options';\nimport React from 'react';\nimport { Skeleton } from 'antd';\nimport Autocomplete from 'react-google-autocomplete';\nimport debounce from 'lodash.debounce';\nimport { CloseCircleFilled } from '@ant-design/icons';\nimport { SelectProps } from 'antd/es/select';\nimport {\n ELocationType,\n ILocationModel,\n locationFormatter,\n parseLocation,\n parseLocationCountryCode\n} from 'common/helpers/location.helper';\nimport { getCurrentLang } from 'common/helpers/i18n';\n\ninterface IComponentProps {\n placeholder?: string;\n value?: ILocationModel;\n onChange?: (value?: ILocationModel) => void;\n disabled?: boolean;\n types?: ELocationType[];\n withCountryCode?: boolean;\n}\n\ninterface IComponentState {\n active: boolean;\n remount: boolean;\n key: string;\n}\n\ntype AllProps = IComponentProps & SelectProps;\n\nexport class LocationInput extends React.PureComponent {\n state: IComponentState = {\n active: false,\n remount: false,\n key: 'key'\n };\n\n onChange = debounce((value?: ILocationModel) => {\n const { onChange } = this.props;\n if (onChange) {\n value ? onChange(value) : onChange(undefined);\n }\n }, 300);\n\n onKey = (event: KeyboardEvent) => {\n const { active } = this.state;\n\n if (active && event.keyCode === 13) {\n event.preventDefault();\n }\n };\n\n remount = () => {\n // eslint-disable-next-line react/no-did-update-set-state\n this.setState({ remount: true }, () => {\n this.setState({ remount: false });\n });\n };\n\n componentDidUpdate(prevProps: AllProps) {\n if (!prevProps.value && this.props.value) {\n this.remount();\n }\n }\n\n delayedRemount() {\n // @ts-ignore\n if (!window.google?.maps) {\n setTimeout(() => {\n this.setState({ key: `key` });\n }, 0);\n }\n setTimeout(() => {\n // @ts-ignore\n if (window.google?.maps && this.state.key === 'key') {\n this.setState({ key: `${Math.random()}` });\n }\n }, 1000);\n }\n\n componentDidCatch() {\n this.delayedRemount();\n }\n\n render() {\n const {\n placeholder = '',\n value,\n disabled,\n className = '',\n types = [ELocationType.Address],\n withCountryCode,\n allowClear\n } = this.props;\n const { remount, key } = this.state;\n const initValue = locationFormatter(value);\n const lang = getCurrentLang();\n\n return (\n \n {/* @ts-ignore */}\n {!remount && window.google?.maps ? (\n <>\n
{\n this.setState({ active: true });\n }}\n onPlaceSelected={(place: any) => {\n if (!place || !place.geometry) {\n this.onChange(undefined);\n return;\n }\n\n const res: ILocationModel = {\n region:\n parseLocation(place, ELocationType.RegionLevelOne) || parseLocation(place, ELocationType.RegionLevelTwo),\n country: parseLocation(place, ELocationType.Country),\n city: parseLocation(place, ELocationType.City),\n placeId: place.place_id || ''\n };\n\n if (withCountryCode) {\n res.countryCode = parseLocationCountryCode(place);\n }\n\n this.onChange(res);\n this.setState({ active: false });\n }}\n options={{\n types\n }}\n onKeyPress={this.onKey}\n onKeyDown={this.onKey}\n onKeyUp={this.onKey}\n onChange={() => this.onChange(undefined)}\n disabled={disabled}\n />\n {allowClear && value && (\n {\n this.props?.onChange && this.props?.onChange(undefined);\n this.setState({ remount: true }, () => {\n this.setState({ remount: false });\n });\n }}\n >\n \n
\n )}\n >\n ) : (\n (() => {\n this.delayedRemount();\n return ;\n })()\n )}\n \n );\n }\n}\n","import * as React from 'react';\nimport Select, { SelectProps } from 'antd/es/select';\nimport { useTranslation } from 'react-i18next';\nimport { PlayerAgeGroup } from 'entities/Player/Player.models';\n\nexport const AgeGroupSelector: React.FC> = props => {\n const { t } = useTranslation();\n return (\n triggerNode as HTMLElement} {...props}>\n {PlayerAgeGroup.map(age => (\n \n {t(`${age}`)}\n \n ))}\n \n );\n};\n","import Card from 'antd/es/card';\nimport Col from 'antd/es/col';\nimport Input from 'antd/es/input';\nimport Row from 'antd/es/row';\nimport Typography from 'antd/es/typography';\nimport React, { ChangeEvent } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useDebouncedCallback } from 'use-debounce';\nimport { ELocationType, ILocationModel } from 'common/helpers/location.helper';\nimport { LocationInput } from 'common/components/Input/LocationInput';\nimport { AgeGroupSelector } from 'common/components/Selector/AgeGroupSelector';\n// import { TagsCheckbox } from 'common/components/TagsCheckbox/TagsCheckbox';\nimport { EPlayerAgeGroup, IPlayerAcademyCollectionFilter } from 'entities/Player/Player.models';\n\ninterface IComponentProps {\n onFilterChange: (filter: Partial) => void;\n filter?: Partial;\n}\n\nexport const AcademyListFilterCard: React.FC = props => {\n const { t } = useTranslation();\n const { onFilterChange, filter } = props;\n const nameValue = filter?.name;\n const locationValue = filter?.location;\n const ageGroupValue = filter?.ageGroup;\n // const resultRanges = filter?.resultRangesValue;\n\n const autocompleteSearch = useDebouncedCallback((text: string) => {\n const name = text === '' ? undefined : text;\n onFilterChange({ name });\n }, 300);\n\n const locationSearch = (location?: ILocationModel) => {\n if (JSON.stringify(filter?.location) !== JSON.stringify(location)) {\n onFilterChange({ location });\n }\n };\n\n const onChangeAgeSelector = (ageGroup: EPlayerAgeGroup) => {\n onFilterChange({ ageGroup });\n };\n\n // const onChangeTags = (resultRangesValue?: { id: string }[]) => {\n // onFilterChange({ resultRangesValue });\n // };\n\n return (\n \n \n {/* */}\n {/* */}\n {/* */}\n {/*
*/}\n {/* */}\n \n {t('Academy name')} \n ) => autocompleteSearch.callback(e.target.value)}\n />\n \n\n \n {t('Age group')} \n \n \n \n {t('City or region')} \n \n \n
\n \n );\n};\n","import React, { useEffect, useState, Fragment } from 'react';\nimport Col from 'antd/es/col';\nimport Radio from 'antd/es/radio';\nimport Row from 'antd/es/row';\nimport { useTranslation } from 'react-i18next';\nimport { useHistory, useParams } from 'react-router';\nimport { useDebouncedCallback } from 'use-debounce';\nimport { useMediaPredicate } from 'react-media-hook';\nimport { ERequestType } from 'common/models/commonModels';\nimport { objectToQuery, queryToObject } from 'common/helpers/filters.helper';\nimport { MEDIA_DESKTOP } from 'common/const/config.const';\nimport { EPlayerAcademyTabKeys, IPlayerAcademyCollectionFilter } from 'entities/Player/Player.models';\nimport { AcademyList } from 'entities/Academy/components/List/AcademyList';\nimport { AcademyListFilterCard } from 'entities/Academy/components/List/AcademyListFilterCard';\n\nconst selectTab = (key?: EPlayerAcademyTabKeys | string): EPlayerAcademyTabKeys => {\n switch (key) {\n case EPlayerAcademyTabKeys.Search:\n return EPlayerAcademyTabKeys.Search;\n\n case EPlayerAcademyTabKeys.MyRequests:\n return EPlayerAcademyTabKeys.MyRequests;\n\n case EPlayerAcademyTabKeys.Follow:\n return EPlayerAcademyTabKeys.Follow;\n\n default:\n return EPlayerAcademyTabKeys.Search;\n }\n};\n\nconst PlayerAcademyTabComponent: React.FC = () => {\n const isDesktop: boolean = useMediaPredicate(`(min-width: ${MEDIA_DESKTOP})`);\n const { id: playerId } = useParams();\n const history = useHistory();\n const { t } = useTranslation();\n const [renderIndex, setRenderIndex] = useState(Math.random());\n\n const initState = {\n tab: EPlayerAcademyTabKeys.Search,\n location: undefined,\n name: undefined,\n ageGroup: undefined,\n resultRangesValue: undefined\n };\n\n const [state, setState] = useState>({\n ...initState,\n ...queryToObject>(initState)\n });\n\n const debPush = useDebouncedCallback((val: any) => {\n history.replace(val);\n }, 300);\n\n useEffect(() => {\n debPush.callback({ search: objectToQuery(state) });\n }, [state]);\n\n const onTabChange = (tab: string) => {\n setState({ ...state, tab: selectTab(tab) });\n };\n\n const { tab: activeTab, ...filter } = state;\n\n const isRequestTab = activeTab === EPlayerAcademyTabKeys.MyRequests;\n const isFollowTab = activeTab === EPlayerAcademyTabKeys.Follow;\n const requestType = isRequestTab ? ERequestType.PlayerToAcademy : isFollowTab ? ERequestType.AcademyToPlayer : undefined;\n\n return (\n <>\n \n \n onTabChange(key.target.value)}\n >\n \n {t('Search')}\n \n \n {t('My requests')}\n \n \n {t('Follow on me')}\n \n \n
\n \n \n setState({ ...state, ...partialFilter })} />\n \n {\n setState({ ...initState, tab: tabNew });\n setRenderIndex(Math.random());\n }}\n />\n >\n );\n};\n\nexport const PlayerAcademyTab = PlayerAcademyTabComponent;\n","import React from 'react';\nimport classNames from 'classnames';\nimport AntdInputNumber, { InputNumberProps } from 'antd/es/input-number';\n\ninterface IProps extends InputNumberProps {}\n\nconst DEFAULT_PRECISION = 2;\nconst DEFAULT_STEP = 1;\nconst DEFAULT_MIN = 0;\nconst DEFAULT_MAX = 9999;\n\nconst Component: React.FC = props => {\n const { className, min = DEFAULT_MIN, max = DEFAULT_MAX, step = DEFAULT_STEP, precision = DEFAULT_PRECISION, ...rest } = props;\n\n return (\n \n );\n};\n\nexport const InputNumber = Component;\n","import React from 'react';\nimport Select, { SelectProps } from 'antd/es/select';\nimport Tooltip from 'antd/es/tooltip';\nimport { useTranslation } from 'react-i18next';\nimport { EFieldPositions, FIELD_POSITIONS } from 'entities/Player/Player.models';\n\ninterface IProps extends SelectProps {\n availablePositions?: EFieldPositions[];\n max?: number;\n}\n\nconst SELECT_STYLE = { width: '100%' };\n\nexport const FieldPositionSelector: React.FC = props => {\n const { t } = useTranslation();\n const { availablePositions, ...allProps } = props;\n\n return (\n triggerNode as HTMLElement}\n style={SELECT_STYLE}\n maxTagCount=\"responsive\"\n optionLabelProp=\"value\"\n {...allProps}\n >\n {Object.entries(FIELD_POSITIONS)\n .filter(([position]) => Array.isArray(availablePositions) && availablePositions.includes(position as EFieldPositions))\n .map(([position, { label }]) => (\n \n \n \n {position} ({t(label)})\n \n \n \n ))}\n \n );\n};\n","import React, { Dispatch, SetStateAction } from 'react';\nimport ReactCrop from 'react-image-crop';\nimport { ICrop } from 'common/components/AvatarEditor/AvatarEditor';\n\ninterface IProps {\n src: string | ArrayBuffer | null | undefined;\n crop: ICrop;\n setCrop: Dispatch>;\n setImage: Dispatch>;\n}\n\nconst cropOptions = {\n minWidth: 100,\n minHeight: 100\n};\n\nconst imageStyle = { maxHeight: 600 };\n\nexport const AvatarEditorBody: React.FC = ({ src, crop, setCrop, setImage }) => {\n return (\n \n );\n};\n","import React, { useCallback, useEffect, useState } from 'react';\nimport Avatar from 'antd/es/avatar';\nimport Dropdown from 'antd/es/dropdown';\nimport Menu from 'antd/es/menu';\nimport message from 'antd/es/message';\nimport Modal from 'antd/es/modal';\nimport Spin from 'antd/es/spin';\nimport Upload from 'antd/es/upload';\nimport CameraOutlined from '@ant-design/icons/CameraOutlined';\nimport { useTranslation } from 'react-i18next';\nimport { RcFile } from 'antd/es/upload/interface';\nimport { useMediaPredicate } from 'react-media-hook';\nimport { AvatarEditorBody } from 'common/components/AvatarEditor/AvatarEditorBody';\nimport { checkImage } from 'common/helpers/loader.helper';\nimport { MEDIA_DESKTOP } from 'common/const/config.const';\nimport { uploadImage } from 'entities/Image/Image.transport';\nimport { getImageUrl } from 'entities/Image/Image.helper';\nimport { EImageSize } from 'entities/Image/Image.models';\n\nconst modalWidth = 700;\nconst avatarSize = 88;\n\nexport interface ICrop {\n aspect: number;\n height: number;\n unit?: string;\n width: number;\n x: number;\n y: number;\n}\n\nexport interface IProps {\n onChange: (imageId: string | null) => void;\n avatarId: string | null;\n}\n\nconst cropOptions = {\n aspect: 1,\n width: 100,\n height: 100,\n x: 0,\n y: 0\n};\n\nexport const AvatarEditor: React.FC = ({ onChange, avatarId }) => {\n const { t } = useTranslation();\n const isDesktop: boolean = useMediaPredicate(`(min-width: ${MEDIA_DESKTOP})`);\n const [isEditorVisible, setEditorVisible] = useState(false);\n const [src, setSrc] = useState();\n const [fileName, setFilename] = useState('');\n const [image, setImage] = useState(undefined);\n const [crop, setCrop] = useState(cropOptions);\n const [loading, setLoading] = useState(false);\n const [avatarSrc, setAvatarSrc] = useState(undefined);\n\n useEffect(() => {\n setAvatarSrc(getImageUrl(avatarId, EImageSize.X96));\n }, [avatarId]);\n\n const openEditor = useCallback(() => {\n setEditorVisible(true);\n }, []);\n\n const closeEditor = useCallback(() => {\n setEditorVisible(false);\n setSrc(null);\n setImage(undefined);\n }, []);\n\n const handleUpload = useCallback((file: RcFile): boolean => {\n if (checkImage(file)) {\n setFilename(file.name);\n const reader = new FileReader();\n reader.addEventListener('load', () => {\n setSrc(reader.result);\n openEditor();\n });\n reader.readAsDataURL(file);\n }\n return false;\n }, []);\n\n const menu = React.useMemo(\n () => (\n \n