Skip to content

Commit

Permalink
🌱 Reseeded next-leaflet
Browse files Browse the repository at this point in the history
  • Loading branch information
ThijmenGThN committed Dec 6, 2023
1 parent c69742f commit 80942a9
Show file tree
Hide file tree
Showing 86 changed files with 2,332 additions and 1,509 deletions.
11 changes: 8 additions & 3 deletions src/components/auth/OAuth.tsx → .disabled/(auth)/OAuth.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
"use client"

import { useEffect, useState } from "react"
import { useTranslations } from "next-intl"
import { signIn, getProviders } from "next-auth/react"

const callbackUrl = '/dashboard'

export default function Component() {
const t = useTranslations()

const [providers, setProviders] = useState<Array<any>>([])

useEffect(() => { getProviders().then(({ credentials, ...OAuth }: any) => setProviders(Object.values(OAuth))) }, [])
useEffect(() => { getProviders().then(({ credentials, ...OAuth }: any) => setProviders(Object.values(OAuth))) }, [])

return providers.length > 0 && (
<>
Expand All @@ -18,7 +21,7 @@ export default function Component() {
</div>
<div className="relative flex justify-center text-sm font-medium leading-6">
<span className="bg-white px-6 text-gray-900">
Or continue with
{t('auth.or-continue-with')}
</span>
</div>
</div>
Expand All @@ -30,7 +33,9 @@ export default function Component() {
<button className="flex w-full items-center justify-center gap-3 rounded-md bg-black hover:bg-zinc-900 px-3 py-1.5 text-white"
onClick={() => signIn(provider.id, { callbackUrl })}
>
<span className="text-sm font-semibold leading-6">{provider.name}</span>
<span className="text-sm font-semibold leading-6">
{provider.name}
</span>
</button>
</li>
)
Expand Down
93 changes: 93 additions & 0 deletions .disabled/(auth)/forgot/[token]/Reset.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
"use client"

import { z } from 'zod'
import Link from 'next/link'
import Image from 'next/image'
import jwt from 'jsonwebtoken'
import { signIn } from "next-auth/react"
import { useTranslations } from 'next-intl'

import gravatar from '@/helpers/gravatar'

import Form from '@/components/Form'

import aLogo from '@/assets/logo.webp'

const callbackUrl = '/dashboard'

export default function Component({ token, email }: { token: string, email: string }) {
const t = useTranslations('auth')

const onSubmit = async ({ password }: any) => {
const { ok, status } = await fetch('/api/auth/forgot/update', { method: 'POST', body: JSON.stringify({ token, password }) })

if (status == 401) return new Error(t('password-reset-has-expired'))
if (!ok) return new Error(t('sorry-something-unexpected-happened'))

signIn('credentials', { email, password, callbackUrl })
}

return (
<div className="flex min-h-full flex-1 flex-col justify-center py-12 sm:px-6 lg:px-8">
<div className="sm:mx-auto sm:w-full sm:max-w-md">
<Link href="/">
<Image
className="mx-auto h-10 w-auto"
src={aLogo}
alt=""
/>
</Link>
<h2 className="mt-6 text-center text-2xl font-bold leading-9 tracking-tight text-gray-900">
{t('update-your-password')}
</h2>
</div>

<div className="relative my-10 sm:mx-auto sm:w-full sm:max-w-[480px]">
<div className="bg-white px-6 py-12 shadow sm:rounded-lg sm:px-12 flex flex-col gap-y-4">
<div className="flex flex-col items-center justify-center gap-y-4">
<Image
className="h-16 w-16 rounded-full bg-gray-50 border"
src={gravatar(email)}
width={80}
height={80}
alt=""
/>
<p className="text-sm font-medium text-gray-900">
{email}
</p>
</div>

<div className="mt-8">
<Form
onSubmit={onSubmit}
validator={
z.object({
password: z.string()
.min(8, { message: t('this-password-is-too-short') })
.max(64, { message: t('this-password-is-too-long') }),
repeatPassword: z.string()
.min(8, { message: t('this-password-is-too-short') })
.max(64, { message: t('this-password-is-too-long') })
}).refine(({ password, repeatPassword }) => password == repeatPassword, { message: t('the-passwords-do-not-match'), path: ['repeatPassword'] })
}
submit={{ label: t('confirm'), position: 'full' }}
fields={[
{ id: 'password', type: 'password', label: t('password') },
{ id: 'repeatPassword', type: 'password', label: t('repeat-password') }
]}
options={[
'showPassword'
]}
/>
</div>
</div>

<div className="absolute -bottom-10 left-5 text-center text-sm text-gray-500">
<Link href="/login">
{t('sign-in-to-a-different-account')}
</Link>
</div>
</div>
</div>
)
}
51 changes: 51 additions & 0 deletions .disabled/(auth)/forgot/[token]/error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"use client"

import Link from 'next/link'
import Image from 'next/image'
import { useTranslations } from 'next-intl'

import aLogo from '@/assets/logo.webp'

export default function Error() {
const t = useTranslations('auth')

return (
<div className="flex min-h-full flex-1 flex-col justify-center py-12 sm:px-6 lg:px-8">
<div className="sm:mx-auto sm:w-full sm:max-w-md">
<Link href="/">
<Image
className="mx-auto h-10 w-auto"
src={aLogo}
alt=""
/>
</Link>
<h2 className="mt-6 text-center text-2xl font-bold leading-9 tracking-tight text-gray-900">
{t('password-reset-has-expired')}
</h2>
</div>

<div className="relative my-10 sm:mx-auto sm:w-full sm:max-w-[480px]">
<div className="bg-white px-6 py-12 shadow sm:rounded-lg sm:px-12 flex flex-col gap-y-4">

<p className="text-sm text-center font-medium text-gray-900">
{t('the-password-reset-has-reached-its-expiration-date')}
</p>

<Link href="/forgot" className="mt-5 flex w-full gap-x-2 items-center justify-center rounded-md bg-primary px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-primary-600 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary">
{t('reset-your-password-again')}
</Link>

<Link href='/register' className="flex items-center justify-center w-full rounded-md bg-white px-3.5 py-2.5 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50">
{t('sign-up-for-a-new-account')}
</Link>
</div>

<div className="absolute -bottom-10 left-5 text-center text-sm text-gray-500">
<Link href="/login">
{t('sign-in-to-a-different-account')}
</Link>
</div>
</div>
</div>
)
}
23 changes: 23 additions & 0 deletions .disabled/(auth)/forgot/[token]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import jwt from 'jsonwebtoken'

import prisma from '@/prisma/client'

import Reset from './Reset'

export default async function Page({ params: { token } }: { params: { token: string } }) {

if (!process.env.NEXTAUTH_SECRET) throw new Error('Internal server error, please try again later.')

let { email }: any = jwt.decode(token)

jwt.verify(token, process.env.NEXTAUTH_SECRET)

const { passwordResetToken }: any = await prisma.user.findUnique({ where: { email } })

if (token != passwordResetToken) throw new Error('The password reset has reached its expiration date.')

return <Reset
token={token}
email={email}
/>
}
92 changes: 92 additions & 0 deletions .disabled/(auth)/forgot/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
"use client"

import { z } from "zod"
import Link from "next/link"
import Image from 'next/image'
import { useState } from "react"
import { useTranslations } from "next-intl"

import gravatar from "@/helpers/gravatar"

import Form from "@/components/Form"

import aLogo from '@/assets/logo.webp'

export default function Page() {
const t = useTranslations('auth')

const [formEmail, setFormEmail] = useState<string>()
const [hasBeenSent, setHasBeenSent] = useState<boolean>(false)

const onSubmit = async ({ email }: any) => {
const { ok, status } = await fetch('/api/auth/forgot', { method: 'POST', body: JSON.stringify({ email }) })

if (status == 406) return new Error(t('an-account-with-this-email-address-does-not-exists'))
if (!ok) return new Error(t('sorry-something-unexpected-happened'))

setFormEmail(email)
setHasBeenSent(true)
}

return (
<div className="flex min-h-full flex-1 flex-col justify-center py-12 sm:px-6 lg:px-8">
<div className="sm:mx-auto sm:w-full sm:max-w-md">
<Link href="/">
<Image
className="mx-auto h-10 w-auto"
src={aLogo}
alt=""
/>
</Link>
<h2 className="mt-6 text-center text-2xl font-bold leading-9 tracking-tight text-gray-900">
{t('reset-your-password')}
</h2>
</div>

<div className="relative my-10 sm:mx-auto sm:w-full sm:max-w-[480px]">
<div className="bg-white px-6 py-12 shadow sm:rounded-lg sm:px-12">
{
hasBeenSent
? <div className="flex flex-col items-center justify-center gap-y-4">
<Image
className="h-16 w-16 rounded-full bg-gray-50 border"
src={gravatar(formEmail ?? '')}
width={80}
height={80}
alt=""
/>
<p className="text-sm font-medium text-gray-900">
{formEmail}
</p>

<p className="text-sm mt-4 text-center font-medium text-gray-900">
{t('we-have-sent-you-an-email-to-reset-your-password')}
</p>
</div>
: <Form
onSubmit={onSubmit}
validator={
z.object({
email: z.string()
.min(2, { message: t('this-email-address-is-too-short') })
.max(64, { message: t('this-email-address-is-too-long') })
.email(t('this-email-address-is-not-valid'))
})
}
submit={{ label: t('continue'), position: 'full' }}
fields={[
{ id: 'email', type: 'email', label: t('email-address') }
]}
/>
}
</div>

<div className="absolute -bottom-10 left-5 text-center text-sm text-gray-500">
<Link href="/login">
{t('sign-in-to-your-account')}
</Link>
</div>
</div>
</div>
)
}
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,38 +1,49 @@
"use client"

import { z } from "zod"
import Link from "next/link"
import { useEffect } from "react"
import { useRouter } from "next/navigation"
import { signIn } from "next-auth/react"

import validate from '@/helpers/validation'
import { useTranslations } from "next-intl"

import Form from '@/components/Form'

const callbackUrl = '/dashboard'

export default function Component() {
const t = useTranslations('auth')
const router = useRouter()

const onSubmit = ({ email, password }: any) => new Promise<void>(async (resolve, throwError) => {
async function onSubmit({ email, password }: { email: string, password: string }) {
const { error }: any = await signIn('credentials', { email, password, redirect: false })
if (error) return throwError("Invalid credentials, try again or reset your password")
if (error) return new Error(t('invalid-credentials-try-again-or-reset-your-password'))

router.refresh()
router.push(callbackUrl)
})
}

// Already load the dashboard to make the signin feel swift.
useEffect(() => { router.prefetch(callbackUrl) }, [router])

return (
<>
<Form
onSubmit={onSubmit}
submit={{ label: "Sign in", position: 'full' }}
validator={validate.forms.login}
submit={{ label: t('sign-in'), position: 'full' }}
validator={
z.object({
email: z.string()
.min(2, { message: t('this-email-address-is-too-short') })
.max(64, { message: t('this-email-address-is-too-long') }).email(t('this-email-address-is-not-valid')),
password: z.string()
.min(8, { message: t('this-password-is-too-short') })
.max(64, { message: t('this-password-is-too-long') })
})
}
fields={[
{ id: 'email', type: 'email', label: 'Email address' },
{ id: 'password', type: 'password', label: 'Password' }
{ id: 'email', type: 'email', label: t('email-address') },
{ id: 'password', type: 'password', label: t('password') }
]}
options={[
'showPassword'
Expand All @@ -42,12 +53,12 @@ export default function Component() {
<div className="flex mt-5 items-center justify-between">
<div className="text-sm leading-6">
<Link href="/forgot" className="font-semibold text-primary hover:text-primary-600">
Forgot password?
{t('forgot-password')}
</Link>
</div>
<div className="text-sm leading-6">
<Link href="/register" className="font-semibold text-primary hover:text-primary-600">
Create an account
{t('create-an-account')}
</Link>
</div>
</div>
Expand Down
Loading

0 comments on commit 80942a9

Please sign in to comment.