diff --git a/src/actions/add-user-info.ts b/src/actions/add-user-info.ts index ed82293..a8141f0 100644 --- a/src/actions/add-user-info.ts +++ b/src/actions/add-user-info.ts @@ -4,10 +4,10 @@ import { eq, InferInsertModel } from "drizzle-orm"; import db from "@/db"; import { userInfo } from "@/db/schema/user-info"; -import { users } from "@/db/schema/users"; // ← add this +import { users } from "@/db/schema/users"; import { auth } from "@/lib/auth"; -type Payload = Omit, "userId">; +type Payload = Omit, "userId"> & { email?: string }; export async function addUserInfo(data: Payload): Promise { const session = await auth(); @@ -16,13 +16,19 @@ export async function addUserInfo(data: Payload): Promise { throw new Error("Unauthorized"); } + // Remving email field + const { email, ...rest } = data; + await db.insert(userInfo).values({ userId: session.user.id, - ...data, + ...rest, }); await db .update(users) - .set({ infoFilled: true }) + .set({ + infoFilled: true, + ...(email ? { email: email.trim() } : {}), + }) .where(eq(users.id, session.user.id)); } diff --git a/src/actions/get-user-info.ts b/src/actions/get-user-info.ts new file mode 100644 index 0000000..f145de8 --- /dev/null +++ b/src/actions/get-user-info.ts @@ -0,0 +1,44 @@ +"use server"; + +import { eq } from "drizzle-orm"; + +import db from "@/db"; +import { userInfo } from "@/db/schema/user-info"; +import { users } from "@/db/schema/users"; +import { auth } from "@/lib/auth"; + +type UserInfoWithEmail = typeof userInfo.$inferSelect & { email: string | null }; + +export default async function getUserInfo(): Promise { + try { + const session = await auth(); + + if (!session?.user?.id) { + throw new Error("Unauthorized"); + } + + const userInfoData = await db + .select() + .from(userInfo) + .where(eq(userInfo.userId, session.user.id)) + .limit(1); + + if (!userInfoData[0]) { + return null; + } + + const userData = await db + .select({ email: users.email }) + .from(users) + .where(eq(users.id, session.user.id)) + .limit(1); + + return { + ...userInfoData[0], + email: userData[0]?.email ?? null, + }; + } catch (error) { + console.error("GET USER INFO ERROR:", error); + throw error; + } +} diff --git a/src/actions/update-user-info.ts b/src/actions/update-user-info.ts new file mode 100644 index 0000000..4181d5a --- /dev/null +++ b/src/actions/update-user-info.ts @@ -0,0 +1,54 @@ +"use server"; + +import { eq, InferInsertModel } from "drizzle-orm"; + +import db from "@/db"; +import { userInfo } from "@/db/schema/user-info"; +import { users } from "@/db/schema/users"; +import { auth } from "@/lib/auth"; + +type UserInfoInsert = InferInsertModel; +type Payload = Partial> & { email?: string }; + +export async function updateUserInfo(data: Payload): Promise { + const session = await auth(); + + if (!session?.user?.id) { + throw new Error("Unauthorized"); + } + + if (!data || Object.keys(data).length === 0) { + console.error("No data to update"); + return; + } + + const { email, ...rest } = data; + + const safeData = { + ...rest, + addressLine2: rest.addressLine2?.trim() || null, + preferredNeighborhood: rest.preferredNeighborhood?.trim() || null, + gender: rest.gender?.trim() || null, + shirtSize: rest.shirtSize?.trim() || null, + medicalNotes: rest.medicalNotes?.trim() || null, + }; + + try { + await db + .update(userInfo) + .set(safeData) + .where(eq(userInfo.userId, session.user.id)); + + if (email) { + await db + .update(users) + .set({ email: email.trim() }) + .where(eq(users.id, session.user.id)); + } + } catch (error: any) { + console.error("UPDATE ERROR:", error); + console.error("ERROR MESSAGE:", error?.message); + console.error("ERROR CAUSE:", error?.cause); + throw error; + } +} diff --git a/src/app/(profile)/account/update-profile/page.tsx b/src/app/(profile)/account/update-profile/page.tsx index ccd06d4..d1e050d 100644 --- a/src/app/(profile)/account/update-profile/page.tsx +++ b/src/app/(profile)/account/update-profile/page.tsx @@ -1,7 +1,13 @@ import { Box, Typography } from "@mui/material"; import React from "react"; -export default function UpdateProfile(): React.ReactElement { +import getUserInfo from "@/actions/get-user-info"; +import BasicInfoForm from "@/app/(profile)/info/page"; + +export default async function UpdateProfile(): Promise { + const userData = await getUserInfo(); + const mode = userData ? "editForm" : "submitForm"; + return ( <> - - Update Profile - + Update Profile - - - Update profile will go here later - + + ); diff --git a/src/app/(profile)/info/page.tsx b/src/app/(profile)/info/page.tsx index dcfb8ee..84c9d7c 100644 --- a/src/app/(profile)/info/page.tsx +++ b/src/app/(profile)/info/page.tsx @@ -17,6 +17,7 @@ import { useSession } from "next-auth/react"; import * as React from "react"; import { addUserInfo } from "@/actions/add-user-info"; +import { updateUserInfo } from "@/actions/update-user-info"; import FormLayout from "@/components/layout/FormLayout/"; type BasicInfoFormState = { @@ -39,26 +40,34 @@ type BasicInfoFormState = { medicalNotes?: string; }; -export default function BasicInfoForm(): React.ReactElement { - const [form, setForm] = React.useState({ - firstName: "", - lastName: "", - addressLine1: "", - addressLine2: "", - city: "", - state: "", - postalCode: "", - country: "", - phoneNumber: "", - isTextOptedIn: false, - birthMonth: "", - birthDay: "", - birthYear: "", - preferredNeighborhood: "", - gender: "", - shirtSize: "", - medicalNotes: "", - }); +type BasicInfoFormProps = { + initialData?: Partial; + mode?: "submitForm" | "editForm"; +}; + +export default function BasicInfoForm({ + initialData, + mode = "submitForm", +}: BasicInfoFormProps): React.ReactElement { + const [form, setForm] = React.useState(() => ({ + firstName: initialData?.firstName ?? "", + lastName: initialData?.lastName ?? "", + addressLine1: initialData?.addressLine1 ?? "", + addressLine2: initialData?.addressLine2 ?? "", + city: initialData?.city ?? "", + state: initialData?.state ?? "", + postalCode: initialData?.postalCode ?? "", + country: initialData?.country ?? "US", + phoneNumber: initialData?.phoneNumber ?? "", + isTextOptedIn: initialData?.isTextOptedIn ?? false, + birthMonth: initialData?.birthMonth?.toString() ?? "", + birthDay: initialData?.birthDay?.toString() ?? "", + birthYear: initialData?.birthYear?.toString() ?? "", + preferredNeighborhood: initialData?.preferredNeighborhood ?? "", + gender: initialData?.gender ?? "", + shirtSize: initialData?.shirtSize ?? "", + medicalNotes: initialData?.medicalNotes ?? "", + })); const { update } = useSession(); const router = useRouter(); @@ -77,44 +86,50 @@ export default function BasicInfoForm(): React.ReactElement { ): Promise { e.preventDefault(); - try { - await addUserInfo({ - firstName: form.firstName.trim(), - lastName: form.lastName.trim(), - - addressLine1: form.addressLine1.trim(), - addressLine2: form.addressLine2 || null, - city: form.city.trim(), - state: form.state.trim(), - postalCode: form.postalCode.trim(), - country: "US", + const payload = { + firstName: form.firstName.trim(), + lastName: form.lastName.trim(), + addressLine1: form.addressLine1.trim(), + addressLine2: form.addressLine2 || null, + city: form.city.trim(), + state: form.state.trim(), + postalCode: form.postalCode.trim(), + country: "US", + phoneNumber: form.phoneNumber.trim(), + isTextOptedIn: form.isTextOptedIn, + birthMonth: Number(form.birthMonth), + birthDay: Number(form.birthDay), + birthYear: Number(form.birthYear), + preferredNeighborhood: form.preferredNeighborhood || null, + gender: form.gender || null, + shirtSize: form.shirtSize || null, + medicalNotes: form.medicalNotes || null, + }; - phoneNumber: form.phoneNumber.trim(), - isTextOptedIn: form.isTextOptedIn, - - birthMonth: Number(form.birthMonth), - birthDay: Number(form.birthDay), - birthYear: Number(form.birthYear), - - preferredNeighborhood: form.preferredNeighborhood || null, - gender: form.gender || null, - shirtSize: form.shirtSize || null, - medicalNotes: form.medicalNotes || null, - }); - - await update(); - router.push("/"); + try { + if (mode === "editForm") { + await updateUserInfo(payload); + alert("Profile updated successfully."); + } else { + await addUserInfo(payload); + await update(); + router.push("/"); + } } catch (error) { - console.error("add user info failed", error); - alert("Error in adding information."); + console.error("form submit failed", error); + alert("Error saving information."); } } return ( {/* Name */}