aboutsummaryrefslogtreecommitdiff
path: root/web/src
diff options
context:
space:
mode:
authorAndrew Lee <andrew@alee14.me>2025-03-23 01:39:11 -0400
committerAndrew Lee <andrew@alee14.me>2025-03-23 01:39:11 -0400
commitd7c46a9eae28046bb26da182abc298dc18ed5a10 (patch)
treea1f9955a757b150b88ed5398ef851ab2d1d4a46b /web/src
parentb60e681998a456adecb93b5fe04b66ad4ac9abb6 (diff)
downloadAleeBot-d7c46a9eae28046bb26da182abc298dc18ed5a10.tar.gz
AleeBot-d7c46a9eae28046bb26da182abc298dc18ed5a10.tar.bz2
AleeBot-d7c46a9eae28046bb26da182abc298dc18ed5a10.zip
Replacing Astro with Next.JS; Prefix warning; Consistent env vars
Diffstat (limited to 'web/src')
-rw-r--r--web/src/app/api/auth/[...nextauth]/route.js2
-rw-r--r--web/src/app/components/sign-in.jsx14
-rw-r--r--web/src/app/components/sign-out.jsx14
-rw-r--r--web/src/app/dashboard/page.js16
-rw-r--r--web/src/app/favicon.icobin0 -> 25931 bytes
-rw-r--r--web/src/app/globals.css26
-rw-r--r--web/src/app/layout.js29
-rw-r--r--web/src/app/page.js15
-rw-r--r--web/src/components/Quotes.jsx88
-rw-r--r--web/src/layouts/Layout.astro22
-rw-r--r--web/src/lib/auth.js6
-rw-r--r--web/src/pages/index.astro45
-rw-r--r--web/src/styles/Quote.css33
13 files changed, 122 insertions, 188 deletions
diff --git a/web/src/app/api/auth/[...nextauth]/route.js b/web/src/app/api/auth/[...nextauth]/route.js
new file mode 100644
index 0000000..5951f83
--- /dev/null
+++ b/web/src/app/api/auth/[...nextauth]/route.js
@@ -0,0 +1,2 @@
+import { handlers } from "@/lib/auth"
+export const { GET, POST } = handlers
diff --git a/web/src/app/components/sign-in.jsx b/web/src/app/components/sign-in.jsx
new file mode 100644
index 0000000..bb891c7
--- /dev/null
+++ b/web/src/app/components/sign-in.jsx
@@ -0,0 +1,14 @@
+import { signIn } from "@/lib/auth"
+
+export default function SignIn() {
+ return (
+ <form
+ action={async () => {
+ "use server"
+ await signIn("discord")
+ }}
+ >
+ <button type="submit">Login with Discord</button>
+ </form>
+ )
+}
diff --git a/web/src/app/components/sign-out.jsx b/web/src/app/components/sign-out.jsx
new file mode 100644
index 0000000..69162a4
--- /dev/null
+++ b/web/src/app/components/sign-out.jsx
@@ -0,0 +1,14 @@
+import { signOut } from "@/lib/auth"
+
+export default function SignOut() {
+ return (
+ <form
+ action={async () => {
+ "use server"
+ await signOut("discord")
+ }}
+ >
+ <button type="submit">Log out</button>
+ </form>
+ )
+}
diff --git a/web/src/app/dashboard/page.js b/web/src/app/dashboard/page.js
new file mode 100644
index 0000000..065bfb0
--- /dev/null
+++ b/web/src/app/dashboard/page.js
@@ -0,0 +1,16 @@
+import { redirect } from "next/navigation";
+import { auth } from "@/lib/auth";
+import SignOut from "@/app/components/sign-out";
+
+export default async function Home() {
+ const session = await auth();
+ if (!session) redirect("/");
+
+ return (
+ <div>
+ <h1>Dashboard</h1>
+ <p>Welcome {session.user?.name}</p>
+ <SignOut />
+ </div>
+ )
+}
diff --git a/web/src/app/favicon.ico b/web/src/app/favicon.ico
new file mode 100644
index 0000000..718d6fe
--- /dev/null
+++ b/web/src/app/favicon.ico
Binary files differ
diff --git a/web/src/app/globals.css b/web/src/app/globals.css
new file mode 100644
index 0000000..a2dc41e
--- /dev/null
+++ b/web/src/app/globals.css
@@ -0,0 +1,26 @@
+@import "tailwindcss";
+
+:root {
+ --background: #ffffff;
+ --foreground: #171717;
+}
+
+@theme inline {
+ --color-background: var(--background);
+ --color-foreground: var(--foreground);
+ --font-sans: var(--font-geist-sans);
+ --font-mono: var(--font-geist-mono);
+}
+
+@media (prefers-color-scheme: dark) {
+ :root {
+ --background: #0a0a0a;
+ --foreground: #ededed;
+ }
+}
+
+body {
+ background: var(--background);
+ color: var(--foreground);
+ font-family: Arial, Helvetica, sans-serif;
+}
diff --git a/web/src/app/layout.js b/web/src/app/layout.js
new file mode 100644
index 0000000..bec6c45
--- /dev/null
+++ b/web/src/app/layout.js
@@ -0,0 +1,29 @@
+import { Geist, Geist_Mono } from "next/font/google";
+import "./globals.css";
+
+const geistSans = Geist({
+ variable: "--font-geist-sans",
+ subsets: ["latin"],
+});
+
+const geistMono = Geist_Mono({
+ variable: "--font-geist-mono",
+ subsets: ["latin"],
+});
+
+export const metadata = {
+ title: "AleeBot",
+ description: "Generated by create next app",
+};
+
+export default function RootLayout({ children }) {
+ return (
+ <html lang="en">
+ <body
+ className={`${geistSans.variable} ${geistMono.variable} antialiased`}
+ >
+ {children}
+ </body>
+ </html>
+ );
+}
diff --git a/web/src/app/page.js b/web/src/app/page.js
new file mode 100644
index 0000000..1890f99
--- /dev/null
+++ b/web/src/app/page.js
@@ -0,0 +1,15 @@
+import { redirect } from "next/navigation";
+import SignIn from "@/app/components/sign-in";
+import { auth } from "@/lib/auth";
+
+export default async function Home() {
+ const session = await auth();
+ if (session) redirect("/dashboard");
+ return (
+ <>
+ <main>
+ <SignIn />
+ </main>
+ </>
+ );
+}
diff --git a/web/src/components/Quotes.jsx b/web/src/components/Quotes.jsx
deleted file mode 100644
index 1eb258a..0000000
--- a/web/src/components/Quotes.jsx
+++ /dev/null
@@ -1,88 +0,0 @@
-import { useState, useEffect } from 'react';
-import '../styles/Quote.css'
-import { API_URL } from "astro:env/client";
-
-export function PendingQuotes() {
- const [quotes, setQuotes] = useState([]);
-
- const fetchQuotes = async () => {
- try {
- const response = await fetch(`${API_URL}/api/pending-quotes`);
- const data = await response.json();
- setQuotes(data);
- } catch (error) {
- console.error('Failed to fetch quotes:', error);
- }
- };
-
- useEffect(() => {
- fetchQuotes();
- }, []);
-
- const approveQuote = async (id) => {
- try {
- const response = await fetch(`${API_URL}/api/approve-quote`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({ id }),
- });
-
- if (response.ok) {
- fetchQuotes(); // Refresh the listing after approving the quote
- } else {
- console.error('Failed to approve quote');
- }
- } catch (error) {
- console.error('Error approving quote:', error);
- }
- };
-
- const rejectQuote = async (id) => {
- try {
- const response = await fetch(`${API_URL}/api/reject-quote`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({ id }),
- });
-
- if (response.ok) {
- fetchQuotes(); // Refresh the listing after approving the quote
- } else {
- console.error('Failed to reject quote');
- }
- } catch (error) {
- console.error('Error rejecting quote:', error);
- }
- };
-
- return (
- <div>
- <h1>Pending Quotes</h1>
- {quotes.length > 0 ? (
- <ul className="quoteList">
- {quotes.map((quote) => (
- <li key={quote.id} className="quoteList">
- <div className="quote">
- <div className="author">
- <img src={quote.authorImage} alt="No Profile" width="50" height="50"/>
- <h1 className="quoteAuthor">{quote.author}</h1>
- </div>
- <p className="quoteText">{quote.quote}</p>
- <small>- {quote.year}</small>
- <small>Submitted by {quote.submitterAuthor} ({quote.submitterID})</small>
- </div>
- <button onClick={() => approveQuote(quote.id)}>Approve</button>
- <button onClick={() => rejectQuote(quote.id)}>Reject</button>
- </li>
- ))}
- </ul>
- ) : (
- <p>No pending quotes available.</p>
- )}
- </div>
- );
-}
diff --git a/web/src/layouts/Layout.astro b/web/src/layouts/Layout.astro
deleted file mode 100644
index 2f6032d..0000000
--- a/web/src/layouts/Layout.astro
+++ /dev/null
@@ -1,22 +0,0 @@
-<!doctype html>
-<html lang="en">
- <head>
- <meta charset="UTF-8" />
- <meta name="viewport" content="width=device-width" />
- <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
- <meta name="generator" content={Astro.generator} />
- <title>AleeBot Web Interface</title>
- </head>
- <body>
- <slot />
- </body>
-</html>
-
-<style>
- html,
- body {
- margin: 0;
- width: 100%;
- height: 100%;
- }
-</style>
diff --git a/web/src/lib/auth.js b/web/src/lib/auth.js
new file mode 100644
index 0000000..bc482b1
--- /dev/null
+++ b/web/src/lib/auth.js
@@ -0,0 +1,6 @@
+import NextAuth from "next-auth"
+import Discord from "next-auth/providers/discord"
+
+export const { handlers, signIn, signOut, auth } = NextAuth({
+ providers: [Discord],
+})
diff --git a/web/src/pages/index.astro b/web/src/pages/index.astro
deleted file mode 100644
index f1dc6e7..0000000
--- a/web/src/pages/index.astro
+++ /dev/null
@@ -1,45 +0,0 @@
----
-import Layout from '../layouts/Layout.astro';
-import { PendingQuotes } from '../components/Quotes';
-
----
-
-<Layout>
- <div class="container">
- <h1 id="version">AleeBot</h1>
- <PendingQuotes client:load />
- </div>
-</Layout>
-
-<style>
- @import url('https://fonts.googleapis.com/css2?family=Exo+2:ital,wght@0,100..900;1,100..900&display=swap');
- html,
- body {
- margin: 0;
- width: 100%;
- height: 100%;
- font-family: "Exo 2", sans-serif;
- }
-
- .container {
- margin: 2em;
- }
-
-</style>
-
-<script>
- import { API_URL } from "astro:env/client"
- document.addEventListener('DOMContentLoaded', async () => {
- try {
- const version = await fetch(`${API_URL}/api/version`).then((res) => res.json());
- const versionElement = document.getElementById('version');
- if (versionElement) {
- versionElement.textContent = `AleeBot ${version}`;
- } else {
- console.error('Element with ID "version" not found.');
- }
- } catch (e) {
- console.error('Failed to fetch version:', e);
- }
- });
-</script>
diff --git a/web/src/styles/Quote.css b/web/src/styles/Quote.css
deleted file mode 100644
index 8adfb29..0000000
--- a/web/src/styles/Quote.css
+++ /dev/null
@@ -1,33 +0,0 @@
-.quote {
- display: flex;
- flex-direction: column;
- background: #555555;
- color: #FFFFFF;
- padding: 1em;
-}
-
-ul.quoteList {
- margin: 0;
- padding: 0;
-}
-
-li.quoteList {
- list-style-type: none;
- margin-top: 1em;
- margin-bottom: 1em;
-}
-
-.author {
- display: flex;
- flex-direction: row;
-}
-
-h1.quoteAuthor {
- font-size: 1.5em;
- padding: 0;
- margin: 0 0 0 .5em;
-}
-
-.quoteText {
- margin: .5em 0;
-}