Skip to content

Commit

Permalink
Merge pull request #4 from QPixel/id-page
Browse files Browse the repository at this point in the history
Id page
  • Loading branch information
QPixel authored Mar 25, 2024
2 parents ecc20fa + 8389827 commit 50acd6e
Show file tree
Hide file tree
Showing 10 changed files with 228 additions and 111 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ pnpm-debug.log*
# macOS-specific files
.DS_Store

.vercel
.vercel
.env*.local
59 changes: 31 additions & 28 deletions src/lib/components/counter.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,45 @@
import { format } from "date-fns";
import { Button } from "$lib/components/ui/button";
import { leaderboard_store } from "./get-leaderboard";
import type { CounterData } from "src/pages/api/counter";
export let isAuthed: boolean;
export let id: number | undefined;
export let serverData: CounterData;
let didError = false;
let error = "";
export const increment = () => {
counter_store.increment().catch((e) => {
export const increment = async () => {
await counter_store.increment().then((resolved_username) => {
leaderboard_store.update_local(id!, resolved_username);
}).catch((e) => {
didError = true;
error = e.message;
return "";
});
leaderboard_store.update_local(id!);
};
counter_store.init(serverData);
</script>

{#await counter_store.init()}
<p>Loading</p>
{:then}
<div class="space-y-4 flex flex-col justify-center">
<h1 class="text-3xl font-semibold w-full text-center">
Riley has said
<br class="md:hidden"/>Womp Womp
</h1>
<h1 class="text-red-500 text-center text-3xl font-semibold rounded-lg border px-9 py-2 w-fit mx-auto">{$counter_store.total} times</h1>
<p class="text-center">
Last Updated: {format($counter_store.lastUpdated, "MM/dd 'at' hh:mm a")} by {$counter_store.resolved_username}
</p>
{#if didError}
<p class="text-red-500">{error}</p>
{/if}
{#if isAuthed}
<Button
on:click={increment}
size="lg"
class="w-full bg-red-500 hover:bg-red-300 font-bold text-xl"
disabled={didError}>Add to the Total</Button
>
{/if}
</div>
{/await}

<div class="space-y-4 flex flex-col justify-center">
<h1 class="text-3xl font-semibold w-full text-center">
Riley has said
<br class="md:hidden"/>Womp Womp
</h1>
<h1 class="text-red-500 text-center text-3xl font-semibold rounded-lg border px-9 py-2 w-fit mx-auto">{$counter_store.total} times</h1>
<p class="text-center">
Last Updated: {format($counter_store.last_updated, "MM/dd 'at' hh:mm a")} by {$counter_store.resolved_username}
</p>
{#if didError}
<p class="text-red-500">{error}</p>
{/if}
{#if isAuthed}
<Button
on:click={increment}
size="lg"
class="w-full bg-red-500 hover:bg-red-300 font-bold text-xl"
disabled={didError}>Add to the Total</Button
>
{/if}
</div>
25 changes: 13 additions & 12 deletions src/lib/components/get-counter.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { writable } from "svelte/store";
import type { CounterData } from "src/pages/api/counter";

function getCounter() {
const { subscribe, update, set } = writable({
const { subscribe, update, set } = writable<CounterData>({
total: 0,
lastUpdated: new Date(),
updatedBy: 0,
last_updated: new Date(),
updated_by: 0,
resolved_username: '',
});

return {
subscribe,
init: async () => {
const data = await fetch('/api/counter');
const json = await data.json();
// TODO: type data
init: (data: CounterData) => {
set({
...json,
...data,
});
},
update,
Expand All @@ -31,18 +31,19 @@ function getCounter() {
}
return res;
});
const json = await data.json();
if (json.total === undefined || json.lastUpdated === undefined) {
const json = await data.json() as CounterData;
if (json.total === undefined || json.last_updated === undefined) {
throw new Error('Invalid response');
}
update((v) => {
return {
total: json.total,
lastUpdated: new Date(json.lastUpdated),
updatedBy: json.updatedBy,
resolved_username: v.resolved_username,
last_updated: new Date(json.last_updated),
updated_by: json.updated_by,
resolved_username: json.resolved_username,
}
});
return json.resolved_username;
}
}
}
Expand Down
39 changes: 24 additions & 15 deletions src/lib/components/get-leaderboard.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,42 @@
import { writable } from "svelte/store";
import type { LeaderboardData } from "src/pages/api/leaderboard";

function getLeaderboard() {
const { subscribe, set, update } = writable<{
updatedBy: number;
total: number;
resolved_username: string;
}[]>([]);
const { subscribe, set, update } = writable<LeaderboardData>([]);

return {
subscribe,
init: async () => {
const data = await fetch('/api/leaderboard');
if (!data.ok) {
throw new Error('Failed to fetch leaderboard');
}
const json = await data.json();
set(json);
init: (data: any) => {
set(data);
},
update_local: (id: number) => {
update_local: (id: number, resolved_username = "") => {
update((v) => {
if (v.length === 0) {
return [{
updated_by: id,
total: 1,
resolved_username: resolved_username !== "" ? resolved_username : "Unknown",
}];
}

if (!v.some((entry) => entry.updated_by === id)){
v.push({
updated_by: id,
total: 1,
resolved_username: resolved_username !== "" ? resolved_username : "Unknown",
})
return v.sort((a, b) => b.total - a.total);
}

return v.map((entry) => {
if (entry.updatedBy === id) {
if (entry.updated_by === id) {
return {
...entry,
total: entry.total + 1,
};
}
return entry;
});
}).sort((a, b) => b.total - a.total);
});
}
}
Expand Down
38 changes: 19 additions & 19 deletions src/lib/components/leaderboard.svelte
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
<script lang="ts">
import { leaderboard_store } from "./get-leaderboard";
export let serverData: any;
leaderboard_store.init(serverData);
</script>

{#await leaderboard_store.init()}
<p>Loading</p>
{:then}
{#if $leaderboard_store.length !== 0}
<div class="space-y-4">
<ol class="divide-solid divide-y border-2 rounded-lg p-2">
{#each $leaderboard_store as player, i}
<li class="text-xl p-2">
{i + 1}. {player.resolved_username} - {player.total}
</li>
{/each}
</ol>
</div>
{:else}
<p>No players have been added to the leaderboard yet.</p>
{/if}
{:catch error}
<p class="text-red-500">{error.message}</p>
{/await}
{#if $leaderboard_store.length !== 0}
<div class="space-y-4">
<ol class="divide-solid divide-y border-2 rounded-lg p-2">
{#each $leaderboard_store as player, i}
<li class="text-xl p-2">
{i + 1}. {player.resolved_username} - {player.total}
</li>
{/each}
</ol>
</div>
{:else}
<p>No players have been added to the leaderboard yet.</p>
{/if}
25 changes: 19 additions & 6 deletions src/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,25 @@ import { defineMiddleware } from "astro:middleware";
export const onRequest = defineMiddleware(({request, cookies, redirect}, next) => {
const url = new URL(request.url);
const query = url.searchParams.get('id');
let idRegex = url.pathname.match(/\/([\d]+)/g);
if (idRegex) {
if (!cookies.has('id')) {
cookies.set('id', idRegex[0].replace('/', ''), {
path: '/',
expires: new Date(new Date().getTime() + 1000 * 60 * 60 * 24 * 365),
});
cookies.set('triedToIncrement', '0', {
path: '/',

});
cookies.set('resetAt', new Date(new Date().getTime() + 1000 * 60 * 60 * 24).toISOString(), {
path: '/',

});
}
return next();
}

if (query && url.pathname === "/") {
cookies.set('id', query, {
path: '/',
Expand All @@ -16,13 +35,7 @@ export const onRequest = defineMiddleware(({request, cookies, redirect}, next) =
path: '/',

});
if (query === '2') {
console.log("maddie requested", query, url, request);
}
return redirect('/');
}
if (query === '2') {
console.log("maddie requested", query, url, request);
}
return next();
});
65 changes: 65 additions & 0 deletions src/pages/[id].astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
---
import "../styles/global.css";
import {
Card,
CardContent,
CardTitle,
CardHeader,
} from "$lib/components/ui/card";
import Counter from "$lib/components/counter.svelte";
import Leaderboard from "$lib/components/leaderboard.svelte";
import { getCounterData } from "./api/counter";
import { getLeaderboard } from "./api/leaderboard";
import SpeedInsights from "@vercel/speed-insights/astro";
const { id } = Astro.params;
if (typeof id !== "undefined") {
if (isNaN(parseInt(id))) {
return new Response("Invalid ID", { status: 400 });
}
}
const counterData = await getCounterData();
const leaderboardData = await getLeaderboard();
---

<html lang="en" class="dark">
<head>
<meta charset="utf-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width" />
<meta name="generator" content={Astro.generator} />
<title>Womp Womp</title>
</head>
<body class="bg-background min-h-screen w-full">
<main
class="min-h-screen flex md:justify-center items-center flex-col max-w-lg p-2 mx-auto"
>
<header class="text-left mt-16">
<h1 class="font-semibold text-3xl">The Womp Womp Counter</h1>
</header>
<div class="h-full w-full space-y-5 mt-5">
<Card class="w-full">
<CardContent class="pt-6">
<Counter
client:load
isAuthed={typeof id !== "undefined"}
id={parseInt(id!)}
serverData={counterData}
/>
</CardContent>
</Card>
<Card class="w-full">
<CardHeader>
<CardTitle class={"text-4xl"}>Leaderboard</CardTitle>
</CardHeader>
<CardContent>
<Leaderboard client:load serverData={leaderboardData} />
</CardContent>
</Card>
</div>
</main>
<SpeedInsights />
</body>
</html>
Loading

0 comments on commit 50acd6e

Please sign in to comment.