From 17aa65a686b4a8e2ccd65dedac8126259f640ed5 Mon Sep 17 00:00:00 2001 From: i701 Date: Mon, 28 Jul 2025 10:03:17 +0500 Subject: [PATCH] =?UTF-8?q?feat(user-update-form):=20display=20field=20err?= =?UTF-8?q?ors=20in=20user=20update=20form=20=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- actions/user-actions.ts | 30 ++++++++++++++++++++-------- components/auth/verify-otp-form.tsx | 11 +++++----- components/user/user-update-form.tsx | 24 +++++++++++++--------- 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/actions/user-actions.ts b/actions/user-actions.ts index 6c41dfd..09e2d91 100644 --- a/actions/user-actions.ts +++ b/actions/user-actions.ts @@ -129,18 +129,19 @@ export type UpdateUserFormState = { payload?: FormData; }; + export async function updateUser( _prevState: UpdateUserFormState, formData: FormData, ): Promise { const userId = formData.get("userId") as string; const data: Record = {}; + for (const [key, value] of formData.entries()) { if (value !== undefined && value !== "") { data[key] = typeof value === "number" ? value : String(value); } } - console.log("data in update user action", data); const session = await getServerSession(authOptions); const response = await fetch( @@ -154,29 +155,42 @@ export async function updateUser( body: JSON.stringify(data), }, ); - console.log("response in update user action", response); + + const json = await response.json(); if (!response.ok) { - const errorData = await response.json(); + const isFieldErrorObject = + json && + typeof json === "object" && + !Array.isArray(json) && + Object.values(json).every( + (val) => Array.isArray(val) && val.every((v) => typeof v === "string"), + ); + return { message: - errorData.message || - errorData.detail || - "An error occurred while updating the user.", - fieldErrors: errorData.field_errors || {}, + json.message || + json.detail || + (isFieldErrorObject + ? "Please correct the highlighted fields." + : "An error occurred while updating the user."), + fieldErrors: isFieldErrorObject ? json : json.field_errors || {}, payload: formData, }; } - const updatedUser = (await response.json()) as User; + // Successful update + const updatedUser = json as User; revalidatePath("/users/[userId]/update", "page"); revalidatePath("/users/[userId]/verify", "page"); + return { ...updatedUser, message: "User updated successfully", }; } + export async function updateUserAgreement( _prevState: UpdateUserFormState, formData: FormData, diff --git a/components/auth/verify-otp-form.tsx b/components/auth/verify-otp-form.tsx index ac6710f..7c6f055 100644 --- a/components/auth/verify-otp-form.tsx +++ b/components/auth/verify-otp-form.tsx @@ -1,17 +1,18 @@ "use client"; -import { Button } from "@/components/ui/button"; -import { Input } from "@/components/ui/input"; -import { Label } from "@/components/ui/label"; import { zodResolver } from "@hookform/resolvers/zod"; import { Loader2 } from "lucide-react"; -import { signIn } from "next-auth/react"; import Link from "next/link"; import { useRouter, useSearchParams } from "next/navigation"; +import { signIn } from "next-auth/react"; import { useTransition } from "react"; import { type SubmitHandler, useForm } from "react-hook-form"; import { toast } from "sonner"; import { z } from "zod"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; + const OTPSchema = z.object({ pin: z.string().min(6, { message: "Your one-time password must be 6 characters.", @@ -59,7 +60,7 @@ export default function VerifyOTPForm({ return (
diff --git a/components/user/user-update-form.tsx b/components/user/user-update-form.tsx index abe23d3..75f3215 100644 --- a/components/user/user-update-form.tsx +++ b/components/user/user-update-form.tsx @@ -6,15 +6,6 @@ import { type UpdateUserFormState, updateUser } from "@/actions/user-actions"; import { Button } from "@/components/ui/button"; import { FloatingLabelInput } from "@/components/ui/floating-label"; import type { UserProfile } from "@/lib/types/user"; -// import { -// Select, -// SelectContent, -// SelectGroup, -// SelectItem, -// SelectLabel, -// SelectTrigger, -// SelectValue, -// } from "@/components/ui/select"; export default function UserUpdateForm({ user }: { user: UserProfile }) { const initialState: UpdateUserFormState = { @@ -59,6 +50,21 @@ export default function UserUpdateForm({ user }: { user: UserProfile }) { Update User Information
+
+ {state.fieldErrors && Object.keys(state.fieldErrors).length > 0 ? ( +
+ {Object.entries(state.fieldErrors).map(([field, errors]) => ( +
+ {errors.map((error, index) => ( +

+ Error in {field}: {error} +

+ ))} +
+ ))} +
+ ) : null} +