diff --git a/package-lock.json b/package-lock.json index 59392137..abb395cc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,6 +34,7 @@ "@tanstack/react-table": "8.20.6", "axios": "1.7.9", "better-sqlite3": "11.7.0", + "canvas-confetti": "^1.9.3", "class-variance-authority": "0.7.1", "clsx": "2.1.1", "cmdk": "1.0.4", @@ -5417,6 +5418,16 @@ ], "license": "CC-BY-4.0" }, + "node_modules/canvas-confetti": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/canvas-confetti/-/canvas-confetti-1.9.3.tgz", + "integrity": "sha512-rFfTURMvmVEX1gyXFgn5QMn81bYk70qa0HLzcIOSVEyl57n6o9ItHeBtUSWdvKAPY0xlvBHno4/v3QPrT83q9g==", + "license": "ISC", + "funding": { + "type": "donate", + "url": "https://www.paypal.me/kirilvatev" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", diff --git a/package.json b/package.json index 8ef20ebf..22312604 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "@tanstack/react-table": "8.20.6", "axios": "1.7.9", "better-sqlite3": "11.7.0", + "canvas-confetti": "^1.9.3", "class-variance-authority": "0.7.1", "clsx": "2.1.1", "cmdk": "1.0.4", diff --git a/src/app/components/SupporterMessage.tsx b/src/app/components/SupporterMessage.tsx new file mode 100644 index 00000000..7706e190 --- /dev/null +++ b/src/app/components/SupporterMessage.tsx @@ -0,0 +1,46 @@ +"use client"; + +import React from "react"; +import confetti from "canvas-confetti"; + +export default function SupporterMessage({ tier }: { tier: string }) { + return ( +
+ { + // Get the bounding box of the element + const rect = ( + e.target as HTMLElement + ).getBoundingClientRect(); + + // Trigger confetti centered on the word "Pangolin" + confetti({ + particleCount: 100, + spread: 70, + origin: { + x: (rect.left + rect.width / 2) / window.innerWidth, + y: rect.top / window.innerHeight + }, + colors: ["#FFA500", "#FF4500", "#FFD700"] + }); + }} + > + Pangolin + + {/* SVG Star */} + + + + {/* Popover */} +
+ Thank you for supporting Pangolin as a {tier}! +
+
+ ); +} diff --git a/src/app/globals.css b/src/app/globals.css index cb32e061..db1d8feb 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -2,65 +2,63 @@ @tailwind components; @tailwind utilities; - @layer base { - :root { - --background: 0 0% 100%; - --foreground: 20 0.0% 10.0%; - --card: 0 0% 100%; - --card-foreground: 20 0.0% 10.0%; - --popover: 0 0% 100%; - --popover-foreground: 20 0.0% 10.0%; - --primary: 24.6 95% 53.1%; - --primary-foreground: 60 9.1% 97.8%; - --secondary: 60 4.8% 95.9%; - --secondary-foreground: 24 9.8% 10%; - --muted: 60 4.8% 85.0%; - --muted-foreground: 25 5.3% 44.7%; - --accent: 60 4.8% 90%; - --accent-foreground: 24 9.8% 10%; - --destructive: 0 84.2% 60.2%; - --destructive-foreground: 60 9.1% 97.8%; - --border: 20 5.9% 80%; - --input: 20 5.9% 75%; - --ring: 24.6 95% 53.1%; - --radius: 0.75rem; - --chart-1: 12 76% 61%; - --chart-2: 173 58% 39%; - --chart-3: 197 37% 24%; - --chart-4: 43 74% 66%; - --chart-5: 27 87% 67%; - } + :root { + --background: 0 0% 100%; + --foreground: 20 0% 10%; + --card: 0 0% 100%; + --card-foreground: 20 0% 10%; + --popover: 0 0% 100%; + --popover-foreground: 20 0% 10%; + --primary: 24.6 95% 53.1%; + --primary-foreground: 60 9.1% 97.8%; + --secondary: 60 4.8% 95.9%; + --secondary-foreground: 24 9.8% 10%; + --muted: 60 4.8% 85%; + --muted-foreground: 25 5.3% 44.7%; + --accent: 60 4.8% 90%; + --accent-foreground: 24 9.8% 10%; + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 60 9.1% 97.8%; + --border: 20 5.9% 80%; + --input: 20 5.9% 75%; + --ring: 24.6 95% 53.1%; + --radius: 0.75rem; + --chart-1: 12 76% 61%; + --chart-2: 173 58% 39%; + --chart-3: 197 37% 24%; + --chart-4: 43 74% 66%; + --chart-5: 27 87% 67%; + } - .dark { - --background: 20 0.0% 10.0%; - --foreground: 60 9.1% 97.8%; - --card: 20 0.0% 10.0%; - --card-foreground: 60 9.1% 97.8%; - --popover: 20 0.0% 10.0%; - --popover-foreground: 60 9.1% 97.8%; - --primary: 20.5 90.2% 48.2%; - --primary-foreground: 60 9.1% 97.8%; - --secondary: 12 6.5% 15.0%; - --secondary-foreground: 60 9.1% 97.8%; - --muted: 12 6.5% 25.0%; - --muted-foreground: 24 5.4% 63.9%; - --accent: 12 2.5% 15.0%; - --accent-foreground: 60 9.1% 97.8%; - --destructive: 0 72.2% 50.6%; - --destructive-foreground: 60 9.1% 97.8%; - --border: 12 6.5% 30.0%; - --input: 12 6.5% 35.0%; - --ring: 20.5 90.2% 48.2%; - --chart-1: 220 70% 50%; - --chart-2: 160 60% 45%; - --chart-3: 30 80% 55%; - --chart-4: 280 65% 60%; - --chart-5: 340 75% 55%; - } + .dark { + --background: 20 0% 10%; + --foreground: 60 9.1% 97.8%; + --card: 20 0% 10%; + --card-foreground: 60 9.1% 97.8%; + --popover: 20 0% 10%; + --popover-foreground: 60 9.1% 97.8%; + --primary: 20.5 90.2% 48.2%; + --primary-foreground: 60 9.1% 97.8%; + --secondary: 12 6.5% 15%; + --secondary-foreground: 60 9.1% 97.8%; + --muted: 12 6.5% 25%; + --muted-foreground: 24 5.4% 63.9%; + --accent: 12 2.5% 15%; + --accent-foreground: 60 9.1% 97.8%; + --destructive: 0 72.2% 50.6%; + --destructive-foreground: 60 9.1% 97.8%; + --border: 12 6.5% 30%; + --input: 12 6.5% 35%; + --ring: 20.5 90.2% 48.2%; + --chart-1: 220 70% 50%; + --chart-2: 160 60% 45%; + --chart-3: 30 80% 55%; + --chart-4: 280 65% 60%; + --chart-5: 340 75% 55%; + } } - @layer base { * { @apply border-border; @@ -70,4 +68,3 @@ @apply bg-background text-foreground; } } - diff --git a/src/app/layout.tsx b/src/app/layout.tsx index bc322572..9a6f7cb9 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -12,13 +12,14 @@ import SupportStatusProvider from "@app/providers/SupporterStatusProvider"; import { createApiClient, internal, priv } from "@app/lib/api"; import { AxiosResponse } from "axios"; import { IsSupporterKeyVisibleResponse } from "@server/routers/supporterKey"; +import SupporterMessage from "./components/SupporterMessage"; export const metadata: Metadata = { title: `Dashboard - Pangolin`, description: "" }; -export const dynamic = 'force-dynamic'; +export const dynamic = "force-dynamic"; // const font = Figtree({ subsets: ["latin"] }); const font = Inter({ subsets: ["latin"] }); @@ -34,9 +35,9 @@ export default async function RootLayout({ visible: true } as any; - const res = await priv.get< - AxiosResponse - >("supporter-key/visible"); + const res = await priv.get>( + "supporter-key/visible" + ); supporterData.visible = res.data.data.visible; supporterData.tier = res.data.data.tier; @@ -61,9 +62,15 @@ export default async function RootLayout({ {/* Footer */}