Skip to content

Commit

Permalink
Style the points page
Browse files Browse the repository at this point in the history
Big thanks to the_fnkymnky for this! 🙏
  • Loading branch information
AdamLearns committed Feb 21, 2024
1 parent b125551 commit 956e880
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 23 deletions.
17 changes: 11 additions & 6 deletions packages/database/src/BotDatabase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ import type {

const CONFIG_PRIMARY_BOT_USER_ID = "primary_bot_user_id"

export interface NameAndPointTotal {
export interface PointStanding {
name: string
rank: number
numPoints: number
}

Expand Down Expand Up @@ -422,7 +423,7 @@ export class BotDatabase implements BotStorageLayer {
})
}

async getTopPointsWithTwitchNames(): Promise<NameAndPointTotal[]> {
async getTopPointsWithTwitchNames(): Promise<PointStanding[]> {
const response = await db
.selectFrom("points")
.innerJoin("users", "points.user_id", "users.id")
Expand All @@ -432,14 +433,18 @@ export class BotDatabase implements BotStorageLayer {
"user_correlation.twitch_id",
"twitch_names.twitch_id",
)
.select(["twitch_names.name", "points.num_points"])
.orderBy("points.num_points", "desc")
.select([
"twitch_names.name",
"points.num_points",
sql<number>`DENSE_RANK() OVER (ORDER BY num_points DESC)`.as("rank"),
])
.orderBy("rank", "asc")
.orderBy("twitch_names.name", "asc")
.where("points.num_points", ">", 0)
.execute()

return response.map(({ name, num_points }) => {
return { name, numPoints: num_points }
return response.map(({ name, num_points, rank }) => {
return { name, numPoints: num_points, rank }
})
}
}
134 changes: 117 additions & 17 deletions packages/web/src/pages/points.astro
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,130 @@ const topPoints = await botDatabase.getTopPointsWithTwitchNames()
---

<HtmlLayout pageTitle={"Adam Learns top points"}>
<h2 class="text-xl">
Point totals in <a
class="text-fuchsia-200 underline"
href="https://twitch.tv/AdamLearnsLive">Adam's Twitch channel</a
<div
class="flex w-screen justify-center border-b border-slate-300 bg-slate-50 py-3 dark:border-slate-800 dark:bg-slate-900"
>
<svg
class="w-16"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 91 91"
>
</h2>
<div class="mb-4 text-sm">
(note that points are only ever given by Adam or moderators and don't really
mean anything 🤫)
<g clip-path="url(#a)">
<path
fill="#4C51BF"
d="M45.5 91C70.629 91 91 70.629 91 45.5S70.629 0 45.5 0 0 20.371 0 45.5 20.371 91 45.5 91Z"
></path>
<path
fill="#fff"
d="M71.7 46c1.7-.9 3.3-1.8 5-2.7.2-.1.3-.2.6-.4-.3-.2-.5-.3-.8-.4-10.3-5.5-20.7-11-31-16.6-.3-.2-.6-.2-.8 0C34.2 31.4 23.8 37 13.4 42.6c-.1.1-.3.2-.5.3.2.1.4.2.5.3 3.9 2.3 7.9 4.6 11.8 6.9.2.1.4.3.4.6.1 1.5.1 3 0 4.4-.1.7.3 1.3.9 1.7.3.2.6.3.9.4 1.3.4 2.6.9 3.9 1.1 3.9.8 7.9 1.2 12 1.2 3.4 0 6.8-.2 10.3-.4 2.6-.1 5.1-.6 7.6-1.3 1-.3 1.9-.7 2.8-1.2.4-.2.6-.6.7-1.1.1-1.2.1-2.3-.1-3.5-.2-1.1.4-2.2 1.5-2.6 1.3-.7 2.6-1.6 4-2.4v4.8c0 .3-.1.6-.4.8-.7.6-.8 1.7-.2 2.4l.1.1c.6.7 1.7.7 2.4.1l.1-.1c.6-.7.6-1.9-.2-2.5 0 0-.1 0-.1-.1-.2-.2-.3-.4-.3-.6v-5.3c-.2-.2 0-.5.2-.6ZM61.6 56.1c-1.2.4-2.5.7-3.8 1-4.2.6-8.5.9-12.8.9-3.2-.2-6.4-.2-9.6-.5-1.9-.2-3.9-.6-5.8-.9-.4-.1-.8-.2-1.2-.5-.1-.1-.4-.3-.4-.5s.3-.5.5-.5c1.1-.4 2.3-.7 3.4-.9 5.5-.8 11.1-1.1 16.7-.8 3.6 0 7.3.4 10.8 1 .7.2 1.5.4 2.2.7.2.1.5.4.5.6 0 .2-.3.4-.5.4Zm2.3-9.6c-1.3-1.1-2.9-2-4.5-2.7-2.1-.8-4.3-1.3-6.5-1.6-3.2-.5-6.4-.6-9.6-.5-4 0-7.9.6-11.7 1.8-1.9.6-3.6 1.5-5.1 2.8-.1.1-.2.1-.3.2-.2-.5 0-1.1.4-1.5 1.3-1.2 2.8-2.2 4.5-2.8 2.6-1 5.2-1.7 8-1.9 2.8-.3 5.6-.4 8.4-.3 4.3 0 8.5.9 12.4 2.6 1.2.6 2.3 1.4 3.3 2.2.8.6.8.6.7 1.7Z"
></path>
<path
fill="#fff"
d="M69.2 55.9c-.2 3.2-.5 6.3-.7 9.4 1.1-1.1 1.9-2.4 3.8-1.9v-7.6c-1 .5-2.1.5-3.1.1Z"
></path>
</g>
<defs>
<clipPath id="a">
<path fill="#fff" d="M0 0h91v91H0z"></path>
</clipPath>
</defs>
</svg>
</div>

<div class="h-screen bg-slate-50 dark:bg-slate-900">
<div class="pt-8 sm:mx-auto sm:max-w-xl sm:rounded-lg">
<h1
class="mb-2 text-center text-2xl font-bold text-slate-800 dark:text-slate-50"
>
Point totals in <a
href="https://twitch.tv/AdamLearnsLive"
class="text-indigo-700 hover:text-indigo-500 hover:underline dark:text-indigo-300 dark:hover:text-indigo-500"
>Adam's Twitch channel</a
>
</h1>
<table class="w-full table-auto border-collapse text-sm">
<caption
class="caption-top pb-4 text-xs text-slate-600 dark:text-slate-400"
>
(note that points are only ever given by Adam or moderators and don't
really mean anything 🤫)
</caption>
<thead>
<tr
class="border border-slate-200 font-medium text-slate-400 dark:border-slate-700 dark:text-slate-200"
>
<th class="px-8 pb-3 pt-3 text-center">Rank</th>
<th class="px-8 pb-3 pt-3 text-left">User</th>
<th class="px-8 pb-3 pt-3 text-right">Points</th>
</tr>
</thead>
<tbody class="bg-white dark:bg-slate-800">
{
topPoints.map(({ name, numPoints, rank }) => {
const medalColors = ["gold", "silver", "bronze"]
const showMedal = rank < 4
const medalClasses = showMedal
? `medal-rank medal-${medalColors[rank - 1]}`
: ""
const rankHtml = showMedal ? (
<div class="medal">
<div class={medalClasses}>
<span>{rank}</span>
</div>
<span class="left-ribbon" />
<span class="right-ribbon" />
</div>
) : (
<span>{rank}</span>
)
return (
<tr class="relative border border-slate-200 text-slate-500 dark:border-slate-700 dark:text-slate-400">
<td class="relative py-4 text-center">{rankHtml}</td>
<td class="items-center gap-2 py-4">{name}</td>
<td class="py-4 pr-8 text-right">{numPoints}</td>
</tr>
)
})
}
</tbody>
</table>
</div>
</div>
<ol class="mx-8 list-decimal">
{
topPoints.map(({ name, numPoints }) => (
<li>
{name}: {numPoints}
</li>
))
}
</ol>
</HtmlLayout>
<style>
body {
background-color: rgb(0, 0, 57);
color: white;
margin: 1rem;
}
.medal {
@apply relative mx-auto w-8;
}

.medal-rank {
@apply relative z-20 flex h-8 w-8 items-center justify-center rounded-full bg-gradient-to-br text-center text-lg font-bold leading-3 text-white shadow-inner;
}

.medal-rank span {
@apply text-center drop-shadow-sm;
}

.medal-gold {
@apply from-amber-400 to-amber-700 shadow-amber-200;
}
.medal-silver {
@apply from-gray-300 to-gray-600 shadow-gray-200;
}
.medal-bronze {
@apply from-orange-700 to-orange-950 shadow-orange-700;
}

.left-ribbon {
@apply absolute left-[2px] top-[28px] block h-3 rotate-[20deg] border-x-[7px] border-y-[6px] border-red-700 border-b-transparent;
}

.right-ribbon {
@apply absolute right-[2px] top-[28px] block h-3 rotate-[-20deg] border-x-[7px] border-y-[6px] border-red-700 border-b-transparent;
}
</style>

0 comments on commit 956e880

Please sign in to comment.