feat(user-verification): implement user verification functionality and update dialog UI
All checks were successful
Build and Push Docker Images / Build and Push Docker Images (push) Successful in 6m54s

This commit is contained in:
2025-07-16 02:03:03 +05:00
parent 7a02cb2415
commit dc3b5f9bf9
2 changed files with 79 additions and 85 deletions

View File

@ -9,52 +9,43 @@ import type { ApiError } from "@/lib/backend-types";
import type { User } from "@/lib/types/user"; import type { User } from "@/lib/types/user";
import { handleApiResponse } from "@/utils/tryCatch"; import { handleApiResponse } from "@/utils/tryCatch";
export async function VerifyUser(_userId: string) { type VerifyUserResponse = {
// const user = await prisma.user.findUnique({ "ok": boolean,
// where: { "mismatch_fields": string[] | null,
// id: userId, "error": string | null,
// }, "detail": string | null
// include: {Rejectuser } | {
// atoll: true, "message": boolean,
// island: true, };
// }, export async function verifyUser(userId: string) {
// }); const session = await getServerSession(authOptions);
// if (!user) { if (!session?.apiToken) {
// throw new Error("User not found"); return { ok: false, error: 'Not authenticated' } as const;
// } }
// const isValidPerson = await VerifyUserDetails({ user });
// if (!isValidPerson) try {
// throw new Error("The user details does not match national data."); const r = await fetch(
// if (isValidPerson) { `${process.env.SARLINK_API_BASE_URL}/api/auth/users/${userId}/verify/`,
// await prisma.user.update({ {
// where: { method: 'PUT',
// id: userId, headers: {
// }, 'Content-Type': 'application/json',
// data: { Authorization: `Token ${session.apiToken}`,
// verified: true, },
// }, },
// }); );
// const ninjaClient = await CreateClient({ const body = (await r.json().catch(() => ({}))) as VerifyUserResponse &
// group_settings_id: "", { message?: string; detail?: string };
// address1: "",
// city: user.atoll?.name || "", if (!r.ok) {
// state: user.island?.name || "", const msg = body?.message || body?.detail || 'User verification failed';
// postal_code: "", return { ok: false, error: msg, mismatch_fields: body?.mismatch_fields || null } as const;
// country_id: "462", }
// address2: user.address || "",
// contacts: { return { ok: true, data: body } as const;
// first_name: user.name?.split(" ")[0] || "", } catch (err) {
// last_name: user.name?.split(" ")[1] || "", return { ok: false, error: (err as Error).message } as const;
// email: user.email || "", }
// phone: user.phoneNumber || "",
// send_email: false,
// custom_value1: user.dob?.toISOString().split("T")[0] || "",
// custom_value2: user.id_card || "",
// custom_value3: "",
// },
// });
// }
// revalidatePath("/users");
} }
export async function getProfile() { export async function getProfile() {

View File

@ -2,27 +2,26 @@
import { Check, CheckCheck } from "lucide-react"; import { Check, CheckCheck } from "lucide-react";
import { useState } from "react"; import { useState } from "react";
import { toast } from "sonner"; import { toast } from "sonner";
import { VerifyUser } from "@/actions/user-actions"; import { verifyUser } from "@/actions/user-actions";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import type { UserProfile } from "@/lib/types/user"; import type { UserProfile } from "@/lib/types/user";
export function UserVerifyDialog({ user }: { user: UserProfile }) { export function UserVerifyDialog({ user }: { user: UserProfile }) {
const userId = user.id; const userId = user.id;
const [disabled, setDisabled] = useState(false); const [disabled, setDisabled] = useState(false);
const [open, setOpen] = useState(false);
return ( return (
<AlertDialog> <Dialog open={open} onOpenChange={setOpen}>
<AlertDialogTrigger asChild> <DialogTrigger asChild>
<Button <Button
variant={user.verified ? "secondary" : "default"} variant={user.verified ? "secondary" : "default"}
disabled={disabled || user.verified} disabled={disabled || user.verified}
@ -30,11 +29,11 @@ export function UserVerifyDialog({ user }: { user: UserProfile }) {
{user.verified ? <CheckCheck size={16} /> : <Check size={16} />} {user.verified ? <CheckCheck size={16} /> : <Check size={16} />}
{user.verified ? "Verified" : "Verify"} {user.verified ? "Verified" : "Verify"}
</Button> </Button>
</AlertDialogTrigger> </DialogTrigger>
<AlertDialogContent> <DialogContent>
<AlertDialogHeader> <DialogHeader>
<AlertDialogTitle className="text-muted-foreground">Verify User</AlertDialogTitle> <DialogTitle className="text-muted-foreground">Verify User</DialogTitle>
<AlertDialogDescription> <DialogDescription>
Are you sure you want to verify the following user? Are you sure you want to verify the following user?
<span className="inline-block my-4"> <span className="inline-block my-4">
<li> <li>
@ -52,31 +51,35 @@ export function UserVerifyDialog({ user }: { user: UserProfile }) {
</li> </li>
<li>Phone Number: {user.mobile}</li> <li>Phone Number: {user.mobile}</li>
</span> </span>
</AlertDialogDescription> </DialogDescription>
</AlertDialogHeader> </DialogHeader>
<AlertDialogFooter> <DialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel> <Button
<AlertDialogAction
disabled={disabled} disabled={disabled}
onClick={() => { onClick={async () => {
setOpen(true);
setDisabled(true); setDisabled(true);
toast.promise(VerifyUser(String(userId)), { const res = await verifyUser(String(userId));
loading: "Verifying...", if (res.ok) toast.success('User Verified!');
success: () => { else toast.warning(res.error, {
setDisabled(false); description: <div>
return "User Verified!"; <p className="italic">The following fields do not match</p>
}, <ul className="list-disc list-inside p-2">
error: (error: Error) => { {res.mismatch_fields?.map((field) => (
setDisabled(false); <li key={field}>{field}</li>
return error.message || "Something went wrong"; ))}
}, </ul>
</div>,
closeButton: true,
duration: 10000,
}); });
setDisabled(false);
}} }}
> >
{disabled ? "Verifying..." : "Verify"} {disabled ? "Verifying..." : "Verify"}
</AlertDialogAction> </Button>
</AlertDialogFooter> </DialogFooter>
</AlertDialogContent> </DialogContent>
</AlertDialog> </Dialog>
); );
} }