feat: login page with nextauth.js
This commit is contained in:
parent
599c59bb38
commit
a0f3aed326
7 changed files with 77 additions and 3 deletions
7
.env.example
Normal file
7
.env.example
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
NEXTAUTH_URL=https://tomodachishare.trafficlunar.net
|
||||||
|
AUTH_SECRET=XXXXXXXXXXXXXXXX
|
||||||
|
|
||||||
|
DISCORD_ID=XXXXXXXXXXXXXXXX
|
||||||
|
DISCORD_SECRET=XXXXXXXXXXXXXXXX
|
||||||
|
GITHUB_ID=XXXXXXXXXXXXXXXX
|
||||||
|
GITHUB_SECRET=XXXXXXXXXXXXXXXX
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -32,6 +32,7 @@ yarn-error.log*
|
||||||
|
|
||||||
# env files (can opt-in for committing if needed)
|
# env files (can opt-in for committing if needed)
|
||||||
.env*
|
.env*
|
||||||
|
!.env.example
|
||||||
|
|
||||||
# vercel
|
# vercel
|
||||||
.vercel
|
.vercel
|
||||||
|
|
|
||||||
23
src/app/api/auth/[...nextauth]/route.ts
Normal file
23
src/app/api/auth/[...nextauth]/route.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
import NextAuth, { AuthOptions } from "next-auth";
|
||||||
|
import Discord from "next-auth/providers/discord";
|
||||||
|
import Github from "next-auth/providers/github";
|
||||||
|
|
||||||
|
export const authOptions: AuthOptions = {
|
||||||
|
pages: {
|
||||||
|
signIn: "/login",
|
||||||
|
},
|
||||||
|
providers: [
|
||||||
|
Discord({
|
||||||
|
clientId: process.env.DISCORD_ID!,
|
||||||
|
clientSecret: process.env.DISCORD_SECRET!,
|
||||||
|
}),
|
||||||
|
Github({
|
||||||
|
clientId: process.env.GITHUB_ID!,
|
||||||
|
clientSecret: process.env.GITHUB_SECRET!,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const handler = NextAuth(authOptions);
|
||||||
|
|
||||||
|
export { handler as GET, handler as POST };
|
||||||
19
src/app/components/login-buttons.tsx
Normal file
19
src/app/components/login-buttons.tsx
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { Icon } from "@iconify/react/dist/iconify.js";
|
||||||
|
import { signIn } from "next-auth/react";
|
||||||
|
|
||||||
|
export default function LoginButtons() {
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col items-center gap-2 mt-8">
|
||||||
|
<button onClick={() => signIn("discord")} className="button gap-2 !px-3 !bg-indigo-400 !border-indigo-500 hover:!bg-indigo-500">
|
||||||
|
<Icon icon="ic:baseline-discord" fontSize={32} />
|
||||||
|
Login with Discord
|
||||||
|
</button>
|
||||||
|
<button onClick={() => signIn("github")} className="button gap-2 !px-3 !bg-zinc-700 !border-zinc-800 hover:!bg-zinc-800 text-white">
|
||||||
|
<Icon icon="mdi:github" fontSize={32} />
|
||||||
|
Login with GitHub
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -13,5 +13,5 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
@apply flex justify-center items-center px-5 py-2 bg-orange-300 border-2 border-orange-400 rounded-full shadow-md hover:bg-orange-400;
|
@apply flex justify-center items-center px-5 py-2 bg-orange-300 border-2 border-orange-400 rounded-full shadow-md hover:bg-orange-400 transition cursor-pointer;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
23
src/app/login/page.tsx
Normal file
23
src/app/login/page.tsx
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { getServerSession } from "next-auth";
|
||||||
|
|
||||||
|
import { authOptions } from "../api/auth/[...nextauth]/route";
|
||||||
|
import LoginButtons from "../components/login-buttons";
|
||||||
|
import { redirect, RedirectType } from "next/navigation";
|
||||||
|
|
||||||
|
export default async function LoginPage() {
|
||||||
|
const session = await getServerSession(authOptions);
|
||||||
|
|
||||||
|
// If the user is already logged in, redirect
|
||||||
|
if (session) {
|
||||||
|
redirect("/");
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col items-center">
|
||||||
|
<h1 className="text-3xl font-medium">Welcome to TomodachiShare!</h1>
|
||||||
|
<h2 className="text-lg">Choose your login method</h2>
|
||||||
|
|
||||||
|
<LoginButtons />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
return (
|
return (
|
||||||
<div className="max-w-5xl grid grid-cols-3 gap-4">
|
<div className="max-w-5xl grid grid-cols-3 gap-4">
|
||||||
{[...Array(3)].map(() => (
|
{/* testing purposes only */}
|
||||||
<div className="bg-zinc-50 rounded-3xl border-2 border-amber-300 shadow-lg p-3 transition hover:scale-105">
|
{[...Array(3)].map((_, index) => (
|
||||||
|
<div key={index} className="bg-zinc-50 rounded-3xl border-2 border-amber-300 shadow-lg p-3 transition hover:scale-105">
|
||||||
<img src="https://placehold.co/600x400" alt="mii" className="rounded-xl" />
|
<img src="https://placehold.co/600x400" alt="mii" className="rounded-xl" />
|
||||||
<div className="p-4">
|
<div className="p-4">
|
||||||
<h3 className="font-bold text-2xl">Frieren</h3>
|
<h3 className="font-bold text-2xl">Frieren</h3>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue