From 989ac31fa29ec2f0ce1d16696afe500a3a365782 Mon Sep 17 00:00:00 2001 From: GZTime Date: Mon, 7 Aug 2023 11:40:18 +0800 Subject: [PATCH] feat(frontend): default scale to the latest 7 days for long game --- .../ClientApp/src/components/GameCard.tsx | 13 +++--------- .../ClientApp/src/components/RecentGame.tsx | 10 ++++------ .../src/components/RecentGameSlide.tsx | 9 ++++----- .../ClientApp/src/components/TimeLine.tsx | 20 +++++++++++++------ .../ClientApp/src/components/WithGameTab.tsx | 10 +++------- .../ClientApp/src/pages/admin/games/Index.tsx | 7 +++---- .../ClientApp/src/pages/games/[id]/Index.tsx | 2 +- src/GZCTF/ClientApp/src/utils/useGame.ts | 9 +++++++-- 8 files changed, 39 insertions(+), 41 deletions(-) diff --git a/src/GZCTF/ClientApp/src/components/GameCard.tsx b/src/GZCTF/ClientApp/src/components/GameCard.tsx index c0d775d1f..b39ae2634 100644 --- a/src/GZCTF/ClientApp/src/components/GameCard.tsx +++ b/src/GZCTF/ClientApp/src/components/GameCard.tsx @@ -1,4 +1,3 @@ -import dayjs, { Dayjs } from 'dayjs' import { FC } from 'react' import { Link } from 'react-router-dom' import { @@ -15,6 +14,7 @@ import { } from '@mantine/core' import { mdiChevronTripleRight, mdiFlagOutline } from '@mdi/js' import { Icon } from '@mdi/react' +import { getGameStatus } from '@Utils/useGame' import { BasicGameInfoModel } from '@Api' export enum GameStatus { @@ -33,21 +33,14 @@ interface GameCardProps { game: BasicGameInfoModel } -export const getGameStatus = (start: Dayjs, end: Dayjs) => { - const now = dayjs() - return end < now ? GameStatus.Ended : start > now ? GameStatus.Coming : GameStatus.OnGoing -} - const GameCard: FC = ({ game, ...others }) => { const theme = useMantineTheme() - const { summary, title, poster, start, end, limit } = game - const startTime = dayjs(start) - const endTime = dayjs(end) + const { summary, title, poster, limit } = game + const { startTime, endTime, status } = getGameStatus(game) const duration = endTime.diff(startTime, 'hours') - const status = getGameStatus(startTime, endTime) const color = GameColorMap.get(status) return ( diff --git a/src/GZCTF/ClientApp/src/components/RecentGame.tsx b/src/GZCTF/ClientApp/src/components/RecentGame.tsx index 757e95c0a..9f8639a2e 100644 --- a/src/GZCTF/ClientApp/src/components/RecentGame.tsx +++ b/src/GZCTF/ClientApp/src/components/RecentGame.tsx @@ -14,7 +14,8 @@ import { } from '@mantine/core' import { mdiFlagOutline } from '@mdi/js' import { Icon } from '@mdi/react' -import { getGameStatus, GameColorMap, GameStatus } from '@Components/GameCard' +import { GameColorMap, GameStatus } from '@Components/GameCard' +import { getGameStatus } from '@Utils/useGame' import { BasicGameInfoModel } from '@Api' export interface RecentGameProps { @@ -26,12 +27,9 @@ const POSTER_HEIGHT = '15vh' const RecentGame: FC = ({ game, ...others }) => { const theme = useMantineTheme() - const { title, poster, start, end } = game + const { title, poster } = game + const { startTime, endTime, status } = getGameStatus(game) - const startTime = dayjs(start) - const endTime = dayjs(end) - - const status = getGameStatus(startTime, endTime) const color = GameColorMap.get(status) const duration = diff --git a/src/GZCTF/ClientApp/src/components/RecentGameSlide.tsx b/src/GZCTF/ClientApp/src/components/RecentGameSlide.tsx index 88ddd5379..9d48c0126 100644 --- a/src/GZCTF/ClientApp/src/components/RecentGameSlide.tsx +++ b/src/GZCTF/ClientApp/src/components/RecentGameSlide.tsx @@ -2,8 +2,9 @@ import dayjs from 'dayjs' import { FC } from 'react' import { Link } from 'react-router-dom' import { Badge, Group, Stack, Title, createStyles, Paper } from '@mantine/core' -import { getGameStatus, GameColorMap, GameStatus } from '@Components/GameCard' +import { GameColorMap, GameStatus } from '@Components/GameCard' import { RecentGameProps } from '@Components/RecentGame' +import { getGameStatus } from '@Utils/useGame' const useStyles = createStyles((theme) => ({ card: { @@ -29,12 +30,10 @@ const useStyles = createStyles((theme) => ({ const RecentGameSlide: FC = ({ game, ...others }) => { const { classes } = useStyles() - const { title, poster, start, end } = game + const { title, poster } = game - const startTime = dayjs(start) - const endTime = dayjs(end) + const { startTime, endTime, status } = getGameStatus(game) - const status = getGameStatus(startTime, endTime) const color = GameColorMap.get(status) const duration = diff --git a/src/GZCTF/ClientApp/src/components/TimeLine.tsx b/src/GZCTF/ClientApp/src/components/TimeLine.tsx index e2f004f0a..6996083b2 100644 --- a/src/GZCTF/ClientApp/src/components/TimeLine.tsx +++ b/src/GZCTF/ClientApp/src/components/TimeLine.tsx @@ -3,7 +3,7 @@ import ReactEcharts from 'echarts-for-react' import { FC, useEffect, useState } from 'react' import { useParams } from 'react-router-dom' import { useMantineTheme } from '@mantine/core' -import { useGame, useGameScoreboard } from '@Utils/useGame' +import { getGameStatus, useGame, useGameScoreboard } from '@Utils/useGame' interface TimeLineProps { organization: string | null @@ -18,6 +18,15 @@ const TimeLine: FC = ({ organization }) => { const { game } = useGame(numId) + const { startTime, endTime, progress } = getGameStatus(game) + + const totDuration = endTime.diff(startTime, 'd') + const longGame = totDuration > 14 + const weekProgress = (7 / totDuration) * 100 + + const scaleStart = progress - weekProgress + const scaleEnd = progress + const [now, setNow] = useState(new Date()) const [chartData, setChartData] = useState() @@ -25,7 +34,6 @@ const TimeLine: FC = ({ organization }) => { if (!scoreboard?.timeLines || !game) return const timeLine = scoreboard?.timeLines[organization ?? 'all'] ?? [] - const endTime = dayjs(game.end) const current = dayjs() const last = endTime.diff(current, 's') < 0 ? endTime : current @@ -138,14 +146,14 @@ const TimeLine: FC = ({ organization }) => { dataZoom: [ { type: 'inside', - start: 0, - end: 100, + start: longGame ? scaleStart : 0, + end: longGame ? scaleEnd : 100, xAxisIndex: 0, filterMode: 'none', }, { - start: 0, - end: 100, + start: longGame ? scaleStart : 0, + end: longGame ? scaleEnd : 100, xAxisIndex: 0, showDetail: false, }, diff --git a/src/GZCTF/ClientApp/src/components/WithGameTab.tsx b/src/GZCTF/ClientApp/src/components/WithGameTab.tsx index 5ddbf5345..cc64c4a8c 100644 --- a/src/GZCTF/ClientApp/src/components/WithGameTab.tsx +++ b/src/GZCTF/ClientApp/src/components/WithGameTab.tsx @@ -9,7 +9,7 @@ import { Icon } from '@mdi/react' import CustomProgress from '@Components/CustomProgress' import IconTabs from '@Components/IconTabs' import { RequireRole } from '@Components/WithRole' -import { useGame } from '@Utils/useGame' +import { getGameStatus, useGame } from '@Utils/useGame' import { usePageTitle } from '@Utils/usePageTitle' import { useUserRole } from '@Utils/useUser' import { DetailedGameInfoModel, ParticipationStatus, Role } from '@Api' @@ -47,12 +47,9 @@ const pages = [ dayjs.extend(duration) const GameCountdown: FC<{ game?: DetailedGameInfoModel }> = ({ game }) => { - const start = dayjs(game?.start ?? new Date()) - const end = dayjs(game?.end ?? new Date()) - const total = end.diff(start) + const { endTime, progress } = getGameStatus(game) const [now, setNow] = useState(dayjs()) - const current = now.diff(start) useEffect(() => { if (!game || dayjs() > dayjs(game.end)) return @@ -60,8 +57,7 @@ const GameCountdown: FC<{ game?: DetailedGameInfoModel }> = ({ game }) => { return () => clearInterval(interval) }, [game]) - const progress = (current / total) * 100 - const countdown = dayjs.duration(end.diff(now)) + const countdown = dayjs.duration(endTime.diff(now)) return ( { {games && games.map((game) => { - const startTime = dayjs(game.start) - const endTime = dayjs(game.end) - const status = getGameStatus(startTime, endTime) + const { startTime, endTime, status } = getGameStatus(game) const color = GameColorMap.get(status) return ( diff --git a/src/GZCTF/ClientApp/src/pages/games/[id]/Index.tsx b/src/GZCTF/ClientApp/src/pages/games/[id]/Index.tsx index 18f156fce..400c57565 100644 --- a/src/GZCTF/ClientApp/src/pages/games/[id]/Index.tsx +++ b/src/GZCTF/ClientApp/src/pages/games/[id]/Index.tsx @@ -263,7 +263,7 @@ const GameDetail: FC = () => { - + {ControlButtons} diff --git a/src/GZCTF/ClientApp/src/utils/useGame.ts b/src/GZCTF/ClientApp/src/utils/useGame.ts index 98b8231c3..60fad8262 100644 --- a/src/GZCTF/ClientApp/src/utils/useGame.ts +++ b/src/GZCTF/ClientApp/src/utils/useGame.ts @@ -1,4 +1,5 @@ import dayjs from 'dayjs' +import { GameStatus } from '@Components/GameCard' import { OnceSWRConfig } from '@Utils/useConfig' import api, { DetailedGameInfoModel, ParticipationStatus } from '@Api' @@ -11,14 +12,18 @@ export const getGameStatus = (game?: DetailedGameInfoModel) => { const finished = current > duriation const started = current > 0 - const progress = started ? (finished ? 100 : current / duriation) : 0 + const total = endTime.diff(startTime, 'minute') + const progress = started ? (finished ? 1 : current / duriation) : 0 + const status = started ? (finished ? GameStatus.Ended : GameStatus.OnGoing) : GameStatus.Coming return { startTime, endTime, finished, started, - progress, + progress: progress * 100, + total, + status, } }