Skip to content

Commit 5bed698

Browse files
beambeambeamgxjakkapRangsimanJerathrxpt2005fpp
authored
feat: final design, certificate (#216)
* Feat/close register (#186) * feat: update landing page and navbar for improved user flow * refactor: clean up imports and remove unused variables in member registration components * feat: add middleware for redirecting /register to /teams and configure request path matching * refactor: simplify TeamDone component layout and update button text for clarity * style: update button border radius in TeamDone component for improved aesthetics * feat: enhance TeamDone component with visual indicators for completed information sections * refactor: update Requirement component layout and styling for improved user experience * fix: wrong env in auth-client for kirin (#187) * Feat/1st round info table (#188) * feat: add Round 1 Competition page and team table components * feat: add CSV export functionality to team table * refactor: verify dialog to team dialog * feat: add VerifyForm component for Round 1 verification process * refactor: remove verify dialog * refactor: restructure TeamDialog layout for improved readability and organization * refactor: simplify TeamDialog usage in team table by integrating VerifyFormParent for enhanced verification interaction * refactor: adjust TeamDialog layout for better responsiveness and improved child component positioning * feat: add Team Award page and table components for displaying team awards * chore: fix all lint error * refactor: update CSV export functionality in team table to include index and adjust field names --------- Co-authored-by: beambeambeam <supawitmarayat@gmail.com> * refactor: update code name prefix from "BMHK" to "BH" across team table components and related formatting functions * feat: add missing array type for members in Team type definition * feat: sponsors section (#198) * fix: sponsor section layout (#200) * fix: hide dateAndContest on first load to wait for server time (#202) * chore: remove register phase from landing section (#205) * fix: change background and logo in login page (#207) * chore: bump turbo to version 2.5.8 * feat: home bg for final round (#208) * feat: add final hero * fix: final footer (#209) * Feat/cert gen (#210) * fix: sponsor section layout (#201) * fix: hide dateAndContest on first load to wait for server time (#203) * Feat/staff change award (#204) * feat: add awardAudit table to schema for tracking award changes * feat: create award_audit table for tracking award changes and add related foreign key constraints * feat: implement award change functionality with dialog, form, and history components * refactor: update award options to use English labels and remove redundant display of English names in history * fix: enhance award update button logic to prevent submission with unchanged award * feat: add "None" option to award selection and improve dialog layout for better user experience * fix: update award query state key and sort award history by change date * feat: implement AwardChangeContext for managing award change state across components * refactor: adjust dashboard layout by removing TimeLeftCard and updating grid structure * chore: fix lint error * feat: update dependencies and implement OpenAPI generation * feat: add certificate generation router * feat: add pdf-lib dependency and update pnpm-lock.yaml * feat: implement certificate generation and preview functionality * refactor: remove certificate generation endpoint from API * feat: enhance certificate generation with member selection and preview functionality * refactor: separate certificate generation logic into dedicated module and restore API endpoint * fix: adjust page size for generated PDF certificate * feat: integrate @react-pdf/renderer for certificate generation and update dependencies * feat: add Poppins and Prompt font families with OFL licensing information * feat: enhance certificate generation by adding asset copying and integrating new fonts * feat: update certificate generation layout with new text styles and add bottom-left artwork * feat: enhance certificate layout with new styles and add top-right artwork * feat: add professor signatures and related styles to certificate layout * feat: update certificate document to dynamically display member names and team information * feat: add adviser support to certificate generation and update member selection logic * feat: implement adviser certificate template and update generation logic for dynamic content * feat: expand award certificate templates and enhance generation logic for dynamic award display * feat: update award enumeration and adjust registration logic for certificate generation * feat: improve certificate loading states and enhance member selection interface * fix: update lower image reference in certificate template and add new image asset * feat: add top image to certificate templates and update related generation logic * fix: update top image references in certificate templates for consistency --------- Co-authored-by: Jakkaphat Chalermphanaphan <gunt@guntxjakka.me> * chore: remove gital's and chicha's contact info (#211) * Fix/timeline end photo missing (#213) * feat: add link to winner announcement * Revert "feat: add link to winner announcement" This reverts commit 2e77635. * fix: add missing image to timeline component, add announcement link * perf: reduce image sizes (#214) * 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 * feat/dynamics font size (#217) * feat: dynamic font size calculation for certificate names * feat: update name font size calculation to include middlename in certificate generation * fix: adjust gap size in certificate styles and refine font size calculation logic * chore: update metadata (#218) * chore: update metadata * fix: use svg lazyloading for footer icon --------- Co-authored-by: Jakkaphat Chalermphanaphan <gunt@guntxjakka.me> Co-authored-by: Rangsiman Jerabunjerdchai <61783407+RangsimanJera@users.noreply.github.com> Co-authored-by: Theeraphat Jaingam <jain.theera@gmail.com> Co-authored-by: Feen Phoorin <118984693+2005fpp@users.noreply.github.com>
1 parent c44873b commit 5bed698

File tree

101 files changed

+5236
-325
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

101 files changed

+5236
-325
lines changed

apps/api/package.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
"type": "module",
44
"scripts": {
55
"dev": "tsx watch src/index.ts",
6-
"build": "tsc",
6+
"build": "tsc && pnpm copy-assets",
7+
"copy-assets": "mkdir -p dist/routers/cert && cp -r src/routers/cert/poppins src/routers/cert/prompt src/routers/cert/imgs dist/routers/cert/",
78
"start": "node dist/index.js",
89
"lint": "eslint .",
910
"lint:fix": "eslint . --fix"
@@ -12,17 +13,24 @@
1213
"@aws-sdk/client-s3": "^3.873.0",
1314
"@aws-sdk/s3-request-presigner": "^3.873.0",
1415
"@hono/node-server": "^1.19.0",
16+
"@orpc/openapi": "^1.9.2",
1517
"@orpc/server": "^1.8.4",
18+
"@orpc/zod": "^1.9.2",
19+
"@react-pdf/renderer": "^4.3.1",
20+
"@scalar/hono-api-reference": "^0.9.19",
1621
"@workspace/auth": "workspace:*",
1722
"@workspace/db": "workspace:*",
1823
"drizzle-orm": "^0.36.4",
1924
"hono": "^4.9.4",
2025
"ntp-time-sync": "^0.5.0",
26+
"pdf-lib": "^1.17.1",
27+
"react": "^19.2.0",
2128
"tsx": "^4.20.4",
2229
"zod": "^4.0.17"
2330
},
2431
"devDependencies": {
2532
"@types/node": "^20.11.17",
33+
"@types/react": "^19.2.2",
2634
"@workspace/eslint-config": "workspace:*",
2735
"tsc-alias": "^1.8.16",
2836
"typescript": "^5.8.3"

apps/api/src/enum.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
export const AWARD_ENUM = {
2-
FIRST_ROUND: "FIRST_ROUND",
3-
SECOND_ROUND: "SECOND_ROUND",
2+
NONE: "NONE",
3+
REGISTERED: "REGISTERED",
4+
ROUND_1_PARTICIPANT: "ROUND_1_PARTICIPANT",
5+
ROUND_2_PARTICIPANT: "ROUND_2_PARTICIPANT",
46
HONORABLE_MENTION: "HONORABLE_MENTION",
5-
FIRST_RUNNER_UP: "FIRST_RUNNER_UP",
6-
SECOND_RUNNER_UP: "SECOND_RUNNER_UP",
7-
WINNER: "WINNER",
7+
THIRD_PLACE: "3RD_PLACE",
8+
SECOND_PLACE: "2ND_PLACE",
9+
FIRST_PLACE: "1ST_PLACE",
810
} as const

apps/api/src/index.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import { createContext } from "@/lib/context"
22
import { appRouter } from "@/routers"
33
import { serve } from "@hono/node-server"
4+
import { OpenAPIGenerator } from "@orpc/openapi"
45
import { RPCHandler } from "@orpc/server/fetch"
6+
import { ZodToJsonSchemaConverter } from "@orpc/zod/zod4"
7+
import { Scalar } from "@scalar/hono-api-reference"
58
import { auth } from "@workspace/auth"
69
import { Hono } from "hono"
710
import { cors } from "hono/cors"
@@ -57,6 +60,28 @@ app.get("/time", async (c) => {
5760
})
5861
})
5962

63+
const isDevelopment = process.env.NODE_ENV === "development" || process.env.NODE_ENV !== "production"
64+
65+
if (isDevelopment) {
66+
const generator = new OpenAPIGenerator({
67+
schemaConverters: [new ZodToJsonSchemaConverter()],
68+
})
69+
70+
const spec = await generator.generate(appRouter, {
71+
info: {
72+
title: "BMHK 2025 API",
73+
version: "1.0.0",
74+
},
75+
})
76+
77+
app.use(
78+
"/reference",
79+
Scalar({
80+
content: spec,
81+
})
82+
)
83+
}
84+
6085
serve(
6186
{
6287
fetch: app.fetch,
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
export const Awards = {
2+
Registered: "REGISTERED",
3+
Round1Participant: "ROUND_1_PARTICIPANT",
4+
Round2Participant: "ROUND_2_PARTICIPANT",
5+
HonorableMention: "HONORABLE_MENTION",
6+
ThirdPlace: "3RD_PLACE",
7+
SecondPlace: "2ND_PLACE",
8+
FirstPlace: "1ST_PLACE",
9+
} as const
10+
11+
export type AwardKeys = (typeof Awards)[keyof typeof Awards]
12+
13+
type GradientColors = {
14+
start: string
15+
end: string
16+
}
17+
18+
type CertificateTemplate = {
19+
of: string
20+
award: string | null
21+
awardTextCSS: {
22+
color?: string
23+
background?: string
24+
backgroundClip?: string
25+
WebkitBackgroundClip?: string
26+
WebkitTextFillColor?: string
27+
}
28+
gradient?: GradientColors
29+
teamPrefix: "อาจารย์ที่ปรึกษา จากทีม" | "จากทีม"
30+
lowerImage: string
31+
topImage: string
32+
}
33+
34+
export const adviser: CertificateTemplate = {
35+
of: "APPRECIATION",
36+
award: null,
37+
awardTextCSS: {
38+
color: "#282828",
39+
},
40+
teamPrefix: "อาจารย์ที่ปรึกษา จากทีม",
41+
lowerImage: "lower-default.png",
42+
topImage: "top-right-art-no-icon.png",
43+
}
44+
45+
export const awardCertificates: Record<AwardKeys, CertificateTemplate> = {
46+
[Awards.Registered]: {
47+
of: "PARTICIPATION",
48+
award: "เข้าร่วมการแข่งขัน",
49+
awardTextCSS: { color: "#9F83DC" },
50+
teamPrefix: "จากทีม",
51+
lowerImage: "lower-default.png",
52+
topImage: "top-right-art-no-icon.png",
53+
},
54+
[Awards.Round1Participant]: {
55+
of: "PARTICIPATION",
56+
award: "ผ่านเข้ารอบ 36 ทีมสุดท้าย",
57+
awardTextCSS: { color: "#9F83DC" },
58+
teamPrefix: "จากทีม",
59+
lowerImage: "lower-default.png",
60+
topImage: "top-right-art-no-icon.png",
61+
},
62+
[Awards.Round2Participant]: {
63+
of: "PARTICIPATION",
64+
award: "ผ่านเข้ารอบ 12 ทีมสุดท้าย",
65+
awardTextCSS: { color: "#9F83DC" },
66+
teamPrefix: "จากทีม",
67+
lowerImage: "lower-default.png",
68+
topImage: "top-right-art-no-icon.png",
69+
},
70+
[Awards.HonorableMention]: {
71+
of: "ACHIEVEMENT",
72+
award: "ได้รับรางวัลชมเชย",
73+
awardTextCSS: { color: "#9B9B9B" },
74+
gradient: { start: "#9B9B9B", end: "#BCBCBC" },
75+
teamPrefix: "จากทีม",
76+
lowerImage: "lower-special.png",
77+
topImage: "top-right-art.png",
78+
},
79+
[Awards.ThirdPlace]: {
80+
of: "ACHIEVEMENT",
81+
award: "ได้รับรางวัลรองชนะเลิศอันดับที่สอง",
82+
awardTextCSS: { color: "#C63C51" },
83+
gradient: { start: "#C63C51", end: "#601D27" },
84+
teamPrefix: "จากทีม",
85+
lowerImage: "lower-3rd.png",
86+
topImage: "top-right-art.png",
87+
},
88+
[Awards.SecondPlace]: {
89+
of: "ACHIEVEMENT",
90+
award: "ได้รับรางวัลรองชนะเลิศอันดับที่หนึ่ง",
91+
awardTextCSS: { color: "rgba(140, 48, 97, 0.65)" },
92+
gradient: { start: "rgba(140, 48, 97, 0.65)", end: "rgba(212, 0, 113, 0.65)" },
93+
teamPrefix: "จากทีม",
94+
lowerImage: "lower-2.png",
95+
topImage: "top-right-art.png",
96+
},
97+
[Awards.FirstPlace]: {
98+
of: "ACHIEVEMENT",
99+
award: "ได้รับรางวัลชนะเลิศ",
100+
awardTextCSS: { color: "#9F83DC" },
101+
gradient: { start: "#9F83DC", end: "#FFCCF7" },
102+
teamPrefix: "จากทีม",
103+
lowerImage: "lower-1st.png",
104+
topImage: "top-right-art.png",
105+
},
106+
}

0 commit comments

Comments
 (0)