Skip to content

Commit 7c55ea9

Browse files
committedFeb 11, 2024··
Move more pages, final touches for go live
1 parent b837f1a commit 7c55ea9

21 files changed

+191
-178
lines changed
 

‎src/components/Widget.astro

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ const { title, label } = Astro.props
1111

1212
<div class:list={[styles.box.base, "relative overflow-auto p-3 sm:p-4"]}>
1313
<div class="sticky left-0 top-0 flex flex-wrap items-center gap-x-5 gap-y-1">
14-
<h3 class="font-display flex-auto text-lg font-bold text-gray-200">
14+
<h3 class="font-display flex-auto text-base font-bold text-gray-300">
1515
{title}
1616
</h3>
17-
<p class="text-md font-bold text-gray-400">
17+
<p class="text-sm font-bold text-gray-500">
1818
{label}
1919
</p>
2020
</div>

‎src/components/Footer.astro ‎src/components/layout/Footer.astro

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import Svg from "@jasikpark/astro-svg-loader"
33
---
44

5-
<footer class="mt-8 border-t border-white/10 p-4 md:p-6">
5+
<footer class="mt-4 border-t border-gray-900 py-32 text-center md:mt-8">
66
<div class="mx-auto">
77
<nav class="flex columns-2 flex-wrap justify-center gap-x-8 gap-y-2 pb-6 sm:space-x-12" aria-label="Footer">
88
<a href="/api" class="text-sm leading-6 text-gray-100 hover:text-white">API</a>
@@ -32,7 +32,7 @@ import Svg from "@jasikpark/astro-svg-loader"
3232
<div class="flex flex-auto justify-center whitespace-nowrap text-gray-600 lg:flex-none lg:justify-end">
3333
<span>Made by</span>
3434
<a href="https://casuals.co" class="text-gray-500 hover:text-gray-300" target="_blank" rel="noopener">
35-
<Svg src={import("../assets/thecasuals.svg?raw")} class="-mt-1 ml-1 inline-block h-4 fill-current" />
35+
<Svg src={import("../../assets/thecasuals.svg?raw")} class="-mt-1 ml-1 inline-block h-4 fill-current" />
3636
</a>
3737
</div>
3838
</div>

‎src/components/layout/Header.astro

+27
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,32 @@
1+
---
2+
import type { ImageMetadata } from "astro"
3+
import { getImage } from "astro:assets"
4+
import HeaderContent from "./HeaderContent.astro"
5+
6+
interface Props {
7+
backdropImage?: string | ImageMetadata | null
8+
title?: string
9+
section?: string
10+
}
11+
12+
const { backdropImage, section, title } = Astro.props
13+
const isUrl = typeof backdropImage === "string"
14+
const imageUrl = backdropImage ? (isUrl ? backdropImage : (await getImage(backdropImage)).src) : null
15+
---
16+
117
<div
218
class="relative -mt-20 border-b border-white/5 bg-gradient-to-r from-gray-900 via-gray-800 to-gray-900 pt-20 [--tw-gradient-via-position:40%] md:-mt-16 md:pt-16"
319
>
20+
{
21+
backdropImage && (
22+
<div class="absolute inset-0 overflow-hidden">
23+
<div
24+
class="h-full w-full bg-cover bg-center opacity-40 mix-blend-lighten blur-3xl brightness-50 saturate-150"
25+
style={`background-image: url(${imageUrl})`}
26+
/>
27+
</div>
28+
)
29+
}
30+
{(section || title) && <HeaderContent section={section} title={title} />}
431
<slot />
532
</div>

‎src/components/layout/HeaderContent.astro

+17-6
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,26 @@ interface Props {
99
const { title, section } = Astro.props
1010
---
1111

12-
<div class:list={[styles.layout.container, styles.layout.containerPadding]}>
13-
<div class="py-4 flex items-center">
12+
<div class:list={[styles.layout.container, styles.layout.containerPadding, "relative"]}>
13+
<div class="flex items-center py-4">
14+
{
15+
Astro.slots.has("left") && (
16+
<div>
17+
<slot name="left" />
18+
</div>
19+
)
20+
}
1421
<div class="flex-auto py-4">
15-
{section && <p class="mb-2 text-base font-bold text-white/60">{section}</p>}
22+
{section && <p class="text-base font-bold text-white/60">{section}</p>}
1623
{title && <h1 class="text-xl font-black text-white/90 md:text-3xl">{title}</h1>}
1724
<slot />
1825
</div>
19-
<div>
20-
<slot name="actions" />
21-
</div>
26+
{
27+
Astro.slots.has("right") && (
28+
<div>
29+
<slot name="right" />
30+
</div>
31+
)
32+
}
2233
</div>
2334
</div>

‎src/components/layout/HeaderMeta.astro

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const items = await Promise.all(
2323
class:list={[
2424
styles.layout.container,
2525
styles.layout.containerPadding,
26-
"flex flex-wrap items-center gap-y-4 gap-4 md:gap-8 py-4",
26+
"flex flex-wrap items-center gap-y-4 gap-4 md:gap-8 py-4 mix-blend-lighten",
2727
]}
2828
>
2929
{

‎src/components/layout/Main.astro

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
import { styles } from "../../lib/theme"
33
---
44

5-
<div class:list={["basis-2/3 flex flex-col", styles.layout.gap]}>
5+
<div class:list={["basis-3/4 flex flex-col", styles.layout.gap]}>
66
<slot />
77
</div>

‎src/components/layout/MainNav.astro

+1-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import { styles } from "../../lib/theme"
33
const currentRoute = new URL(Astro.request.url).pathname
44
const navLinks = [
5-
{ href: "/dev/example", text: "Home" },
65
{ href: "/leaderboards/ranked_1v1", text: "Leaderboard" },
76
{ href: "/stats", text: "Stats" },
87
{ href: "/social", text: "Content" },
@@ -13,7 +12,7 @@ const navLinks = [
1312
---
1413

1514
<div
16-
class="sticky top-0 to-black-20 backdrop-blur z-10 h-20 w-full border-b border-white/5 bg-gradient-to-r from-black/40 via-black/25 mix-blend-screen md:h-16"
15+
class="to-black-20 sticky top-0 z-10 h-20 w-full border-b border-white/5 bg-gradient-to-r from-black/40 via-black/25 mix-blend-screen backdrop-blur md:h-16"
1716
>
1817
<nav
1918
class:list={[

‎src/components/layout/Section.astro

+4-3
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,16 @@ import { styles } from "../../lib/theme"
44
interface Props {
55
title?: string
66
description?: string
7+
class?: string
78
}
8-
const { title, description } = Astro.props
9+
const { title, description, class: classes } = Astro.props
910
const hasHeader = title || description || Astro.slots.header || Astro.slots.controls
1011
---
1112

12-
<div class:list={[styles.layout.container, styles.layout.containerPadding, "pt-4 md:pt-6"]}>
13+
<div class:list={[styles.layout.container, styles.layout.containerPadding, "pt-4 md:pt-6", classes]}>
1314
{
1415
hasHeader && (
15-
<div class="flex justify-between my-4 md:my-6 gap-4">
16+
<div class="my-4 flex justify-between gap-4 md:my-6">
1617
<div class="flex-auto">
1718
{title && <h2 class="text-2xl font-bold text-white">{title}</h2>}
1819
{description && <p class="text-gray-400">{description}</p>}

‎src/components/layout/Sidebar.astro

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { styles } from "../../lib/theme"
33
---
44

55
<div
6-
class:list={["flex md:grid grid-cols-2 only:*:[grid-column:span_2] basis-1/3 lg:flex flex-col", styles.layout.gap]}
6+
class:list={["flex md:grid grid-cols-2 only:*:[grid-column:span_2] basis-1/4 lg:flex flex-col", styles.layout.gap]}
77
>
88
<slot />
99
</div>

‎src/components/widgets/GameLengthChart.tsx

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
// @ts-nocheck
2-
32
import { onMount } from "solid-js"
43
import { Chart, Colors, Title, Tooltip, type ChartOptions, type ChartData } from "chart.js"
54
import { Bar } from "solid-chartjs"
@@ -38,12 +37,12 @@ export function GameLengthChart(props: GameLengthProps) {
3837
{
3938
label: "Wins",
4039
data: wins,
41-
backgroundColor: "#5EC269",
40+
backgroundColor: "#4CA154",
4241
},
4342
{
4443
label: "Losses",
4544
data: losses,
46-
backgroundColor: "#DD524C",
45+
backgroundColor: "#CA3A31",
4746
},
4847
],
4948
}

‎src/components/widgets/MatchPreview.astro

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const mainPlayer = match.players.find((player) => player.player?.player_id === m
1818
<div
1919
class:list={[
2020
"size-6 text-sm ml-1 flex justify-center items-center rounded text-gray-800 font-extrabold uppercase",
21-
mainPlayer.result === "win" ? "bg-green-500" : mainPlayer.result === "loss" ? "bg-red-500" : "bg-gray-500",
21+
mainPlayer.result === "win" ? "bg-green-600" : mainPlayer.result === "loss" ? "bg-red-600" : "bg-gray-500",
2222
]}
2323
>
2424
{mainPlayer.result === "win" ? "W" : mainPlayer.result === "loss" ? "L" : "-"}
@@ -33,7 +33,7 @@ const mainPlayer = match.players.find((player) => player.player?.player_id === m
3333
<span
3434
class:list={[
3535
"w-8 flex-none text-xs whitespace-nowrap text-right",
36-
player.mmr_diff! > 0 ? "text-green-500" : player.mmr_diff! < 0 ? "text-red-500" : "text-gray-500",
36+
player.mmr_diff! > 0 ? "text-green-600" : player.mmr_diff! < 0 ? "text-red-600" : "text-gray-500",
3737
]}
3838
>
3939
{player.mmr_diff! > 0 ? "" : ""}

‎src/components/widgets/PlayerActivity.astro

+8-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import type { PlayerActivityStats, PlayerResponse } from "../../lib/api"
33
import Widget from "../Widget.astro"
44
import { Tooltip } from "../ui/Tooltip"
55
6+
const WEEKS_DISPLAYED = 15
7+
68
interface Props {
79
player: PlayerResponse
810
activity: PlayerActivityStats
@@ -33,9 +35,13 @@ type Day = { date: Date; win_rate: number; games_count: number; size: number; to
3335
type Week = Day[]
3436
const today = new Date()
3537
// get the date of monday 12 weeks ago, fully including this week
36-
const start = new Date(today.getFullYear(), today.getMonth(), today.getDate() - today.getDay() - 11 * 7)
38+
const start = new Date(
39+
today.getFullYear(),
40+
today.getMonth(),
41+
today.getDate() - today.getDay() - (WEEKS_DISPLAYED - 1) * 7
42+
)
3743
const weeks: Week[] = []
38-
for (let i = 0; i < 12; i++) {
44+
for (let i = 0; i < WEEKS_DISPLAYED; i++) {
3945
const week: Week = []
4046
for (let j = 0; j < 7; j++) {
4147
const date = new Date(start.getFullYear(), start.getMonth(), start.getDate() + i * 7 + j)

‎src/layouts/Layout.astro

+3-48
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,16 @@
11
---
2-
import Footer from "../components/Footer.astro"
32
import Root from "./Root.astro"
4-
3+
import MainNav from "../components/layout/MainNav.astro"
4+
import Footer from "../components/layout/Footer.astro"
55
export interface Props {
66
title: string
77
}
88
99
const { title } = Astro.props
10-
const currentRoute = new URL(Astro.request.url).pathname
11-
12-
const navLinks = [
13-
{ href: "/leaderboards/ranked_1v1", text: "Leaderboard" },
14-
{ href: "/stats", text: "Stats" },
15-
{ href: "/social", text: "Content" },
16-
{ href: "/api", text: "API" },
17-
{ href: "/tools", text: "Tools" },
18-
// { href: "/creators", text: "Creators" },
19-
]
2010
---
2111

2212
<Root title={title}>
23-
<div class="sticky top-0 z-10 w-full border-b border-gray-700/50 bg-gray-800/80 backdrop-blur-md">
24-
<nav class="font-display mx-auto flex max-w-screen-2xl flex-wrap items-center gap-y-2 py-2 md:min-h-16 md:py-4">
25-
<a
26-
href="/"
27-
class="basis-full whitespace-nowrap px-4 pr-2 text-xl font-extrabold text-gray-200 md:basis-auto md:px-7 md:pr-3"
28-
>
29-
Stormgate World</a
30-
>
31-
32-
<div class="flex flex-auto flex-wrap gap-1 gap-y-2 pl-2 pr-4 md:gap-4 md:px-4 md:pr-7">
33-
{
34-
navLinks.map(({ href, text }) => (
35-
<a
36-
href={href}
37-
class:list={[
38-
"font-bold rounded px-2 text-sm xs:text-base md:px-3 py-1 md:py-1.5",
39-
currentRoute === href ? "bg-white/5 text-gray-50" : "hover:bg-white/5 text-gray-200 ",
40-
]}
41-
>
42-
{text}
43-
</a>
44-
))
45-
}
46-
47-
<div class="flex-auto"></div>
48-
<a
49-
href="https://playstormgate.com"
50-
target="_blank"
51-
class="hidden whitespace-nowrap rounded-md border-white/20 bg-gray-100/20 px-6 py-2 text-sm font-bold text-gray-100 transition hover:bg-gray-100/30 sm:block"
52-
data-class="bg-white rounded-full text-sm mr-4 px-6 py-2 border text-black my-6 inline-block font-bold border-white hover:bg-gray-100 transition"
53-
>
54-
Official Website
55-
</a>
56-
</div>
57-
</nav>
58-
</div>
13+
<MainNav />
5914
<slot />
6015
<Footer />
6116
</Root>

‎src/layouts/New.astro

-15
This file was deleted.

‎src/layouts/Page.astro

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
---
22
import type { MarkdownLayoutProps } from "astro"
33
import Layout from "./Layout.astro"
4+
import Header from "../components/layout/Header.astro"
5+
import HeaderContent from "../components/layout/HeaderContent.astro"
6+
import { styles } from "../lib/theme"
47
58
type Props = MarkdownLayoutProps<{
69
title: string
@@ -9,7 +12,15 @@ const { title } = Astro.props.frontmatter
912
---
1013

1114
<Layout title={title}>
12-
<section class="relative mx-auto my-12 flex max-w-screen-lg flex-wrap gap-12 px-4 md:flex-nowrap">
15+
<Header title={title} />
16+
<section
17+
<div
18+
class:list={[
19+
styles.layout.container,
20+
styles.layout.containerPadding,
21+
"relative mx-auto my-12 flex flex-wrap gap-12 px-4 md:flex-nowrap",
22+
]}
23+
>
1324
<div>
1425
<ul class="sticky top-20 min-w-48">
1526
<li class="mb-4 text-2xl font-bold text-white">Contents</li>

‎src/lib/format.ts

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
export function formatDateRelative(date: Date, format: "short" | "medium" = "medium") {
2+
const now = new Date()
3+
const diff = now.getTime() - date.getTime()
4+
const years = Math.floor(diff / (1000 * 60 * 60 * 24 * 30 * 12))
5+
const months = Math.floor(diff / (1000 * 60 * 60 * 24 * 30))
6+
const days = Math.floor(diff / (1000 * 60 * 60 * 24))
7+
const hours = Math.floor(diff / (1000 * 60 * 60))
8+
const minutes = Math.floor(diff / (1000 * 60))
9+
if (format == "short") {
10+
if (years > 0) return `${years}y`
11+
else if (months > 0) return `${months}mo`
12+
else if (days > 0) return `${days}d`
13+
else if (hours > 0) return `${hours}h`
14+
else return `${minutes}m`
15+
}
16+
if (years > 0) return `${years} year${years > 1 ? "s" : ""} ago`
17+
else if (months > 0) return `${months} month${months > 1 ? "s" : ""} ago`
18+
else if (days > 0) return `${days} day${days > 1 ? "s" : ""} ago`
19+
else if (hours > 0) return `${hours} hour${hours > 1 ? "s" : ""} ago`
20+
else if (minutes > 0) return `${minutes} minute${minutes > 1 ? "s" : ""} ago`
21+
else return "today"
22+
}

‎src/lib/theme.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export const styles = {
55
gap: `gap-4 md:gap-6`,
66
},
77
box: {
8-
base: `bg-gray-900/70 border border-gray-800/50 rounded-none md:rounded-xl -mx-4 md:mx-0`
8+
base: `bg-gray-900/70 border border-gray-800/50 rounded-none md:rounded-xl -mx-4 md:mx-0`,
99
},
1010
button: {
1111
base: `inline-flex items-center justify-center rounded-sm

‎src/pages/dev/example.astro

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
import Layout from "../../layouts/New.astro"
2+
import Layout from "../../layouts/Layout.astro"
33
import Header from "../../components/layout/Header.astro"
44
import HeaderContent from "../../components/layout/HeaderContent.astro"
55
import HeaderMeta from "../../components/layout/HeaderMeta.astro"

‎src/pages/players/[id]-[username].astro

+19-16
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
export const prerender = false
3-
import Layout from "../../layouts/New.astro"
3+
import Layout from "../../layouts/Layout.astro"
44
import Header from "../../components/layout/Header.astro"
55
import HeaderContent from "../../components/layout/HeaderContent.astro"
66
@@ -20,6 +20,7 @@ import HeaderMeta from "../../components/layout/HeaderMeta.astro"
2020
import Section from "../../components/layout/Section.astro"
2121
import Main from "../../components/layout/Main.astro"
2222
import Sidebar from "../../components/layout/Sidebar.astro"
23+
import { formatDateRelative } from "../../lib/format"
2324
2425
type Theme = keyof typeof styles.badges
2526
@@ -53,21 +54,27 @@ const highestLeague = player?.leaderboard_entries?.reduce(
5354
---
5455

5556
<Layout title={player?.nickname!}>
56-
<Header>
57-
<HeaderContent section="Players">
58-
<div class="flex items-center gap-3">
59-
{player.avatar_url && <img src={player.avatar_url} alt={player.nickname} class="w-6 rounded-sm md:w-8" />}
60-
<h1 class="text-xl font-black text-white/90 md:text-3xl">{player.nickname}</h1>
61-
</div>
62-
<div slot="actions">
63-
<RankedBadge entry={highestLeague} class="w-16 md:w-20" client:load />
64-
</div>
57+
<Header backdropImage={player.avatar_url}>
58+
<HeaderContent section="Players" title={player.nickname!}>
59+
{
60+
player.avatar_url && (
61+
<img
62+
slot="left"
63+
src={player.avatar_url}
64+
alt={player.nickname}
65+
class="mr-4 size-8 flex-none rounded md:size-16"
66+
/>
67+
)
68+
}
69+
<RankedBadge slot="right" entry={highestLeague} class="w-16 md:w-20" client:load />
6570
</HeaderContent>
6671
<HeaderMeta
6772
items={[
6873
{
6974
icon: import("lucide-static/icons/activity.svg?raw"),
70-
label: `Last Match ${new Date(player.last_match_ended_at!).toLocaleDateString()}`,
75+
label: `Last Match ${formatDateRelative(
76+
new Date(playerMatches.matches[0]?.created_at || player.last_match_ended_at!)
77+
)}`,
7178
},
7279
{ icon: import("lucide-static/icons/hash.svg?raw"), label: player.id },
7380
]}
@@ -76,7 +83,7 @@ const highestLeague = player?.leaderboard_entries?.reduce(
7683
<Section>
7784
<Main>
7885
<Widget title="Top Ranks">
79-
<div class="flex flex-row gap-2 -mx-2">
86+
<div class="flex flex-row flex-wrap gap-2">
8087
{
8188
player.leaderboard_entries.map((entry) => (
8289
<div
@@ -98,7 +105,6 @@ const highestLeague = player?.leaderboard_entries?.reduce(
98105
<span class:list={["text-xs", styles.badges[entry.race as Theme].badgeLabel]}>Points</span>
99106
<p>
100107
{Math.round(entry.points)}
101-
102108
<RankedBadge entry={entry} class="inline-block w-4" client:load />
103109
</p>
104110
</div>
@@ -119,11 +125,8 @@ const highestLeague = player?.leaderboard_entries?.reduce(
119125
</Main>
120126
<Sidebar>
121127
{playerActivity?.history && <PlayerActivity activity={playerActivity} {player} />}
122-
123128
{playerMatchupStats.matchups.length > 0 && <PlayerMatchupStats playerMatchupStats={playerMatchupStats} />}
124-
125129
{playerMatchupStats.matchups.length > 0 && <PlayerGameLengthStats playerMatchupStats={playerMatchupStats} />}
126-
127130
{playerOpponents.opponents.length > 0 && <PlayerOpponents opponents={playerOpponents} />}
128131
</Sidebar>
129132
</Section>

‎src/pages/stats.astro

+59-60
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ import { StatisticsApi } from "../lib/api/services/StatisticsApi"
99
import { formatNumber } from "../lib/utils"
1010
import Timeago from "../components/Timeago.astro"
1111
import { LeagueDropdown } from "../components/widgets/LeagueDropdown"
12+
import Header from "../components/layout/Header.astro"
13+
import Section from "../components/layout/Section.astro"
14+
import HeaderMeta from "../components/layout/HeaderMeta.astro"
15+
import { formatDateRelative } from "../lib/format"
16+
import Main from "../components/layout/Main.astro"
1217
1318
const league = new URLSearchParams(Astro.url.search).get("league")
1419
const { races, cached_at } = await StatisticsApi.getStatistics({ league })
@@ -65,70 +70,64 @@ const factions = [
6570
---
6671

6772
<Layout title="Statistics">
68-
<div class="w-full border-b border-gray-700/50 bg-gray-800/50 backdrop-blur-lg">
69-
<div class="mx-auto flex max-w-screen-md flex-wrap items-center justify-between gap-4 px-4 py-8 md:px-7">
70-
<div>
71-
<p class="font-bold text-gray-500">Game</p>
72-
<h1 class="flex-auto text-2xl font-bold text-white">Statistics</h1>
73-
</div>
74-
<p class="text-xs text-gray-500">
75-
Last updated <Timeago date={new Date(cached_at)} />
76-
</p>
73+
<Header section="Insights" title="Statistics">
74+
<HeaderMeta
75+
items={[
76+
{
77+
icon: import("lucide-static/icons/clock.svg?raw"),
78+
label: `Last updated ${formatDateRelative(new Date(cached_at))}`,
79+
},
80+
]}
81+
/>
82+
</Header>
83+
<Section title="Factions" class="!max-w-screen-md">
84+
{
85+
league && (
86+
<p slot="header" class="text-balance text-sm text-gray-500">
87+
League stats are based on <em>all matches</em> by players who are currently in the {league} league.
88+
</p>
89+
)
90+
}
91+
<div slot="controls">
92+
<LeagueDropdown selected={league} queryParam="league" client:idle />
7793
</div>
78-
</div>
79-
<div class="mx-auto w-full max-w-screen-md p-4 md:px-7 md:py-8">
80-
<div class="flex justify-between py-4">
81-
<div>
82-
<h2 class="flex-auto text-2xl font-bold text-white">Factions</h2>
83-
<p class="text-gray-400">Excludes Mirrors.</p>
94+
<div>
95+
<div class="flex w-full flex-wrap gap-4 sm:flex-nowrap">
8496
{
85-
league && (
86-
<p class="text-balance text-sm text-gray-500">
87-
League stats are based on <em>all matches</em> by players who are currently in the {league} league.
88-
</p>
89-
)
97+
factions.map((faction) => (
98+
<div class="min-w-0 flex-auto rounded-xl border border-gray-800 bg-gray-900 p-4">
99+
<h2 class="mb-4 text-xl font-black">{faction.name}</h2>
100+
<div class="flex gap-2 xs:gap-4">
101+
<Image src={faction.icon} alt="Vanguard" class="size-12 xs:size-16" />
102+
<div class="flex flex-col">
103+
<span class="text-sm font-bold text-gray-300">Win Rate</span>
104+
<span
105+
class:list={[
106+
"text-xl xs:text-3xl font-black",
107+
faction.stats.winrate >= 50 ? "text-lime-500" : "text-red-500",
108+
]}
109+
>
110+
{faction.stats.winrate}%
111+
</span>
112+
</div>
113+
<div class="flex flex-col">
114+
<span class="text-sm font-bold text-gray-300">Pick Rate</span>
115+
<span class="text-xl font-black xs:text-3xl">{faction.stats.pickrate}%</span>
116+
</div>
117+
</div>
118+
<WinrateChart data={faction.stats.history.data} labels={faction.stats.history.labels} client:idle />
119+
{/*<WinrateChart data={faction.stats.duration.data} labels={faction.stats.duration.labels} client:idle />*/}
120+
<p class="mt-2 pl-1 text-xs leading-snug text-gray-500">
121+
Based on {formatNumber(faction.stats.matches.count!)} matches in the past 7 days, excl.{" "}
122+
{formatNumber(faction.stats.matches.mirrors!)} mirrors
123+
</p>
124+
</div>
125+
))
90126
}
91127
</div>
92-
<div class="flex-none">
93-
<LeagueDropdown selected={league} queryParam="league" client:idle />
128+
<div class="mt-4 min-w-0 flex-auto rounded-xl border border-gray-800 bg-gray-900 p-6">
129+
<h2 class="flex-auto text-center text-2xl font-bold text-gray-600">More stats soon</h2>
94130
</div>
95131
</div>
96-
97-
<div class="flex w-full flex-wrap gap-4 sm:flex-nowrap">
98-
{
99-
factions.map((faction) => (
100-
<div class="min-w-0 flex-auto rounded-xl border border-gray-800 bg-gray-900 p-4">
101-
<h2 class="mb-4 text-xl font-black">{faction.name}</h2>
102-
<div class="flex gap-2 xs:gap-4">
103-
<Image src={faction.icon} alt="Vanguard" class="size-12 xs:size-16" />
104-
<div class="flex flex-col">
105-
<span class="text-sm font-bold text-gray-300">Win Rate</span>
106-
<span
107-
class:list={[
108-
"text-xl xs:text-3xl font-black",
109-
faction.stats.winrate >= 50 ? "text-lime-500" : "text-red-500",
110-
]}
111-
>
112-
{faction.stats.winrate}%
113-
</span>
114-
</div>
115-
<div class="flex flex-col">
116-
<span class="text-sm font-bold text-gray-300">Pick Rate</span>
117-
<span class="text-xl font-black xs:text-3xl">{faction.stats.pickrate}%</span>
118-
</div>
119-
</div>
120-
<WinrateChart data={faction.stats.history.data} labels={faction.stats.history.labels} client:idle />
121-
{/*<WinrateChart data={faction.stats.duration.data} labels={faction.stats.duration.labels} client:idle />*/}
122-
<p class="mt-2 pl-1 text-xs leading-snug text-gray-500">
123-
Based on {formatNumber(faction.stats.matches.count!)} matches in the past 7 days, excl.{" "}
124-
{formatNumber(faction.stats.matches.mirrors!)} mirrors
125-
</p>
126-
</div>
127-
))
128-
}
129-
</div>
130-
<div class="mt-4 min-w-0 flex-auto rounded-xl border border-gray-800 bg-gray-900 p-6">
131-
<h2 class="flex-auto text-center text-2xl font-bold text-gray-600">More stats soon</h2>
132-
</div>
133-
</div>
132+
</Section>
134133
</Layout>

‎src/pages/tools.astro

+6-11
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import type { ToolContent } from "../lib/content"
55
import luminiteImage from "../assets/content/luminite.png"
66
import replayRenamerImage from "../assets/content/replay-renamer.png"
77
import bobBotImage from "../assets/content/bob-bot.png"
8+
import Header from "../components/layout/Header.astro"
9+
import Section from "../components/layout/Section.astro"
810
911
const toolsContent: ToolContent[] = [
1012
{
@@ -43,17 +45,10 @@ const toolsContent: ToolContent[] = [
4345
---
4446

4547
<Layout title="Tools">
46-
<div class="w-full border-b border-gray-700/50 bg-gray-800/50 backdrop-blur-lg">
47-
<div class="mx-auto flex max-w-screen-lg flex-wrap items-center justify-between gap-4 px-4 py-8 md:px-7">
48-
<div>
49-
<p class="font-bold text-gray-500">Community</p>
50-
<h1 class="flex-auto text-2xl font-bold text-white">Tools and Projects</h1>
51-
</div>
52-
</div>
53-
</div>
54-
<div class="mx-auto w-full max-w-screen-lg p-4 md:px-7 md:py-8">
55-
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">
48+
<Header title="Tools and Projects" section="Community" />
49+
<Section>
50+
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
5651
{toolsContent.map((c) => <Card data={c} />)}
5752
</div>
58-
</div>
53+
</Section>
5954
</Layout>

0 commit comments

Comments
 (0)
Please sign in to comment.