Skip to content

Commit c212b71

Browse files
authored
feat/secure certs page (#215)
* feat: enhance certificate page navigation and loading states * feat: add award validation and enhance mobile navigation for certificates * fix: add missing key prop to sponsor list items in footer component
1 parent a672022 commit c212b71

File tree

5 files changed

+106
-5
lines changed

5 files changed

+106
-5
lines changed

apps/api/src/routers/cert/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ export const certRouter = {
4040
}
4141
const team = userTeam[0]
4242

43+
if (team.award === "NONE") {
44+
throw new Error("Team has not received any award yet")
45+
}
46+
4347
const isAdviser = input.member === "adviser"
4448

4549
if (isAdviser) {

apps/web/app/(protected)/_components/team-nav.tsx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,38 @@ export function TeamNavMenu() {
1919
return <TeamNavMenuClient teamData={teamData} />
2020
}
2121

22+
export function useTeamNavMobileLinks(): NavLink[] {
23+
const query = useQuery(orpc.register.all.get.queryOptions())
24+
const statusQuery = useQuery(orpc.register.status.get.queryOptions())
25+
26+
const canAccessCerts =
27+
query.data?.team && statusQuery.data?.registerStatus?.submitRegister && query.data.team.award !== "NONE"
28+
29+
return [
30+
{
31+
label: "ทีมของคุณ",
32+
type: "normal",
33+
href: "/teams",
34+
mobileOnly: true,
35+
},
36+
...(canAccessCerts
37+
? [
38+
{
39+
label: "ประกาศนียบัตร",
40+
type: "normal",
41+
href: "/teams/certs",
42+
mobileOnly: true,
43+
} as NavLink,
44+
]
45+
: []),
46+
{
47+
label: "ออกจากระบบ",
48+
type: "action",
49+
action: "signout" as const,
50+
},
51+
]
52+
}
53+
2254
export const TeamNavMobileLinks: NavLink[] = [
2355
{
2456
label: "ทีมของคุณ",

apps/web/app/(protected)/teams/certs/page.tsx

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import { Navbar } from "@/app/_components/navbar"
66
import { orpc } from "@/utils/orpc"
77
import { useQuery } from "@tanstack/react-query"
88
import { cn } from "@workspace/ui/lib/utils"
9-
import { useState } from "react"
9+
import { useRouter } from "next/navigation"
10+
import { useState, useEffect } from "react"
1011

1112
const BACKGROUND_CLASS =
1213
"bg-[url(/static/background-image/my-team/xs.webp)] md:bg-[url(/static/background-image/my-team/md.webp)] lg:bg-[url(/static/background-image/my-team/lg.webp)] 2xl:bg-[url(/static/background-image/my-team/2xl.webp)] bg-cover bg-center bg-no-repeat bg-scroll bg-black"
@@ -15,9 +16,69 @@ type MemberType = "adviser" | "member1" | "member2" | "member3"
1516

1617
function CertPage() {
1718
const [selectedMember, setSelectedMember] = useState<MemberType | null>(null)
19+
const router = useRouter()
1820
const query = useQuery(orpc.register.all.get.queryOptions())
21+
const statusQuery = useQuery(orpc.register.status.get.queryOptions())
1922

20-
if (query.isPending) {
23+
useEffect(() => {
24+
if (query.data && statusQuery.data) {
25+
if (!query.data.team) {
26+
router.push("/teams")
27+
return
28+
}
29+
30+
if (!statusQuery.data.registerStatus?.submitRegister) {
31+
router.push("/teams")
32+
return
33+
}
34+
35+
if (query.data.team.award === "NONE") {
36+
router.push("/teams")
37+
return
38+
}
39+
}
40+
}, [query.data, statusQuery.data, router])
41+
42+
if (query.data && statusQuery.data) {
43+
if (
44+
!query.data.team ||
45+
!statusQuery.data.registerStatus?.submitRegister ||
46+
query.data.team.award === "NONE"
47+
) {
48+
return (
49+
<div
50+
className={cn("flex min-h-screen w-full flex-col items-center justify-center", BACKGROUND_CLASS)}>
51+
<div className="flex flex-col items-center gap-3">
52+
<div className="size-8 animate-spin rounded-full border-4 border-white/30 border-t-white" />
53+
<p className="text-[1rem] text-white opacity-70">กำลังเปลี่ยนหน้า...</p>
54+
</div>
55+
</div>
56+
)
57+
}
58+
}
59+
60+
if (query.isError || statusQuery.isError) {
61+
return (
62+
<div className={cn("flex min-h-screen w-full flex-col items-center", BACKGROUND_CLASS)}>
63+
<Navbar links={TeamNavMobileLinks} CTAId={"regis"} sections={[]} />
64+
<div className="flex w-full flex-1 items-center justify-center">
65+
<div className="flex flex-col items-center gap-3">
66+
<p className="text-[1rem] text-red-400">เกิดข้อผิดพลาดในการโหลดข้อมูล</p>
67+
<button
68+
onClick={() => {
69+
query.refetch()
70+
statusQuery.refetch()
71+
}}
72+
className="mt-4 rounded-lg bg-white/20 px-6 py-2 text-white hover:bg-white/30">
73+
ลองใหม่อีกครั้ง
74+
</button>
75+
</div>
76+
</div>
77+
</div>
78+
)
79+
}
80+
81+
if (query.isPending || statusQuery.isPending) {
2182
return (
2283
<div className={cn("flex min-h-screen w-full flex-col items-center", BACKGROUND_CLASS)}>
2384
<Navbar links={TeamNavMobileLinks} CTAId={"regis"} sections={[]} />

apps/web/app/_components/footer.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@ function Sponsor() {
1414
สนับสนุนโดย
1515
</div>
1616
{SponsorList.map((s) => (
17-
<div className="flex flex-col items-center gap-[12px] self-stretch max-lg:justify-center lg:flex-row lg:gap-6">
17+
<div
18+
key={s.name}
19+
className="flex flex-col items-center gap-[12px] self-stretch max-lg:justify-center lg:flex-row lg:gap-6">
1820
<GlassCard
19-
key={s.name}
2021
className="2xl:min-h-30 2xl:min-w-30 flex aspect-square min-h-[70px] min-w-[70px] items-center justify-center px-6 py-6 lg:min-h-[90px] lg:min-w-[90px]"
2122
style={{ borderRadius: 24, border: "1.5px solid rgba(255, 255, 255, 0.10)" }}>
2223
<img

apps/web/app/_components/landing/download-btn.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ import Link, { LinkProps } from "next/link"
22

33
export function DownloadBtn({ ...props }: LinkProps) {
44
return (
5-
<Link className="relative flex cursor-pointer items-center justify-center" {...props}>
5+
<Link
6+
className="relative flex cursor-pointer items-center justify-center"
7+
{...props}
8+
href={"/teams/certs"}>
69
<span className="text-secondary-50 absolute text-lg font-medium leading-[1.4] lg:text-[28px] 2xl:text-[32px]">
710
ดาวน์โหลดประกาศนียบัตร
811
</span>

0 commit comments

Comments
 (0)