mirror of
https://github.com/i701/sarlink-portal.git
synced 2025-07-01 15:23:58 +00:00
Enhance user verification and data validation features
- Updated `next.config.ts` to include remote image patterns for user verification. - Introduced `VerifyUserDetails` function in `lib/person.ts` to validate user data against national records. - Added `usePerson` hook for fetching national data based on ID card. - Enhanced `signup` and `signin` functions in `auth-actions.ts` to handle user verification status and send notifications for pending verifications. - Refactored `VerifyUser` function in `user-actions.ts` to incorporate national data validation. - Improved UI components in the user verification page to display both database and national information. - Updated `InputReadOnly` component to support customizable label classes for better styling. These changes improve the user verification process, ensuring data integrity and enhancing the overall user experience.
This commit is contained in:
@ -9,7 +9,6 @@ import type { Island, Prisma } from "@prisma/client";
|
||||
import { Loader2 } from "lucide-react";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
import * as React from "react";
|
||||
import { useActionState } from "react";
|
||||
|
||||
import {
|
||||
Select,
|
||||
@ -31,7 +30,7 @@ export default function SignUpForm({ atolls }: { atolls: AtollWithIslands[] }) {
|
||||
const [atoll, setAtoll] = React.useState<AtollWithIslands>();
|
||||
const [islands, setIslands] = React.useState<Island[]>();
|
||||
|
||||
const [actionState, action, isPending] = useActionState(signup, {
|
||||
const [actionState, action, isPending] = React.useActionState(signup, {
|
||||
message: "",
|
||||
});
|
||||
|
||||
@ -45,6 +44,7 @@ export default function SignUpForm({ atolls }: { atolls: AtollWithIslands[] }) {
|
||||
const phoneNumberFromUrl = params.get("phone_number");
|
||||
const NUMBER_WITHOUT_DASH = phoneNumberFromUrl?.split("-").join("");
|
||||
|
||||
|
||||
return (
|
||||
<form
|
||||
action={action}
|
||||
@ -59,17 +59,17 @@ export default function SignUpForm({ atolls }: { atolls: AtollWithIslands[] }) {
|
||||
<Input
|
||||
className={cn(
|
||||
"text-base",
|
||||
actionState.errors?.fieldErrors.name && "border-2 border-red-500",
|
||||
actionState?.errors?.fieldErrors.name && "border-2 border-red-500",
|
||||
)}
|
||||
name="name"
|
||||
type="text"
|
||||
disabled={isPending}
|
||||
defaultValue={(actionState.payload?.get("name") || "") as string}
|
||||
defaultValue={(actionState?.payload?.get("name") || "") as string}
|
||||
placeholder="Full Name"
|
||||
/>
|
||||
{actionState.errors?.fieldErrors.name && (
|
||||
{actionState?.errors?.fieldErrors.name && (
|
||||
<span className="text-sm inline-block text-red-500">
|
||||
{actionState.errors?.fieldErrors.name}
|
||||
{actionState?.errors?.fieldErrors.name}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
@ -82,22 +82,22 @@ export default function SignUpForm({ atolls }: { atolls: AtollWithIslands[] }) {
|
||||
type="text"
|
||||
maxLength={7}
|
||||
disabled={isPending}
|
||||
defaultValue={(actionState.payload?.get("id_card") || "") as string}
|
||||
defaultValue={(actionState?.payload?.get("id_card") || "") as string}
|
||||
className={cn(
|
||||
"text-base",
|
||||
actionState.errors?.fieldErrors?.id_card &&
|
||||
actionState?.errors?.fieldErrors?.id_card &&
|
||||
"border-2 border-red-500",
|
||||
)}
|
||||
placeholder="ID Card"
|
||||
/>
|
||||
{actionState?.errors?.fieldErrors?.id_card?.[0] && (
|
||||
<span className="text-sm inline-block text-red-500">
|
||||
{actionState.errors.fieldErrors.id_card[0]}
|
||||
{actionState?.errors.fieldErrors.id_card[0]}
|
||||
</span>
|
||||
)}
|
||||
{actionState.db_error === "id_card" && (
|
||||
{actionState?.db_error === "id_card" && (
|
||||
<span className="text-sm inline-block text-red-500">
|
||||
{actionState.message}
|
||||
{actionState?.message}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
@ -128,9 +128,9 @@ export default function SignUpForm({ atolls }: { atolls: AtollWithIslands[] }) {
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
{actionState.errors?.fieldErrors?.atoll_id && (
|
||||
{actionState?.errors?.fieldErrors?.atoll_id && (
|
||||
<span className="text-sm inline-block text-red-500">
|
||||
{actionState.errors?.fieldErrors?.atoll_id}
|
||||
{actionState?.errors?.fieldErrors?.atoll_id}
|
||||
</span>
|
||||
)}
|
||||
</Select>
|
||||
@ -153,9 +153,9 @@ export default function SignUpForm({ atolls }: { atolls: AtollWithIslands[] }) {
|
||||
))}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
{actionState.errors?.fieldErrors?.island_id && (
|
||||
{actionState?.errors?.fieldErrors?.island_id && (
|
||||
<span className="text-sm inline-block text-red-500">
|
||||
{actionState.errors?.fieldErrors?.island_id}
|
||||
{actionState?.errors?.fieldErrors?.island_id}
|
||||
</span>
|
||||
)}
|
||||
</Select>
|
||||
@ -169,20 +169,20 @@ export default function SignUpForm({ atolls }: { atolls: AtollWithIslands[] }) {
|
||||
<Input
|
||||
className={cn(
|
||||
"text-base",
|
||||
actionState.errors?.fieldErrors?.address &&
|
||||
actionState?.errors?.fieldErrors?.address &&
|
||||
"border-2 border-red-500",
|
||||
)}
|
||||
disabled={isPending}
|
||||
name="address"
|
||||
defaultValue={
|
||||
(actionState.payload?.get("address") || "") as string
|
||||
(actionState?.payload?.get("address") || "") as string
|
||||
}
|
||||
type="text"
|
||||
placeholder="Address"
|
||||
/>
|
||||
{actionState.errors?.fieldErrors?.address && (
|
||||
{actionState?.errors?.fieldErrors?.address && (
|
||||
<span className="text-sm inline-block text-red-500">
|
||||
{actionState.errors?.fieldErrors?.address}
|
||||
{actionState?.errors?.fieldErrors?.address}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
@ -194,17 +194,17 @@ export default function SignUpForm({ atolls }: { atolls: AtollWithIslands[] }) {
|
||||
<Input
|
||||
className={cn(
|
||||
"text-base",
|
||||
actionState.errors?.fieldErrors?.dob && "border-2 border-red-500",
|
||||
actionState?.errors?.fieldErrors?.dob && "border-2 border-red-500",
|
||||
)}
|
||||
name="dob"
|
||||
disabled={isPending}
|
||||
defaultValue={(actionState.payload?.get("dob") || "") as string}
|
||||
defaultValue={(actionState?.payload?.get("dob") || "") as string}
|
||||
type="date"
|
||||
placeholder="Date of birth"
|
||||
/>
|
||||
{actionState.errors?.fieldErrors?.dob && (
|
||||
{actionState?.errors?.fieldErrors?.dob && (
|
||||
<span className="text-sm inline-block text-red-500">
|
||||
{actionState.errors?.fieldErrors?.dob}
|
||||
{actionState?.errors?.fieldErrors?.dob}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
@ -216,17 +216,17 @@ export default function SignUpForm({ atolls }: { atolls: AtollWithIslands[] }) {
|
||||
<Input
|
||||
className={cn(
|
||||
"text-base",
|
||||
actionState.errors?.fieldErrors.accNo && "border-2 border-red-500",
|
||||
actionState?.errors?.fieldErrors.accNo && "border-2 border-red-500",
|
||||
)}
|
||||
name="accNo"
|
||||
type="number"
|
||||
disabled={isPending}
|
||||
defaultValue={(actionState.payload?.get("accNo") || "") as string}
|
||||
defaultValue={(actionState?.payload?.get("accNo") || "") as string}
|
||||
placeholder="Account no"
|
||||
/>
|
||||
{actionState.errors?.fieldErrors.accNo && (
|
||||
{actionState?.errors?.fieldErrors.accNo && (
|
||||
<span className="text-sm inline-block text-red-500">
|
||||
{actionState.errors?.fieldErrors.accNo}
|
||||
{actionState?.errors?.fieldErrors.accNo}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
@ -241,7 +241,7 @@ export default function SignUpForm({ atolls }: { atolls: AtollWithIslands[] }) {
|
||||
disabled={isPending}
|
||||
className={cn(
|
||||
!phoneNumberFromUrl &&
|
||||
actionState.errors?.fieldErrors?.phone_number &&
|
||||
actionState?.errors?.fieldErrors?.phone_number &&
|
||||
"border-2 border-red-500 rounded-md",
|
||||
)}
|
||||
defaultValue={NUMBER_WITHOUT_DASH ?? ""}
|
||||
@ -251,19 +251,19 @@ export default function SignUpForm({ atolls }: { atolls: AtollWithIslands[] }) {
|
||||
</div>
|
||||
{actionState?.errors?.fieldErrors?.phone_number?.[0] && (
|
||||
<span className="text-sm inline-block text-red-500">
|
||||
{actionState.errors.fieldErrors.phone_number[0]}
|
||||
{actionState?.errors.fieldErrors.phone_number[0]}
|
||||
</span>
|
||||
)}
|
||||
{actionState.db_error === "phone_number" && (
|
||||
{actionState?.db_error === "phone_number" && (
|
||||
<span className="text-sm inline-block text-red-500">
|
||||
{actionState.message}
|
||||
{actionState?.message}
|
||||
</span>
|
||||
)}
|
||||
<div className="flex flex-col gap-2 items-start justify-start py-2">
|
||||
<div className="flex gap-2 items-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
defaultChecked={(actionState.payload?.get("terms") || "") as string === 'on'}
|
||||
defaultChecked={(actionState?.payload?.get("terms") || "") as string === 'on'}
|
||||
name="terms" id="terms" />
|
||||
<label
|
||||
htmlFor="terms"
|
||||
@ -277,16 +277,16 @@ export default function SignUpForm({ atolls }: { atolls: AtollWithIslands[] }) {
|
||||
</Link>
|
||||
</label>
|
||||
</div>
|
||||
{actionState.errors?.fieldErrors?.terms && (
|
||||
{actionState?.errors?.fieldErrors?.terms && (
|
||||
<span className="text-sm inline-block text-red-500">
|
||||
{actionState.errors?.fieldErrors?.terms}
|
||||
{actionState?.errors?.fieldErrors?.terms}
|
||||
</span>
|
||||
)}
|
||||
<div className="flex gap-2 items-center">
|
||||
|
||||
<input
|
||||
type="checkbox"
|
||||
defaultChecked={(actionState.payload?.get("policy") || "") as string === 'on'}
|
||||
defaultChecked={(actionState?.payload?.get("policy") || "") as string === 'on'}
|
||||
name="policy" id="terms" />
|
||||
<label
|
||||
htmlFor="terms"
|
||||
@ -300,9 +300,9 @@ export default function SignUpForm({ atolls }: { atolls: AtollWithIslands[] }) {
|
||||
</Link>
|
||||
</label>
|
||||
</div>
|
||||
{actionState.errors?.fieldErrors?.policy && (
|
||||
{actionState?.errors?.fieldErrors?.policy && (
|
||||
<span className="text-sm inline-block text-red-500">
|
||||
{actionState.errors?.fieldErrors?.policy}
|
||||
{actionState?.errors?.fieldErrors?.policy}
|
||||
</span>
|
||||
)}
|
||||
|
||||
|
Reference in New Issue
Block a user