Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/routes/dashboard/+page.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { requireUser } from "#lib/server/page.ts";
import { randomQuote } from "#lib/server/quotes.ts";

const LAST_QUOTE_COOKIE = "last_quote";
const PLAYER_TWO_BANNER_COOKIE = "playertwo_banner_dismissed";

export const load: PageServerLoad = async ({ locals, cookies }) => {
const user = requireUser(locals);
Expand All @@ -16,5 +17,10 @@ export const load: PageServerLoad = async ({ locals, cookies }) => {
const lastIndex = Number.parseInt(cookies.get(LAST_QUOTE_COOKIE) ?? "", 10);
const quote = randomQuote(Number.isNaN(lastIndex) ? undefined : lastIndex);
cookies.set(LAST_QUOTE_COOKIE, String(quote.index), { path: "/dashboard", httpOnly: true, sameSite: "lax" });
return { stats, curlExample, quote: quote.text };
return {
stats,
curlExample,
quote: quote.text,
playerTwoBannerDismissed: cookies.get(PLAYER_TWO_BANNER_COOKIE) === "1",
};
};
39 changes: 39 additions & 0 deletions src/routes/dashboard/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@
let agentBannerDismissed = $state(false);
const showAgentBanner = $derived(!user.agentBannerDismissed && !agentBannerDismissed);

let playerTwoBannerDismissed = $state(false);
const showPlayerTwoBanner = $derived(!data.playerTwoBannerDismissed && !playerTwoBannerDismissed);

const dismissPlayerTwoBanner = () => {
playerTwoBannerDismissed = true;
document.cookie = "playertwo_banner_dismissed=1; path=/dashboard; max-age=31536000; samesite=lax";
};

const dismissAgentBanner = async () => {
agentBannerDismissed = true;
await fetch("/api/dismiss-agent-banner", { method: "POST" });
Expand Down Expand Up @@ -79,6 +87,37 @@
<StatsGrid stats={data.stats} />
</section>

{#if showPlayerTwoBanner}
<aside class="@container relative mt-3 overflow-hidden rounded-lg border border-white/10 bg-[#1a1e24] text-white" aria-label="Player Two">
<a
href="https://playertwo.hackclub.com/?ref=hackclub-ai-banner"
target="_blank"
rel="noopener"
class="group focus-visible:ring-ring/50 flex min-h-16 items-center gap-3 rounded-lg py-2 pr-11 pl-4 outline-none focus-visible:ring-3 @md:gap-4 @2xl:pr-72"
>
<img src="/playertwo/logo.webp" alt="Player Two" width="247" height="128" class="h-8 w-auto shrink-0 @md:h-10" />
<span class="min-w-0 text-xs leading-snug text-pretty @md:text-sm">
Train an AI model that can play a game, get <strong class="font-semibold whitespace-nowrap">free co-op games!</strong>
</span>
<img
src="/playertwo/games.webp"
alt=""
width="458"
height="176"
class="pointer-events-none absolute top-1 right-10 hidden h-22 w-auto transition-transform group-hover:-translate-y-0.5 @2xl:block"
/>
</a>
<button
type="button"
class="absolute top-1/2 right-2 flex size-7 -translate-y-1/2 items-center justify-center rounded-md text-white/60 transition-colors hover:bg-white/10 hover:text-white focus-visible:ring-3 focus-visible:ring-white/40 outline-none"
aria-label="Dismiss Player Two banner"
onclick={dismissPlayerTwoBanner}
>
<CloseIcon class="size-4" />
</button>
</aside>
{/if}

<section class="mt-10" aria-labelledby="links-heading">
<h2 id="links-heading" class="mb-4 text-sm font-medium">Jump to</h2>
<ul role="list" class="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3">
Expand Down
Binary file added static/playertwo/games.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added static/playertwo/logo.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading