huge refactor
This commit is contained in:
parent
819abb008f
commit
645af393f8
|
@ -11,7 +11,7 @@ export interface Props extends LineSvgProps {
|
||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const LineChart = ({ data, loading, ...rest }: Props) => {
|
const LineChart = ({ data, loading, yScale, xScale, ...rest }: Props) => {
|
||||||
const { t } = useTranslation(LINE_CHART);
|
const { t } = useTranslation(LINE_CHART);
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
|
@ -37,6 +37,8 @@ const LineChart = ({ data, loading, ...rest }: Props) => {
|
||||||
// tooltip={PointTooltip}
|
// tooltip={PointTooltip}
|
||||||
data={data}
|
data={data}
|
||||||
{...rest}
|
{...rest}
|
||||||
|
xScale={xScale?.type === 'time' ? { useUTC: false, ...xScale } : xScale}
|
||||||
|
yScale={yScale?.type === 'time' ? { useUTC: false, ...yScale } : yScale}
|
||||||
theme={darkTheme}
|
theme={darkTheme}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
@ -8,7 +8,6 @@ function PointTooltip(props: PointTooltipProps | BarTooltipDatum) {
|
||||||
'point' in props
|
'point' in props
|
||||||
? `X: ${props.point.data.xFormatted}, Y: ${props.point.data.yFormatted}`
|
? `X: ${props.point.data.xFormatted}, Y: ${props.point.data.yFormatted}`
|
||||||
: `${props.indexValue} - ${props.value}`;
|
: `${props.indexValue} - ${props.value}`;
|
||||||
console.log(props);
|
|
||||||
return (
|
return (
|
||||||
<Tooltip open placement="top" arrow title={title}>
|
<Tooltip open placement="top" arrow title={title}>
|
||||||
<div></div>
|
<div></div>
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import useDateUtils from '@libs/date/useDateUtils';
|
||||||
import { AUTHOR } from '@config/app';
|
import { AUTHOR } from '@config/app';
|
||||||
|
|
||||||
import useStyles from './styles';
|
import useStyles from './styles';
|
||||||
import { AppBar, Toolbar, Container, Typography } from '@material-ui/core';
|
import { AppBar, Toolbar, Container, Typography } from '@material-ui/core';
|
||||||
|
|
||||||
export default function Header() {
|
export default function Header() {
|
||||||
|
const dateUtils = useDateUtils();
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -12,7 +14,7 @@ export default function Header() {
|
||||||
<Container>
|
<Container>
|
||||||
<Toolbar disableGutters className={classes.toolbar}>
|
<Toolbar disableGutters className={classes.toolbar}>
|
||||||
<Typography align="center" className={classes.copyright}>
|
<Typography align="center" className={classes.copyright}>
|
||||||
© {new Date().getFullYear()} {AUTHOR}
|
© {dateUtils.getYear(dateUtils.date())} {AUTHOR}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
</Container>
|
</Container>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { get, isString, isNumber } from 'lodash';
|
import { get, isString, isNumber } from 'lodash';
|
||||||
import { format } from 'date-fns';
|
import useDateUtils from '@libs/date/useDateUtils';
|
||||||
import { DATE_FORMAT } from '@config/app';
|
import { DATE_FORMAT } from '@config/app';
|
||||||
|
|
||||||
import { TableRow, TableCell, Checkbox, Tooltip } from '@material-ui/core';
|
import { TableRow, TableCell, Checkbox, Tooltip } from '@material-ui/core';
|
||||||
|
@ -28,6 +28,8 @@ function EnhancedTableRow<T extends object>({
|
||||||
size = 'medium',
|
size = 'medium',
|
||||||
index,
|
index,
|
||||||
}: Props<T>) {
|
}: Props<T>) {
|
||||||
|
const dateUtils = useDateUtils();
|
||||||
|
|
||||||
const handleSelect = () => {
|
const handleSelect = () => {
|
||||||
if (onSelect) {
|
if (onSelect) {
|
||||||
onSelect(row);
|
onSelect(row);
|
||||||
|
@ -35,15 +37,30 @@ function EnhancedTableRow<T extends object>({
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatValue = (
|
const formatValue = (
|
||||||
v: string | number,
|
v: string | number | Date,
|
||||||
type: 'datetime' | 'date' | 'normal'
|
type: 'datetime' | 'dateutc' | 'date' | 'normal'
|
||||||
) => {
|
) => {
|
||||||
if ((isString(v) || isNumber(v)) && type === 'date') {
|
if ((isString(v) || isNumber(v) || v instanceof Date) && type === 'date') {
|
||||||
return format(new Date(v), DATE_FORMAT.DAY_MONTH_AND_YEAR);
|
return dateUtils.format(
|
||||||
|
dateUtils.date(v),
|
||||||
|
DATE_FORMAT.DAY_MONTH_AND_YEAR
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if ((isString(v) || isNumber(v)) && type === 'datetime') {
|
if (
|
||||||
return format(
|
(isString(v) || isNumber(v) || v instanceof Date) &&
|
||||||
new Date(v),
|
type === 'dateutc'
|
||||||
|
) {
|
||||||
|
return dateUtils.format(
|
||||||
|
dateUtils.dateInTZ(v, 'UTC'),
|
||||||
|
DATE_FORMAT.DAY_MONTH_AND_YEAR
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
(isString(v) || isNumber(v) || v instanceof Date) &&
|
||||||
|
type === 'datetime'
|
||||||
|
) {
|
||||||
|
return dateUtils.format(
|
||||||
|
dateUtils.date(v),
|
||||||
DATE_FORMAT.HOUR_MINUTES_SECONDS_DAY_MONTH_AND_YEAR
|
DATE_FORMAT.HOUR_MINUTES_SECONDS_DAY_MONTH_AND_YEAR
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ export type Column<T = any> = {
|
||||||
sortable?: boolean;
|
sortable?: boolean;
|
||||||
valueFormatter?: (v: T, i: number) => React.ReactNode;
|
valueFormatter?: (v: T, i: number) => React.ReactNode;
|
||||||
disablePadding?: boolean;
|
disablePadding?: boolean;
|
||||||
type?: 'normal' | 'datetime' | 'date';
|
type?: 'normal' | 'dateutc' | 'datetime' | 'date';
|
||||||
align?: 'left' | 'right' | 'center';
|
align?: 'left' | 'right' | 'center';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export const DEFAULT_LANGUAGE = process.env.REACT_APP_DEFAULT_LANGUAGE ?? 'en';
|
export const DEFAULT_LANGUAGE = process.env.REACT_APP_DEFAULT_LANGUAGE ?? 'pl';
|
||||||
|
|
||||||
export const NAME = 'TWHelp';
|
export const NAME = 'TWHelp';
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,8 @@ import { Switch, Route } from 'react-router-dom';
|
||||||
import { CssBaseline } from '@material-ui/core';
|
import { CssBaseline } from '@material-ui/core';
|
||||||
import ScrollToTop from '@common/ScrollToTop/ScrollToTop';
|
import ScrollToTop from '@common/ScrollToTop/ScrollToTop';
|
||||||
|
|
||||||
|
import VersionProvider from '../libs/VersionContext/Provider';
|
||||||
|
import DateUtilsProvider from '../libs/date/DateUtilsProvider';
|
||||||
import IndexPage from './IndexPage/IndexPage';
|
import IndexPage from './IndexPage/IndexPage';
|
||||||
import NotFoundPage from './NotFoundPage/NotFoundPage';
|
import NotFoundPage from './NotFoundPage/NotFoundPage';
|
||||||
import SearchPage from './SearchPage/SearchPage';
|
import SearchPage from './SearchPage/SearchPage';
|
||||||
|
@ -13,20 +15,24 @@ import ServerPage from './ServerPage/ServerPage';
|
||||||
function App() {
|
function App() {
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Switch>
|
<VersionProvider>
|
||||||
<Route path={ROUTES.INDEX_PAGE} exact>
|
<DateUtilsProvider>
|
||||||
<IndexPage />
|
<Switch>
|
||||||
</Route>
|
<Route path={ROUTES.INDEX_PAGE} exact>
|
||||||
<Route path={ROUTES.SEARCH_PAGE} exact>
|
<IndexPage />
|
||||||
<SearchPage />
|
</Route>
|
||||||
</Route>
|
<Route path={ROUTES.SEARCH_PAGE} exact>
|
||||||
<Route path={ROUTES.SERVER_PAGE.INDEX_PAGE}>
|
<SearchPage />
|
||||||
<ServerPage />
|
</Route>
|
||||||
</Route>
|
<Route path={ROUTES.SERVER_PAGE.INDEX_PAGE}>
|
||||||
<Route path="*">
|
<ServerPage />
|
||||||
<NotFoundPage />
|
</Route>
|
||||||
</Route>
|
<Route path="*">
|
||||||
</Switch>
|
<NotFoundPage />
|
||||||
|
</Route>
|
||||||
|
</Switch>
|
||||||
|
</DateUtilsProvider>
|
||||||
|
</VersionProvider>
|
||||||
<CssBaseline />
|
<CssBaseline />
|
||||||
<ScrollToTop />
|
<ScrollToTop />
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
|
|
@ -76,7 +76,6 @@ function GridItem({ t, server, hideTooltip = true }: Props) {
|
||||||
classes={{
|
classes={{
|
||||||
tooltip: classes.tooltip,
|
tooltip: classes.tooltip,
|
||||||
}}
|
}}
|
||||||
arrow
|
|
||||||
title={serverInfo}
|
title={serverInfo}
|
||||||
>
|
>
|
||||||
<InfoIcon color="inherit" />
|
<InfoIcon color="inherit" />
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import useDateUtils from '@libs/date/useDateUtils';
|
||||||
import useServer from '@features/ServerPage/libs/ServerContext/useServer';
|
import useServer from '@features/ServerPage/libs/ServerContext/useServer';
|
||||||
import useStyles from './useStyles';
|
import useStyles from './useStyles';
|
||||||
import formatDistanceToNow from '@libs/date/formatDistanceToNow';
|
|
||||||
import formatNumber from '@utils/formatNumber';
|
import formatNumber from '@utils/formatNumber';
|
||||||
import extractVersionCodeFromHostname from '@utils/extractVersionCodeFromHostname';
|
|
||||||
|
|
||||||
import { Typography } from '@material-ui/core';
|
import { Typography } from '@material-ui/core';
|
||||||
|
|
||||||
import { Locale } from '@libs/date/locales';
|
|
||||||
import { TFunction } from 'i18next';
|
import { TFunction } from 'i18next';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
|
@ -21,6 +19,7 @@ const ServerInfo = ({ t }: Props) => {
|
||||||
dataUpdatedAt,
|
dataUpdatedAt,
|
||||||
numberOfVillages,
|
numberOfVillages,
|
||||||
} = useServer();
|
} = useServer();
|
||||||
|
const dateUtils = useDateUtils();
|
||||||
|
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
|
||||||
|
@ -46,10 +45,7 @@ const ServerInfo = ({ t }: Props) => {
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography>
|
<Typography>
|
||||||
{t('pageLayout.sidebar.serverInfo.dataUpdatedAt', {
|
{t('pageLayout.sidebar.serverInfo.dataUpdatedAt', {
|
||||||
date: formatDistanceToNow(new Date(dataUpdatedAt), {
|
date: dateUtils.formatDistanceToNow(new Date(dataUpdatedAt), {
|
||||||
locale: extractVersionCodeFromHostname(
|
|
||||||
window.location.hostname
|
|
||||||
) as Locale,
|
|
||||||
addSuffix: true,
|
addSuffix: true,
|
||||||
}),
|
}),
|
||||||
})}
|
})}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import {
|
||||||
withDefault,
|
withDefault,
|
||||||
DateTimeParam,
|
DateTimeParam,
|
||||||
} from 'use-query-params';
|
} from 'use-query-params';
|
||||||
|
import useDateUtils from '@libs/date/useDateUtils';
|
||||||
import useScrollToElement from '@libs/useScrollToElement';
|
import useScrollToElement from '@libs/useScrollToElement';
|
||||||
import { validateRowsPerPage } from '@common/Table/helpers';
|
import { validateRowsPerPage } from '@common/Table/helpers';
|
||||||
import { ENNOBLEMENTS } from './queries';
|
import { ENNOBLEMENTS } from './queries';
|
||||||
|
@ -27,11 +28,12 @@ export interface Props {
|
||||||
|
|
||||||
function LatestSavedEnnoblements({ t, server }: Props) {
|
function LatestSavedEnnoblements({ t, server }: Props) {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const now = useRef(new Date());
|
const dateUtils = useDateUtils();
|
||||||
|
const now = useRef(dateUtils.date());
|
||||||
const [query, setQuery] = useQueryParams({
|
const [query, setQuery] = useQueryParams({
|
||||||
page: withDefault(NumberParam, 0),
|
page: withDefault(NumberParam, 0),
|
||||||
limit: withDefault(NumberParam, LIMIT),
|
limit: withDefault(NumberParam, LIMIT),
|
||||||
ennobledAtGTE: withDefault(DateTimeParam, new Date(0)),
|
ennobledAtGTE: withDefault(DateTimeParam, dateUtils.date(0)),
|
||||||
ennobledAtLTE: withDefault(DateTimeParam, now.current),
|
ennobledAtLTE: withDefault(DateTimeParam, now.current),
|
||||||
});
|
});
|
||||||
const limit = validateRowsPerPage(query.limit);
|
const limit = validateRowsPerPage(query.limit);
|
||||||
|
@ -46,8 +48,8 @@ function LatestSavedEnnoblements({ t, server }: Props) {
|
||||||
offset: query.page * limit,
|
offset: query.page * limit,
|
||||||
sort: ['ennobledAt DESC'],
|
sort: ['ennobledAt DESC'],
|
||||||
filter: {
|
filter: {
|
||||||
ennobledAtGTE: query.ennobledAtGTE,
|
ennobledAtGTE: dateUtils.zonedTimeToUTC(query.ennobledAtGTE),
|
||||||
ennobledAtLTE: query.ennobledAtLTE,
|
ennobledAtLTE: dateUtils.zonedTimeToUTC(query.ennobledAtLTE),
|
||||||
},
|
},
|
||||||
server,
|
server,
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { useQuery } from '@apollo/client';
|
import { useQuery } from '@apollo/client';
|
||||||
|
import useDateUtils from '@libs/date/useDateUtils';
|
||||||
import { STATISTICS } from './queries';
|
import { STATISTICS } from './queries';
|
||||||
import { LIMIT } from './constants';
|
import { LIMIT } from './constants';
|
||||||
|
|
||||||
|
@ -19,6 +20,7 @@ export interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
function PlayerStatistics({ server, t }: Props) {
|
function PlayerStatistics({ server, t }: Props) {
|
||||||
|
const dateUtils = useDateUtils();
|
||||||
const { loading: loadingData, data: queryRes } = useQuery<
|
const { loading: loadingData, data: queryRes } = useQuery<
|
||||||
ServerStats,
|
ServerStats,
|
||||||
ServerStatsQueryVariables
|
ServerStatsQueryVariables
|
||||||
|
@ -40,16 +42,18 @@ function PlayerStatistics({ server, t }: Props) {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
id: t<string>('playerStatistics.players'),
|
id: t<string>('playerStatistics.players'),
|
||||||
data: items.map(item => ({
|
data: items.map(item => {
|
||||||
x: new Date(item.createDate),
|
return {
|
||||||
y: item.activePlayers,
|
x: dateUtils.dateInTZ(item.createDate, 'UTC'),
|
||||||
})),
|
y: item.activePlayers,
|
||||||
|
};
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}, [items, loading, t]);
|
}, [items, loading, t, dateUtils]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper size="large" style={{ overflow: 'hidden' }}>
|
<Paper size="large" style={{ overflow: 'visible' }}>
|
||||||
<TableToolbar>
|
<TableToolbar>
|
||||||
<Typography variant="h4">{t('playerStatistics.title')}</Typography>
|
<Typography variant="h4">{t('playerStatistics.title')}</Typography>
|
||||||
</TableToolbar>
|
</TableToolbar>
|
||||||
|
@ -70,7 +74,6 @@ function PlayerStatistics({ server, t }: Props) {
|
||||||
}}
|
}}
|
||||||
xFormat="time:%Y-%m-%d"
|
xFormat="time:%Y-%m-%d"
|
||||||
axisBottom={{
|
axisBottom={{
|
||||||
tickSize: 0,
|
|
||||||
tickValues: 'every 6 days',
|
tickValues: 'every 6 days',
|
||||||
tickPadding: 5,
|
tickPadding: 5,
|
||||||
tickRotation: 0,
|
tickRotation: 0,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { useQuery } from '@apollo/client';
|
import { useQuery } from '@apollo/client';
|
||||||
import useServer from '@features/ServerPage/libs/ServerContext/useServer';
|
import useServer from '@features/ServerPage/libs/ServerContext/useServer';
|
||||||
|
import useDateUtils from '@libs/date/useDateUtils';
|
||||||
import formatNumber from '@utils/formatNumber';
|
import formatNumber from '@utils/formatNumber';
|
||||||
import { SERVER_PAGE } from '@config/routes';
|
import { SERVER_PAGE } from '@config/routes';
|
||||||
import { DAILY_PLAYER_STATS } from './queries';
|
import { DAILY_PLAYER_STATS } from './queries';
|
||||||
|
@ -24,6 +25,7 @@ export interface Props {
|
||||||
|
|
||||||
function TodaysBestStatsPlayers({ t }: Props) {
|
function TodaysBestStatsPlayers({ t }: Props) {
|
||||||
const server = useServer();
|
const server = useServer();
|
||||||
|
const dateUtils = useDateUtils();
|
||||||
const [mode, setMode] = useState<Mode>('scoreAtt');
|
const [mode, setMode] = useState<Mode>('scoreAtt');
|
||||||
const { loading: loadingData, data } = useQuery<
|
const { loading: loadingData, data } = useQuery<
|
||||||
DailyPlayerStatsList,
|
DailyPlayerStatsList,
|
||||||
|
@ -34,7 +36,7 @@ function TodaysBestStatsPlayers({ t }: Props) {
|
||||||
limit: LIMIT,
|
limit: LIMIT,
|
||||||
sort: [mode + ' DESC'],
|
sort: [mode + ' DESC'],
|
||||||
filter: {
|
filter: {
|
||||||
createDate: server.historyUpdatedAt,
|
createDate: dateUtils.toJSON(dateUtils.date(server.historyUpdatedAt)),
|
||||||
},
|
},
|
||||||
server: server.key,
|
server: server.key,
|
||||||
},
|
},
|
||||||
|
|
|
@ -16,7 +16,7 @@ export const COLUMNS: Column<DailyPlayerStatsRecord>[] = [
|
||||||
field: 'createDate',
|
field: 'createDate',
|
||||||
label: 'todaysBestStatsPlayers.columns.createDate',
|
label: 'todaysBestStatsPlayers.columns.createDate',
|
||||||
sortable: false,
|
sortable: false,
|
||||||
type: 'date',
|
type: 'dateutc',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { useQuery } from '@apollo/client';
|
import { useQuery } from '@apollo/client';
|
||||||
import useServer from '@features/ServerPage/libs/ServerContext/useServer';
|
import useServer from '@features/ServerPage/libs/ServerContext/useServer';
|
||||||
|
import useDateUtils from '@libs/date/useDateUtils';
|
||||||
import formatNumber from '@utils/formatNumber';
|
import formatNumber from '@utils/formatNumber';
|
||||||
import { SERVER_PAGE } from '@config/routes';
|
import { SERVER_PAGE } from '@config/routes';
|
||||||
import { DAILY_TRIBE_STATS } from './queries';
|
import { DAILY_TRIBE_STATS } from './queries';
|
||||||
|
@ -23,6 +24,7 @@ export interface Props {
|
||||||
|
|
||||||
function TodaysBestStatsTribes({ t }: Props) {
|
function TodaysBestStatsTribes({ t }: Props) {
|
||||||
const server = useServer();
|
const server = useServer();
|
||||||
|
const dateUtils = useDateUtils();
|
||||||
const [mode, setMode] = useState<Mode>('scoreAtt');
|
const [mode, setMode] = useState<Mode>('scoreAtt');
|
||||||
const { loading: loadingData, data } = useQuery<
|
const { loading: loadingData, data } = useQuery<
|
||||||
DailyTribeStatsList,
|
DailyTribeStatsList,
|
||||||
|
@ -33,11 +35,12 @@ function TodaysBestStatsTribes({ t }: Props) {
|
||||||
limit: LIMIT,
|
limit: LIMIT,
|
||||||
sort: [mode + ' DESC'],
|
sort: [mode + ' DESC'],
|
||||||
filter: {
|
filter: {
|
||||||
createDate: server.historyUpdatedAt,
|
createDate: dateUtils.toJSON(dateUtils.date(server.historyUpdatedAt)),
|
||||||
},
|
},
|
||||||
server: server.key,
|
server: server.key,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
console.log(dateUtils.toJSON(dateUtils.date(server.historyUpdatedAt)));
|
||||||
const records = data?.dailyTribeStats?.items ?? [];
|
const records = data?.dailyTribeStats?.items ?? [];
|
||||||
const loading = loadingData && records.length === 0;
|
const loading = loadingData && records.length === 0;
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ export const COLUMNS: Column<DailyTribeStatsRecord>[] = [
|
||||||
field: 'createDate',
|
field: 'createDate',
|
||||||
label: 'todaysBestStatsTribes.columns.createDate',
|
label: 'todaysBestStatsTribes.columns.createDate',
|
||||||
sortable: false,
|
sortable: false,
|
||||||
type: 'date',
|
type: 'dateutc',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { useQuery } from '@apollo/client';
|
import { useQuery } from '@apollo/client';
|
||||||
|
import useDateUtils from '@libs/date/useDateUtils';
|
||||||
import { STATISTICS } from './queries';
|
import { STATISTICS } from './queries';
|
||||||
import { LIMIT } from './constants';
|
import { LIMIT } from './constants';
|
||||||
|
|
||||||
|
@ -19,6 +20,7 @@ export interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
function TribeStatistics({ server, t }: Props) {
|
function TribeStatistics({ server, t }: Props) {
|
||||||
|
const dateUtils = useDateUtils();
|
||||||
const { loading: loadingData, data: queryRes } = useQuery<
|
const { loading: loadingData, data: queryRes } = useQuery<
|
||||||
ServerStats,
|
ServerStats,
|
||||||
ServerStatsQueryVariables
|
ServerStatsQueryVariables
|
||||||
|
@ -40,16 +42,18 @@ function TribeStatistics({ server, t }: Props) {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
id: t<string>('tribeStatistics.tribes'),
|
id: t<string>('tribeStatistics.tribes'),
|
||||||
data: items.map(item => ({
|
data: items.map(item => {
|
||||||
x: new Date(item.createDate),
|
return {
|
||||||
y: item.activeTribes,
|
x: dateUtils.dateInTZ(item.createDate, 'UTC'),
|
||||||
})),
|
y: item.activeTribes,
|
||||||
|
};
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}, [items, loading, t]);
|
}, [items, loading, t, dateUtils]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper size="large" style={{ overflow: 'hidden' }}>
|
<Paper size="large" style={{ overflow: 'visible' }}>
|
||||||
<TableToolbar>
|
<TableToolbar>
|
||||||
<Typography variant="h4">{t('tribeStatistics.title')}</Typography>
|
<Typography variant="h4">{t('tribeStatistics.title')}</Typography>
|
||||||
</TableToolbar>
|
</TableToolbar>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { subDays, isEqual as isEqualDate } from 'date-fns';
|
|
||||||
import { useQuery } from '@apollo/client';
|
import { useQuery } from '@apollo/client';
|
||||||
import { useQueryParams, NumberParam, withDefault } from 'use-query-params';
|
import { useQueryParams, NumberParam, withDefault } from 'use-query-params';
|
||||||
|
import useDateUtils from '@libs/date/useDateUtils';
|
||||||
import useScrollToElement from '@libs/useScrollToElement';
|
import useScrollToElement from '@libs/useScrollToElement';
|
||||||
import { validateRowsPerPage } from '@common/Table/helpers';
|
import { validateRowsPerPage } from '@common/Table/helpers';
|
||||||
import formatNumber from '@utils/formatNumber';
|
import formatNumber from '@utils/formatNumber';
|
||||||
|
@ -27,6 +27,7 @@ export interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
function PlayerHistory({ t, server, playerID }: Props) {
|
function PlayerHistory({ t, server, playerID }: Props) {
|
||||||
|
const dateUtils = useDateUtils();
|
||||||
const [query, setQuery] = useQueryParams({
|
const [query, setQuery] = useQueryParams({
|
||||||
page: withDefault(NumberParam, 0),
|
page: withDefault(NumberParam, 0),
|
||||||
limit: withDefault(NumberParam, LIMIT),
|
limit: withDefault(NumberParam, LIMIT),
|
||||||
|
@ -55,15 +56,21 @@ function PlayerHistory({ t, server, playerID }: Props) {
|
||||||
const playerHistoryItems = useMemo(() => {
|
const playerHistoryItems = useMemo(() => {
|
||||||
const dailyPlayerStatsItems = queryData?.dailyPlayerStats?.items ?? [];
|
const dailyPlayerStatsItems = queryData?.dailyPlayerStats?.items ?? [];
|
||||||
return (queryData?.playerHistory?.items ?? []).map(phItem => {
|
return (queryData?.playerHistory?.items ?? []).map(phItem => {
|
||||||
const dateOfTheDayBeforeDate = subDays(new Date(phItem.createDate), 1);
|
const dateOfTheDayBeforeDate = dateUtils.subDays(
|
||||||
|
dateUtils.date(phItem.createDate),
|
||||||
|
1
|
||||||
|
);
|
||||||
return {
|
return {
|
||||||
...phItem,
|
...phItem,
|
||||||
stats: dailyPlayerStatsItems.find(dpsItem =>
|
stats: dailyPlayerStatsItems.find(dpsItem =>
|
||||||
isEqualDate(new Date(dpsItem.createDate), dateOfTheDayBeforeDate)
|
dateUtils.isEqual(
|
||||||
|
dateUtils.date(dpsItem.createDate),
|
||||||
|
dateOfTheDayBeforeDate
|
||||||
|
)
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}, [queryData]);
|
}, [queryData, dateUtils]);
|
||||||
const loading = playerHistoryItems.length === 0 && queryLoading;
|
const loading = playerHistoryItems.length === 0 && queryLoading;
|
||||||
const total = queryData?.playerHistory?.total ?? 0;
|
const total = queryData?.playerHistory?.total ?? 0;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { format } from 'date-fns';
|
import useDateUtils from '@libs/date/useDateUtils';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import useTitle from '@libs/useTitle';
|
import useTitle from '@libs/useTitle';
|
||||||
import useServer from '@features/ServerPage/libs/ServerContext/useServer';
|
import useServer from '@features/ServerPage/libs/ServerContext/useServer';
|
||||||
|
@ -28,6 +28,7 @@ function IndexPage() {
|
||||||
const { key } = useServer();
|
const { key } = useServer();
|
||||||
const player = usePlayer();
|
const player = usePlayer();
|
||||||
const { t } = useTranslation(SERVER_PAGE.PLAYER_PAGE.INDEX_PAGE);
|
const { t } = useTranslation(SERVER_PAGE.PLAYER_PAGE.INDEX_PAGE);
|
||||||
|
const dateUtils = useDateUtils();
|
||||||
useTitle(t('title', { key, name: player.name }));
|
useTitle(t('title', { key, name: player.name }));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -39,8 +40,8 @@ function IndexPage() {
|
||||||
{[
|
{[
|
||||||
{
|
{
|
||||||
field: 'joinedAt',
|
field: 'joinedAt',
|
||||||
value: format(
|
value: dateUtils.format(
|
||||||
new Date(player.joinedAt),
|
dateUtils.date(player.joinedAt),
|
||||||
DATE_FORMAT.DAY_MONTH_AND_YEAR
|
DATE_FORMAT.DAY_MONTH_AND_YEAR
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
@ -83,32 +84,32 @@ function IndexPage() {
|
||||||
{
|
{
|
||||||
field: 'deletedAt',
|
field: 'deletedAt',
|
||||||
value: player.deletedAt
|
value: player.deletedAt
|
||||||
? format(
|
? dateUtils.format(
|
||||||
new Date(player.deletedAt),
|
dateUtils.date(player.deletedAt),
|
||||||
DATE_FORMAT.DAY_MONTH_AND_YEAR
|
DATE_FORMAT.DAY_MONTH_AND_YEAR
|
||||||
)
|
)
|
||||||
: '-',
|
: '-',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'bestRank',
|
field: 'bestRank',
|
||||||
subtitle: format(
|
subtitle: dateUtils.format(
|
||||||
new Date(player.bestRankAt),
|
dateUtils.date(player.bestRankAt),
|
||||||
DATE_FORMAT.HOUR_MINUTES_DAY_MONTH_AND_YEAR
|
DATE_FORMAT.HOUR_MINUTES_DAY_MONTH_AND_YEAR
|
||||||
),
|
),
|
||||||
value: player.bestRank,
|
value: player.bestRank,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'mostPoints',
|
field: 'mostPoints',
|
||||||
subtitle: format(
|
subtitle: dateUtils.format(
|
||||||
new Date(player.mostPointsAt),
|
dateUtils.date(player.mostPointsAt),
|
||||||
DATE_FORMAT.HOUR_MINUTES_DAY_MONTH_AND_YEAR
|
DATE_FORMAT.HOUR_MINUTES_DAY_MONTH_AND_YEAR
|
||||||
),
|
),
|
||||||
value: formatNumber('commas', player.mostPoints),
|
value: formatNumber('commas', player.mostPoints),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'mostVillages',
|
field: 'mostVillages',
|
||||||
subtitle: format(
|
subtitle: dateUtils.format(
|
||||||
new Date(player.mostVillagesAt),
|
dateUtils.date(player.mostVillagesAt),
|
||||||
DATE_FORMAT.HOUR_MINUTES_DAY_MONTH_AND_YEAR
|
DATE_FORMAT.HOUR_MINUTES_DAY_MONTH_AND_YEAR
|
||||||
),
|
),
|
||||||
value: formatNumber('commas', player.mostVillages),
|
value: formatNumber('commas', player.mostVillages),
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React, { useState, useMemo } from 'react';
|
import React, { useState, useMemo } from 'react';
|
||||||
import { useQuery } from '@apollo/client';
|
import { useQuery } from '@apollo/client';
|
||||||
|
import useDateUtils from '@libs/date/useDateUtils';
|
||||||
import formatNumber from '@utils/formatNumber';
|
import formatNumber from '@utils/formatNumber';
|
||||||
import { PLAYER_HISTORY } from './queries';
|
import { PLAYER_HISTORY } from './queries';
|
||||||
import { LIMIT } from './constants';
|
import { LIMIT } from './constants';
|
||||||
|
@ -24,6 +25,7 @@ function Statistics({ t, server, playerID }: Props) {
|
||||||
const [mode, setMode] = useState<Mode>('points');
|
const [mode, setMode] = useState<Mode>('points');
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isMobileDevice = useMediaQuery(theme.breakpoints.down('sm'));
|
const isMobileDevice = useMediaQuery(theme.breakpoints.down('sm'));
|
||||||
|
const dateUtils = useDateUtils();
|
||||||
const { data: queryRes, loading } = useQuery<
|
const { data: queryRes, loading } = useQuery<
|
||||||
PlayerHistory,
|
PlayerHistory,
|
||||||
PlayerHistoryQueryVariables
|
PlayerHistoryQueryVariables
|
||||||
|
@ -51,12 +53,12 @@ function Statistics({ t, server, playerID }: Props) {
|
||||||
{
|
{
|
||||||
id: t<string>('statistics.modes.' + mode),
|
id: t<string>('statistics.modes.' + mode),
|
||||||
data: items.map(item => ({
|
data: items.map(item => ({
|
||||||
x: new Date(item.createDate),
|
x: dateUtils.dateInTZ(item.createDate, 'UTC'),
|
||||||
y: item[mode],
|
y: item[mode],
|
||||||
})),
|
})),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}, [items, loading, t, mode]);
|
}, [items, loading, t, mode, dateUtils]);
|
||||||
const xyFormat = (v: string | number | Date) =>
|
const xyFormat = (v: string | number | Date) =>
|
||||||
typeof v === 'string' || typeof v === 'number'
|
typeof v === 'string' || typeof v === 'number'
|
||||||
? formatNumber('commas', v)
|
? formatNumber('commas', v)
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useState, useRef } from 'react';
|
||||||
import {
|
import {
|
||||||
useQueryParams,
|
useQueryParams,
|
||||||
NumberParam,
|
NumberParam,
|
||||||
withDefault,
|
withDefault,
|
||||||
StringParam,
|
StringParam,
|
||||||
DateTimeParam,
|
DateParam,
|
||||||
} from 'use-query-params';
|
} from 'use-query-params';
|
||||||
import { useDebouncedCallback } from 'use-debounce';
|
import { useDebouncedCallback } from 'use-debounce';
|
||||||
|
import useDateUtils from '@libs/date/useDateUtils';
|
||||||
import useUpdateEffect from '@libs/useUpdateEffect';
|
import useUpdateEffect from '@libs/useUpdateEffect';
|
||||||
import useScrollToElement from '@libs/useScrollToElement';
|
import useScrollToElement from '@libs/useScrollToElement';
|
||||||
import useServer from '@features/ServerPage/libs/ServerContext/useServer';
|
import useServer from '@features/ServerPage/libs/ServerContext/useServer';
|
||||||
|
@ -33,13 +34,14 @@ export interface Props {
|
||||||
function Ranking({ t }: Props) {
|
function Ranking({ t }: Props) {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const server = useServer();
|
const server = useServer();
|
||||||
const defaultDate = new Date(server.historyUpdatedAt);
|
const dateUtils = useDateUtils();
|
||||||
|
const defaultDate = useRef(dateUtils.date(server.historyUpdatedAt));
|
||||||
const [query, setQuery] = useQueryParams({
|
const [query, setQuery] = useQueryParams({
|
||||||
page: withDefault(NumberParam, 0),
|
page: withDefault(NumberParam, 0),
|
||||||
limit: withDefault(NumberParam, LIMIT),
|
limit: withDefault(NumberParam, LIMIT),
|
||||||
q: withDefault(StringParam, ''),
|
q: withDefault(StringParam, ''),
|
||||||
sort: withDefault(SortParam, DEFAULT_SORT),
|
sort: withDefault(SortParam, DEFAULT_SORT),
|
||||||
createDate: withDefault(DateTimeParam, defaultDate),
|
createDate: withDefault(DateParam, defaultDate.current),
|
||||||
});
|
});
|
||||||
const limit = validateRowsPerPage(query.limit);
|
const limit = validateRowsPerPage(query.limit);
|
||||||
const [q, setQ] = useState(query.q);
|
const [q, setQ] = useState(query.q);
|
||||||
|
@ -58,7 +60,7 @@ function Ranking({ t }: Props) {
|
||||||
server.key,
|
server.key,
|
||||||
query.q,
|
query.q,
|
||||||
query.sort.toString(),
|
query.sort.toString(),
|
||||||
query.createDate
|
dateUtils.toJSON(query.createDate)
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -16,7 +16,7 @@ const usePlayers = (
|
||||||
server: string,
|
server: string,
|
||||||
q: string,
|
q: string,
|
||||||
sort: string,
|
sort: string,
|
||||||
createDate: Date
|
createDate: Date | string
|
||||||
): QueryResult => {
|
): QueryResult => {
|
||||||
const { loading: loadingStats, data } = useQuery<
|
const { loading: loadingStats, data } = useQuery<
|
||||||
DailyStats,
|
DailyStats,
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useState, useRef } from 'react';
|
||||||
import {
|
import {
|
||||||
useQueryParams,
|
useQueryParams,
|
||||||
NumberParam,
|
NumberParam,
|
||||||
withDefault,
|
withDefault,
|
||||||
StringParam,
|
StringParam,
|
||||||
DateTimeParam,
|
DateParam,
|
||||||
} from 'use-query-params';
|
} from 'use-query-params';
|
||||||
import { useDebouncedCallback } from 'use-debounce';
|
import { useDebouncedCallback } from 'use-debounce';
|
||||||
|
import useDateUtils from '@libs/date/useDateUtils';
|
||||||
import useUpdateEffect from '@libs/useUpdateEffect';
|
import useUpdateEffect from '@libs/useUpdateEffect';
|
||||||
import useScrollToElement from '@libs/useScrollToElement';
|
import useScrollToElement from '@libs/useScrollToElement';
|
||||||
import useServer from '@features/ServerPage/libs/ServerContext/useServer';
|
import useServer from '@features/ServerPage/libs/ServerContext/useServer';
|
||||||
|
@ -34,13 +35,14 @@ export interface Props {
|
||||||
function Ranking({ t }: Props) {
|
function Ranking({ t }: Props) {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const server = useServer();
|
const server = useServer();
|
||||||
const defaultDate = new Date(server.historyUpdatedAt);
|
const dateUtils = useDateUtils();
|
||||||
|
const defaultDate = useRef(dateUtils.date(server.historyUpdatedAt));
|
||||||
const [query, setQuery] = useQueryParams({
|
const [query, setQuery] = useQueryParams({
|
||||||
page: withDefault(NumberParam, 0),
|
page: withDefault(NumberParam, 0),
|
||||||
limit: withDefault(NumberParam, LIMIT),
|
limit: withDefault(NumberParam, LIMIT),
|
||||||
q: withDefault(StringParam, ''),
|
q: withDefault(StringParam, ''),
|
||||||
sort: withDefault(SortParam, DEFAULT_SORT),
|
sort: withDefault(SortParam, DEFAULT_SORT),
|
||||||
createDate: withDefault(DateTimeParam, defaultDate),
|
createDate: withDefault(DateParam, defaultDate.current),
|
||||||
});
|
});
|
||||||
const limit = validateRowsPerPage(query.limit);
|
const limit = validateRowsPerPage(query.limit);
|
||||||
const [q, setQ] = useState(query.q);
|
const [q, setQ] = useState(query.q);
|
||||||
|
@ -59,7 +61,7 @@ function Ranking({ t }: Props) {
|
||||||
server.key,
|
server.key,
|
||||||
query.q,
|
query.q,
|
||||||
query.sort.toString(),
|
query.sort.toString(),
|
||||||
query.createDate
|
dateUtils.toJSON(query.createDate)
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -16,7 +16,7 @@ const useTribes = (
|
||||||
server: string,
|
server: string,
|
||||||
q: string,
|
q: string,
|
||||||
sort: string,
|
sort: string,
|
||||||
createDate: Date
|
createDate: Date | string
|
||||||
): QueryResult => {
|
): QueryResult => {
|
||||||
const { loading: loadingStats, data } = useQuery<
|
const { loading: loadingStats, data } = useQuery<
|
||||||
DailyStats,
|
DailyStats,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { subDays, isEqual as isEqualDate } from 'date-fns';
|
|
||||||
import { useQuery } from '@apollo/client';
|
import { useQuery } from '@apollo/client';
|
||||||
import { useQueryParams, NumberParam, withDefault } from 'use-query-params';
|
import { useQueryParams, NumberParam, withDefault } from 'use-query-params';
|
||||||
|
import useDateUtils from '@libs/date/useDateUtils';
|
||||||
import useScrollToElement from '@libs/useScrollToElement';
|
import useScrollToElement from '@libs/useScrollToElement';
|
||||||
import { validateRowsPerPage } from '@common/Table/helpers';
|
import { validateRowsPerPage } from '@common/Table/helpers';
|
||||||
import formatNumber from '@utils/formatNumber';
|
import formatNumber from '@utils/formatNumber';
|
||||||
|
@ -25,6 +25,7 @@ export interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
function TribeHistory({ t, server, tribeID }: Props) {
|
function TribeHistory({ t, server, tribeID }: Props) {
|
||||||
|
const dateUtils = useDateUtils();
|
||||||
const [query, setQuery] = useQueryParams({
|
const [query, setQuery] = useQueryParams({
|
||||||
page: withDefault(NumberParam, 0),
|
page: withDefault(NumberParam, 0),
|
||||||
limit: withDefault(NumberParam, LIMIT),
|
limit: withDefault(NumberParam, LIMIT),
|
||||||
|
@ -53,15 +54,21 @@ function TribeHistory({ t, server, tribeID }: Props) {
|
||||||
const tribeHistoryItems = useMemo(() => {
|
const tribeHistoryItems = useMemo(() => {
|
||||||
const dailyTribeStatsItems = queryData?.dailyTribeStats?.items ?? [];
|
const dailyTribeStatsItems = queryData?.dailyTribeStats?.items ?? [];
|
||||||
return (queryData?.tribeHistory?.items ?? []).map(phItem => {
|
return (queryData?.tribeHistory?.items ?? []).map(phItem => {
|
||||||
const dateOfTheDayBeforeDate = subDays(new Date(phItem.createDate), 1);
|
const dateOfTheDayBeforeDate = dateUtils.subDays(
|
||||||
|
dateUtils.date(phItem.createDate),
|
||||||
|
1
|
||||||
|
);
|
||||||
return {
|
return {
|
||||||
...phItem,
|
...phItem,
|
||||||
stats: dailyTribeStatsItems.find(dpsItem =>
|
stats: dailyTribeStatsItems.find(dpsItem =>
|
||||||
isEqualDate(new Date(dpsItem.createDate), dateOfTheDayBeforeDate)
|
dateUtils.isEqual(
|
||||||
|
dateUtils.date(dpsItem.createDate),
|
||||||
|
dateOfTheDayBeforeDate
|
||||||
|
)
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}, [queryData]);
|
}, [queryData, dateUtils]);
|
||||||
const loading = tribeHistoryItems.length === 0 && queryLoading;
|
const loading = tribeHistoryItems.length === 0 && queryLoading;
|
||||||
const total = queryData?.tribeHistory?.total ?? 0;
|
const total = queryData?.tribeHistory?.total ?? 0;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { format } from 'date-fns';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import useDateUtils from '@libs/date/useDateUtils';
|
||||||
import useTitle from '@libs/useTitle';
|
import useTitle from '@libs/useTitle';
|
||||||
import useServer from '@features/ServerPage/libs/ServerContext/useServer';
|
import useServer from '@features/ServerPage/libs/ServerContext/useServer';
|
||||||
import useTribe from '../../libs/TribePageContext/useTribe';
|
import useTribe from '../../libs/TribePageContext/useTribe';
|
||||||
|
@ -20,6 +20,7 @@ import {
|
||||||
import Statistics from './components/Statistics/Statistics';
|
import Statistics from './components/Statistics/Statistics';
|
||||||
|
|
||||||
function IndexPage() {
|
function IndexPage() {
|
||||||
|
const dateUtils = useDateUtils();
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const { key } = useServer();
|
const { key } = useServer();
|
||||||
const tribe = useTribe();
|
const tribe = useTribe();
|
||||||
|
@ -35,8 +36,8 @@ function IndexPage() {
|
||||||
{[
|
{[
|
||||||
{
|
{
|
||||||
field: 'createdAt',
|
field: 'createdAt',
|
||||||
value: format(
|
value: dateUtils.format(
|
||||||
new Date(tribe.createdAt),
|
dateUtils.date(tribe.createdAt),
|
||||||
DATE_FORMAT.DAY_MONTH_AND_YEAR
|
DATE_FORMAT.DAY_MONTH_AND_YEAR
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
@ -77,32 +78,32 @@ function IndexPage() {
|
||||||
{
|
{
|
||||||
field: 'deletedAt',
|
field: 'deletedAt',
|
||||||
value: tribe.deletedAt
|
value: tribe.deletedAt
|
||||||
? format(
|
? dateUtils.format(
|
||||||
new Date(tribe.deletedAt),
|
dateUtils.date(tribe.deletedAt),
|
||||||
DATE_FORMAT.DAY_MONTH_AND_YEAR
|
DATE_FORMAT.DAY_MONTH_AND_YEAR
|
||||||
)
|
)
|
||||||
: '-',
|
: '-',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'bestRank',
|
field: 'bestRank',
|
||||||
subtitle: format(
|
subtitle: dateUtils.format(
|
||||||
new Date(tribe.bestRankAt),
|
dateUtils.date(tribe.bestRankAt),
|
||||||
DATE_FORMAT.HOUR_MINUTES_DAY_MONTH_AND_YEAR
|
DATE_FORMAT.HOUR_MINUTES_DAY_MONTH_AND_YEAR
|
||||||
),
|
),
|
||||||
value: tribe.bestRank,
|
value: tribe.bestRank,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'mostPoints',
|
field: 'mostPoints',
|
||||||
subtitle: format(
|
subtitle: dateUtils.format(
|
||||||
new Date(tribe.mostPointsAt),
|
dateUtils.date(tribe.mostPointsAt),
|
||||||
DATE_FORMAT.HOUR_MINUTES_DAY_MONTH_AND_YEAR
|
DATE_FORMAT.HOUR_MINUTES_DAY_MONTH_AND_YEAR
|
||||||
),
|
),
|
||||||
value: formatNumber('commas', tribe.mostPoints),
|
value: formatNumber('commas', tribe.mostPoints),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'mostVillages',
|
field: 'mostVillages',
|
||||||
subtitle: format(
|
subtitle: dateUtils.format(
|
||||||
new Date(tribe.mostVillagesAt),
|
dateUtils.date(tribe.mostVillagesAt),
|
||||||
DATE_FORMAT.HOUR_MINUTES_DAY_MONTH_AND_YEAR
|
DATE_FORMAT.HOUR_MINUTES_DAY_MONTH_AND_YEAR
|
||||||
),
|
),
|
||||||
value: formatNumber('commas', tribe.mostVillages),
|
value: formatNumber('commas', tribe.mostVillages),
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React, { useState, useMemo } from 'react';
|
import React, { useState, useMemo } from 'react';
|
||||||
import { useQuery } from '@apollo/client';
|
import { useQuery } from '@apollo/client';
|
||||||
|
import useDateUtils from '@libs/date/useDateUtils';
|
||||||
import formatNumber from '@utils/formatNumber';
|
import formatNumber from '@utils/formatNumber';
|
||||||
import { TRIBE_HISTORY } from './queries';
|
import { TRIBE_HISTORY } from './queries';
|
||||||
import { LIMIT } from './constants';
|
import { LIMIT } from './constants';
|
||||||
|
@ -23,6 +24,7 @@ export interface Props {
|
||||||
function Statistics({ t, server, tribeID }: Props) {
|
function Statistics({ t, server, tribeID }: Props) {
|
||||||
const [mode, setMode] = useState<Mode>('points');
|
const [mode, setMode] = useState<Mode>('points');
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
const dateUtils = useDateUtils();
|
||||||
const isMobileDevice = useMediaQuery(theme.breakpoints.down('sm'));
|
const isMobileDevice = useMediaQuery(theme.breakpoints.down('sm'));
|
||||||
const { data: queryRes, loading } = useQuery<
|
const { data: queryRes, loading } = useQuery<
|
||||||
TribeHistory,
|
TribeHistory,
|
||||||
|
@ -51,12 +53,12 @@ function Statistics({ t, server, tribeID }: Props) {
|
||||||
{
|
{
|
||||||
id: t<string>('statistics.modes.' + mode),
|
id: t<string>('statistics.modes.' + mode),
|
||||||
data: items.map(item => ({
|
data: items.map(item => ({
|
||||||
x: new Date(item.createDate),
|
x: dateUtils.dateInTZ(item.createDate, 'UTC'),
|
||||||
y: item[mode],
|
y: item[mode],
|
||||||
})),
|
})),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}, [items, loading, t, mode]);
|
}, [items, loading, t, mode, dateUtils]);
|
||||||
const xyFormat = (v: string | number | Date) =>
|
const xyFormat = (v: string | number | Date) =>
|
||||||
typeof v === 'string' || typeof v === 'number'
|
typeof v === 'string' || typeof v === 'number'
|
||||||
? formatNumber('commas', v)
|
? formatNumber('commas', v)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React, { useMemo, useState } from 'react';
|
import React, { useMemo, useState } from 'react';
|
||||||
import { addDays, differenceInDays, format, isBefore } from 'date-fns';
|
import useDateUtils from '@libs/date/useDateUtils';
|
||||||
import useMembers from './useMembers';
|
import useMembers from './useMembers';
|
||||||
import formatNumber from '@utils/formatNumber';
|
import formatNumber from '@utils/formatNumber';
|
||||||
import { DATE_FORMAT } from '@config/app';
|
import { DATE_FORMAT } from '@config/app';
|
||||||
|
@ -28,6 +28,7 @@ function Members({ t, server, tribeID }: Props) {
|
||||||
server,
|
server,
|
||||||
HOW_MANY_DAYS_BACK
|
HOW_MANY_DAYS_BACK
|
||||||
);
|
);
|
||||||
|
const dateUtils = useDateUtils();
|
||||||
const columns = useMemo<Column<Player>[]>(() => {
|
const columns = useMemo<Column<Player>[]>(() => {
|
||||||
const columns: Column<Player>[] = [
|
const columns: Column<Player>[] = [
|
||||||
{
|
{
|
||||||
|
@ -66,19 +67,24 @@ function Members({ t, server, tribeID }: Props) {
|
||||||
|
|
||||||
const maxDate =
|
const maxDate =
|
||||||
dailyPlayerStats.length > 0
|
dailyPlayerStats.length > 0
|
||||||
? new Date(dailyPlayerStats[0].createDate)
|
? dateUtils.date(dailyPlayerStats[0].createDate)
|
||||||
: null;
|
: null;
|
||||||
const minDate =
|
const minDate =
|
||||||
dailyPlayerStats.length > 0
|
dailyPlayerStats.length > 0
|
||||||
? new Date(dailyPlayerStats[dailyPlayerStats.length - 1].createDate)
|
? dateUtils.date(
|
||||||
|
dailyPlayerStats[dailyPlayerStats.length - 1].createDate
|
||||||
|
)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
if (maxDate && minDate && isBefore(minDate, maxDate)) {
|
if (maxDate && minDate && dateUtils.isBefore(minDate, maxDate)) {
|
||||||
let diff = differenceInDays(maxDate, minDate) + 1;
|
let diff = dateUtils.differenceInDays(maxDate, minDate) + 1;
|
||||||
if (diff <= HOW_MANY_DAYS_BACK) {
|
if (diff <= HOW_MANY_DAYS_BACK) {
|
||||||
for (let i = 0; i < diff; i++) {
|
for (let i = 0; i < diff; i++) {
|
||||||
const date = addDays(minDate, i);
|
const date = dateUtils.addDays(minDate, i);
|
||||||
const formatted = format(date, DATE_FORMAT.DAY_MONTH_AND_YEAR);
|
const formatted = dateUtils.format(
|
||||||
|
date,
|
||||||
|
DATE_FORMAT.DAY_MONTH_AND_YEAR
|
||||||
|
);
|
||||||
columns.push({
|
columns.push({
|
||||||
field: formatted,
|
field: formatted,
|
||||||
label: formatted,
|
label: formatted,
|
||||||
|
@ -86,7 +92,8 @@ function Members({ t, server, tribeID }: Props) {
|
||||||
valueFormatter: (p: Player) => {
|
valueFormatter: (p: Player) => {
|
||||||
const record = p.dailyPlayerStatsRecords
|
const record = p.dailyPlayerStatsRecords
|
||||||
? p.dailyPlayerStatsRecords.find(
|
? p.dailyPlayerStatsRecords.find(
|
||||||
r => new Date(r.createDate).getTime() === date.getTime()
|
r =>
|
||||||
|
dateUtils.date(r.createDate).getTime() === date.getTime()
|
||||||
)
|
)
|
||||||
: undefined;
|
: undefined;
|
||||||
return <ColouredNumber num={record ? record[mode] : 0} />;
|
return <ColouredNumber num={record ? record[mode] : 0} />;
|
||||||
|
@ -116,7 +123,7 @@ function Members({ t, server, tribeID }: Props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return columns;
|
return columns;
|
||||||
}, [dailyPlayerStats, t, server, mode]);
|
}, [dailyPlayerStats, t, server, mode, dateUtils]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper>
|
<Paper>
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import React, { useRef, useMemo, useState } from 'react';
|
import React, { useRef, useMemo, useState } from 'react';
|
||||||
import { subDays } from 'date-fns';
|
|
||||||
import { useQueryParams, DateTimeParam, withDefault } from 'use-query-params';
|
import { useQueryParams, DateTimeParam, withDefault } from 'use-query-params';
|
||||||
import { useApolloClient } from '@apollo/client';
|
import { useApolloClient } from '@apollo/client';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import useDateUtils from '@libs/date/useDateUtils';
|
||||||
import useTitle from '@libs/useTitle';
|
import useTitle from '@libs/useTitle';
|
||||||
import useServer from '../../libs/ServerContext/useServer';
|
import useServer from '../../libs/ServerContext/useServer';
|
||||||
import useSide from './useSide';
|
import useSide from './useSide';
|
||||||
|
@ -34,11 +34,15 @@ import {
|
||||||
} from './types';
|
} from './types';
|
||||||
|
|
||||||
function WarStatsPage() {
|
function WarStatsPage() {
|
||||||
const now = useRef(new Date());
|
const dateUtils = useDateUtils();
|
||||||
|
const now = useRef(dateUtils.date());
|
||||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||||
const [results, setResults] = useState<ResultsT | null>(null);
|
const [results, setResults] = useState<ResultsT | null>(null);
|
||||||
const [query, setQuery] = useQueryParams({
|
const [query, setQuery] = useQueryParams({
|
||||||
ennobledAtGTE: withDefault(DateTimeParam, subDays(now.current, 1)),
|
ennobledAtGTE: withDefault(
|
||||||
|
DateTimeParam,
|
||||||
|
dateUtils.subDays(now.current, 1)
|
||||||
|
),
|
||||||
ennobledAtLTE: withDefault(DateTimeParam, now.current),
|
ennobledAtLTE: withDefault(DateTimeParam, now.current),
|
||||||
});
|
});
|
||||||
const client = useApolloClient();
|
const client = useApolloClient();
|
||||||
|
@ -96,8 +100,8 @@ function WarStatsPage() {
|
||||||
const sideTwoPlayerIDs = sideTwoPlayers.map(player => player.id);
|
const sideTwoPlayerIDs = sideTwoPlayers.map(player => player.id);
|
||||||
const sideTwoTribeIDs = sideTwoTribes.map(tribe => tribe.id);
|
const sideTwoTribeIDs = sideTwoTribes.map(tribe => tribe.id);
|
||||||
const defFilter = {
|
const defFilter = {
|
||||||
ennobledAtGTE: query.ennobledAtGTE,
|
ennobledAtGTE: dateUtils.zonedTimeToUTC(query.ennobledAtGTE),
|
||||||
ennobledAtLTE: query.ennobledAtLTE,
|
ennobledAtLTE: dateUtils.zonedTimeToUTC(query.ennobledAtLTE),
|
||||||
};
|
};
|
||||||
const { data } = await client.query<
|
const { data } = await client.query<
|
||||||
EnnoblementsQueryResult,
|
EnnoblementsQueryResult,
|
||||||
|
|
|
@ -111,7 +111,6 @@ function Results({ data, server }: Props) {
|
||||||
axisTop={null}
|
axisTop={null}
|
||||||
axisRight={null}
|
axisRight={null}
|
||||||
axisBottom={{
|
axisBottom={{
|
||||||
tickSize: 0,
|
|
||||||
tickPadding: 5,
|
tickPadding: 5,
|
||||||
tickRotation: 0,
|
tickRotation: 0,
|
||||||
format: isWidthDown750 ? () => '' : undefined,
|
format: isWidthDown750 ? () => '' : undefined,
|
||||||
|
|
|
@ -4,15 +4,11 @@ import { ThemeProvider } from '@material-ui/styles';
|
||||||
import { ApolloProvider } from '@apollo/client';
|
import { ApolloProvider } from '@apollo/client';
|
||||||
import { BrowserRouter, Route } from 'react-router-dom';
|
import { BrowserRouter, Route } from 'react-router-dom';
|
||||||
import { I18nextProvider } from 'react-i18next';
|
import { I18nextProvider } from 'react-i18next';
|
||||||
import { MuiPickersUtilsProvider } from '@material-ui/pickers';
|
|
||||||
import { QueryParamProvider } from 'use-query-params';
|
import { QueryParamProvider } from 'use-query-params';
|
||||||
import DateFnsUtils from '@date-io/date-fns';
|
|
||||||
import App from './features/App';
|
import App from './features/App';
|
||||||
import createTheme from './theme/createTheme';
|
import createTheme from './theme/createTheme';
|
||||||
import createGraphQLClient from './libs/graphql/createClient';
|
import createGraphQLClient from './libs/graphql/createClient';
|
||||||
import initI18N from './libs/i18n/init';
|
import initI18N from './libs/i18n/init';
|
||||||
import { getLocale } from './libs/date/locales';
|
|
||||||
import extractVersionCodeFromHostname from './utils/extractVersionCodeFromHostname';
|
|
||||||
import { URI as API_URI } from './config/api';
|
import { URI as API_URI } from './config/api';
|
||||||
import reportWebVitals from './reportWebVitals';
|
import reportWebVitals from './reportWebVitals';
|
||||||
|
|
||||||
|
@ -21,16 +17,9 @@ const jsx = (
|
||||||
<ThemeProvider theme={createTheme()}>
|
<ThemeProvider theme={createTheme()}>
|
||||||
<I18nextProvider i18n={initI18N()}>
|
<I18nextProvider i18n={initI18N()}>
|
||||||
<ApolloProvider client={createGraphQLClient(API_URI)}>
|
<ApolloProvider client={createGraphQLClient(API_URI)}>
|
||||||
<MuiPickersUtilsProvider
|
<QueryParamProvider ReactRouterRoute={Route}>
|
||||||
utils={DateFnsUtils}
|
<App />
|
||||||
locale={getLocale(
|
</QueryParamProvider>
|
||||||
extractVersionCodeFromHostname(window.location.hostname)
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<QueryParamProvider ReactRouterRoute={Route}>
|
|
||||||
<App />
|
|
||||||
</QueryParamProvider>
|
|
||||||
</MuiPickersUtilsProvider>
|
|
||||||
</ApolloProvider>
|
</ApolloProvider>
|
||||||
</I18nextProvider>
|
</I18nextProvider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
|
|
65
src/libs/VersionContext/Provider.tsx
Normal file
65
src/libs/VersionContext/Provider.tsx
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
import React, { useMemo } from 'react';
|
||||||
|
import { useQuery } from '@apollo/client';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import extractVersionCodeFromHostname from '@utils/extractVersionCodeFromHostname';
|
||||||
|
import { VERSIONS } from './queries';
|
||||||
|
import Context from './context';
|
||||||
|
import * as NAMESPACES from '@config/namespaces';
|
||||||
|
|
||||||
|
import { VersionsQueryVariables } from '@libs/graphql/types';
|
||||||
|
import { VersionList } from './types';
|
||||||
|
|
||||||
|
import NotFoundPage from '@features/NotFoundPage/NotFoundPage';
|
||||||
|
import Spinner from '@common/Spinner/Spinner';
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Provider({ children }: Props) {
|
||||||
|
const { t } = useTranslation(NAMESPACES.COMMON);
|
||||||
|
const versionCode = useMemo(() => {
|
||||||
|
return extractVersionCodeFromHostname(window.location.hostname);
|
||||||
|
}, []);
|
||||||
|
const { loading: loadingVersion, data } = useQuery<
|
||||||
|
VersionList,
|
||||||
|
VersionsQueryVariables
|
||||||
|
>(VERSIONS, {
|
||||||
|
fetchPolicy: 'cache-first',
|
||||||
|
variables: {
|
||||||
|
limit: 1,
|
||||||
|
filter: {
|
||||||
|
code: [versionCode],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const version =
|
||||||
|
data?.versions?.items && data.versions.items.length > 0
|
||||||
|
? data.versions.items[0]
|
||||||
|
: undefined;
|
||||||
|
const loading = loadingVersion && !version;
|
||||||
|
|
||||||
|
if (loading) {
|
||||||
|
return (
|
||||||
|
<Spinner
|
||||||
|
containerProps={{
|
||||||
|
width: '100%',
|
||||||
|
height: '100vh',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
}}
|
||||||
|
description={t('versionContextProvider.loading')}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!version) {
|
||||||
|
return <NotFoundPage />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <Context.Provider value={version}>{children}</Context.Provider>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Provider;
|
11
src/libs/VersionContext/context.ts
Normal file
11
src/libs/VersionContext/context.ts
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import { createContext } from 'react';
|
||||||
|
import { Version } from './types';
|
||||||
|
|
||||||
|
const ctx = createContext<Version>({
|
||||||
|
code: '',
|
||||||
|
host: '',
|
||||||
|
name: '',
|
||||||
|
timezone: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
export default ctx;
|
324
src/libs/VersionContext/dateUtils.ts
Normal file
324
src/libs/VersionContext/dateUtils.ts
Normal file
|
@ -0,0 +1,324 @@
|
||||||
|
import addDays from 'date-fns/addDays';
|
||||||
|
import addMonths from 'date-fns/addMonths';
|
||||||
|
import addYears from 'date-fns/addYears';
|
||||||
|
import differenceInMilliseconds from 'date-fns/differenceInMilliseconds';
|
||||||
|
import eachDayOfInterval from 'date-fns/eachDayOfInterval';
|
||||||
|
import endOfDay from 'date-fns/endOfDay';
|
||||||
|
import endOfWeek from 'date-fns/endOfWeek';
|
||||||
|
import endOfYear from 'date-fns/endOfYear';
|
||||||
|
import format from 'date-fns/format';
|
||||||
|
import getHours from 'date-fns/getHours';
|
||||||
|
import getSeconds from 'date-fns/getSeconds';
|
||||||
|
import getYear from 'date-fns/getYear';
|
||||||
|
import isAfter from 'date-fns/isAfter';
|
||||||
|
import isBefore from 'date-fns/isBefore';
|
||||||
|
import isEqual from 'date-fns/isEqual';
|
||||||
|
import isSameDay from 'date-fns/isSameDay';
|
||||||
|
import isSameYear from 'date-fns/isSameYear';
|
||||||
|
import isSameMonth from 'date-fns/isSameMonth';
|
||||||
|
import isSameHour from 'date-fns/isSameHour';
|
||||||
|
import isValid from 'date-fns/isValid';
|
||||||
|
import dateFnsParse from 'date-fns/parse';
|
||||||
|
import setHours from 'date-fns/setHours';
|
||||||
|
import setMinutes from 'date-fns/setMinutes';
|
||||||
|
import setMonth from 'date-fns/setMonth';
|
||||||
|
import setSeconds from 'date-fns/setSeconds';
|
||||||
|
import setYear from 'date-fns/setYear';
|
||||||
|
import startOfDay from 'date-fns/startOfDay';
|
||||||
|
import startOfMonth from 'date-fns/startOfMonth';
|
||||||
|
import endOfMonth from 'date-fns/endOfMonth';
|
||||||
|
import startOfWeek from 'date-fns/startOfWeek';
|
||||||
|
import startOfYear from 'date-fns/startOfYear';
|
||||||
|
import { utcToZonedTime } from 'date-fns-tz';
|
||||||
|
|
||||||
|
import { Locale } from 'date-fns';
|
||||||
|
import { IUtils } from '@date-io/core/IUtils';
|
||||||
|
|
||||||
|
export default class DateUtils implements IUtils<Date> {
|
||||||
|
public static timezone?: string;
|
||||||
|
|
||||||
|
public locale?: Locale;
|
||||||
|
|
||||||
|
public yearFormat = 'yyyy';
|
||||||
|
|
||||||
|
public yearMonthFormat = 'MMMM yyyy';
|
||||||
|
|
||||||
|
public dateTime12hFormat = 'MMMM do hh:mm aaaa';
|
||||||
|
|
||||||
|
public dateTime24hFormat = 'MMMM do HH:mm';
|
||||||
|
|
||||||
|
public time12hFormat = 'hh:mm a';
|
||||||
|
|
||||||
|
public time24hFormat = 'HH:mm';
|
||||||
|
|
||||||
|
public dateFormat = 'MMMM do';
|
||||||
|
|
||||||
|
constructor({ locale }: { locale?: Locale } = {}) {
|
||||||
|
this.locale = locale;
|
||||||
|
}
|
||||||
|
|
||||||
|
public addDays(value: Date, count: number) {
|
||||||
|
return addDays(value, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public isValid(value: any) {
|
||||||
|
return isValid(this.date(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public getDiff(value: Date, comparing: Date | string) {
|
||||||
|
return differenceInMilliseconds(value, this.date(comparing));
|
||||||
|
}
|
||||||
|
|
||||||
|
public isAfter(value: Date, comparing: Date) {
|
||||||
|
return isAfter(value, comparing);
|
||||||
|
}
|
||||||
|
|
||||||
|
public isBefore(value: Date, comparing: Date) {
|
||||||
|
return isBefore(value, comparing);
|
||||||
|
}
|
||||||
|
|
||||||
|
public startOfDay(value: Date) {
|
||||||
|
return startOfDay(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public endOfDay(value: Date) {
|
||||||
|
return endOfDay(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getHours(value: Date) {
|
||||||
|
return getHours(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public setHours(value: Date, count: number) {
|
||||||
|
return setHours(value, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public setMinutes(value: Date, count: number) {
|
||||||
|
return setMinutes(value, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getSeconds(value: Date) {
|
||||||
|
return getSeconds(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public setSeconds(value: Date, count: number) {
|
||||||
|
return setSeconds(value, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public isSameDay(value: Date, comparing: Date) {
|
||||||
|
return isSameDay(value, comparing);
|
||||||
|
}
|
||||||
|
|
||||||
|
public isSameMonth(value: Date, comparing: Date) {
|
||||||
|
return isSameMonth(value, comparing);
|
||||||
|
}
|
||||||
|
|
||||||
|
public isSameYear(value: Date, comparing: Date) {
|
||||||
|
return isSameYear(value, comparing);
|
||||||
|
}
|
||||||
|
|
||||||
|
public isSameHour(value: Date, comparing: Date) {
|
||||||
|
return isSameHour(value, comparing);
|
||||||
|
}
|
||||||
|
|
||||||
|
public startOfMonth(value: Date) {
|
||||||
|
return startOfMonth(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public endOfMonth(value: Date) {
|
||||||
|
return endOfMonth(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getYear(value: Date) {
|
||||||
|
return getYear(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public setYear(value: Date, count: number) {
|
||||||
|
return setYear(value, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public date(value?: any) {
|
||||||
|
if (typeof value === 'undefined') {
|
||||||
|
if (!DateUtils.timezone) {
|
||||||
|
return new Date();
|
||||||
|
}
|
||||||
|
return utcToZonedTime(new Date(), DateUtils.timezone);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value instanceof Date) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!DateUtils.timezone) {
|
||||||
|
return new Date(value);
|
||||||
|
}
|
||||||
|
return utcToZonedTime(value, DateUtils.timezone);
|
||||||
|
}
|
||||||
|
|
||||||
|
public parse(value: string, formatString: string) {
|
||||||
|
if (value === '') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dateFnsParse(value, formatString, this.date(), {
|
||||||
|
locale: this.locale,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public format(date: Date, formatString: string) {
|
||||||
|
return format(date, formatString, { locale: this.locale });
|
||||||
|
}
|
||||||
|
|
||||||
|
public isEqual(date: any, comparing: any) {
|
||||||
|
if (date === null && comparing === null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isEqual(date, comparing);
|
||||||
|
}
|
||||||
|
|
||||||
|
public isNull(date: Date) {
|
||||||
|
return date === null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isAfterDay(date: Date, value: Date) {
|
||||||
|
return isAfter(date, endOfDay(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public isBeforeDay(date: Date, value: Date) {
|
||||||
|
return isBefore(date, startOfDay(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public isBeforeYear(date: Date, value: Date) {
|
||||||
|
return isBefore(date, startOfYear(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public isAfterYear(date: Date, value: Date) {
|
||||||
|
return isAfter(date, endOfYear(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public formatNumber(numberToFormat: string) {
|
||||||
|
return numberToFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMinutes(date: Date) {
|
||||||
|
return date.getMinutes();
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMonth(date: Date) {
|
||||||
|
return date.getMonth();
|
||||||
|
}
|
||||||
|
|
||||||
|
public setMonth(date: Date, count: number) {
|
||||||
|
return setMonth(date, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMeridiemText(ampm: 'am' | 'pm') {
|
||||||
|
return ampm === 'am' ? 'AM' : 'PM';
|
||||||
|
}
|
||||||
|
|
||||||
|
public getNextMonth(date: Date) {
|
||||||
|
return addMonths(date, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getPreviousMonth(date: Date) {
|
||||||
|
return addMonths(date, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMonthArray(date: Date) {
|
||||||
|
const firstMonth = startOfYear(date);
|
||||||
|
const monthArray = [firstMonth];
|
||||||
|
|
||||||
|
while (monthArray.length < 12) {
|
||||||
|
const prevMonth = monthArray[monthArray.length - 1];
|
||||||
|
monthArray.push(this.getNextMonth(prevMonth));
|
||||||
|
}
|
||||||
|
|
||||||
|
return monthArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
public mergeDateAndTime(date: Date, time: Date) {
|
||||||
|
return this.setMinutes(
|
||||||
|
this.setHours(date, this.getHours(time)),
|
||||||
|
this.getMinutes(time)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getWeekdays() {
|
||||||
|
const now = new Date();
|
||||||
|
return eachDayOfInterval({
|
||||||
|
start: startOfWeek(now, { locale: this.locale }),
|
||||||
|
end: endOfWeek(now, { locale: this.locale }),
|
||||||
|
}).map(day => this.format(day, 'EEEEEE'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public getWeekArray(date: Date) {
|
||||||
|
const start = startOfWeek(startOfMonth(date), { locale: this.locale });
|
||||||
|
const end = endOfWeek(endOfMonth(date), { locale: this.locale });
|
||||||
|
|
||||||
|
let count = 0;
|
||||||
|
let current = start;
|
||||||
|
const nestedWeeks: Date[][] = [];
|
||||||
|
|
||||||
|
while (isBefore(current, end)) {
|
||||||
|
const weekNumber = Math.floor(count / 7);
|
||||||
|
nestedWeeks[weekNumber] = nestedWeeks[weekNumber] || [];
|
||||||
|
nestedWeeks[weekNumber].push(current);
|
||||||
|
current = addDays(current, 1);
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nestedWeeks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getYearRange(start: Date, end: Date) {
|
||||||
|
const startDate = startOfYear(start);
|
||||||
|
const endDate = endOfYear(end);
|
||||||
|
const years: Date[] = [];
|
||||||
|
|
||||||
|
let current = startDate;
|
||||||
|
while (isBefore(current, endDate)) {
|
||||||
|
years.push(current);
|
||||||
|
current = addYears(current, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return years;
|
||||||
|
}
|
||||||
|
|
||||||
|
// displaying methpds
|
||||||
|
public getCalendarHeaderText(date: Date) {
|
||||||
|
return this.format(date, this.yearMonthFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getYearText(date: Date) {
|
||||||
|
return this.format(date, 'yyyy');
|
||||||
|
}
|
||||||
|
|
||||||
|
public getDatePickerHeaderText(date: Date) {
|
||||||
|
return this.format(date, 'EEE, MMM d');
|
||||||
|
}
|
||||||
|
|
||||||
|
public getDateTimePickerHeaderText(date: Date) {
|
||||||
|
return this.format(date, 'MMM d');
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMonthText(date: Date) {
|
||||||
|
return this.format(date, 'MMMM');
|
||||||
|
}
|
||||||
|
|
||||||
|
public getDayText(date: Date) {
|
||||||
|
return this.format(date, 'd');
|
||||||
|
}
|
||||||
|
|
||||||
|
public getHourText(date: Date, ampm: boolean) {
|
||||||
|
return this.format(date, ampm ? 'hh' : 'HH');
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMinuteText(date: Date) {
|
||||||
|
return this.format(date, 'mm');
|
||||||
|
}
|
||||||
|
|
||||||
|
public getSecondText(date: Date) {
|
||||||
|
return this.format(date, 'ss');
|
||||||
|
}
|
||||||
|
}
|
14
src/libs/VersionContext/queries.ts
Normal file
14
src/libs/VersionContext/queries.ts
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import { gql } from '@apollo/client';
|
||||||
|
|
||||||
|
export const VERSIONS = gql`
|
||||||
|
query versions($filter: VersionFilter, $sort: [String!], $limit: Int) {
|
||||||
|
versions(filter: $filter, sort: $sort, limit: $limit) {
|
||||||
|
items {
|
||||||
|
code
|
||||||
|
host
|
||||||
|
timezone
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
12
src/libs/VersionContext/types.ts
Normal file
12
src/libs/VersionContext/types.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { List } from '@libs/graphql/types';
|
||||||
|
|
||||||
|
export type Version = {
|
||||||
|
code: string;
|
||||||
|
host: string;
|
||||||
|
name: string;
|
||||||
|
timezone: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type VersionList = {
|
||||||
|
versions?: List<Version[]>;
|
||||||
|
};
|
3
src/libs/VersionContext/useDateUtils.ts
Normal file
3
src/libs/VersionContext/useDateUtils.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import { useUtils } from '@material-ui/pickers';
|
||||||
|
|
||||||
|
export default useUtils;
|
9
src/libs/VersionContext/useVersion.ts
Normal file
9
src/libs/VersionContext/useVersion.ts
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import { useContext } from 'react';
|
||||||
|
import ctx from './context';
|
||||||
|
import { Version } from './types';
|
||||||
|
|
||||||
|
const useVersion = (): Version => {
|
||||||
|
return useContext(ctx);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useVersion;
|
376
src/libs/date/DateUtils.ts
Normal file
376
src/libs/date/DateUtils.ts
Normal file
|
@ -0,0 +1,376 @@
|
||||||
|
import addDays from 'date-fns/addDays';
|
||||||
|
import addMonths from 'date-fns/addMonths';
|
||||||
|
import addYears from 'date-fns/addYears';
|
||||||
|
import subDays from 'date-fns/subDays';
|
||||||
|
import differenceInMilliseconds from 'date-fns/differenceInMilliseconds';
|
||||||
|
import eachDayOfInterval from 'date-fns/eachDayOfInterval';
|
||||||
|
import endOfDay from 'date-fns/endOfDay';
|
||||||
|
import endOfWeek from 'date-fns/endOfWeek';
|
||||||
|
import endOfYear from 'date-fns/endOfYear';
|
||||||
|
import format from 'date-fns/format';
|
||||||
|
import getHours from 'date-fns/getHours';
|
||||||
|
import getSeconds from 'date-fns/getSeconds';
|
||||||
|
import getYear from 'date-fns/getYear';
|
||||||
|
import isAfter from 'date-fns/isAfter';
|
||||||
|
import isBefore from 'date-fns/isBefore';
|
||||||
|
import isEqual from 'date-fns/isEqual';
|
||||||
|
import isSameDay from 'date-fns/isSameDay';
|
||||||
|
import isSameYear from 'date-fns/isSameYear';
|
||||||
|
import isSameMonth from 'date-fns/isSameMonth';
|
||||||
|
import isSameHour from 'date-fns/isSameHour';
|
||||||
|
import isValid from 'date-fns/isValid';
|
||||||
|
import dateFnsParse from 'date-fns/parse';
|
||||||
|
import setHours from 'date-fns/setHours';
|
||||||
|
import setMinutes from 'date-fns/setMinutes';
|
||||||
|
import setMonth from 'date-fns/setMonth';
|
||||||
|
import setSeconds from 'date-fns/setSeconds';
|
||||||
|
import setYear from 'date-fns/setYear';
|
||||||
|
import startOfDay from 'date-fns/startOfDay';
|
||||||
|
import startOfMonth from 'date-fns/startOfMonth';
|
||||||
|
import endOfMonth from 'date-fns/endOfMonth';
|
||||||
|
import startOfWeek from 'date-fns/startOfWeek';
|
||||||
|
import startOfYear from 'date-fns/startOfYear';
|
||||||
|
import differenceInDays from 'date-fns/differenceInDays';
|
||||||
|
import formatDistanceToNow from 'date-fns/formatDistanceToNow';
|
||||||
|
import { utcToZonedTime, zonedTimeToUtc } from 'date-fns-tz';
|
||||||
|
|
||||||
|
import { Locale } from 'date-fns';
|
||||||
|
import { IUtils } from '@date-io/core/IUtils';
|
||||||
|
|
||||||
|
export default class DateUtils implements IUtils<Date> {
|
||||||
|
public static timezone?: string;
|
||||||
|
|
||||||
|
public locale?: Locale;
|
||||||
|
|
||||||
|
public yearFormat = 'yyyy';
|
||||||
|
|
||||||
|
public yearMonthFormat = 'MMMM yyyy';
|
||||||
|
|
||||||
|
public dateTime12hFormat = 'MMMM do hh:mm aaaa';
|
||||||
|
|
||||||
|
public dateTime24hFormat = 'MMMM do HH:mm';
|
||||||
|
|
||||||
|
public time12hFormat = 'hh:mm a';
|
||||||
|
|
||||||
|
public time24hFormat = 'HH:mm';
|
||||||
|
|
||||||
|
public dateFormat = 'MMMM do';
|
||||||
|
|
||||||
|
constructor({ locale }: { locale?: Locale } = {}) {
|
||||||
|
this.locale = locale;
|
||||||
|
}
|
||||||
|
|
||||||
|
public addDays(value: Date, count: number) {
|
||||||
|
return addDays(value, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public subDays(date: Date, amount: number): Date {
|
||||||
|
return subDays(date, amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public isValid(value: any) {
|
||||||
|
return isValid(this.date(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public getDiff(value: Date, comparing: Date | string) {
|
||||||
|
return differenceInMilliseconds(value, this.date(comparing));
|
||||||
|
}
|
||||||
|
|
||||||
|
public differenceInDays(dateLeft: Date, dateRight: Date): number {
|
||||||
|
return differenceInDays(dateLeft, dateRight);
|
||||||
|
}
|
||||||
|
|
||||||
|
public isAfter(value: Date, comparing: Date) {
|
||||||
|
return isAfter(value, comparing);
|
||||||
|
}
|
||||||
|
|
||||||
|
public isBefore(value: Date, comparing: Date) {
|
||||||
|
return isBefore(value, comparing);
|
||||||
|
}
|
||||||
|
|
||||||
|
public startOfDay(value: Date) {
|
||||||
|
return startOfDay(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public endOfDay(value: Date) {
|
||||||
|
return endOfDay(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getHours(value: Date) {
|
||||||
|
return getHours(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public setHours(value: Date, count: number) {
|
||||||
|
return setHours(value, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public setMinutes(value: Date, count: number) {
|
||||||
|
return setMinutes(value, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getSeconds(value: Date) {
|
||||||
|
return getSeconds(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public setSeconds(value: Date, count: number) {
|
||||||
|
return setSeconds(value, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public isSameDay(value: Date, comparing: Date) {
|
||||||
|
return isSameDay(value, comparing);
|
||||||
|
}
|
||||||
|
|
||||||
|
public isSameMonth(value: Date, comparing: Date) {
|
||||||
|
return isSameMonth(value, comparing);
|
||||||
|
}
|
||||||
|
|
||||||
|
public isSameYear(value: Date, comparing: Date) {
|
||||||
|
return isSameYear(value, comparing);
|
||||||
|
}
|
||||||
|
|
||||||
|
public isSameHour(value: Date, comparing: Date) {
|
||||||
|
return isSameHour(value, comparing);
|
||||||
|
}
|
||||||
|
|
||||||
|
public startOfMonth(value: Date) {
|
||||||
|
return startOfMonth(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public endOfMonth(value: Date) {
|
||||||
|
return endOfMonth(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getYear(value: Date) {
|
||||||
|
return getYear(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public setYear(value: Date, count: number) {
|
||||||
|
return setYear(value, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public dateInTZ(value: any, timezone: string): Date {
|
||||||
|
const date = new Date(value);
|
||||||
|
return new Date(date.toLocaleString('en-US', { timeZone: timezone }));
|
||||||
|
}
|
||||||
|
|
||||||
|
public date(value?: any) {
|
||||||
|
if (typeof value === 'undefined') {
|
||||||
|
if (!DateUtils.timezone) {
|
||||||
|
return new Date();
|
||||||
|
}
|
||||||
|
return this.dateInTZ(new Date(), DateUtils.timezone);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value instanceof Date) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!DateUtils.timezone) {
|
||||||
|
return new Date(value);
|
||||||
|
}
|
||||||
|
return this.dateInTZ(value, DateUtils.timezone);
|
||||||
|
}
|
||||||
|
|
||||||
|
public parse(value: string, formatString: string) {
|
||||||
|
if (value === '') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dateFnsParse(value, formatString, this.date(), {
|
||||||
|
locale: this.locale,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public format(date: Date, formatString: string) {
|
||||||
|
return format(date, formatString, { locale: this.locale });
|
||||||
|
}
|
||||||
|
|
||||||
|
public toJSON(date: Date) {
|
||||||
|
return (
|
||||||
|
this.format(date, 'yyyy-MM-dd') +
|
||||||
|
'T' +
|
||||||
|
this.format(date, 'HH:mm:ss') +
|
||||||
|
'Z'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public isEqual(date: any, comparing: any) {
|
||||||
|
if (date === null && comparing === null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isEqual(date, comparing);
|
||||||
|
}
|
||||||
|
|
||||||
|
public isNull(date: Date) {
|
||||||
|
return date === null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isAfterDay(date: Date, value: Date) {
|
||||||
|
return isAfter(date, endOfDay(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public isBeforeDay(date: Date, value: Date) {
|
||||||
|
return isBefore(date, startOfDay(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public isBeforeYear(date: Date, value: Date) {
|
||||||
|
return isBefore(date, startOfYear(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public isAfterYear(date: Date, value: Date) {
|
||||||
|
return isAfter(date, endOfYear(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public formatNumber(numberToFormat: string) {
|
||||||
|
return numberToFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMinutes(date: Date) {
|
||||||
|
return date.getMinutes();
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMonth(date: Date) {
|
||||||
|
return date.getMonth();
|
||||||
|
}
|
||||||
|
|
||||||
|
public setMonth(date: Date, count: number) {
|
||||||
|
return setMonth(date, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMeridiemText(ampm: 'am' | 'pm') {
|
||||||
|
return ampm === 'am' ? 'AM' : 'PM';
|
||||||
|
}
|
||||||
|
|
||||||
|
public getNextMonth(date: Date) {
|
||||||
|
return addMonths(date, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getPreviousMonth(date: Date) {
|
||||||
|
return addMonths(date, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMonthArray(date: Date) {
|
||||||
|
const firstMonth = startOfYear(date);
|
||||||
|
const monthArray = [firstMonth];
|
||||||
|
|
||||||
|
while (monthArray.length < 12) {
|
||||||
|
const prevMonth = monthArray[monthArray.length - 1];
|
||||||
|
monthArray.push(this.getNextMonth(prevMonth));
|
||||||
|
}
|
||||||
|
|
||||||
|
return monthArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
public mergeDateAndTime(date: Date, time: Date) {
|
||||||
|
return this.setMinutes(
|
||||||
|
this.setHours(date, this.getHours(time)),
|
||||||
|
this.getMinutes(time)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getWeekdays() {
|
||||||
|
const now = new Date();
|
||||||
|
return eachDayOfInterval({
|
||||||
|
start: startOfWeek(now, { locale: this.locale }),
|
||||||
|
end: endOfWeek(now, { locale: this.locale }),
|
||||||
|
}).map(day => this.format(day, 'EEEEEE'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public getWeekArray(date: Date) {
|
||||||
|
const start = startOfWeek(startOfMonth(date), { locale: this.locale });
|
||||||
|
const end = endOfWeek(endOfMonth(date), { locale: this.locale });
|
||||||
|
|
||||||
|
let count = 0;
|
||||||
|
let current = start;
|
||||||
|
const nestedWeeks: Date[][] = [];
|
||||||
|
|
||||||
|
while (isBefore(current, end)) {
|
||||||
|
const weekNumber = Math.floor(count / 7);
|
||||||
|
nestedWeeks[weekNumber] = nestedWeeks[weekNumber] || [];
|
||||||
|
nestedWeeks[weekNumber].push(current);
|
||||||
|
current = addDays(current, 1);
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nestedWeeks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getYearRange(start: Date, end: Date) {
|
||||||
|
const startDate = startOfYear(start);
|
||||||
|
const endDate = endOfYear(end);
|
||||||
|
const years: Date[] = [];
|
||||||
|
|
||||||
|
let current = startDate;
|
||||||
|
while (isBefore(current, endDate)) {
|
||||||
|
years.push(current);
|
||||||
|
current = addYears(current, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return years;
|
||||||
|
}
|
||||||
|
|
||||||
|
// displaying methpds
|
||||||
|
public getCalendarHeaderText(date: Date) {
|
||||||
|
return this.format(date, this.yearMonthFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getYearText(date: Date) {
|
||||||
|
return this.format(date, 'yyyy');
|
||||||
|
}
|
||||||
|
|
||||||
|
public getDatePickerHeaderText(date: Date) {
|
||||||
|
return this.format(date, 'EEE, MMM d');
|
||||||
|
}
|
||||||
|
|
||||||
|
public getDateTimePickerHeaderText(date: Date) {
|
||||||
|
return this.format(date, 'MMM d');
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMonthText(date: Date) {
|
||||||
|
return this.format(date, 'MMMM');
|
||||||
|
}
|
||||||
|
|
||||||
|
public getDayText(date: Date) {
|
||||||
|
return this.format(date, 'd');
|
||||||
|
}
|
||||||
|
|
||||||
|
public getHourText(date: Date, ampm: boolean) {
|
||||||
|
return this.format(date, ampm ? 'hh' : 'HH');
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMinuteText(date: Date) {
|
||||||
|
return this.format(date, 'mm');
|
||||||
|
}
|
||||||
|
|
||||||
|
public getSecondText(date: Date) {
|
||||||
|
return this.format(date, 'ss');
|
||||||
|
}
|
||||||
|
|
||||||
|
public formatDistanceToNow(
|
||||||
|
date: Date,
|
||||||
|
opts: {
|
||||||
|
includeSeconds?: boolean;
|
||||||
|
addSuffix?: boolean;
|
||||||
|
} = {}
|
||||||
|
) {
|
||||||
|
return formatDistanceToNow(date, {
|
||||||
|
...opts,
|
||||||
|
locale: this.locale,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public UTCToZonedTime(date: Date): Date {
|
||||||
|
if (!DateUtils.timezone) {
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
return utcToZonedTime(date, DateUtils.timezone);
|
||||||
|
}
|
||||||
|
|
||||||
|
public zonedTimeToUTC(date: Date): Date {
|
||||||
|
if (!DateUtils.timezone) {
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
return zonedTimeToUtc(date, DateUtils.timezone);
|
||||||
|
}
|
||||||
|
}
|
30
src/libs/date/DateUtilsProvider.tsx
Normal file
30
src/libs/date/DateUtilsProvider.tsx
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import React, { useMemo } from 'react';
|
||||||
|
import useVersion from '@libs/VersionContext/useVersion';
|
||||||
|
import { getLocale } from './locales';
|
||||||
|
import DateUtils from './DateUtils';
|
||||||
|
|
||||||
|
import { MuiPickersUtilsProvider } from '@material-ui/pickers';
|
||||||
|
import Context from './context';
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
function DateUtilsProvider({ children }: Props) {
|
||||||
|
const version = useVersion();
|
||||||
|
const locale = useMemo(() => {
|
||||||
|
return getLocale(version.code);
|
||||||
|
}, [version.code]);
|
||||||
|
const dateUtils = useMemo(() => {
|
||||||
|
DateUtils.timezone = version.timezone;
|
||||||
|
return new DateUtils({ locale });
|
||||||
|
}, [version.timezone, locale]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MuiPickersUtilsProvider utils={DateUtils}>
|
||||||
|
<Context.Provider value={dateUtils}>{children}</Context.Provider>
|
||||||
|
</MuiPickersUtilsProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DateUtilsProvider;
|
7
src/libs/date/context.ts
Normal file
7
src/libs/date/context.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import { createContext } from 'react';
|
||||||
|
import DateUtils from './DateUtils';
|
||||||
|
|
||||||
|
const ctx = createContext<DateUtils>(new DateUtils());
|
||||||
|
ctx.displayName = 'DateUtilsProvider';
|
||||||
|
|
||||||
|
export default ctx;
|
8
src/libs/date/useDateUtils.ts
Normal file
8
src/libs/date/useDateUtils.ts
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import { useContext } from 'react';
|
||||||
|
import ctx from './context';
|
||||||
|
|
||||||
|
const useDateUtils = () => {
|
||||||
|
return useContext(ctx);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useDateUtils;
|
|
@ -13,6 +13,9 @@ const translations = {
|
||||||
closed: 'Closed',
|
closed: 'Closed',
|
||||||
open: 'Open',
|
open: 'Open',
|
||||||
},
|
},
|
||||||
|
versionContextProvider: {
|
||||||
|
loading: 'Loading...',
|
||||||
|
},
|
||||||
devNote: `This website is still under development and some things may be broken.`,
|
devNote: `This website is still under development and some things may be broken.`,
|
||||||
mainLayout: {
|
mainLayout: {
|
||||||
header: {
|
header: {
|
||||||
|
|
|
@ -13,6 +13,9 @@ const translations = {
|
||||||
closed: 'Zamknięty',
|
closed: 'Zamknięty',
|
||||||
open: 'Otwarty',
|
open: 'Otwarty',
|
||||||
},
|
},
|
||||||
|
versionContextProvider: {
|
||||||
|
loading: 'Ładowanie...',
|
||||||
|
},
|
||||||
devNote: `Strona jest ciągle w procesie tworzenia i mogą występować błędy.`,
|
devNote: `Strona jest ciągle w procesie tworzenia i mogą występować błędy.`,
|
||||||
mainLayout: {
|
mainLayout: {
|
||||||
header: {
|
header: {
|
||||||
|
|
Reference in New Issue
Block a user