Skip to content

Commit 082b08b

Browse files
committed
Add Ranking Table
1 parent 2b3e6b7 commit 082b08b

15 files changed

+2319
-2547
lines changed

package.json

+2
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,14 @@
3131
"@types/react": "17.0.26",
3232
"@types/uuid": "^8.3.1",
3333
"autoprefixer": "^10.3.6",
34+
"chrome-aws-lambda": "^10.1.0",
3435
"eslint": "7.32.0",
3536
"eslint-config-next": "11.1.2",
3637
"husky": "^7.0.0",
3738
"postcss": "^8.3.8",
3839
"prettier": "^2.4.1",
3940
"pretty-quick": "^3.1.1",
41+
"puppeteer-core": "^12.0.1",
4042
"tailwindcss": "^2.2.16",
4143
"typescript": "4.4.3"
4244
}

public/contest-day-1.csv

-704
This file was deleted.

public/contest-day-2.csv

-704
This file was deleted.

src/components/Meta.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import type { NextPage } from 'next'
22
import Head from 'next/head'
3+
import { memo } from 'react'
34

4-
export const MetaData: NextPage = () => {
5+
export const MetaData: NextPage = memo(() => {
56
return (
67
<Head>
78
<title>Thailand Online Competitive Programming Contest 2021</title>
@@ -12,4 +13,4 @@ export const MetaData: NextPage = () => {
1213
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
1314
</Head>
1415
)
15-
}
16+
})

src/components/main/TOCPC.tsx

+7
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ export const TOCPC = () => {
3333
20-21 NOV 2021
3434
</p>
3535
</div>
36+
<div className="pt-6">
37+
<Link href="/ranking" passHref>
38+
<p className="py-4 text-center text-white font-display">
39+
ดูอันดับการเข้าแข่งขัน
40+
</p>
41+
</Link>
42+
</div>
3643
{/* {auth?.user === null && (
3744
<div className="pt-6">
3845
{ <Link href="/thankyou" passHref> }

src/components/ranking.tsx

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { FC, memo, useMemo } from 'react'
2+
import contestData from 'data/contest-data.json'
3+
import { Table } from './ranking/table'
4+
5+
export interface IColumn {
6+
code: string
7+
name: string
8+
}
9+
10+
export interface IData {
11+
rank: number
12+
name: string
13+
// woody: number
14+
// longjump: number
15+
// parentheses: number
16+
// moles: number
17+
// arranging: number
18+
// guitar: number
19+
total: number
20+
}
21+
22+
export const Ranking: FC = () => {
23+
const Columns: Array<IColumn> = useMemo(() => {
24+
return [
25+
{ name: 'อันดับ', code: 'rank' },
26+
{ name: 'ชื่อ', code: 'name' },
27+
// { name: 'woody', code: 'woody' },
28+
// { name: 'longjump', code: 'longjump' },
29+
// { name: 'parentheses', code: 'parentheses' },
30+
// { name: 'moles', code: 'moles' },
31+
// { name: 'arranging', code: 'arranging' },
32+
// { name: 'guitar', code: 'guitar' },
33+
{ name: 'คะแนน', code: 'total' },
34+
]
35+
}, [])
36+
37+
const Data: Array<IData> = useMemo(() => {
38+
const data = contestData.map((c) => {
39+
return {
40+
rank: c.rank,
41+
name: c.name,
42+
// woody: c.woody,
43+
// longjump: c.longjump,
44+
// parentheses: c.parentheses,
45+
// moles: c.moles,
46+
// arranging: c.arranging,
47+
// guitar: c.guitar,
48+
total: c.total,
49+
}
50+
})
51+
52+
return data
53+
}, [])
54+
55+
return (
56+
<main className="relative w-full min-h-screen bg-gray-900 overflow-hidden">
57+
<div className="flex flex-col items-center">
58+
<div className="flex flex-col mx-auto px-8 sm:px-36 mt-28 sm:mt-40 w-full">
59+
<h1 className="font-display text-3xl text-white mb-8">
60+
อันดับผู้เข้าแข่งขัน
61+
</h1>
62+
<Table columns={Columns} data={Data} />
63+
</div>
64+
</div>
65+
</main>
66+
)
67+
}

src/components/ranking/table.tsx

+133
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import classNames from 'classnames'
2+
import { IColumn, IData } from 'components/ranking'
3+
import { useWindowDimensions } from 'lib/useWindowDimensions'
4+
import { ElementHandle } from 'puppeteer-core'
5+
import { FC, useState } from 'react'
6+
7+
type Columns = 'rank' | 'name' | 'total'
8+
9+
const SortAscendingIcon: FC<{ className?: string }> = ({ className }) => {
10+
return (
11+
<svg
12+
width="24"
13+
height="24"
14+
viewBox="0 0 24 24"
15+
fill="none"
16+
className={className}
17+
style={{ display: 'inline ' }}
18+
xmlns="http://www.w3.org/2000/svg"
19+
>
20+
<path
21+
d="M3 4H16M3 8H12M3 12H9M13 12L17 8M17 8L21 12M17 8V20"
22+
stroke="#fff"
23+
strokeWidth="2"
24+
strokeLinecap="round"
25+
strokeLinejoin="round"
26+
/>
27+
</svg>
28+
)
29+
}
30+
31+
const SortDescendingIcon: FC<{ className?: string }> = ({ className }) => {
32+
return (
33+
<svg
34+
width="24"
35+
height="24"
36+
viewBox="0 0 24 24"
37+
fill="none"
38+
className={className}
39+
style={{ display: 'inline ' }}
40+
xmlns="http://www.w3.org/2000/svg"
41+
>
42+
<path
43+
d="M3 4H16M3 8H12M3 12H12M17 8V20M17 20L13 16M17 20L21 16"
44+
stroke="#fff"
45+
strokeWidth="2"
46+
strokeLinecap="round"
47+
strokeLinejoin="round"
48+
/>
49+
</svg>
50+
)
51+
}
52+
53+
export const Table: FC<{ columns: Array<IColumn>; data: Array<IData> }> = ({
54+
columns,
55+
data,
56+
}) => {
57+
const { width } = useWindowDimensions()
58+
59+
// const nColumns =
60+
// width < 540
61+
// ? columns.filter((c) => lowWidthColumns.includes(c.code))
62+
// : columns
63+
// const nData =
64+
// width < 540
65+
// ? data.map((d) => {
66+
// return {
67+
// rank: d.rank,
68+
// name: d.name,
69+
// total: d.total,
70+
// },
71+
// })
72+
// : data
73+
74+
const nColumns = columns
75+
const [nData, setData] = useState(data)
76+
77+
const calculateCellStyles = (type: 'head' | 'data', cell: string) => {
78+
let styles: Array<string> = []
79+
if (cell === 'rank') styles.push('w-1/4')
80+
if (cell === 'rank' && type === 'data') styles.push('text-center')
81+
if (cell === 'name') styles.push('w-full text-left')
82+
if (cell === 'total') styles.push('pr-6 text-center')
83+
84+
return styles.join(' ')
85+
}
86+
87+
return (
88+
<table className="w-full max-w-xl overflow-y-scroll block border border-gray-600 rounded-xl pb-4 bg-gray-900 pt-4">
89+
<thead>
90+
<tr>
91+
{nColumns.map((col, i) => {
92+
return (
93+
<th
94+
key={i}
95+
className={classNames(
96+
'h-4 border-b border-gray-600 pb-4',
97+
calculateCellStyles('head', col.code)
98+
)}
99+
>
100+
<span className="font-display text-white">{col.name}</span>
101+
</th>
102+
)
103+
})}
104+
</tr>
105+
</thead>
106+
<tbody>
107+
{nData.map((d, i) => {
108+
return (
109+
<tr className="bg-gray-900" key={i}>
110+
{Object.keys(d).map((dItem, i) => {
111+
return (
112+
<td
113+
key={i}
114+
className={classNames(
115+
'h-8 border-b border-gray-600 py-4',
116+
117+
calculateCellStyles('data', dItem)
118+
)}
119+
>
120+
<span className="font-display text-white font-light">
121+
{/*@ts-ignore*/}
122+
{d[dItem]}
123+
</span>
124+
</td>
125+
)
126+
})}
127+
</tr>
128+
)
129+
})}
130+
</tbody>
131+
</table>
132+
)
133+
}

0 commit comments

Comments
 (0)