From 9a1dd39dedd4675c982a253b67e24feea89bad4f Mon Sep 17 00:00:00 2001 From: Dayong Lee Date: Sat, 2 Mar 2024 22:53:04 +0900 Subject: [PATCH] fix(fe): change index based number to letter (#1533) * refactor: change converToLetter logic * fix: change number base to letter base in dropdown * fix: change number base to letter base in description * fix: add contest feature in problem tab --- .../problem/[problemId]/layout.tsx | 2 +- .../[contestId]/problem/[problemId]/page.tsx | 17 +++++++--- .../problem/[problemOrder]/layout.tsx | 17 ++++++++++ frontend-client/components/DataTable.tsx | 3 ++ .../components/EditorDescription.tsx | 13 +++++-- frontend-client/components/EditorLayout.tsx | 34 ++++++++++--------- .../components/EditorResizablePanel.tsx | 11 ++++-- frontend-client/lib/utils.ts | 7 +--- 8 files changed, 70 insertions(+), 34 deletions(-) create mode 100644 frontend-client/app/contest/[contestId]/problem/[problemOrder]/layout.tsx diff --git a/frontend-client/app/contest/[contestId]/problem/[problemId]/layout.tsx b/frontend-client/app/contest/[contestId]/problem/[problemId]/layout.tsx index 9e387d9128..4e8a13b51c 100644 --- a/frontend-client/app/contest/[contestId]/problem/[problemId]/layout.tsx +++ b/frontend-client/app/contest/[contestId]/problem/[problemId]/layout.tsx @@ -4,7 +4,7 @@ export default async function layout({ params, children }: { - params: { problemId: string; contestId: string } + params: { problemId: number; contestId: number } children: React.ReactNode }) { const { problemId, contestId } = params diff --git a/frontend-client/app/contest/[contestId]/problem/[problemId]/page.tsx b/frontend-client/app/contest/[contestId]/problem/[problemId]/page.tsx index 9ee4d446ce..04f6b8fb1f 100644 --- a/frontend-client/app/contest/[contestId]/problem/[problemId]/page.tsx +++ b/frontend-client/app/contest/[contestId]/problem/[problemId]/page.tsx @@ -1,14 +1,21 @@ import { EditorDescription } from '@/components/EditorDescription' -import { fetcher } from '@/lib/utils' -import type { ProblemDetail } from '@/types/type' +import { fetcher, fetcherWithAuth } from '@/lib/utils' +import type { ContestProblem, ProblemDetail } from '@/types/type' export default async function DescriptionPage({ params }: { - params: { problemId: number } + params: { problemId: number; contestId: number } }) { const { problemId } = params const problem: ProblemDetail = await fetcher(`problem/${problemId}`).json() - - return + const contestProblems: { problems: ContestProblem[] } = await fetcherWithAuth( + `contest/${params.contestId}/problem` + ).json() + return ( + + ) } diff --git a/frontend-client/app/contest/[contestId]/problem/[problemOrder]/layout.tsx b/frontend-client/app/contest/[contestId]/problem/[problemOrder]/layout.tsx new file mode 100644 index 0000000000..4e8a13b51c --- /dev/null +++ b/frontend-client/app/contest/[contestId]/problem/[problemOrder]/layout.tsx @@ -0,0 +1,17 @@ +import EditorLayout from '@/components/EditorLayout' + +export default async function layout({ + params, + children +}: { + params: { problemId: number; contestId: number } + children: React.ReactNode +}) { + const { problemId, contestId } = params + + return ( + + {children} + + ) +} diff --git a/frontend-client/components/DataTable.tsx b/frontend-client/components/DataTable.tsx index 95560f3be9..8e7f4defab 100644 --- a/frontend-client/components/DataTable.tsx +++ b/frontend-client/components/DataTable.tsx @@ -41,6 +41,8 @@ interface DataTableProps { * tailwindcss class name for each header * @param name * name of the table, used for routing + * @param linked + * if true, each row is linked to the detail page * @example * ```tsx * // page.tsx @@ -50,6 +52,7 @@ interface DataTableProps { * createTime: 'w-1/4 md:w-1/6' * }} * name="notice" + * linked # for routing * /> * ``` * ```tsx diff --git a/frontend-client/components/EditorDescription.tsx b/frontend-client/components/EditorDescription.tsx index 772e55e23f..f5a0d53dce 100644 --- a/frontend-client/components/EditorDescription.tsx +++ b/frontend-client/components/EditorDescription.tsx @@ -7,7 +7,8 @@ import { AccordionTrigger } from '@/components/ui/accordion' import { Badge } from '@/components/ui/badge' -import type { ProblemDetail } from '@/types/type' +import { convertToLetter } from '@/lib/utils' +import type { ContestProblem, ProblemDetail } from '@/types/type' import { motion } from 'framer-motion' import { sanitize } from 'isomorphic-dompurify' import { CheckCircle, Lightbulb, Tag } from 'lucide-react' @@ -42,13 +43,19 @@ const useCopy = () => { return { copiedID, copy } } -export function EditorDescription({ problem }: { problem: ProblemDetail }) { +export function EditorDescription({ + problem, + contestProblems +}: { + problem: ProblemDetail + contestProblems?: ContestProblem[] +}) { const { copiedID, copy } = useCopy() return (
-

{`#${problem.id}. ${problem.title}`}

+

{`#${contestProblems ? convertToLetter(contestProblems.find((item) => item.id === problem.id)?.order as number) : problem.id}. ${problem.title}`}

@@ -56,14 +56,14 @@ export default async function EditorLayout({ {contest ? ( -

{`${problems?.problems.find((item) => item.id === Number(problemId))?.order}. ${problem.title}`}

+

{`${convertToLetter(problems?.problems.find((item) => item.id === Number(problemId))?.order as number)}. ${problem.title}`}

{problems?.problems.map((p: ContestProblem) => ( - {`${p.order}. ${p.title}`} + {`${convertToLetter(p.order)}. ${p.title}`} ))} @@ -75,7 +75,9 @@ export default async function EditorLayout({
- {children} + + {children} +
) } diff --git a/frontend-client/components/EditorResizablePanel.tsx b/frontend-client/components/EditorResizablePanel.tsx index dd19480020..fe050d90db 100644 --- a/frontend-client/components/EditorResizablePanel.tsx +++ b/frontend-client/components/EditorResizablePanel.tsx @@ -21,10 +21,12 @@ import EditorHeader from './EditorHeader' interface ProblemEditorProps { problem: ProblemDetail children: React.ReactNode + contestId?: number } export default function EditorMainResizablePanel({ problem, + contestId, children }: ProblemEditorProps) { // get programming language from localStorage for default value @@ -34,6 +36,7 @@ export default function EditorMainResizablePanel({ ) const { code, setCode, setLanguage, language } = useEditorStore() const pathname = usePathname() + const base = contestId ? `/contest/${contestId}` : '' useEffect(() => { if (!language) { @@ -58,13 +61,13 @@ export default function EditorMainResizablePanel({
- + - + { - const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' - const firstDigit = Math.floor(n / 26) - 1 - - return firstDigit >= 0 - ? alphabet[firstDigit] + alphabet[n % 26] - : alphabet[n % 26] + return String.fromCharCode(65 + n) }