[WIP]: /server/:key/ranking/player

- add PageLayout
This commit is contained in:
Dawid Wysokiński 2020-12-19 14:49:36 +01:00
parent 5f6e9eb363
commit 6df12861bf
19 changed files with 279 additions and 17 deletions

View File

@ -24,4 +24,7 @@ export const SERVER_PAGE = {
VILLAGE_PAGE: {
INDEX_PAGE: 'server-page/village-page/index-page',
},
RANKING_PAGE: {
COMMON: 'server-page/ranking-page/common',
},
};

View File

@ -20,6 +20,7 @@ export const SERVER_PAGE = {
INDEX_PAGE: '/server/:key/village/:id',
},
RANKING_PAGE: {
BASE: '/server/:key/ranking',
PLAYER_PAGE: {
INDEX_PAGE: '/server/:key/ranking/player',
OD_PAGE: '/server/:key/ranking/player/od',

View File

@ -7,6 +7,7 @@ import IndexPage from './features/IndexPage/IndexPage';
import PlayerPage from './features/PlayerPage/PlayerPage';
import TribePage from './features/TribePage/TribePage';
import VillagePage from './features/VillagePage/VillagePage';
import RankingPage from './features/RankingPage/RankingPage';
import NotFoundPage from '../NotFoundPage/NotFoundPage';
const EnhancedRoute = ({ children, ...rest }: RouteProps) => {
@ -32,6 +33,9 @@ function ServerPage() {
<EnhancedRoute exact path={SERVER_PAGE.VILLAGE_PAGE.INDEX_PAGE}>
<VillagePage />
</EnhancedRoute>
<EnhancedRoute path={SERVER_PAGE.RANKING_PAGE.BASE}>
<RankingPage />
</EnhancedRoute>
<Route path="*">
<NotFoundPage />
</Route>

View File

@ -43,46 +43,54 @@ const Sidebar = ({ t, className, open, variant, onClose, onOpen }: Props) => {
to: ROUTES.SERVER_PAGE.INDEX_PAGE,
params: { key },
Icon: <DashboardIcon color="inherit" />,
exact: true,
},
{
name: t('pageLayout.sidebar.routes.rankings.name'),
Icon: <GradeIcon color="inherit" />,
to: ROUTES.SERVER_PAGE.RANKING_PAGE.BASE,
nested: [
{
name: t('pageLayout.sidebar.routes.rankings.player.index'),
to: ROUTES.SERVER_PAGE.RANKING_PAGE.PLAYER_PAGE.INDEX_PAGE,
params: { key },
Icon: <GradeIcon color="inherit" />,
exact: true,
},
{
name: t('pageLayout.sidebar.routes.rankings.player.od'),
to: ROUTES.SERVER_PAGE.RANKING_PAGE.PLAYER_PAGE.OD_PAGE,
params: { key },
Icon: <GradeIcon color="inherit" />,
exact: true,
},
{
name: t('pageLayout.sidebar.routes.rankings.player.archive'),
to: ROUTES.SERVER_PAGE.RANKING_PAGE.PLAYER_PAGE.ARCHIVE_PAGE,
params: { key },
Icon: <GradeIcon color="inherit" />,
exact: true,
},
{
name: t('pageLayout.sidebar.routes.rankings.tribe.index'),
to: ROUTES.SERVER_PAGE.RANKING_PAGE.TRIBE_PAGE.INDEX_PAGE,
params: { key },
Icon: <GradeIcon color="inherit" />,
exact: true,
},
{
name: t('pageLayout.sidebar.routes.rankings.tribe.od'),
to: ROUTES.SERVER_PAGE.RANKING_PAGE.TRIBE_PAGE.OD_PAGE,
params: { key },
Icon: <GradeIcon color="inherit" />,
exact: true,
},
{
name: t('pageLayout.sidebar.routes.rankings.tribe.archive'),
to: ROUTES.SERVER_PAGE.RANKING_PAGE.TRIBE_PAGE.ARCHIVE_PAGE,
params: { key },
Icon: <GradeIcon color="inherit" />,
exact: true,
},
],
},
@ -91,12 +99,14 @@ const Sidebar = ({ t, className, open, variant, onClose, onOpen }: Props) => {
to: ROUTES.SERVER_PAGE.ENNOBLEMENTS_PAGE,
params: { key },
Icon: <BeenhereIcon color="inherit" />,
exact: true,
},
{
name: t('pageLayout.sidebar.routes.map'),
to: ROUTES.SERVER_PAGE.MAP_PAGE,
params: { key },
Icon: <MapIcon color="inherit" />,
exact: true,
},
];

View File

@ -1,5 +1,5 @@
import React, { Fragment, useState } from 'react';
import { useLocation, generatePath } from 'react-router-dom';
import { useLocation, generatePath, matchPath } from 'react-router-dom';
import { Route } from './types';
import { makeStyles } from '@material-ui/core/styles';
@ -25,12 +25,8 @@ function ListItem({ route, nestedLevel }: Props) {
const classes = useStyles();
const { pathname } = useLocation();
const hasNested = Array.isArray(route.nested) && route.nested.length > 0;
const generatedPath =
route.to && route.params
? generatePath(route.to, route.params)
: route.to
? route.to
: '';
const isActive =
route.to && matchPath(pathname, { path: route.to, exact: route.exact });
const getItem = () => {
return (
@ -43,12 +39,17 @@ function ListItem({ route, nestedLevel }: Props) {
>
<ListItemIcon
className={clsx({
[classes.activeLink]: generatedPath === pathname,
[classes.activeLink]: isActive,
})}
>
{route.Icon}
</ListItemIcon>
<ListItemText primary={route.name} />
<ListItemText
className={clsx({
[classes.activeLink]: isActive,
})}
primary={route.name}
/>
{hasNested && (
<Fragment>{open ? <ExpandLess /> : <ExpandMore />}</Fragment>
)}
@ -59,14 +60,7 @@ function ListItem({ route, nestedLevel }: Props) {
return (
<Fragment>
{!hasNested && route.to ? (
<Link
to={route.to}
params={route.params}
className={clsx(classes.link, {
[classes.activeLink]: generatedPath === pathname,
})}
color="inherit"
>
<Link to={route.to} params={route.params} color="inherit">
{getItem()}
</Link>
) : (

View File

@ -3,6 +3,7 @@ import { Props } from '@common/Link/Link';
export interface Route {
name: string;
to?: string;
exact?: boolean;
params?: Props['params'];
Icon: React.ReactElement;
nested?: Route[];

View File

@ -0,0 +1,21 @@
import React from 'react';
import { SERVER_PAGE } from '@config/routes';
import { Switch, Route } from 'react-router-dom';
import PlayerPage from './features/PlayerPage/PlayerPage';
import NotFoundPage from '../../../NotFoundPage/NotFoundPage';
function RankingPage() {
return (
<Switch>
<Route path={SERVER_PAGE.RANKING_PAGE.PLAYER_PAGE.INDEX_PAGE}>
<PlayerPage />
</Route>
<Route path="*">
<NotFoundPage />
</Route>
</Switch>
);
}
export default RankingPage;

View File

@ -0,0 +1,78 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import useServer from '@features/ServerPage/libs/ServerContext/useServer';
import useTabs from './useTabs';
import * as NAMESPACES from '@config/namespaces';
import { makeStyles } from '@material-ui/core/styles';
import { Tabs, Tab } from '@material-ui/core';
import Link from '@common/Link/Link';
import ServerPageLayout from '@features/ServerPage/common/PageLayout/PageLayout';
import background from './backgrounds/bg-1-dark.png';
export interface Props {
children: React.ReactNode;
}
function PageLayout({ children }: Props) {
const classes = useStyles();
const server = useServer();
const { t } = useTranslation(NAMESPACES.SERVER_PAGE.RANKING_PAGE.COMMON);
const { currentTab, tabs } = useTabs(t);
return (
<ServerPageLayout noPadding>
<header className={classes.header}>
<Tabs
variant="scrollable"
value={currentTab}
selectionFollowsFocus={false}
>
{tabs.map(({ to, label }) => {
return (
<Tab
key={to}
label={
<Link
to={to}
color="inherit"
params={{ key: server.key }}
style={{ width: '100%', height: '100%' }}
>
{label}
</Link>
}
/>
);
})}
</Tabs>
</header>
<div className={classes.content}>{children}</div>
</ServerPageLayout>
);
}
const useStyles = makeStyles(theme => ({
header: {
width: '100%',
minHeight: theme.spacing(30),
backgroundPosition: 'center',
backgroundSize: 'cover',
backgroundRepeat: 'no-repeat',
display: 'flex',
justifyContent: 'flex-end',
flexDirection: 'column',
backgroundImage: `url(${background})`,
boxShadow: theme.shadows[4],
},
content: {
height: '100%',
padding: theme.spacing(3, 0),
'&.no-padding': {
padding: '0 0',
},
},
}));
export default PageLayout;

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

View File

@ -0,0 +1,58 @@
import { useMemo } from 'react';
import { matchPath, useLocation } from 'react-router-dom';
import * as ROUTES from '@config/routes';
import { TFunction } from 'i18next';
const useTabs = (t: TFunction) => {
const loc = useLocation();
const tabs = useMemo(() => {
return [
{
to: ROUTES.SERVER_PAGE.RANKING_PAGE.PLAYER_PAGE.INDEX_PAGE,
label: t('pageLayout.tabs.playerPage.indexPage'),
},
{
to: ROUTES.SERVER_PAGE.RANKING_PAGE.PLAYER_PAGE.OD_PAGE,
label: t('pageLayout.tabs.playerPage.odPage'),
},
{
to: ROUTES.SERVER_PAGE.RANKING_PAGE.PLAYER_PAGE.DAILY_PAGE,
label: t('pageLayout.tabs.playerPage.dailyPage'),
},
{
to: ROUTES.SERVER_PAGE.RANKING_PAGE.PLAYER_PAGE.ARCHIVE_PAGE,
label: t('pageLayout.tabs.playerPage.archivePage'),
},
{
to: ROUTES.SERVER_PAGE.RANKING_PAGE.TRIBE_PAGE.INDEX_PAGE,
label: t('pageLayout.tabs.tribePage.indexPage'),
},
{
to: ROUTES.SERVER_PAGE.RANKING_PAGE.TRIBE_PAGE.OD_PAGE,
label: t('pageLayout.tabs.tribePage.odPage'),
},
{
to: ROUTES.SERVER_PAGE.RANKING_PAGE.TRIBE_PAGE.DAILY_PAGE,
label: t('pageLayout.tabs.tribePage.dailyPage'),
},
{
to: ROUTES.SERVER_PAGE.RANKING_PAGE.TRIBE_PAGE.ARCHIVE_PAGE,
label: t('pageLayout.tabs.tribePage.archivePage'),
},
];
}, [t]);
const currentTab = useMemo(
() =>
tabs.findIndex(({ to }) => {
return matchPath(loc.pathname, { exact: true, path: to });
}),
[loc.pathname, tabs]
);
return {
tabs,
currentTab,
};
};
export default useTabs;

View File

@ -0,0 +1,21 @@
import React from 'react';
import { SERVER_PAGE } from '@config/routes';
import { Switch, Route } from 'react-router-dom';
import IndexPage from './features/IndexPage/IndexPage';
import NotFoundPage from '../../../NotFoundPage/NotFoundPage';
function PlayerPage() {
return (
<Switch>
<Route exact path={SERVER_PAGE.RANKING_PAGE.PLAYER_PAGE.INDEX_PAGE}>
<IndexPage />
</Route>
<Route path="*">
<NotFoundPage />
</Route>
</Switch>
);
}
export default PlayerPage;

View File

@ -0,0 +1,9 @@
import React from 'react';
import PageLayout from '@features/ServerPage/features/RankingPage/common/PageLayout/PageLayout';
function IndexPage() {
return <PageLayout>elo</PageLayout>;
}
export default IndexPage;

View File

@ -4,6 +4,7 @@ import indexPage from './index-page';
import playerPage from './player-page';
import tribePage from './tribe-page';
import villagePage from './village-page';
import rankingPage from './ranking-page';
const translations = {
[NAMESPACES.SERVER_PAGE.COMMON]: common,
@ -11,6 +12,7 @@ const translations = {
[NAMESPACES.SERVER_PAGE.VILLAGE_PAGE.INDEX_PAGE]: villagePage,
...playerPage,
...tribePage,
...rankingPage,
};
export default translations;

View File

@ -0,0 +1,20 @@
const translations = {
pageLayout: {
tabs: {
playerPage: {
indexPage: 'Players',
odPage: 'Players OD',
dailyPage: 'Players daily',
archivePage: 'Past players',
},
tribePage: {
indexPage: 'Tribes',
odPage: 'Tribes OD',
dailyPage: 'Tribes daily',
archivePage: 'Past tribes',
},
},
},
};
export default translations;

View File

@ -0,0 +1,8 @@
import * as NAMESPACES from '@config/namespaces';
import common from './common';
const translations = {
[NAMESPACES.SERVER_PAGE.RANKING_PAGE.COMMON]: common,
};
export default translations;

View File

@ -4,11 +4,13 @@ import indexPage from './index-page';
import notFoundPage from './not-found-page';
import serverPage from './server-page';
import table from './table';
import lineChart from './line-chart';
const translations = {
[NAMESPACES.COMMON]: common,
[NAMESPACES.INDEX_PAGE]: indexPage,
[NAMESPACES.NOT_FOUND_PAGE]: notFoundPage,
[NAMESPACES.LINE_CHART]: lineChart,
[NAMESPACES.TABLE]: table,
...serverPage,
};

View File

@ -4,6 +4,7 @@ import indexPage from './index-page';
import playerPage from './player-page';
import tribePage from './tribe-page';
import villagePage from './village-page';
import rankingPage from './ranking-page';
const translations = {
[NAMESPACES.SERVER_PAGE.COMMON]: common,
@ -11,6 +12,7 @@ const translations = {
[NAMESPACES.SERVER_PAGE.VILLAGE_PAGE.INDEX_PAGE]: villagePage,
...playerPage,
...tribePage,
...rankingPage,
};
export default translations;

View File

@ -0,0 +1,20 @@
const translations = {
pageLayout: {
tabs: {
playerPage: {
indexPage: 'Gracze',
odPage: 'Gracze OD',
dailyPage: 'Gracze dzienne',
archivePage: 'Byli gracze',
},
tribePage: {
indexPage: 'Plemiona',
odPage: 'Plemiona OD',
dailyPage: 'Plemiona dzienne',
archivePage: 'Byłe plemiona',
},
},
},
};
export default translations;

View File

@ -0,0 +1,8 @@
import * as NAMESPACES from '@config/namespaces';
import common from './common';
const translations = {
[NAMESPACES.SERVER_PAGE.RANKING_PAGE.COMMON]: common,
};
export default translations;