diff --git a/src/app/create-account/page.tsx b/src/app/create-account/page.tsx
index a254c850b..a71f1295a 100644
--- a/src/app/create-account/page.tsx
+++ b/src/app/create-account/page.tsx
@@ -180,7 +180,7 @@ export default function CreateAccount() {
setStep("enterCode")
window.scrollTo({
top: 0,
- behavior: "smooth", // smooth scrolling
+ behavior: "smooth",
})
} catch (error) {
console.error("Error sending OTP", error)
@@ -194,7 +194,10 @@ export default function CreateAccount() {
const onSubmit = async (values: FormSchema) => {
if (!isLoaded) return
-
+ window.scrollTo({
+ top: 0,
+ behavior: "smooth",
+ })
setStep("verifying")
if (process.env.NEXT_PUBLIC_VERCEL_ENV === "production") track("created-account")
diff --git a/src/app/join/page.tsx b/src/app/join/page.tsx
index 28c79e0cb..2e41c2bc1 100644
--- a/src/app/join/page.tsx
+++ b/src/app/join/page.tsx
@@ -146,7 +146,7 @@ export default function Join() {
toast({
variant: "destructive",
title: "Google sign-in failed",
- description: `${error}`,
+ description: `${(error as { message?: string })?.message ?? ""}`,
})
}
}
diff --git a/src/middleware.ts b/src/middleware.ts
index 232207090..e65162f75 100644
--- a/src/middleware.ts
+++ b/src/middleware.ts
@@ -1,5 +1,4 @@
import { clerkMiddleware, createRouteMatcher } from "@clerk/nextjs/server"
-import { el } from "date-fns/locale"
import { eq } from "drizzle-orm"
import { db } from "./server/db"
diff --git a/src/server/api/routers/users/create.ts b/src/server/api/routers/users/create.ts
index ba69b3538..7ac2b5d33 100644
--- a/src/server/api/routers/users/create.ts
+++ b/src/server/api/routers/users/create.ts
@@ -52,82 +52,49 @@ export const create = publicRatedProcedure(Ratelimit.fixedWindow(4, "30s"))
}),
)
.mutation(async ({ ctx, input }) => {
- let createdSquareCustomerId: string | null = null
- let createdClerkUserId: string | null = null
+ // TODO: wrap in a transaction
+ const { result, statusCode } = await squareClient.customersApi.createCustomer({
+ idempotencyKey: randomUUID(),
+ givenName: input.preferred_name,
+ familyName: input.name,
+ emailAddress: input.email,
+ // TODO: convert to user ID (UUIDv7)
+ referenceId: input.clerk_id,
+ })
- try {
- const { result, statusCode } = await squareClient.customersApi.createCustomer({
- idempotencyKey: randomUUID(),
- givenName: input.preferred_name,
- familyName: input.name,
- emailAddress: input.email,
- // TODO: convert to user ID (UUIDv7)
- referenceId: input.clerk_id,
+ if (!result.customer?.id) {
+ throw new TRPCError({
+ code: "INTERNAL_SERVER_ERROR",
+ message: `Failed to create square customer ${statusCode}`,
+ cause: JSON.stringify(result),
})
+ }
- if (!result.customer?.id) {
- throw new TRPCError({
- code: "INTERNAL_SERVER_ERROR",
- message: `Failed to create square customer ${statusCode}`,
- cause: JSON.stringify(result),
- })
- }
- createdSquareCustomerId = result.customer.id
- const clerkUser = await clerkClient().users.getUser(input.clerk_id)
-
- if (!clerkUser) {
- throw new TRPCError({
- code: "NOT_FOUND",
- message: `Clerk user with id: ${input.clerk_id} does not exist`,
- })
- }
- createdClerkUserId = clerkUser.id
+ const clerkUser = await clerkClient().users.getUser(input.clerk_id)
- const [user] = await ctx.db
- .insert(User)
- .values({
- clerk_id: input.clerk_id,
- name: input.name,
- preferred_name: input.preferred_name,
- email: input.email,
- pronouns: input.pronouns,
- student_number: input.student_number,
- university: input.uni,
- github: input.github,
- discord: input.discord,
- subscribe: input.subscribe ?? true,
- square_customer_id: result.customer.id,
- })
- .returning()
- return user
- } catch (err: unknown) {
- if (createdSquareCustomerId) {
- try {
- await squareClient.customersApi.deleteCustomer(createdSquareCustomerId)
- } catch (cleanupErr) {
- console.error("Failed to cleanup Square customer", cleanupErr)
- }
- }
- if (createdClerkUserId) {
- try {
- await clerkClient().users.deleteUser(createdClerkUserId)
- } catch (cleanupErr) {
- console.error("Failed to cleanup Clerk user", cleanupErr)
- }
- }
- let message = "Unknown error"
- if (err instanceof TRPCError) {
- message = err.message
- } else if (err instanceof Error) {
- message = err.message
- } else if (typeof err === "string") {
- message = err
- } else {
- message = JSON.stringify(err)
- }
+ if (!clerkUser) {
throw new TRPCError({
- code: "INTERNAL_SERVER_ERROR",
- message: `Failed to register user: ${message}`,
+ code: "NOT_FOUND",
+ message: `Clerk user with id: ${input.clerk_id} does not exist`,
})
}
+
+ const [user] = await ctx.db
+ .insert(User)
+ .values({
+ clerk_id: input.clerk_id,
+ name: input.name,
+ preferred_name: input.preferred_name,
+ email: input.email,
+ pronouns: input.pronouns,
+ student_number: input.student_number,
+ university: input.uni,
+ github: input.github,
+ discord: input.discord,
+ subscribe: input.subscribe ?? true,
+ square_customer_id: result.customer.id,
+ })
+ .returning()
+
+ return user
})
From 3c954d71269833a8322e5d736edbc7a6d61d1299 Mon Sep 17 00:00:00 2001
From: ErikaKK <491649804@qq.com>
Date: Thu, 4 Sep 2025 21:14:14 +0800
Subject: [PATCH 09/12] edit calling useForm
---
.../create-account/complete-profile/page.tsx | 39 ++++++++++++-------
1 file changed, 26 insertions(+), 13 deletions(-)
diff --git a/src/app/create-account/complete-profile/page.tsx b/src/app/create-account/complete-profile/page.tsx
index bc820177d..7fccd3d1f 100644
--- a/src/app/create-account/complete-profile/page.tsx
+++ b/src/app/create-account/complete-profile/page.tsx
@@ -4,8 +4,8 @@ import { useUser } from "@clerk/nextjs"
import { zodResolver } from "@hookform/resolvers/zod"
import { track } from "@vercel/analytics/react"
import Link from "next/link"
-import { useRouter, useSearchParams } from "next/navigation"
-import * as React from "react"
+import { useRouter } from "next/navigation"
+import { useEffect, useState } from "react"
import { useForm } from "react-hook-form"
import { siDiscord } from "simple-icons"
import * as z from "zod"
@@ -86,26 +86,39 @@ const defaultValues = {
}
export default function CompleteProfile() {
- const [activeView, setActiveView] = React.useState
("form")
- const [loadingSkipPayment, setLoadingSkipPayment] = React.useState(false)
- const [user, setUser] = React.useState()
+ const [activeView, setActiveView] = useState("form")
+ const [loadingSkipPayment, setLoadingSkipPayment] = useState(false)
+ const [user, setUser] = useState()
const router = useRouter()
const { isLoaded, user: clerkUser } = useUser()
- const [step, setStep] = React.useState<"submitForm" | "verifying">("submitForm")
- if (!isLoaded) return null
-
- const clerk_id = clerkUser?.id
- const email = clerkUser?.primaryEmailAddress?.emailAddress ?? ""
- const name = clerkUser?.firstName ? `${clerkUser.firstName} ${clerkUser.lastName ?? ""}`.trim() : ""
+ const [step, setStep] = useState<"submitForm" | "verifying">("submitForm")
const form = useForm({
resolver: zodResolver(formSchema),
defaultValues: {
...defaultValues,
- email: email,
- name: name,
},
})
+ useEffect(() => {
+ async function updateForm() {
+ if (!clerkUser) return null
+ const email = clerkUser?.primaryEmailAddress?.emailAddress ?? ""
+ const name = clerkUser?.firstName ? `${clerkUser.firstName} ${clerkUser.lastName ?? ""}`.trim() : ""
+ const user = await Promise.resolve({
+ ...defaultValues,
+ name: name,
+ email: email,
+ })
+
+ form.reset(user)
+ }
+
+ updateForm()
+ }, [clerkUser])
+ if (!isLoaded) return null
+
+ const clerk_id = clerkUser?.id
+
const { getValues, setError } = form
const utils = api.useUtils()
From 99317b999d455e6015469e6bc58f7f204f0de410 Mon Sep 17 00:00:00 2001
From: ErikaKK <491649804@qq.com>
Date: Thu, 4 Sep 2025 21:42:32 +0800
Subject: [PATCH 10/12] fix useEffect
---
src/app/create-account/complete-profile/page.tsx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/app/create-account/complete-profile/page.tsx b/src/app/create-account/complete-profile/page.tsx
index 7fccd3d1f..a30436dd9 100644
--- a/src/app/create-account/complete-profile/page.tsx
+++ b/src/app/create-account/complete-profile/page.tsx
@@ -100,7 +100,7 @@ export default function CompleteProfile() {
},
})
useEffect(() => {
- async function updateForm() {
+ const updateForm = async () => {
if (!clerkUser) return null
const email = clerkUser?.primaryEmailAddress?.emailAddress ?? ""
const name = clerkUser?.firstName ? `${clerkUser.firstName} ${clerkUser.lastName ?? ""}`.trim() : ""
@@ -113,7 +113,7 @@ export default function CompleteProfile() {
form.reset(user)
}
- updateForm()
+ updateForm().catch(console.error)
}, [clerkUser])
if (!isLoaded) return null
From 00d00a3ae9ca1f92a00c863188b4a92c501372d3 Mon Sep 17 00:00:00 2001
From: ErikaKK <491649804@qq.com>
Date: Sat, 13 Sep 2025 00:23:40 +0800
Subject: [PATCH 11/12] add fetching updated logged-in user
---
src/app/create-account/complete-profile/page.tsx | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/app/create-account/complete-profile/page.tsx b/src/app/create-account/complete-profile/page.tsx
index a30436dd9..dde7006a5 100644
--- a/src/app/create-account/complete-profile/page.tsx
+++ b/src/app/create-account/complete-profile/page.tsx
@@ -223,6 +223,7 @@ export default function CompleteProfile() {
user.role = "member"
utils.users.getCurrent.setData(undefined, user)
+ utils.users.getCurrent.invalidate()
router.push("/dashboard")
}
@@ -231,6 +232,7 @@ export default function CompleteProfile() {
setLoadingSkipPayment(true)
try {
utils.users.getCurrent.setData(undefined, user)
+ utils.users.getCurrent.invalidate()
router.push("/dashboard")
} catch (error) {
console.error(error)
From 0d2df553a817fa49caa9acdeef16fcedac7d2b69 Mon Sep 17 00:00:00 2001
From: ErikaKK <491649804@qq.com>
Date: Sat, 13 Sep 2025 00:42:36 +0800
Subject: [PATCH 12/12] fix error
---
.../create-account/complete-profile/page.tsx | 22 +++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)
diff --git a/src/app/create-account/complete-profile/page.tsx b/src/app/create-account/complete-profile/page.tsx
index dde7006a5..ea99a150f 100644
--- a/src/app/create-account/complete-profile/page.tsx
+++ b/src/app/create-account/complete-profile/page.tsx
@@ -222,9 +222,18 @@ export default function CompleteProfile() {
}
user.role = "member"
- utils.users.getCurrent.setData(undefined, user)
- utils.users.getCurrent.invalidate()
- router.push("/dashboard")
+ try {
+ utils.users.getCurrent.setData(undefined, user)
+ await utils.users.getCurrent.invalidate()
+ router.push("/dashboard")
+ } catch (error) {
+ console.error(error)
+ toast({
+ variant: "destructive",
+ title: "Unable to update user",
+ description: `We were unable to update the user. ${(error as { message?: string })?.message ?? ""}`,
+ })
+ }
}
const handleSkipPayment = async () => {
@@ -232,10 +241,15 @@ export default function CompleteProfile() {
setLoadingSkipPayment(true)
try {
utils.users.getCurrent.setData(undefined, user)
- utils.users.getCurrent.invalidate()
+ await utils.users.getCurrent.invalidate()
router.push("/dashboard")
} catch (error) {
console.error(error)
+ toast({
+ variant: "destructive",
+ title: "Unable to skip payment",
+ description: `Error occurred when trying to skip payment.${(error as { message?: string })?.message ?? ""}`,
+ })
} finally {
setLoadingSkipPayment(false)
}