Skip to content

Commit 32245f6

Browse files
committed
feat: add workshop registration
1 parent 4908da7 commit 32245f6

File tree

6 files changed

+84
-54
lines changed

6 files changed

+84
-54
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"use client"
2+
3+
import { useFormStatus } from "react-dom"
4+
5+
import { Button } from "@/components/ui/button"
6+
import { Icons } from "@/components/icons"
7+
8+
export function RegisterButton() {
9+
const { pending } = useFormStatus()
10+
return (
11+
<Button type="submit" size="sm">
12+
{pending && (
13+
<Icons.spinner
14+
className="mr-2 size-4 animate-spin"
15+
aria-hidden="true"
16+
/>
17+
)}
18+
Register
19+
</Button>
20+
)
21+
}

src/app/(app)/workshop/[workshopId]/page.tsx

+12-10
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { env } from "@/env"
55
import { eq } from "drizzle-orm"
66

77
import { redirects } from "@/config/constants"
8+
import { registerUserAndNotifyAction } from "@/server/actions/registration"
89
import { getUserSession } from "@/server/data/user"
910
import { getWorkshop } from "@/server/data/workshop"
1011
import { db } from "@/server/db"
@@ -19,6 +20,7 @@ import { Shell } from "@/components/shell"
1920

2021
import { OrganizerSection } from "./_components/organizer-section"
2122
import { OrganizerSectionSkeleton } from "./_components/organizer-section-skeleton"
23+
import { RegisterButton } from "./_components/register-button"
2224
import { WorkshopSettings } from "./_components/workshop-settings"
2325

2426
interface WorkshopPageProps {
@@ -68,6 +70,12 @@ export default async function WorkshopPage({ params }: WorkshopPageProps) {
6870

6971
const isCurrentUserWorkshop = workshop.organizerId === user.id
7072

73+
const registerUserAndNotify = registerUserAndNotifyAction.bind(null, {
74+
workshopId: workshop.id,
75+
workshopTitle: workshop.title,
76+
participantId: user.id,
77+
})
78+
7179
return (
7280
<Shell className="max-w-xl gap-4">
7381
<div className="flex w-full flex-col items-start space-y-1">
@@ -122,16 +130,10 @@ export default async function WorkshopPage({ params }: WorkshopPageProps) {
122130
</React.Suspense>
123131

124132
<div className="flex w-full justify-end">
125-
{!isCurrentUserWorkshop ? (
126-
<Button size="sm">
127-
{/* {isPending && (
128-
<Icons.spinner
129-
className="mr-2 size-4 animate-spin"
130-
aria-hidden="true"
131-
/>
132-
)} */}
133-
Register
134-
</Button>
133+
{isCurrentUserWorkshop ? (
134+
<form action={registerUserAndNotify}>
135+
<RegisterButton />
136+
</form>
135137
) : (
136138
<Button size="sm">Start</Button>
137139
)}

src/app/api/email/new-participant/route.ts

-39
This file was deleted.

src/server/actions/registration.ts

+48-3
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,62 @@
11
"use server"
22

33
import { revalidateTag } from "next/cache"
4+
import { env } from "@/env"
45
import { and, eq } from "drizzle-orm"
56

6-
import { getErrorMessage } from "@/utils/handle-error"
7+
import { resend } from "@/lib/resend"
8+
import { getErrorMessage, showErrorToast } from "@/utils/handle-error"
9+
import NewParticipantEmail from "@/components/emails/new-participant-email"
710

11+
import { getWorkshopOrganizer } from "../data/workshop"
812
import { db } from "../db"
913
import { registrations } from "../db/schema"
1014

11-
export async function addParticipantAction(input: {
15+
interface RegisterUserProps {
1216
workshopId: string
1317
participantId: string
14-
}) {
18+
}
19+
20+
export async function registerUserAndNotifyAction(
21+
input: RegisterUserProps & {
22+
workshopTitle: string
23+
}
24+
) {
25+
const { error } = await registerUserAction({
26+
workshopId: input.workshopId,
27+
participantId: input.participantId,
28+
})
29+
30+
if (!error) {
31+
showErrorToast(error)
32+
}
33+
34+
try {
35+
const organizer = await getWorkshopOrganizer(input.workshopId)
36+
37+
if (!organizer) {
38+
throw new Error("Workshop must have an organizer")
39+
}
40+
41+
const { error } = await resend.emails.send({
42+
from: env.EMAIL_FROM_ADDRESS,
43+
to: ["raphicogit@gmail.com"],
44+
subject: "New Registration for your workshop",
45+
react: NewParticipantEmail({
46+
WorkshopTitle: input.workshopTitle,
47+
organizerUsername: organizer.username,
48+
}),
49+
})
50+
51+
if (error) {
52+
console.error(getErrorMessage(error))
53+
}
54+
} catch (err) {
55+
console.error(getErrorMessage(err))
56+
}
57+
}
58+
59+
export async function registerUserAction(input: RegisterUserProps) {
1560
try {
1661
const checkUserRegistered = await db.query.registrations.findFirst({
1762
where: and(

src/server/actions/workshop.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ export async function updateWorkshopAction(
7272
}
7373
}
7474

75-
export async function deleteWorkshopAction(id: string) {
75+
export async function deleteWorkshopAction(workshopId: string) {
7676
try {
7777
const { user } = await getUserSession()
7878

@@ -82,7 +82,7 @@ export async function deleteWorkshopAction(id: string) {
8282

8383
await db
8484
.delete(workshops)
85-
.where(and(eq(workshops.organizerId, user.id), eq(workshops.id, id)))
85+
.where(and(eq(workshops.organizerId, user.id), eq(workshops.id, workshopId)))
8686

8787
revalidateTag(`workshops-${user.id}`)
8888

src/server/data/workshop.ts

+1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ export async function getWorkshopOrganizer(organizerId: string) {
9191
return await db.query.users.findFirst({
9292
columns: {
9393
id: true,
94+
email: true,
9495
username: true,
9596
image: true,
9697
},

0 commit comments

Comments
 (0)