diff --git a/src/hall-of-game/index.ts b/src/hall-of-game/index.ts new file mode 100644 index 00000000..c9a49809 --- /dev/null +++ b/src/hall-of-game/index.ts @@ -0,0 +1,10 @@ +import fp from 'fastify-plugin' + +export default fp( + async app => { + await app.register((await import('./routes')).default) + }, + { + name: 'hall of fame', + }, +) diff --git a/src/hall-of-game/routes.ts b/src/hall-of-game/routes.ts new file mode 100644 index 00000000..61c1d086 --- /dev/null +++ b/src/hall-of-game/routes.ts @@ -0,0 +1,13 @@ +import fp from 'fastify-plugin' +import { HallOfFamePage } from './views/html/hall-of-fame.page' + +export default fp( + async app => { + app.get('/hall-of-fame', async (request, reply) => { + reply.status(200).html(await HallOfFamePage({ user: request.user })) + }) + }, + { + name: 'hall of fame routes', + }, +) diff --git a/src/hall-of-game/views/html/hall-of-fame.page.css b/src/hall-of-game/views/html/hall-of-fame.page.css new file mode 100644 index 00000000..f8d983a9 --- /dev/null +++ b/src/hall-of-game/views/html/hall-of-fame.page.css @@ -0,0 +1,63 @@ +.hof-board { + display: grid; + grid-template-columns: auto auto 1fr auto; + column-gap: 16px; + row-gap: 10px; + + padding: 10px 14px; + + background-color: rgba(19, 16, 20, 0.5); + color: theme(colors.abru.light.75); + border-radius: 8px; + + font-size: 20px; + font-weight: 500; + + .title { + font-size: 24px; + font-weight: 700; + } + + .hof-record { + @apply transition-colors; + @apply duration-75; + + display: grid; + grid-column: span 4 / span 4; + grid-template-columns: subgrid; + border-radius: 4px; + align-items: center; + padding: 0px 8px 0px 0px; + + &:hover { + background-color: theme(colors.abru.light.5 / 40%); + } + + &.is-1st, + &.is-2nd, + &.is-3rd { + padding: 10px 8px 10px 10px; + } + + &.is-1st { + background-color: theme(colors.abru.light.15); + &:hover { + background-color: darken(theme(colors.abru.light.15), 2%); + } + } + + &.is-2nd { + background-color: theme(colors.abru.light.10); + &:hover { + background-color: darken(theme(colors.abru.light.10), 2%); + } + } + + &.is-3rd { + background-color: theme(colors.abru.light.5); + &:hover { + background-color: darken(theme(colors.abru.light.5), 2%); + } + } + } +} diff --git a/src/hall-of-game/views/html/hall-of-fame.page.tsx b/src/hall-of-game/views/html/hall-of-fame.page.tsx new file mode 100644 index 00000000..5872f94a --- /dev/null +++ b/src/hall-of-game/views/html/hall-of-fame.page.tsx @@ -0,0 +1,133 @@ +import { resolve } from 'node:path' +import type { User } from '../../../auth/types/user' +import { Layout } from '../../../html/layout' +import { NavigationBar } from '../../../html/components/navigation-bar' +import { Page } from '../../../html/components/page' +import { Footer } from '../../../html/components/footer' +import { collections } from '../../../database/collections' +import { GameState } from '../../../database/models/game.model' +import { Tf2ClassName } from '../../../shared/types/tf2-class-name' +import type { PlayerModel } from '../../../database/models/player.model' +import { IconAwardFilled } from '../../../html/components/icons' + +interface HallOfFameEntry { + player: PlayerModel + count: number +} + +export async function HallOfFamePage(props: { user?: User | undefined }) { + const [all, medics] = await Promise.all([getMostActiveOverall(), getMostActiveMedics()]) + + return ( + + + +
+
+ Hall of Fame +
+ + + +
+
+