From ed98ae3041facea88de8c0e7bdc7ebcc4d1473d3 Mon Sep 17 00:00:00 2001 From: YooJin Lee <113789141+youznn@users.noreply.github.com> Date: Thu, 15 Feb 2024 16:59:39 +0900 Subject: [PATCH] feat(fe): edit contest page card list (#1386) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: modify fetch paths based on session presence * fix(fe): fix fetch path for the main page * fix: fix contest card overflow error * fix: fix card padding * feat(fe): change badge status when registered * feat: add status at data table * fix(deps): update tiptap monorepo to ^2.2.2 (#1356) * fix(deps): update tiptap monorepo to ^2.2.2 * fix: fix lockfile --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jaemin Choi <1dotolee@gmail.com> * feat(be): implement get-contest api (#1370) * feat(be): implement get-contest api - 참가자 수 participants를 함께 반환하는 getContest api 구현 * docs(be): add get-contest api docs * chore(be): modify get-contest, get-contests to include participants - _count를 활용해 참가자수가 contest 정보에 포함되도록 설정 * test(be): modify test to use contest-with-participants * chore(be): remove unused pipe * chore(be): add is-visible field to problem model (#1366) * chore(be): add is-visible field to problem model * chore(be): modify problem input type - problem input type에서 visible 여부 설정 가능하도록 변경 * docs(be): modify admin create-problem api docs - input에 isVisible 설정 반영 * test(be): add is-visible to input * test(be): add is-visible to problem input * feat(be): add update-visibility api * docs(be): add update-visibility api docs * chore(be): delete useless update-visibility function * chore(be): modify get-problem functions to check is-visible Co-authored-by: SH9480P --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jaemin Choi <1dotolee@gmail.com> Co-authored-by: Jaehyeon Kim Co-authored-by: SH9480P --- .../app/(main)/_components/Badge.tsx | 2 + .../app/(main)/_components/ContestCard.tsx | 10 +++- .../app/(main)/_components/ContestCards.tsx | 2 +- .../(main)/contest/_components/Columns.tsx | 16 ++++++- .../contest/_components/ContestCardList.tsx | 48 ++++++++++++++++--- .../_components/FinishedContestTable.tsx | 3 +- frontend-client/app/(main)/contest/page.tsx | 11 ++++- frontend-client/types/type.ts | 8 +++- 8 files changed, 85 insertions(+), 15 deletions(-) diff --git a/frontend-client/app/(main)/_components/Badge.tsx b/frontend-client/app/(main)/_components/Badge.tsx index d22a3decfe..f7f8d843de 100644 --- a/frontend-client/app/(main)/_components/Badge.tsx +++ b/frontend-client/app/(main)/_components/Badge.tsx @@ -2,6 +2,8 @@ import { cn } from '@/lib/utils' import React from 'react' const variants = { + registeredOngoing: 'bg-rose-700', + registeredUpcoming: 'bg-rose-700', ongoing: 'bg-emerald-700', upcoming: 'bg-blue-700', finished: 'bg-gray-700', diff --git a/frontend-client/app/(main)/_components/ContestCard.tsx b/frontend-client/app/(main)/_components/ContestCard.tsx index 2165d3a614..ab8dceb1e3 100644 --- a/frontend-client/app/(main)/_components/ContestCard.tsx +++ b/frontend-client/app/(main)/_components/ContestCard.tsx @@ -10,7 +10,9 @@ import TimeDiff from './TimeDiff' const variants = { ongoing: 'bg-gradient-to-br from-blue-500 to-blue-950', upcoming: 'bg-gradient-to-br from-emerald-600 to-emerald-900', - finished: 'bg-gray-500' + finished: 'bg-gray-500', + registeredOngoing: 'bg-gradient-to-br from-blue-500 to-blue-950', + registeredUpcoming: 'bg-gradient-to-br from-emerald-600 to-emerald-900' } interface Props { @@ -36,7 +38,11 @@ export default function ContestCard({ contest }: Props) { > -

{contest.status}

+

+ {contest.status.startsWith('registered') + ? 'registered' + : contest.status} +

{contest.title} diff --git a/frontend-client/app/(main)/_components/ContestCards.tsx b/frontend-client/app/(main)/_components/ContestCards.tsx index e634c50f26..938a3d6abc 100644 --- a/frontend-client/app/(main)/_components/ContestCards.tsx +++ b/frontend-client/app/(main)/_components/ContestCards.tsx @@ -8,7 +8,7 @@ const getContests = async () => { const data: { ongoing: Contest[] upcoming: Contest[] - } = await fetcher.get('contest').json() + } = await fetcher.get('contest/ongoing-upcoming').json() data.ongoing.forEach((contest) => { contest.status = 'ongoing' diff --git a/frontend-client/app/(main)/contest/_components/Columns.tsx b/frontend-client/app/(main)/contest/_components/Columns.tsx index baed725b28..a23fac9f4d 100644 --- a/frontend-client/app/(main)/contest/_components/Columns.tsx +++ b/frontend-client/app/(main)/contest/_components/Columns.tsx @@ -1,5 +1,6 @@ 'use client' +import Badge from '@/app/(main)/_components/Badge' import type { Contest } from '@/types/type' import type { ColumnDef } from '@tanstack/react-table' import dayjs from 'dayjs' @@ -14,6 +15,19 @@ export const columns: ColumnDef[] = [

) }, + { + header: 'Status', + accessorKey: 'status', + cell: ({ row }) => ( + +

+ {row.original.status.startsWith('registered') + ? 'registered' + : row.original.status} +

+
+ ) + }, { header: 'Starts at', accessorKey: 'startTime', @@ -27,6 +41,6 @@ export const columns: ColumnDef[] = [ { header: 'Participants', accessorKey: 'participants', - cell: ({ row }) => row.original.id + cell: ({ row }) => row.original.participants } ] diff --git a/frontend-client/app/(main)/contest/_components/ContestCardList.tsx b/frontend-client/app/(main)/contest/_components/ContestCardList.tsx index 75019b86ce..9b760f687a 100644 --- a/frontend-client/app/(main)/contest/_components/ContestCardList.tsx +++ b/frontend-client/app/(main)/contest/_components/ContestCardList.tsx @@ -6,16 +6,17 @@ import { CarouselNext, CarouselPrevious } from '@/components/ui/carousel' -import { fetcher } from '@/lib/utils' +import { fetcher, fetcherWithAuth } from '@/lib/utils' import type { Contest } from '@/types/type' import type { Route } from 'next' +import type { Session } from 'next-auth' import Link from 'next/link' const getContests = async () => { const data: { ongoing: Contest[] upcoming: Contest[] - } = await fetcher.get('contest').json() + } = await fetcher.get('contest/ongoing-upcoming').json() data.ongoing.forEach((contest) => { contest.status = 'ongoing' }) @@ -25,16 +26,49 @@ const getContests = async () => { return data.ongoing.concat(data.upcoming) } +const getRegisteredContests = async () => { + const data: { + registeredOngoing: Contest[] + registeredUpcoming: Contest[] + ongoing: Contest[] + upcoming: Contest[] + } = await fetcherWithAuth + .get('contest/ongoing-upcoming-with-registered') + .json() + data.registeredOngoing.forEach((contest) => { + contest.status = 'registeredOngoing' + }) + data.registeredUpcoming.forEach((contest) => { + contest.status = 'registeredUpcoming' + }) + data.ongoing.forEach((contest) => { + contest.status = 'ongoing' + }) + data.upcoming.forEach((contest) => { + contest.status = 'upcoming' + }) + return data.ongoing.concat( + data.upcoming.concat(data.registeredOngoing.concat(data.registeredUpcoming)) + ) +} + export default async function Contest({ title, - type + type, + session }: { type: string title: string + session?: Session | null }) { - const data = (await getContests()).filter( - (contest) => contest.status.toLowerCase() === type.toLowerCase() + const data = ( + session ? await getRegisteredContests() : await getContests() + ).filter( + (contest) => + contest.status.toLowerCase() === 'registered' + type.toLowerCase() || + contest.status.toLowerCase() === type.toLowerCase() ) + const contestChunks = [] for (let i = 0; i < data.length; i += 3) contestChunks.push(data.slice(i, i + 3)) @@ -50,14 +84,14 @@ export default async function Contest({ - + {contestChunks.map((contestChunk) => ( {contestChunk.map((contest) => ( diff --git a/frontend-client/app/(main)/contest/_components/FinishedContestTable.tsx b/frontend-client/app/(main)/contest/_components/FinishedContestTable.tsx index 045d4c354d..e7fffddaa2 100644 --- a/frontend-client/app/(main)/contest/_components/FinishedContestTable.tsx +++ b/frontend-client/app/(main)/contest/_components/FinishedContestTable.tsx @@ -23,7 +23,8 @@ export default async function FinishedContestTable() { title: 'text-left w-2/5 md:w-3/6', startTime: 'w-1/5 md:w-1/6', endTime: 'w-1/5 md:w-1/6', - participants: 'w-1/5 md:w-1/6' + participants: 'w-1/5 md:w-1/6', + status: 'w-1/4 md:w-1/6' }} name="contest" /> diff --git a/frontend-client/app/(main)/contest/page.tsx b/frontend-client/app/(main)/contest/page.tsx index a288c18a39..8f31b15227 100644 --- a/frontend-client/app/(main)/contest/page.tsx +++ b/frontend-client/app/(main)/contest/page.tsx @@ -1,4 +1,5 @@ import { Skeleton } from '@/components/ui/skeleton' +import { auth } from '@/lib/auth' import { Suspense } from 'react' import ContestCardList from './_components/ContestCardList' import FinishedContestTable from './_components/FinishedContestTable' @@ -40,17 +41,23 @@ function FinishedContestTableFallback() { ) } -export default function Contest() { +export default async function Contest() { + const session = await auth() return ( <>
}> - + }>
diff --git a/frontend-client/types/type.ts b/frontend-client/types/type.ts index cf62e79e6b..aa959e9666 100644 --- a/frontend-client/types/type.ts +++ b/frontend-client/types/type.ts @@ -1,4 +1,9 @@ -export type ContestStatus = 'ongoing' | 'upcoming' | 'finished' +export type ContestStatus = + | 'ongoing' + | 'upcoming' + | 'finished' + | 'registeredOngoing' + | 'registeredUpcoming' export type Level = 'Level1' | 'Level2' | 'Level3' | 'Level4' | 'Level5' export type Language = 'C' | 'Cpp' | 'Golang' | 'Java' | 'Python2' | 'Python3' @@ -9,6 +14,7 @@ export interface Contest { endTime: Date group: { id: string; groupName: string } status: ContestStatus + participants: number } export interface WorkbookProblem {