Skip to content

Commit

Permalink
Merge pull request #4 from ky28059/main
Browse files Browse the repository at this point in the history
Pull more build error fixes, dep updates
  • Loading branch information
ky28059 authored Nov 19, 2024
2 parents df1d5f0 + 72ac553 commit d55c55a
Show file tree
Hide file tree
Showing 8 changed files with 225 additions and 79 deletions.
17 changes: 17 additions & 0 deletions app/login-handler/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { NextRequest, NextResponse } from 'next/server';
import { login } from '@/util/auth';


export async function GET(req: NextRequest) {
const params = req.nextUrl.searchParams;

const token = params.get('token');
if (!token)
return NextResponse.redirect(new URL('/login', req.url));

const res = await login(token);
if ('error' in res)
return NextResponse.redirect(new URL(`/login?error=${res.error}`, req.url));

return NextResponse.redirect(new URL('/profile', req.url));
}
20 changes: 7 additions & 13 deletions app/login/LoginContent.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client'

import { useLayoutEffect, useState } from 'react';
import { useRouter, useSearchParams } from 'next/navigation';
import { useState } from 'react';
import { useRouter } from 'next/navigation';
import Link from 'next/link';
import { login } from '@/util/auth';

Expand All @@ -12,20 +12,14 @@ import IconInput from '@/components/IconInput';
import { FaAddressCard } from 'react-icons/fa6';


export default function LoginContent() {
type LoginContentProps = {
error?: string
}
export default function LoginContent(props: LoginContentProps) {
const [teamToken, setTeamToken] = useState('');
const [error, setError] = useState('');
const [error, setError] = useState(props.error ?? '');

const router = useRouter();
const params = useSearchParams();

// Automatically sign in if the `token` URL search parameter is set.
useLayoutEffect(() => {
const token = params.get('token');
if (!token) return;

void loginCallback(token);
}, [params.get('token')]);

async function loginCallback(teamToken: string) {
const res = await login(teamToken);
Expand Down
13 changes: 11 additions & 2 deletions app/login/page.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
import type { Metadata } from 'next';
import { redirect } from 'next/navigation';

// Components
import LoginContent from '@/app/login/LoginContent';


export const metadata: Metadata = {
title: 'Log in'
}

export default function Login() {
export default async function Login({ searchParams }: { searchParams: Promise<{ token?: string, error?: string }> }) {
const token = (await searchParams).token;
const error = (await searchParams).error;

// Automatically sign in if the `token` search parameter is set.
if (token) return redirect(`/login-handler?token=${token}`)

return (
<div className="container pt-32 pb-24">
<h1 className="text-2xl font-bold mb-8 text-center">
Log in to b01lers internal CTF
</h1>

<LoginContent />
<LoginContent error={error} />
</div>
)
}
8 changes: 4 additions & 4 deletions app/profile/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ import Profile from '@/app/profile/Profile';
import { getProfile } from '@/util/profile';


export async function generateMetadata({ params }: { params: { id: string } }): Promise<Metadata> {
const data = await getProfile(params.id);
export async function generateMetadata({ params }: { params: Promise<{ id: string }> }): Promise<Metadata> {
const data = await getProfile((await params).id);
if (data.kind === 'badUnknownUser') return notFound();

return {
title: data.data.name
}
}

export default async function ProfilePage({ params }: { params: { id: string } }) {
const data = await getProfile(params.id);
export default async function ProfilePage({ params }: { params: Promise<{ id: string }> }) {
const data = await getProfile((await params).id);
if (data.kind === 'badUnknownUser') return notFound();

return (
Expand Down
7 changes: 4 additions & 3 deletions app/verify/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ export const metadata: Metadata = {
title: 'Verify'
}

export default async function Verify({ searchParams }: { searchParams: { token: string } }) {
if (!searchParams.token)
export default async function Verify({ searchParams }: { searchParams: Promise<{ token: string }> }) {
const token = (await searchParams).token;
if (!token)
return redirect('/register');

const res = await verify(searchParams.token);
const res = await verify(token);
if (res.kind === 'goodEmailSet')
return redirect('/profile');
if (res.kind !== 'goodRegister' && res.kind !== 'goodVerify')
Expand Down
54 changes: 22 additions & 32 deletions components/CenteredModal.tsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,34 @@
import { Fragment, ReactNode } from 'react';
import { Dialog, Transition } from '@headlessui/react';
import type { ReactNode } from 'react';
import { Dialog, DialogBackdrop, DialogPanel } from '@headlessui/react';


// A reusable component to wrap a transition and dialog overlay around a screen-centered div.
type CenteredModalProps = {
isOpen: boolean, setIsOpen: (isOpen: boolean) => void,
className: string, children: ReactNode
isOpen: boolean,
setIsOpen: (isOpen: boolean) => void,
className: string,
children: ReactNode
}
export default function CenteredModal(props: CenteredModalProps) {
const { isOpen, setIsOpen, className, children } = props;

return (
<Transition show={isOpen} as={Fragment}>
<Dialog onClose={() => setIsOpen(false)} className="fixed z-40 inset-0 flex items-center justify-center">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-black/40" />
</Transition.Child>
<Dialog
className="fixed z-40 inset-0 flex items-center justify-center"
open={isOpen}
onClose={() => setIsOpen(false)}
>
<DialogBackdrop
transition
className="fixed inset-0 bg-black/40 transition duration-300 data-[closed]:duration-200 ease-out data-[closed]:ease-in data-[closed]:opacity-0"
/>

<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 scale-95"
enterTo="opacity-100 scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
<Dialog.Panel className={className}>
{children}
</Dialog.Panel>
</Transition.Child>
</Dialog>
</Transition>
<DialogPanel
transition
className={className + ' transition duration-300 data-[closed]:duration-200 ease-out data-[closed]:ease-in data-[closed]:scale-95 data-[closed]:opacity-0'}
>
{children}
</DialogPanel>
</Dialog>
)
}
Loading

0 comments on commit d55c55a

Please sign in to comment.