diff --git a/package.json b/package.json index 15541c0..0edc73b 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "@types/react-dom": "^16.9.8", "clsx": "^1.1.1", "date-fns": "^2.16.1", + "date-fns-tz": "^1.0.12", "graphql": "^15.4.0", "i18next": "^19.8.3", "i18next-browser-languagedetector": "^6.0.1", diff --git a/src/common/Form/SearchInput.tsx b/src/common/Form/SearchInput.tsx index 498a9d7..bab5cce 100644 --- a/src/common/Form/SearchInput.tsx +++ b/src/common/Form/SearchInput.tsx @@ -12,7 +12,7 @@ export type Props = TextFieldProps & { onResetValue?: () => void; }; -function SearchInput({ value, onResetValue, style, ...rest }: Props) { +function SearchInput({ value, onResetValue, ...rest }: Props) { const input = useRef(null); return ( @@ -20,7 +20,6 @@ function SearchInput({ value, onResetValue, style, ...rest }: Props) { {...rest} value={value} inputRef={input} - style={{ backgroundColor: 'rgba(0, 0, 0, 0.1)', ...(style ? style : {}) }} InputProps={{ startAdornment: ( { - setQuery({ [id]: new Date(e.target.value) }); + const date = new Date(e.target.value); + setQuery({ [id]: isValid(date) ? date : undefined }); }} InputLabelProps={{ shrink: true, diff --git a/src/features/ServerPage/features/IndexPage/IndexPage.tsx b/src/features/ServerPage/features/IndexPage/IndexPage.tsx index 40c1772..7271558 100644 --- a/src/features/ServerPage/features/IndexPage/IndexPage.tsx +++ b/src/features/ServerPage/features/IndexPage/IndexPage.tsx @@ -59,10 +59,10 @@ function IndexPage() { - + - + diff --git a/src/features/ServerPage/features/IndexPage/components/TodaysBestStatsPlayers/TodaysBestStatsPlayers.tsx b/src/features/ServerPage/features/IndexPage/components/TodaysBestStatsPlayers/TodaysBestStatsPlayers.tsx index 157a80c..47d2bae 100644 --- a/src/features/ServerPage/features/IndexPage/components/TodaysBestStatsPlayers/TodaysBestStatsPlayers.tsx +++ b/src/features/ServerPage/features/IndexPage/components/TodaysBestStatsPlayers/TodaysBestStatsPlayers.tsx @@ -1,6 +1,6 @@ -import React, { useRef, useState } from 'react'; -import { subHours } from 'date-fns'; +import React, { useState } from 'react'; import { useQuery } from '@apollo/client'; +import useServer from '@features/ServerPage/libs/ServerContext/useServer'; import formatNumber from '@utils/formatNumber'; import { SERVER_PAGE } from '@config/routes'; import { DAILY_PLAYER_STATS } from './queries'; @@ -19,12 +19,11 @@ import { DailyPlayerStatsQueryVariables } from '@libs/graphql/types'; import { DailyPlayerStatsList, DailyPlayerStatsRecord, Mode } from './types'; export interface Props { - server: string; t: TFunction; } -function TodaysBestStatsPlayers({ server, t }: Props) { - const createDateGT = useRef(subHours(new Date(), 30)); +function TodaysBestStatsPlayers({ t }: Props) { + const server = useServer(); const [mode, setMode] = useState('scoreAtt'); const { loading: loadingData, data } = useQuery< DailyPlayerStatsList, @@ -35,9 +34,9 @@ function TodaysBestStatsPlayers({ server, t }: Props) { limit: LIMIT, sort: [mode + ' DESC'], filter: { - createDateGT: createDateGT.current, + createDate: server.historyUpdatedAt, }, - server, + server: server.key, }, }); const records = data?.dailyPlayerStats?.items ?? []; @@ -49,7 +48,7 @@ function TodaysBestStatsPlayers({ server, t }: Props) { {t('todaysBestStatsPlayers.title')} @@ -108,7 +107,10 @@ function TodaysBestStatsPlayers({ server, t }: Props) { valueFormatter: index === 0 ? (record: DailyPlayerStatsRecord) => ( - + ) : index === 1 ? (record: DailyPlayerStatsRecord) => diff --git a/src/features/ServerPage/features/IndexPage/components/TodaysBestStatsTribes/TodaysBestStatsTribes.tsx b/src/features/ServerPage/features/IndexPage/components/TodaysBestStatsTribes/TodaysBestStatsTribes.tsx index 70f372b..5ff1a49 100644 --- a/src/features/ServerPage/features/IndexPage/components/TodaysBestStatsTribes/TodaysBestStatsTribes.tsx +++ b/src/features/ServerPage/features/IndexPage/components/TodaysBestStatsTribes/TodaysBestStatsTribes.tsx @@ -1,6 +1,6 @@ -import React, { useRef, useState } from 'react'; -import { subHours } from 'date-fns'; +import React, { useState } from 'react'; import { useQuery } from '@apollo/client'; +import useServer from '@features/ServerPage/libs/ServerContext/useServer'; import formatNumber from '@utils/formatNumber'; import { SERVER_PAGE } from '@config/routes'; import { DAILY_TRIBE_STATS } from './queries'; @@ -18,12 +18,11 @@ import { DailyTribeStatsQueryVariables } from '@libs/graphql/types'; import { DailyTribeStatsList, DailyTribeStatsRecord, Mode } from './types'; export interface Props { - server: string; t: TFunction; } -function TodaysBestStatsTribes({ server, t }: Props) { - const createDateGT = useRef(subHours(new Date(), 30)); +function TodaysBestStatsTribes({ t }: Props) { + const server = useServer(); const [mode, setMode] = useState('scoreAtt'); const { loading: loadingData, data } = useQuery< DailyTribeStatsList, @@ -34,9 +33,9 @@ function TodaysBestStatsTribes({ server, t }: Props) { limit: LIMIT, sort: [mode + ' DESC'], filter: { - createDateGT: createDateGT.current, + createDate: server.historyUpdatedAt, }, - server, + server: server.key, }, }); const records = data?.dailyTribeStats?.items ?? []; @@ -48,7 +47,7 @@ function TodaysBestStatsTribes({ server, t }: Props) { {t('todaysBestStatsTribes.title')} @@ -105,7 +104,7 @@ function TodaysBestStatsTribes({ server, t }: Props) { ? (record: DailyTribeStatsRecord) => ( {record.tribe.tag} diff --git a/src/features/ServerPage/features/RankingPage/features/PlayerPage/features/DailyPage/DailyPage.tsx b/src/features/ServerPage/features/RankingPage/features/PlayerPage/features/DailyPage/DailyPage.tsx index 2e64894..40526bc 100644 --- a/src/features/ServerPage/features/RankingPage/features/PlayerPage/features/DailyPage/DailyPage.tsx +++ b/src/features/ServerPage/features/RankingPage/features/PlayerPage/features/DailyPage/DailyPage.tsx @@ -13,7 +13,7 @@ function DailyPage() { useTitle(t('title', { key })); return ( - + ); } diff --git a/src/features/ServerPage/features/RankingPage/features/PlayerPage/features/DailyPage/components/Ranking/Ranking.tsx b/src/features/ServerPage/features/RankingPage/features/PlayerPage/features/DailyPage/components/Ranking/Ranking.tsx index 3dd23df..ea835bc 100644 --- a/src/features/ServerPage/features/RankingPage/features/PlayerPage/features/DailyPage/components/Ranking/Ranking.tsx +++ b/src/features/ServerPage/features/RankingPage/features/PlayerPage/features/DailyPage/components/Ranking/Ranking.tsx @@ -1,19 +1,23 @@ import React, { useState } from 'react'; +import { format, isValid } from 'date-fns'; import { useQueryParams, NumberParam, withDefault, StringParam, + DateTimeParam, } from 'use-query-params'; import { useDebouncedCallback } from 'use-debounce'; import useUpdateEffect from '@libs/useUpdateEffect'; import useScrollToElement from '@libs/useScrollToElement'; +import useServer from '@features/ServerPage/libs/ServerContext/useServer'; import SortParam from '@libs/serialize-query-params/SortParam'; import useStats from './useStats'; import { validateRowsPerPage } from '@common/Table/helpers'; import { COLUMNS, LIMIT, DEFAULT_SORT } from './constants'; -import { Paper } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; +import { Paper, TextField } from '@material-ui/core'; import Table from '@common/Table/Table'; import TableToolbar from '@common/Table/TableToolbar'; import SearchInput from '@common/Form/SearchInput'; @@ -23,16 +27,19 @@ import { TFunction } from 'i18next'; import { DailyPlayerStatsRecord } from './types'; export interface Props { - server: string; t: TFunction; } -function Ranking({ server, t }: Props) { +function Ranking({ t }: Props) { + const classes = useStyles(); + const server = useServer(); + const defaultDate = new Date(server.historyUpdatedAt); const [query, setQuery] = useQueryParams({ page: withDefault(NumberParam, 0), limit: withDefault(NumberParam, LIMIT), q: withDefault(StringParam, ''), sort: withDefault(SortParam, DEFAULT_SORT), + createDate: withDefault(DateTimeParam, defaultDate), }); const limit = validateRowsPerPage(query.limit); const [q, setQ] = useState(query.q); @@ -47,14 +54,32 @@ function Ranking({ server, t }: Props) { const { dailyStats, total, loading } = useStats( query.page, limit, - server, + server.key, query.q, - query.sort.toString() + query.sort.toString(), + query.createDate ); return ( - + + { + const date = new Date(e.target.value); + setQuery({ createDate: isValid(date) ? date : undefined }); + }} + InputLabelProps={{ + shrink: true, + }} + /> ( - + ); } return newCol; @@ -115,4 +140,22 @@ function Ranking({ server, t }: Props) { ); } +const useStyles = makeStyles(theme => ({ + tableToolbar: { + justifyContent: 'flex-end', + flexWrap: 'wrap', + '& > *': { + margin: theme.spacing(0.5), + [theme.breakpoints.down(700)]: { + marginLeft: 0, + marginRight: 0, + width: '100%', + }, + }, + [theme.breakpoints.down(700)]: { + flexDirection: 'column', + }, + }, +})); + export default Ranking; diff --git a/src/features/ServerPage/features/RankingPage/features/PlayerPage/features/DailyPage/components/Ranking/useStats.ts b/src/features/ServerPage/features/RankingPage/features/PlayerPage/features/DailyPage/components/Ranking/useStats.ts index 5a0a78e..21406ad 100644 --- a/src/features/ServerPage/features/RankingPage/features/PlayerPage/features/DailyPage/components/Ranking/useStats.ts +++ b/src/features/ServerPage/features/RankingPage/features/PlayerPage/features/DailyPage/components/Ranking/useStats.ts @@ -1,6 +1,4 @@ -import { useMemo } from 'react'; import { useQuery } from '@apollo/client'; -import useServer from '@features/ServerPage/libs/ServerContext/useServer'; import { DAILY_PLAYER_STATS } from './queries'; import { DailyPlayerStatsQueryVariables } from '@libs/graphql/types'; @@ -12,17 +10,18 @@ export type QueryResult = { total: number; }; +export type Options = { + addTimezoneOffsetToCreateDate?: boolean; +}; + const usePlayers = ( page: number, limit: number, server: string, q: string, - sort: string + sort: string, + createDate: Date ): QueryResult => { - const { historyUpdatedAt } = useServer(); - const createDateGTE = useMemo(() => { - return historyUpdatedAt.toString().split('T')[0] + 'T00:00:00Z'; - }, [historyUpdatedAt]); const { loading: loadingStats, data } = useQuery< DailyStats, DailyPlayerStatsQueryVariables @@ -37,7 +36,7 @@ const usePlayers = ( exists: true, nameIEQ: '%' + q + '%', }, - createDateGTE, + createDate, }, server, }, diff --git a/src/features/ServerPage/libs/ServerContext/context.ts b/src/features/ServerPage/libs/ServerContext/context.ts index 30ad7ec..a20bc0e 100644 --- a/src/features/ServerPage/libs/ServerContext/context.ts +++ b/src/features/ServerPage/libs/ServerContext/context.ts @@ -7,9 +7,9 @@ const ctx = createContext({ numberOfPlayers: 0, numberOfTribes: 0, numberOfVillages: 0, - dataUpdatedAt: new Date(0), - historyUpdatedAt: new Date(0), - statsUpdatedAt: new Date(0), + dataUpdatedAt: new Date(0).toJSON(), + historyUpdatedAt: new Date(0).toJSON(), + statsUpdatedAt: new Date(0).toJSON(), status: SERVER_STATUS.OPEN, version: { code: '', diff --git a/src/features/ServerPage/libs/ServerContext/queries.ts b/src/features/ServerPage/libs/ServerContext/queries.ts index dd2b5d9..d1ac692 100644 --- a/src/features/ServerPage/libs/ServerContext/queries.ts +++ b/src/features/ServerPage/libs/ServerContext/queries.ts @@ -3,7 +3,6 @@ import { gql } from '@apollo/client'; export const SERVERS = gql` query servers($filter: ServerFilter, $limit: Int) { servers(filter: $filter, limit: $limit) { - total items { key numberOfPlayers diff --git a/src/features/ServerPage/libs/ServerContext/types.ts b/src/features/ServerPage/libs/ServerContext/types.ts index 16395e6..3dd55cc 100644 --- a/src/features/ServerPage/libs/ServerContext/types.ts +++ b/src/features/ServerPage/libs/ServerContext/types.ts @@ -7,9 +7,9 @@ export type Server = { numberOfPlayers: number; numberOfTribes: number; numberOfVillages: number; - dataUpdatedAt: string | Date; - historyUpdatedAt: string | Date; - statsUpdatedAt: string | Date; + dataUpdatedAt: string; + historyUpdatedAt: string; + statsUpdatedAt: string; version: { code: string; host: string; diff --git a/src/libs/date/addTimezoneOffset.ts b/src/libs/date/addTimezoneOffset.ts new file mode 100644 index 0000000..fec2282 --- /dev/null +++ b/src/libs/date/addTimezoneOffset.ts @@ -0,0 +1,8 @@ +import { addMinutes } from 'date-fns'; + +const addTimezoneOffset = (d: Date): Date => { + const offset = d.getTimezoneOffset(); + return addMinutes(d, -1 * offset); +}; + +export default addTimezoneOffset; diff --git a/src/libs/date/format.ts b/src/libs/date/format.ts deleted file mode 100644 index 9c837f5..0000000 --- a/src/libs/date/format.ts +++ /dev/null @@ -1,12 +0,0 @@ -const format = (d: Date) => { - return d.toLocaleString(undefined, { - year: 'numeric', - month: '2-digit', - day: '2-digit', - hour: '2-digit', - minute: '2-digit', - second: '2-digit', - }); -}; - -export default format; diff --git a/src/libs/graphql/types.ts b/src/libs/graphql/types.ts index a8a2097..f1bf5ee 100644 --- a/src/libs/graphql/types.ts +++ b/src/libs/graphql/types.ts @@ -70,6 +70,7 @@ export type DailyPlayerStatsFilter = { createDateGT?: Date | string; createDateGTE?: Date | string; createDateLTE?: Date | string; + createDate?: Date | string; playerFilter?: PlayerFilter; playerID?: number[]; }; @@ -141,6 +142,7 @@ export type LiveEnnoblementsQueryVariables = { export type DailyTribeStatsFilter = { createDateGT?: Date | string; createDateGTE?: Date | string; + createDate?: Date | string; tribeID?: number[]; tribeFilter?: TribeFilter; }; diff --git a/src/libs/i18n/en/server-page/ranking-page/player-page/daily-page.ts b/src/libs/i18n/en/server-page/ranking-page/player-page/daily-page.ts index fd663ab..b5d9208 100644 --- a/src/libs/i18n/en/server-page/ranking-page/player-page/daily-page.ts +++ b/src/libs/i18n/en/server-page/ranking-page/player-page/daily-page.ts @@ -11,6 +11,7 @@ const translations = { scoreTotal: 'OD', }, searchInputPlaceholder: 'Search player', + createDateInputLabel: 'Date', }, }; diff --git a/src/libs/i18n/pl/server-page/ranking-page/player-page/daily-page.ts b/src/libs/i18n/pl/server-page/ranking-page/player-page/daily-page.ts index e8155d2..d2e8cf6 100644 --- a/src/libs/i18n/pl/server-page/ranking-page/player-page/daily-page.ts +++ b/src/libs/i18n/pl/server-page/ranking-page/player-page/daily-page.ts @@ -11,6 +11,7 @@ const translations = { scoreTotal: 'Pokonani ogólnie', }, searchInputPlaceholder: 'Wyszukaj gracza', + createDateInputLabel: 'Data', }, }; diff --git a/yarn.lock b/yarn.lock index 0dbb33d..3f697d3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4225,6 +4225,11 @@ data-urls@^2.0.0: whatwg-mimetype "^2.3.0" whatwg-url "^8.0.0" +date-fns-tz@^1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/date-fns-tz/-/date-fns-tz-1.0.12.tgz#2d680e1099767775cff7a30eac34362d52639fed" + integrity sha512-Ca+9pjGkU90XDHnclfSjz9o7g/ZqyYyYI0aCYmbf65P75oy8gktuaRslO3UPXl3ADgAnF9/KCykQkpU3/xvtWQ== + date-fns@^2.16.1: version "2.16.1" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.16.1.tgz#05775792c3f3331da812af253e1a935851d3834b"