Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into feat/25/allow-admin-t…
Browse files Browse the repository at this point in the history
…o-personalize-logo-and-name

# Conflicts:
#	package.json
  • Loading branch information
LobeTia committed Oct 4, 2024
2 parents f88c7d5 + 836d1a5 commit 2cf8331
Show file tree
Hide file tree
Showing 10 changed files with 204 additions and 197 deletions.
4 changes: 0 additions & 4 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@ NEXTAUTH_SECRET="secret"
STRIPE_PUBLISHABLE_KEY=
STRIPE_PRIVATE_KEY=

# Next Auth Discord Provider
DISCORD_CLIENT_ID=
DISCORD_CLIENT_SECRET=

# Email sending
EMAIL_SERVER_USER=
EMAIL_SERVER_PASSWORD=
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"db:migrate": "prisma migrate dev --create-only",
"db:push": "prisma db push",
"db:studio": "prisma studio",
"db:seed": "prisma seed",

"dev:email": "npx dotenv-run-script dev:email-noenv",
"dev:email-noenv": "email dev --dir src/emails",
Expand Down
17 changes: 16 additions & 1 deletion src/app/actions/validateUserEmail.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
"use server"

import { MembershipStatus } from "@prisma/client"

import { db } from "@/services/db"

import { Target } from "@/app/shared/login/types"

export interface ServerActionState {
checked: boolean
valid: boolean
email?: string
}

interface FormProps {
email: string
target: string
}

export async function validateUserEmail(
prevState: ServerActionState,
data: FormProps,
) {
console.log(data)

const user = await db.user.findUnique({
where: {
email: data.email,
Expand All @@ -29,6 +35,15 @@ export async function validateUserEmail(
valid: false,
}

// No need for further checks if the target is the admin portal
if (data.target === (Target.AdminPortal as string)) {
return {
checked: true,
email: data.email,
valid: true,
}
}

// User without membership means that is not valid
const membership = await db.membership.findFirst({
where: {
Expand Down
18 changes: 0 additions & 18 deletions src/app/admin/@unauthenticated/components/discordSignIn.tsx

This file was deleted.

33 changes: 14 additions & 19 deletions src/app/admin/@unauthenticated/page.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,19 @@
import { DiscordSignIn } from "@/app/admin/@unauthenticated/components/discordSignIn"
import {
Card,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card"
"use client"

import { LoginForm } from "@/app/shared/login/form"
import { Target } from "@/app/shared/login/types"

export default function AdminLogin() {
return (
<Card className="max-w-sm">
<CardHeader>
<CardTitle className="text-2xl">Login</CardTitle>
<CardDescription>
You need to login in order to access the admin
</CardDescription>
</CardHeader>
<CardFooter className={"flex justify-center"}>
<DiscordSignIn />
</CardFooter>
</Card>
<main className="flex h-screen items-center justify-center bg-zinc-900">
<div>
<LoginForm
target={Target.AdminPortal}
description={
"Enter your email below, we're going to send you a magic link"
}
/>
</div>
</main>
)
}
150 changes: 8 additions & 142 deletions src/app/members/@unauthenticated/page.tsx
Original file line number Diff line number Diff line change
@@ -1,152 +1,18 @@
"use client"

import { zodResolver } from "@hookform/resolvers/zod"
import { ExclamationTriangleIcon } from "@radix-ui/react-icons"
import Link from "next/link"
import { signIn } from "next-auth/react"
import { useEffect, useState } from "react"
import { useFormState } from "react-dom"
import { useForm } from "react-hook-form"
import { z } from "zod"

import { validateUserEmail } from "@/app/actions/validateUserEmail"
import { StatefulButton } from "@/components/molecules/statefulButton"
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card"
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form"
import { Input } from "@/components/ui/input"

const formSchema = z.object({
email: z.string().email(),
})
import { LoginForm } from "@/app/shared/login/form"
import { Target } from "@/app/shared/login/types"

export default function MembershipPortalLoginPage() {
const form = useForm<z.infer<typeof formSchema>>({
defaultValues: {
email: "",
},
resolver: zodResolver(formSchema),
})
const [working, setWorking] = useState<boolean>(false)
const [requestedMagicLink, setRequestedMagicLink] = useState<boolean>(false)
const [validateUserEmailState, validateUserEmailAction] = useFormState(
validateUserEmail,
{
checked: false,
valid: false,
},
)

useEffect(() => {
const handler = async () => {
if (!requestedMagicLink && validateUserEmailState.valid) {
setWorking(true)
const reply = await signIn("email", {
email: validateUserEmailState.email,
redirect: false,
})
console.log(reply)
setRequestedMagicLink(true)
setWorking(false)
}
}

void handler()
}, [requestedMagicLink, validateUserEmailState])

return (
<main className="flex h-screen items-center justify-center bg-zinc-900">
<div>
<form action={form.handleSubmit(validateUserEmailAction) as any}>
<Form {...form}>
<Card className="max-w-sm">
<CardHeader>
<CardTitle className="text-2xl">Login</CardTitle>
<CardDescription>
Enter your email below, we're going to send you a magic link
</CardDescription>
</CardHeader>
<CardContent className="grid gap-4">
{validateUserEmailState.checked &&
!validateUserEmailState.valid && (
<Alert variant="destructive">
<ExclamationTriangleIcon className="h-4 w-4" />
<AlertTitle>Error</AlertTitle>
<AlertDescription>
This email doesn't have an account.
<br />
You can create one by{" "}
<Link href={"/signup"} className={"underline"}>
requesting a membership
</Link>
</AlertDescription>
</Alert>
)}

{requestedMagicLink && (
<Alert variant="positive">
<ExclamationTriangleIcon className="h-4 w-4" />
<AlertTitle>Success</AlertTitle>
<AlertDescription>
We've sent you a "magic link" via email.
<br />
Please check your inbox (or spam folder) and click on the
link to proceed.
</AlertDescription>
</Alert>
)}

{!requestedMagicLink && (
<>
<div className="grid">
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl>
<Input
type={"email"}
placeholder="[email protected]"
// The following two attributes disables password manager on this input
autoComplete={"new-password"}
id={"search-address"}
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>

<StatefulButton
className="w-full"
type="submit"
loading={working}
>
Sign in
</StatefulButton>
</>
)}
</CardContent>
</Card>
</Form>
</form>
<LoginForm
target={Target.MembershipPortal}
description={
"Enter your email below, we're going to send you a magic link"
}
/>
</div>
</main>
)
Expand Down
Loading

0 comments on commit 2cf8331

Please sign in to comment.