-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(fe): resolve 504 timeout error in vercel (#1251)
* chore: remove header from main layout * feat: remove api call from main page * feat: add header again * feat: try api call with timeout 3s * feat: log response time * feat: use node-fetch * feat: log fetching timing * feat: use axios * feat: disable standalone output * feat: use nextjs fetch * feat: use suspense component * feat: add problem cards * fix: remove unused component * feat: use skeleton while waiting for API response * feat: set API fetch timeout to 5 seconds * fix: do not show zero time diff * feat: add error page for timeout * feat: add loading fallback in notice page * feat: add loading fallback in problem list page * fix: ignore timediff hydration warning * feat: adjust error message width * feat: add loading fallback in contest page * fix: resolve build error * feat(ci): disable linting on nexjts build * fix(ci): do not perform typecheck for frontend-client Check: vercel/next.js#53959 * feat(fe): remove images.dt.s --------- Co-authored-by: Dayong Lee <dayongkr@gmail.com>
- Loading branch information
Showing
20 changed files
with
477 additions
and
222 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,7 +21,8 @@ module.exports = { | |
{ | ||
namedComponents: 'function-declaration' | ||
} | ||
] | ||
], | ||
'func-style': ['off'] | ||
} | ||
} | ||
] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { fetcher } from '@/lib/utils' | ||
import type { Contest } from '@/types/type' | ||
import type { Route } from 'next' | ||
import Link from 'next/link' | ||
import ContestCard from './ContestCard' | ||
|
||
const getContests = async () => { | ||
const data: { | ||
ongoing: Contest[] | ||
upcoming: Contest[] | ||
} = await fetcher.get('contest').json() | ||
|
||
data.ongoing.forEach((contest) => { | ||
contest.status = 'ongoing' | ||
}) | ||
data.upcoming.forEach((contest) => { | ||
contest.status = 'upcoming' | ||
}) | ||
let contests = data.ongoing.concat(data.upcoming) | ||
|
||
if (contests.length < 3) { | ||
const data: { | ||
finished: Contest[] | ||
} = await fetcher | ||
.get('contest/finished', { | ||
searchParams: { | ||
take: 3 | ||
} | ||
}) | ||
.json() | ||
data.finished.forEach((contest) => { | ||
contest.status = 'finished' | ||
}) | ||
contests = contests.concat(data.finished) | ||
} | ||
|
||
return contests.slice(0, 3) | ||
} | ||
|
||
export default async function ContestCards() { | ||
const contests = await getContests() | ||
|
||
return ( | ||
<> | ||
{contests.map((contest) => { | ||
return ( | ||
<Link | ||
key={contest.id} | ||
href={`/contest/${contest.id}` as Route} | ||
className="inline-block w-full" | ||
> | ||
<ContestCard contest={contest} /> | ||
</Link> | ||
) | ||
})} | ||
</> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { fetcher } from '@/lib/utils' | ||
import type { WorkbookProblem } from '@/types/type' | ||
import type { Route } from 'next' | ||
import Link from 'next/link' | ||
import ProblemCard from './ProblemCard' | ||
|
||
const getProblems = async () => { | ||
const problems: WorkbookProblem[] = await fetcher | ||
.get('problem', { | ||
searchParams: { | ||
take: 3, | ||
workbookId: 1 | ||
} | ||
}) | ||
.json() | ||
|
||
return problems | ||
} | ||
|
||
export default async function ProblemCards() { | ||
const problems = await getProblems() | ||
|
||
return ( | ||
<> | ||
{problems.map((problem) => { | ||
return ( | ||
<Link | ||
key={problem.problemId} | ||
href={`/problem/${problem.problemId}` as Route} | ||
className="inline-block w-full" | ||
> | ||
<ProblemCard problem={problem} /> | ||
</Link> | ||
) | ||
})} | ||
</> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 changes: 32 additions & 0 deletions
32
frontend-client/app/(main)/contest/_components/FinishedContestTable.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import DataTable from '@/components/DataTable' | ||
import { fetcher } from '@/lib/utils' | ||
import type { Contest } from '@/types/type' | ||
import { columns } from './Columns' | ||
|
||
export default async function FinishedContestTable() { | ||
const data: { | ||
finished: Contest[] | ||
} = await fetcher.get('contest/finished?take=51').json() | ||
|
||
data.finished.forEach((contest) => { | ||
contest.status = 'finished' | ||
}) | ||
|
||
return ( | ||
<> | ||
<p className="text-xl font-bold md:text-2xl">Finished</p> | ||
{/* TODO: Add search bar */} | ||
<DataTable | ||
data={data.finished} | ||
columns={columns} | ||
headerStyle={{ | ||
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' | ||
}} | ||
name="contest" | ||
/> | ||
</> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,36 +1,59 @@ | ||
import DataTable from '@/components/DataTable' | ||
import { fetcher } from '@/lib/utils' | ||
import type { Contest } from '@/types/type' | ||
import { columns } from './_components/Columns' | ||
import { Skeleton } from '@/components/ui/skeleton' | ||
import { Suspense } from 'react' | ||
import ContestCardList from './_components/ContestCardList' | ||
import FinishedContestTable from './_components/FinishedContestTable' | ||
|
||
export default async function Contest() { | ||
const data: { | ||
finished: Contest[] | ||
} = await fetcher.get('contest/finished?take=51').json() | ||
data.finished.forEach((contest) => { | ||
contest.status = 'finished' | ||
}) | ||
function ContestCardListFallback() { | ||
return ( | ||
<div> | ||
<Skeleton className="mb-8 h-8 w-24" /> | ||
<div className="flex gap-8"> | ||
<Skeleton className="h-[120px] w-[375px] rounded-xl" /> | ||
<Skeleton className="h-[120px] w-[375px] rounded-xl" /> | ||
</div> | ||
</div> | ||
) | ||
} | ||
|
||
function FinishedContestTableFallback() { | ||
return ( | ||
<div> | ||
<Skeleton className="mb-8 h-8 w-24" /> | ||
<div className="mt-4 flex"> | ||
<span className="w-2/5 md:w-3/6"> | ||
<Skeleton className="h-6 w-20" /> | ||
</span> | ||
<span className="w-1/5 md:w-1/6"> | ||
<Skeleton className="mx-auto h-6 w-20" /> | ||
</span> | ||
<span className="w-1/5 md:w-1/6"> | ||
<Skeleton className="mx-auto h-6 w-20" /> | ||
</span> | ||
<span className="w-1/5 md:w-1/6"> | ||
<Skeleton className="mx-auto h-6 w-20" /> | ||
</span> | ||
</div> | ||
{[...Array(5)].map((_, i) => ( | ||
<Skeleton key={i} className="my-10 flex h-8 w-full rounded-xl" /> | ||
))} | ||
</div> | ||
) | ||
} | ||
|
||
export default function Contest() { | ||
return ( | ||
<> | ||
<div className="mb-12 flex flex-col gap-12"> | ||
<ContestCardList type="Ongoing" /> | ||
<ContestCardList type="Upcoming" /> | ||
<Suspense fallback={<ContestCardListFallback />}> | ||
<ContestCardList type="Ongoing" /> | ||
</Suspense> | ||
<Suspense fallback={<ContestCardListFallback />}> | ||
<ContestCardList type="Upcoming" /> | ||
</Suspense> | ||
</div> | ||
<p className="text-xl font-bold md:text-2xl">Finished</p> | ||
{/* TODO: Add search bar */} | ||
<DataTable | ||
data={data.finished} | ||
columns={columns} | ||
headerStyle={{ | ||
title: 'text-left w-2/4 md:w-4/6', | ||
startTime: 'w-1/4 md:w-1/6', | ||
endTime: 'w-1/4 md:w-1/6', | ||
participants: 'w-1/4 md:w-1/6' | ||
}} | ||
name="contest" | ||
/> | ||
<Suspense fallback={<FinishedContestTableFallback />}> | ||
<FinishedContestTable /> | ||
</Suspense> | ||
</> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
'use client' | ||
|
||
import { Button } from '@/components/ui/button' | ||
import ErrorImg from '@/public/error.webp' | ||
import Image from 'next/image' | ||
import { useRouter } from 'next/navigation' | ||
|
||
interface Props { | ||
error: Error & { digest?: string } | ||
reset: () => void | ||
} | ||
|
||
export default function Error({ error }: Props) { | ||
const router = useRouter() | ||
|
||
return ( | ||
<div className="flex h-full w-full flex-1 flex-col items-center justify-center gap-3 py-12"> | ||
<p className="mt-8 text-2xl font-extrabold">Something Went Wrong!</p> | ||
<p className="mb-4 max-w-[36rem] text-lg font-semibold"> | ||
{error.message || 'Unknown Error'} | ||
</p> | ||
<Button variant="outline" onClick={router.refresh}> | ||
Reload | ||
</Button> | ||
<Image | ||
src={ErrorImg} | ||
alt="Unexpected Error" | ||
height={240} | ||
className="mt-8" | ||
/> | ||
</div> | ||
) | ||
} |
Oops, something went wrong.