diff --git a/package.json b/package.json
index d23a6cc7..e0843a6a 100644
--- a/package.json
+++ b/package.json
@@ -14,10 +14,12 @@
},
"dependencies": {
"@reach/combobox": "^0.10.4",
+ "date-fns": "^2.14.0",
"history": "^4.10.1",
"lodash": "^4.17.15",
"node-sass": "^4.14.1",
"react": "^16.13.1",
+ "react-datepicker": "^3.1.3",
"react-dom": "^16.13.1",
"react-router": "^5.2.0",
"react-router-dom": "^5.2.0",
@@ -42,6 +44,7 @@
"@types/lodash": "^4.14.154",
"@types/node": "^12.0.0",
"@types/react": "^16.9.0",
+ "@types/react-datepicker": "^3.0.2",
"@types/react-dom": "^16.9.0",
"@types/react-router": "^5.1.7",
"@types/react-router-dom": "^5.1.5",
diff --git a/public/index.html b/public/index.html
index e91d53dd..382252e4 100644
--- a/public/index.html
+++ b/public/index.html
@@ -6,7 +6,7 @@
-
+
Instat TV
diff --git a/src/config/procedures.tsx b/src/config/procedures.tsx
index 50f3c0de..21badd69 100644
--- a/src/config/procedures.tsx
+++ b/src/config/procedures.tsx
@@ -2,6 +2,7 @@ export const PROCEDURES = {
auth_user: 'auth_user',
create_user: 'create_user',
get_cities: 'get_cities',
+ get_matches: 'get_matches',
get_players_teams_tournaments: 'get_players_teams_tournaments',
logout_user: 'logout_user',
lst_c_country: 'lst_c_country',
diff --git a/src/features/DateFilter/components/DatePicker/hooks.tsx b/src/features/DateFilter/components/DatePicker/hooks.tsx
new file mode 100644
index 00000000..4de51321
--- /dev/null
+++ b/src/features/DateFilter/components/DatePicker/hooks.tsx
@@ -0,0 +1,25 @@
+import { useEffect } from 'react'
+
+import ru from 'date-fns/locale/ru'
+import en from 'date-fns/locale/en-GB'
+
+import { registerLocale, setDefaultLocale } from 'react-datepicker'
+
+import { useLexicsStore } from 'features/LexicsStore'
+
+/**
+ * react-datepicker использует date-fns локейлы для локализации
+ * регистрируем [en, ru] чтобы названия дней недели менялись при смене языка
+ */
+export const useDatepickerLocales = () => {
+ const { lang } = useLexicsStore()
+
+ useEffect(() => {
+ registerLocale('ru', ru)
+ registerLocale('en', en)
+ }, [])
+
+ useEffect(() => {
+ setDefaultLocale(lang)
+ }, [lang])
+}
diff --git a/src/features/DateFilter/components/DatePicker/index.tsx b/src/features/DateFilter/components/DatePicker/index.tsx
new file mode 100644
index 00000000..31cde6e7
--- /dev/null
+++ b/src/features/DateFilter/components/DatePicker/index.tsx
@@ -0,0 +1,79 @@
+import React from 'react'
+
+import type { ReactDatePickerProps } from 'react-datepicker'
+import DatePickerComponent from 'react-datepicker'
+import 'react-datepicker/dist/react-datepicker.css'
+
+import addMonths from 'date-fns/addMonths'
+
+import { useLexicsStore } from 'features/LexicsStore'
+import { getDisplayDate, getMonthName } from 'features/DateFilter/helpers'
+
+import { useDatepickerLocales } from './hooks'
+import {
+ Wrapper,
+ MonthsWrapper,
+ CurrentMonth,
+ MonthButton,
+} from './styled'
+
+type Args = (
+ Parameters>[0]
+ & { lang: string }
+)
+
+const monthType = 'short'
+
+const renderCustomHeader = ({
+ date,
+ decreaseMonth,
+ increaseMonth,
+ lang,
+}: Args) => {
+ const prevMonth = getMonthName({
+ date: addMonths(date, -1),
+ lang,
+ monthType,
+ })
+ const nextMonth = getMonthName({
+ date: addMonths(date, 1),
+ lang,
+ monthType,
+ })
+ const currentDate = getDisplayDate({
+ date,
+ lang,
+ })
+ return (
+
+ {prevMonth}
+ {currentDate.month}, {currentDate.year}
+ {nextMonth}
+
+ )
+}
+
+type Props = Pick
+
+export const DatePicker = ({
+ onChange,
+ open,
+ selected,
+}: Props) => {
+ const { lang } = useLexicsStore()
+ useDatepickerLocales()
+ return (
+
+ renderCustomHeader({ ...props, lang })}
+ />
+
+ )
+}
diff --git a/src/features/DateFilter/components/DatePicker/styled.tsx b/src/features/DateFilter/components/DatePicker/styled.tsx
new file mode 100644
index 00000000..103877f7
--- /dev/null
+++ b/src/features/DateFilter/components/DatePicker/styled.tsx
@@ -0,0 +1,138 @@
+import styled from 'styled-components/macro'
+
+export const Wrapper = styled.div`
+ position: absolute;
+ left: 0;
+ top: calc(100% + 14px);
+
+ .react-datepicker {
+ margin: 0;
+ border: none;
+ width: 288px;
+ background-color: #666666;
+ box-shadow: 0px 2px 50px #000000;
+ border-radius: 2px;
+ font-family: inherit;
+ color: #fff;
+ }
+
+ .react-datepicker__header {
+ border: none;
+ border-radius: 2;
+ padding-top: 12px;
+ background-color: #666666;
+ }
+
+ .react-datepicker__month-container {
+ width: 100%;
+ }
+
+ .react-datepicker__day-names {
+ margin-top: 24px;
+ margin-bottom: 12px;
+ display: flex;
+ justify-content: space-around;
+ }
+
+ .react-datepicker__day-name {
+ margin: 0;
+ width: 28px;
+ color: inherit;
+ font-size: 16px;
+ line-height: 16px;
+ text-align: center;
+ letter-spacing: 0.1px;
+ }
+
+ .react-datepicker__month {
+ margin: 0;
+ }
+
+ .react-datepicker__week {
+ margin: 8px 0;
+ display: flex;
+ justify-content: space-around;
+ }
+
+ .react-datepicker__day {
+ margin: 0;
+ border: none;
+ outline: none;
+ width: 28px;
+ height: 28px;
+ color: inherit;
+ opacity: 0.6;
+ font-weight: normal;
+ font-size: 12px;
+ border-radius: 50%;
+
+ :hover {
+ background-color: rgba(255, 255, 255, 0.4);
+ }
+ }
+
+ .react-datepicker__day--selected {
+ color: #005EDD;
+ background-color: #ffffff;
+ opacity: 1;
+ }
+
+ .react-datepicker__day--keyboard-selected {
+ color: inherit;
+ background-color: transparent;
+ }
+
+ .react-datepicker__day--outside-month {
+ opacity: 0.2
+ }
+
+ .react-datepicker-popper {
+ transform: translate(0, 0) !important;
+ }
+
+ .react-datepicker-popper[data-placement^="bottom"] {
+ margin-top: 0px;
+ }
+
+ .react-datepicker__input-container,
+ .react-datepicker__triangle {
+ display: none;
+ }
+`
+
+export const MonthsWrapper = styled.div`
+ width: 100%;
+ height: 28px;
+ padding: 0 12px;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ font-weight: 600;
+ font-size: 16px;
+ line-height: 16px;
+ text-align: center;
+ letter-spacing: 0.1px;
+ text-transform: capitalize;
+`
+
+export const CurrentMonth = styled.span`
+ min-width: 100px;
+ height: 100%;
+ padding: 0 14px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background-color: #005EDD;
+ border-radius: 16px;
+`
+
+export const MonthButton = styled.button`
+ border: none;
+ outline: none;
+ padding: 0;
+ opacity: 0.4;
+ color: inherit;
+ background-color: transparent;
+ text-transform: inherit;
+ cursor: pointer;
+`
diff --git a/src/features/DateFilter/helpers.tsx b/src/features/DateFilter/helpers.tsx
new file mode 100644
index 00000000..86f56a4e
--- /dev/null
+++ b/src/features/DateFilter/helpers.tsx
@@ -0,0 +1,27 @@
+type Args = {
+ date: Date,
+ lang: string,
+ monthType?: 'long' | 'short',
+}
+
+export const getMonthName = ({
+ date,
+ lang,
+ monthType,
+}: Args) => (
+ date.toLocaleString(lang, { month: monthType })
+)
+
+export const getDisplayDate = ({
+ date,
+ lang,
+ monthType = 'long',
+}: Args) => ({
+ day: date.getDate(),
+ month: getMonthName({
+ date,
+ lang,
+ monthType,
+ }),
+ year: date.getFullYear(),
+})
diff --git a/src/features/DateFilter/hooks/index.tsx b/src/features/DateFilter/hooks/index.tsx
new file mode 100644
index 00000000..cfea2951
--- /dev/null
+++ b/src/features/DateFilter/hooks/index.tsx
@@ -0,0 +1,69 @@
+import {
+ useState,
+ useCallback,
+ useEffect,
+} from 'react'
+
+import debounce from 'lodash/debounce'
+import format from 'date-fns/format'
+import addDays from 'date-fns/addDays'
+import startOfDay from 'date-fns/startOfDay'
+
+import { getMatches } from 'requests'
+import { useToggle } from 'hooks'
+import { useLexicsStore } from 'features/LexicsStore'
+
+import { getDisplayDate } from '../helpers'
+
+const dateFormat = 'dd/MM/yyyy HH:mm:ss'
+
+export const useDateFilter = () => {
+ const { lang } = useLexicsStore()
+ const {
+ close,
+ isOpen,
+ open,
+ } = useToggle()
+ const fetchMatches = useCallback(debounce(getMatches, 300), [])
+ const [currentDate, setCurrentDate] = useState(new Date())
+
+ const date = getDisplayDate({
+ date: currentDate,
+ lang,
+ })
+
+ const onPreviousClick = () => {
+ setCurrentDate(addDays(currentDate, -1))
+ }
+
+ const onNextClick = () => {
+ setCurrentDate(addDays(currentDate, 1))
+ }
+
+ const onDateChange = (newDate: Date | null) => {
+ if (newDate) {
+ setCurrentDate(newDate)
+ close()
+ }
+ }
+
+ useEffect(() => {
+ const formattedDate = format(startOfDay(currentDate), dateFormat)
+ fetchMatches({
+ date: formattedDate,
+ sportType: 1,
+ tournamentId: 8,
+ })
+ }, [fetchMatches, currentDate])
+
+ return {
+ close,
+ currentDate,
+ date,
+ isOpen,
+ onDateChange,
+ onNextClick,
+ onPreviousClick,
+ open,
+ }
+}
diff --git a/src/features/DateFilter/index.tsx b/src/features/DateFilter/index.tsx
index 640a302f..925b2999 100644
--- a/src/features/DateFilter/index.tsx
+++ b/src/features/DateFilter/index.tsx
@@ -1,5 +1,54 @@
import React from 'react'
-import { Wrapper } from './styled'
+import { OutsideClick } from 'features/OutsideClick'
-export const DateFilter = () =>
+import { useDateFilter } from './hooks'
+import { DatePicker } from './components/DatePicker'
+import {
+ Wrapper,
+ Button,
+ ArrowLeft,
+ ArrowRight,
+ DateButton,
+ Day,
+ MonthYearWrapper,
+ Month,
+ Year,
+} from './styled'
+
+export const DateFilter = () => {
+ const {
+ close,
+ currentDate,
+ date,
+ isOpen,
+ onDateChange,
+ onNextClick,
+ onPreviousClick,
+ open,
+ } = useDateFilter()
+ return (
+
+
+
+
+ {date.day}
+
+ {date.month}
+ {date.year}
+
+
+
+
+
+
+ )
+}
diff --git a/src/features/DateFilter/styled.tsx b/src/features/DateFilter/styled.tsx
index 8646cd0a..22a67329 100644
--- a/src/features/DateFilter/styled.tsx
+++ b/src/features/DateFilter/styled.tsx
@@ -1,3 +1,145 @@
import styled from 'styled-components/macro'
-export const Wrapper = styled.div``
+type Props = {
+ active: boolean,
+}
+
+export const Wrapper = styled.div`
+ position: relative;
+ height: 100%;
+ width: 100%;
+ display: flex;
+ box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3);
+
+ ${({ active }) => (active
+ ? `
+ & ${Button}, ${DateButton} {
+ color: #fff;
+ background-color: #666666;
+ }
+ `
+ : ''
+ )};
+`
+
+export const DateButton = styled.button`
+ border: none;
+ outline: none;
+ padding: 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ text-align: left;
+ width: 192px;
+ height: 100%;
+ border-left: 1px solid #222222;
+ border-right: 1px solid #222222;
+ cursor: pointer;
+ background-color: #3F3F3F;
+ color: #999999;
+
+ :hover {
+ background-color: #484848;
+ }
+
+ :active {
+ color: #fff;
+ background-color: #666666;
+ }
+`
+
+export const Day = styled.span`
+ font-weight: bold;
+ font-size: 38px;
+ letter-spacing: -0.03em;
+`
+
+export const Month = styled.span`
+ font-weight: bold;
+ font-size: 14px;
+`
+
+export const MonthYearWrapper = styled.div`
+ height: 28px;
+ margin-left: 4px;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+`
+
+export const Year = styled.span`
+ font-style: normal;
+ font-weight: 300;
+ font-size: 14px;
+`
+
+const Arrow = styled.div`
+ width: 16px;
+ height: 2px;
+ margin: auto;
+ background-color: #222222;
+
+ &::before {
+ content: '';
+ position: absolute;
+ width: 10px;
+ height: 10px;
+ border-left: 2px solid #222222;
+ border-bottom: 2px solid #222222;
+ }
+`
+
+export const ArrowLeft = styled(Arrow)`
+ &:before {
+ transform: rotate(45deg);
+ top: 19px;
+ left: 17px;
+ }
+`
+
+export const ArrowRight = styled(Arrow)`
+ &:before {
+ transform: rotate(225deg);
+ top: 19px;
+ right: 17px;
+ }
+`
+
+type ButtonProps = {
+ borderLeftRadius?: number,
+ borderRightRadius?: number,
+}
+
+export const Button = styled.button`
+ position: relative;
+ outline: none;
+ border: none;
+ width: 48px;
+ height: 100%;
+ cursor: pointer;
+ background-color: #3F3F3F;
+ ${({ borderLeftRadius }) => (
+ borderLeftRadius
+ ? `
+ border-top-left-radius: ${borderLeftRadius}px;
+ border-bottom-left-radius: ${borderLeftRadius}px;
+ `
+ : ''
+ )}
+ ${({ borderRightRadius }) => (
+ borderRightRadius
+ ? `
+ border-top-right-radius: ${borderRightRadius}px;
+ border-bottom-right-radius: ${borderRightRadius}px;
+ `
+ : ''
+ )}
+
+ :hover {
+ background-color: #484848;
+ }
+
+ :active {
+ background-color: #666666;
+ }
+`
diff --git a/src/features/Menu/styled.tsx b/src/features/Menu/styled.tsx
index 0a9fc0fa..b7f70873 100644
--- a/src/features/Menu/styled.tsx
+++ b/src/features/Menu/styled.tsx
@@ -7,7 +7,7 @@ export const Wrapper = styled.div`
display: flex;
justify-content: center;
align-items: center;
- width: 304px;
+ width: 320px;
height: 48px;
`
export const ToggleButton = styled.button`
diff --git a/src/requests/getMatches.tsx b/src/requests/getMatches.tsx
new file mode 100644
index 00000000..e82b89a6
--- /dev/null
+++ b/src/requests/getMatches.tsx
@@ -0,0 +1,56 @@
+import { DATA_URL, PROCEDURES } from 'config'
+import { callApi, getResponseData } from 'helpers'
+
+const proc = PROCEDURES.get_matches
+
+export type Item = {
+ id: number,
+ matches: Array,
+ name_eng: string,
+ name_rus: string,
+ sport: number,
+}
+
+export type Match = {
+ date: string,
+ id: number,
+ round_id: number,
+ stream_status: number,
+ team1: Team,
+ team2: Team,
+}
+
+export type Team = {
+ id: number,
+ name_eng: string,
+ name_rus: string,
+ score: number,
+}
+
+type Args = {
+ date: string,
+ sportType: number,
+ tournamentId: number,
+}
+
+export const getMatches = ({
+ date,
+ sportType,
+ tournamentId,
+}: Args): Promise> => {
+ const config = {
+ body: {
+ params: {
+ _p_date: date,
+ _p_sport: sportType,
+ _p_tournament_id: tournamentId,
+ },
+ proc,
+ },
+ }
+
+ return callApi({
+ config,
+ url: DATA_URL,
+ }).then(getResponseData(proc))
+}
diff --git a/src/requests/index.tsx b/src/requests/index.tsx
index 528c126b..762d8112 100644
--- a/src/requests/index.tsx
+++ b/src/requests/index.tsx
@@ -5,3 +5,4 @@ export * from './getCountries'
export * from './getCountryCities'
export * from './getLexics'
export * from './getSearchItems'
+export * from './getMatches'