fixing
This commit is contained in:
parent
2e75d679b3
commit
00ddca22b9
|
|
@ -9,16 +9,17 @@ import { Label } from "@/components/ui/label";
|
|||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { Icon } from "@/components/ui/icon";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { FormField } from "@/components/auth/form-field";
|
||||
import {
|
||||
import {
|
||||
ProfileFormProps,
|
||||
RegistrationFormData,
|
||||
InstituteData,
|
||||
UserCategory,
|
||||
registrationSchema
|
||||
registrationSchema,
|
||||
} from "@/types/registration";
|
||||
import { useLocationData, useInstituteData, useRegistration } from "@/hooks/use-registration";
|
||||
import { validatePassword } from "@/lib/registration-utils";
|
||||
import {
|
||||
useLocationData,
|
||||
useInstituteData,
|
||||
useRegistration,
|
||||
} from "@/hooks/use-registration";
|
||||
import dynamic from "next/dynamic";
|
||||
|
||||
const PasswordChecklist = dynamic(() => import("react-password-checklist"), {
|
||||
|
|
@ -34,9 +35,20 @@ export const ProfileForm: React.FC<ProfileFormProps> = ({
|
|||
}) => {
|
||||
const t = useTranslations("LandingPage");
|
||||
const { submitRegistration, loading: submitLoading } = useRegistration();
|
||||
const { provinces, cities, districts, fetchCities, fetchDistricts, loading: locationLoading } = useLocationData();
|
||||
const { institutes, saveInstitute, loading: instituteLoading } = useInstituteData(Number(category));
|
||||
|
||||
const {
|
||||
provinces,
|
||||
cities,
|
||||
districts,
|
||||
fetchCities,
|
||||
fetchDistricts,
|
||||
loading: locationLoading,
|
||||
} = useLocationData();
|
||||
const {
|
||||
institutes,
|
||||
saveInstitute,
|
||||
loading: instituteLoading,
|
||||
} = useInstituteData(Number(category));
|
||||
|
||||
const [selectedProvince, setSelectedProvince] = useState("");
|
||||
const [selectedCity, setSelectedCity] = useState("");
|
||||
const [selectedDistrict, setSelectedDistrict] = useState("");
|
||||
|
|
@ -58,6 +70,7 @@ export const ProfileForm: React.FC<ProfileFormProps> = ({
|
|||
} = useForm<RegistrationFormData>({
|
||||
resolver: zodResolver(registrationSchema),
|
||||
mode: "onChange",
|
||||
defaultValues: { email: userData, },
|
||||
});
|
||||
|
||||
const watchedPassword = watch("password");
|
||||
|
|
@ -132,8 +145,13 @@ export const ProfileForm: React.FC<ProfileFormProps> = ({
|
|||
instituteId = Number(selectedInstitute);
|
||||
}
|
||||
|
||||
const success = await submitRegistration(data, category, userData, instituteId);
|
||||
|
||||
const success = await submitRegistration(
|
||||
data,
|
||||
category,
|
||||
userData,
|
||||
instituteId
|
||||
);
|
||||
|
||||
if (success) {
|
||||
onSuccess?.(data);
|
||||
}
|
||||
|
|
@ -149,7 +167,8 @@ export const ProfileForm: React.FC<ProfileFormProps> = ({
|
|||
<div className="flex flex-col gap-3 px-0 lg:px-[34px] mb-4">
|
||||
<div className="flex flex-col mb-2">
|
||||
<Label htmlFor="institute" className="mb-2">
|
||||
{t("institutions", { defaultValue: "Institution" })} <span className="text-red-500">*</span>
|
||||
{t("institutions", { defaultValue: "Institution" })}{" "}
|
||||
<span className="text-red-500">*</span>
|
||||
</Label>
|
||||
<select
|
||||
className="mb-3 p-2 border text-sm text-slate-400 rounded-md border-slate-300 bg-white cursor-pointer"
|
||||
|
|
@ -175,7 +194,8 @@ export const ProfileForm: React.FC<ProfileFormProps> = ({
|
|||
<>
|
||||
<div>
|
||||
<Label htmlFor="customInstituteName" className="mb-2">
|
||||
{t("instName", { defaultValue: "Institution Name" })} <span className="text-red-500">*</span>
|
||||
{t("instName", { defaultValue: "Institution Name" })}{" "}
|
||||
<span className="text-red-500">*</span>
|
||||
</Label>
|
||||
<Input
|
||||
className="mb-3"
|
||||
|
|
@ -188,11 +208,14 @@ export const ProfileForm: React.FC<ProfileFormProps> = ({
|
|||
</div>
|
||||
<div>
|
||||
<Label htmlFor="instituteAddress" className="mb-2">
|
||||
{t("instAddress", { defaultValue: "Institution Address" })} <span className="text-red-500">*</span>
|
||||
{t("instAddress", { defaultValue: "Institution Address" })}{" "}
|
||||
<span className="text-red-500">*</span>
|
||||
</Label>
|
||||
<Textarea
|
||||
className="mb-3"
|
||||
placeholder={t("addressInst", { defaultValue: "Enter institution address" })}
|
||||
placeholder={t("addressInst", {
|
||||
defaultValue: "Enter institution address",
|
||||
})}
|
||||
rows={3}
|
||||
value={instituteAddress}
|
||||
onChange={(e) => setInstituteAddress(e.target.value)}
|
||||
|
|
@ -212,15 +235,23 @@ export const ProfileForm: React.FC<ProfileFormProps> = ({
|
|||
{(category === "6" || category === "7") && (
|
||||
<div className="px-0 lg:px-[34px] mb-4">
|
||||
<Label className="mb-2">
|
||||
{category === "6" ? t("journalistNumber", { defaultValue: "Journalist Number" }) : "NRP"}
|
||||
{category === "6"
|
||||
? t("journalistNumber", { defaultValue: "Journalist Number" })
|
||||
: "NRP"}
|
||||
<span className="text-red-500">*</span>
|
||||
</Label>
|
||||
<Input
|
||||
type="text"
|
||||
autoComplete="off"
|
||||
className="mb-3"
|
||||
placeholder={t("inputNumberIdentity", { defaultValue: "Enter identity number" })}
|
||||
value={userData?.journalistCertificate || userData?.policeNumber || ""}
|
||||
placeholder={t("inputNumberIdentity", {
|
||||
defaultValue: "Enter identity number",
|
||||
})}
|
||||
value={
|
||||
userData?.journalistCertificate ||
|
||||
userData?.policeNumber ||
|
||||
""
|
||||
}
|
||||
disabled
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -229,17 +260,22 @@ export const ProfileForm: React.FC<ProfileFormProps> = ({
|
|||
{/* Personal Information */}
|
||||
<div className="mb-4 px-0 lg:px-[34px]">
|
||||
<Label className="mb-2">
|
||||
{t("fullName", { defaultValue: "Full Name" })} <span className="text-red-500">*</span>
|
||||
{t("fullName", { defaultValue: "Full Name" })}{" "}
|
||||
<span className="text-red-500">*</span>
|
||||
</Label>
|
||||
<Input
|
||||
type="text"
|
||||
autoComplete="off"
|
||||
className={errors.firstName ? "border-red-500" : ""}
|
||||
{...register("firstName")}
|
||||
placeholder={t("enterFullName", { defaultValue: "Enter your full name" })}
|
||||
placeholder={t("enterFullName", {
|
||||
defaultValue: "Enter your full name",
|
||||
})}
|
||||
/>
|
||||
{errors.firstName && (
|
||||
<div className="text-red-500 text-sm mt-1">{errors.firstName.message}</div>
|
||||
<div className="text-red-500 text-sm mt-1">
|
||||
{errors.firstName.message}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
|
@ -252,14 +288,20 @@ export const ProfileForm: React.FC<ProfileFormProps> = ({
|
|||
autoComplete="off"
|
||||
className={errors.username ? "border-red-500" : ""}
|
||||
{...register("username")}
|
||||
placeholder={t("enterUsername", { defaultValue: "Enter username" })}
|
||||
placeholder={t("enterUsername", {
|
||||
defaultValue: "Enter username",
|
||||
})}
|
||||
onChange={(e) => {
|
||||
const value = e.target.value.replace(/[^\w.-]/g, "").toLowerCase();
|
||||
const value = e.target.value
|
||||
.replace(/[^\w.-]/g, "")
|
||||
.toLowerCase();
|
||||
setValue("username", value);
|
||||
}}
|
||||
/>
|
||||
{errors.username && (
|
||||
<div className="text-red-500 text-sm mt-1">{errors.username.message}</div>
|
||||
<div className="text-red-500 text-sm mt-1">
|
||||
{errors.username.message}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
|
@ -273,42 +315,54 @@ export const ProfileForm: React.FC<ProfileFormProps> = ({
|
|||
className={errors.email ? "border-red-500" : ""}
|
||||
{...register("email")}
|
||||
placeholder="Enter your email"
|
||||
value={userData?.email || ""}
|
||||
value={userData || ""}
|
||||
disabled
|
||||
/>
|
||||
{errors.email && (
|
||||
<div className="text-red-500 text-sm mt-1">{errors.email.message}</div>
|
||||
<div className="text-red-500 text-sm mt-1">
|
||||
{errors.email.message}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col px-0 lg:px-[34px] mb-4">
|
||||
<Label className="mb-2">
|
||||
{t("number", { defaultValue: "Phone Number" })} <span className="text-red-500">*</span>
|
||||
{t("number", { defaultValue: "Phone Number" })}{" "}
|
||||
<span className="text-red-500">*</span>
|
||||
</Label>
|
||||
<Input
|
||||
type="tel"
|
||||
autoComplete="off"
|
||||
className={errors.phoneNumber ? "border-red-500" : ""}
|
||||
{...register("phoneNumber")}
|
||||
placeholder={t("enterNumber", { defaultValue: "Enter phone number" })}
|
||||
placeholder={t("enterNumber", {
|
||||
defaultValue: "Enter phone number",
|
||||
})}
|
||||
/>
|
||||
{errors.phoneNumber && (
|
||||
<div className="text-red-500 text-sm mt-1">{errors.phoneNumber.message}</div>
|
||||
<div className="text-red-500 text-sm mt-1">
|
||||
{errors.phoneNumber.message}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="mb-4 px-0 lg:px-[34px]">
|
||||
<Label htmlFor="address" className="mb-2">
|
||||
{t("address", { defaultValue: "Address" })} <span className="text-red-500">*</span>
|
||||
{t("address", { defaultValue: "Address" })}{" "}
|
||||
<span className="text-red-500">*</span>
|
||||
</Label>
|
||||
<Textarea
|
||||
className={errors.address ? "border-red-500" : ""}
|
||||
{...register("address")}
|
||||
placeholder={t("insertAddress", { defaultValue: "Enter your address" })}
|
||||
placeholder={t("insertAddress", {
|
||||
defaultValue: "Enter your address",
|
||||
})}
|
||||
rows={3}
|
||||
/>
|
||||
{errors.address && (
|
||||
<div className="text-red-500 text-sm mt-1">{errors.address.message}</div>
|
||||
<div className="text-red-500 text-sm mt-1">
|
||||
{errors.address.message}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
|
@ -318,7 +372,8 @@ export const ProfileForm: React.FC<ProfileFormProps> = ({
|
|||
{/* Location Fields */}
|
||||
<div className="flex flex-col px-0 lg:px-[34px] mb-4">
|
||||
<Label htmlFor="provinsi" className="mb-2">
|
||||
{t("province", { defaultValue: "Province" })} <span className="text-red-500">*</span>
|
||||
{t("province", { defaultValue: "Province" })}{" "}
|
||||
<span className="text-red-500">*</span>
|
||||
</Label>
|
||||
<select
|
||||
className={`mb-3 p-2 border rounded-md text-sm text-slate-400 border-slate-300 bg-white cursor-pointer ${
|
||||
|
|
@ -339,13 +394,16 @@ export const ProfileForm: React.FC<ProfileFormProps> = ({
|
|||
))}
|
||||
</select>
|
||||
{errors.provinsi && (
|
||||
<div className="text-red-500 text-sm mt-1">{errors.provinsi.message}</div>
|
||||
<div className="text-red-500 text-sm mt-1">
|
||||
{errors.provinsi.message}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col px-0 lg:px-[34px] mb-4">
|
||||
<Label htmlFor="kota" className="mb-2">
|
||||
{t("city", { defaultValue: "City" })} <span className="text-red-500">*</span>
|
||||
{t("city", { defaultValue: "City" })}{" "}
|
||||
<span className="text-red-500">*</span>
|
||||
</Label>
|
||||
<select
|
||||
className={`mb-3 p-2 border text-sm text-slate-400 rounded-md border-slate-300 bg-white cursor-pointer ${
|
||||
|
|
@ -367,13 +425,16 @@ export const ProfileForm: React.FC<ProfileFormProps> = ({
|
|||
))}
|
||||
</select>
|
||||
{errors.kota && (
|
||||
<div className="text-red-500 text-sm mt-1">{errors.kota.message}</div>
|
||||
<div className="text-red-500 text-sm mt-1">
|
||||
{errors.kota.message}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col px-0 lg:px-[34px] mb-4">
|
||||
<Label htmlFor="kecamatan" className="mb-2">
|
||||
{t("subdistrict", { defaultValue: "Subdistrict" })} <span className="text-red-500">*</span>
|
||||
{t("subdistrict", { defaultValue: "Subdistrict" })}{" "}
|
||||
<span className="text-red-500">*</span>
|
||||
</Label>
|
||||
<select
|
||||
className={`p-2 border text-sm text-slate-400 rounded-md border-slate-300 bg-white cursor-pointer ${
|
||||
|
|
@ -395,14 +456,20 @@ export const ProfileForm: React.FC<ProfileFormProps> = ({
|
|||
))}
|
||||
</select>
|
||||
{errors.kecamatan && (
|
||||
<div className="text-red-500 text-sm mt-1">{errors.kecamatan.message}</div>
|
||||
<div className="text-red-500 text-sm mt-1">
|
||||
{errors.kecamatan.message}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Password Fields */}
|
||||
<div className="mt-3.5 space-y-2 px-0 lg:px-[34px] mb-4">
|
||||
<Label htmlFor="password" className="mb-2 font-medium text-default-600">
|
||||
{t("password", { defaultValue: "Password" })} <span className="text-red-500">*</span>
|
||||
<Label
|
||||
htmlFor="password"
|
||||
className="mb-2 font-medium text-default-600"
|
||||
>
|
||||
{t("password", { defaultValue: "Password" })}{" "}
|
||||
<span className="text-red-500">*</span>
|
||||
</Label>
|
||||
<div className="relative">
|
||||
<Input
|
||||
|
|
@ -414,22 +481,37 @@ export const ProfileForm: React.FC<ProfileFormProps> = ({
|
|||
placeholder={t("inputPass", { defaultValue: "Enter password" })}
|
||||
onChange={(e) => handlePasswordChange(e.target.value)}
|
||||
/>
|
||||
<div className="absolute top-1/2 -translate-y-1/2 ltr:right-4 rtl:left-4 cursor-pointer" onClick={togglePasswordVisibility}>
|
||||
<div
|
||||
className="absolute top-1/2 -translate-y-1/2 ltr:right-4 rtl:left-4 cursor-pointer"
|
||||
onClick={togglePasswordVisibility}
|
||||
>
|
||||
{showPassword ? (
|
||||
<Icon icon="heroicons:eye-slash" className="w-5 h-5 text-default-400" />
|
||||
<Icon
|
||||
icon="heroicons:eye-slash"
|
||||
className="w-5 h-5 text-default-400"
|
||||
/>
|
||||
) : (
|
||||
<Icon icon="heroicons:eye" className="w-5 h-5 text-default-400" />
|
||||
<Icon
|
||||
icon="heroicons:eye"
|
||||
className="w-5 h-5 text-default-400"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{errors.password && (
|
||||
<div className="text-red-500 text-sm mt-1">{errors.password.message}</div>
|
||||
<div className="text-red-500 text-sm mt-1">
|
||||
{errors.password.message}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="mt-3.5 space-y-2 px-0 lg:px-[34px] mb-4">
|
||||
<Label htmlFor="passwordConf" className="mb-2 font-medium text-default-600">
|
||||
{t("confirmPass", { defaultValue: "Confirm Password" })} <span className="text-red-500">*</span>
|
||||
<Label
|
||||
htmlFor="passwordConf"
|
||||
className="mb-2 font-medium text-default-600"
|
||||
>
|
||||
{t("confirmPass", { defaultValue: "Confirm Password" })}{" "}
|
||||
<span className="text-red-500">*</span>
|
||||
</Label>
|
||||
<div className="relative">
|
||||
<Input
|
||||
|
|
@ -438,19 +520,32 @@ export const ProfileForm: React.FC<ProfileFormProps> = ({
|
|||
autoComplete="off"
|
||||
className={errors.passwordConf ? "border-red-500" : ""}
|
||||
{...register("passwordConf")}
|
||||
placeholder={t("samePass", { defaultValue: "Confirm your password" })}
|
||||
placeholder={t("samePass", {
|
||||
defaultValue: "Confirm your password",
|
||||
})}
|
||||
onChange={(e) => handlePasswordConfChange(e.target.value)}
|
||||
/>
|
||||
<div className="absolute top-1/2 -translate-y-1/2 ltr:right-4 rtl:left-4 cursor-pointer" onClick={togglePasswordConfVisibility}>
|
||||
<div
|
||||
className="absolute top-1/2 -translate-y-1/2 ltr:right-4 rtl:left-4 cursor-pointer"
|
||||
onClick={togglePasswordConfVisibility}
|
||||
>
|
||||
{showPasswordConf ? (
|
||||
<Icon icon="heroicons:eye-slash" className="w-5 h-5 text-default-400" />
|
||||
<Icon
|
||||
icon="heroicons:eye-slash"
|
||||
className="w-5 h-5 text-default-400"
|
||||
/>
|
||||
) : (
|
||||
<Icon icon="heroicons:eye" className="w-5 h-5 text-default-400" />
|
||||
<Icon
|
||||
icon="heroicons:eye"
|
||||
className="w-5 h-5 text-default-400"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{errors.passwordConf && (
|
||||
<div className="text-red-500 text-sm mt-1">{errors.passwordConf.message}</div>
|
||||
<div className="text-red-500 text-sm mt-1">
|
||||
{errors.passwordConf.message}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
|
@ -465,10 +560,20 @@ export const ProfileForm: React.FC<ProfileFormProps> = ({
|
|||
// Password validation is handled by the form schema
|
||||
}}
|
||||
messages={{
|
||||
minLength: t("passCharacter", { defaultValue: "Password must be at least 8 characters" }),
|
||||
specialChar: t("passSpecial", { defaultValue: "Password must contain at least one special character" }),
|
||||
number: t("passNumber", { defaultValue: "Password must contain at least one number" }),
|
||||
capital: t("passCapital", { defaultValue: "Password must contain at least one uppercase letter" }),
|
||||
minLength: t("passCharacter", {
|
||||
defaultValue: "Password must be at least 8 characters",
|
||||
}),
|
||||
specialChar: t("passSpecial", {
|
||||
defaultValue:
|
||||
"Password must contain at least one special character",
|
||||
}),
|
||||
number: t("passNumber", {
|
||||
defaultValue: "Password must contain at least one number",
|
||||
}),
|
||||
capital: t("passCapital", {
|
||||
defaultValue:
|
||||
"Password must contain at least one uppercase letter",
|
||||
}),
|
||||
match: t("passSame", { defaultValue: "Passwords must match" }),
|
||||
}}
|
||||
/>
|
||||
|
|
@ -478,10 +583,18 @@ export const ProfileForm: React.FC<ProfileFormProps> = ({
|
|||
<div className="flex justify-center items-center mt-2 mb-4 px-[34px]">
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={isSubmitting || submitLoading || locationLoading || instituteLoading}
|
||||
disabled={
|
||||
isSubmitting ||
|
||||
submitLoading ||
|
||||
locationLoading ||
|
||||
instituteLoading
|
||||
}
|
||||
className="border w-[550px] text-center bg-red-700 text-white hover:bg-white hover:text-red-700"
|
||||
>
|
||||
{isSubmitting || submitLoading || locationLoading || instituteLoading ? (
|
||||
{isSubmitting ||
|
||||
submitLoading ||
|
||||
locationLoading ||
|
||||
instituteLoading ? (
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin" />
|
||||
Processing...
|
||||
|
|
@ -495,4 +608,4 @@ export const ProfileForm: React.FC<ProfileFormProps> = ({
|
|||
</form>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ export const RegistrationOTPForm: React.FC<RegistrationOTPFormProps> = ({
|
|||
className,
|
||||
}) => {
|
||||
const t = useTranslations("LandingPage");
|
||||
const { verifyOTP, resendOTP, loading, error, formattedTime, canResend } = useOTP();
|
||||
const { verifyOTP, resendOTP, loading, error, formattedTime, canResend } =
|
||||
useOTP();
|
||||
const [otpValue, setOtpValue] = useState("");
|
||||
|
||||
const handleOTPChange = (value: string) => {
|
||||
|
|
@ -36,8 +37,14 @@ export const RegistrationOTPForm: React.FC<RegistrationOTPFormProps> = ({
|
|||
}
|
||||
|
||||
try {
|
||||
const userData = await verifyOTP(email, otpValue, category, memberIdentity);
|
||||
onSuccess?.(userData);
|
||||
const userData = await verifyOTP(
|
||||
email,
|
||||
otpValue,
|
||||
category,
|
||||
memberIdentity
|
||||
);
|
||||
if (userData?.error) return false;
|
||||
onSuccess(email);
|
||||
} catch (error: any) {
|
||||
onError?.(error.message || "OTP verification failed");
|
||||
}
|
||||
|
|
@ -95,39 +102,39 @@ export const RegistrationOTPForm: React.FC<RegistrationOTPFormProps> = ({
|
|||
className="gap-2"
|
||||
>
|
||||
<InputOTPGroup>
|
||||
<InputOTPSlot
|
||||
index={0}
|
||||
<InputOTPSlot
|
||||
index={0}
|
||||
onKeyDown={handleTypeOTP}
|
||||
className="w-12 h-12 text-lg"
|
||||
/>
|
||||
<InputOTPSlot
|
||||
index={1}
|
||||
<InputOTPSlot
|
||||
index={1}
|
||||
onKeyDown={handleTypeOTP}
|
||||
className="w-12 h-12 text-lg"
|
||||
/>
|
||||
</InputOTPGroup>
|
||||
<InputOTPSeparator />
|
||||
<InputOTPGroup>
|
||||
<InputOTPSlot
|
||||
index={2}
|
||||
<InputOTPSlot
|
||||
index={2}
|
||||
onKeyDown={handleTypeOTP}
|
||||
className="w-12 h-12 text-lg"
|
||||
/>
|
||||
<InputOTPSlot
|
||||
index={3}
|
||||
<InputOTPSlot
|
||||
index={3}
|
||||
onKeyDown={handleTypeOTP}
|
||||
className="w-12 h-12 text-lg"
|
||||
/>
|
||||
</InputOTPGroup>
|
||||
<InputOTPSeparator />
|
||||
<InputOTPGroup>
|
||||
<InputOTPSlot
|
||||
index={4}
|
||||
<InputOTPSlot
|
||||
index={4}
|
||||
onKeyDown={handleTypeOTP}
|
||||
className="w-12 h-12 text-lg"
|
||||
/>
|
||||
<InputOTPSlot
|
||||
index={5}
|
||||
<InputOTPSlot
|
||||
index={5}
|
||||
onKeyDown={handleTypeOTP}
|
||||
className="w-12 h-12 text-lg"
|
||||
/>
|
||||
|
|
@ -151,10 +158,11 @@ export const RegistrationOTPForm: React.FC<RegistrationOTPFormProps> = ({
|
|||
disabled={!canResend || loading}
|
||||
className="bg-slate-300 dark:bg-black text-center rounded-lg mr-1 w-[200px] py-2 text-base"
|
||||
>
|
||||
{canResend
|
||||
{canResend
|
||||
? t("resend", { defaultValue: "Resend OTP" })
|
||||
: `${t("resending", { defaultValue: "Resending" })} (${formattedTime})`
|
||||
}
|
||||
: `${t("resending", {
|
||||
defaultValue: "Resending",
|
||||
})} (${formattedTime})`}
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
|
|
@ -176,18 +184,21 @@ export const RegistrationOTPForm: React.FC<RegistrationOTPFormProps> = ({
|
|||
{/* Help Text */}
|
||||
<div className="text-center px-8">
|
||||
<p className="text-sm text-gray-600">
|
||||
{t("otpHelp", { defaultValue: "Didn't receive the code? Check your spam folder or" })}{" "}
|
||||
{t("otpHelp", {
|
||||
defaultValue:
|
||||
"Didn't receive the code? Check your spam folder or",
|
||||
})}{" "}
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleResendOTP}
|
||||
disabled={!canResend || loading}
|
||||
className="text-blue-600 hover:text-blue-800 underline disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
{t("resendOTP", { defaultValue: "resend OTP" })}
|
||||
{t("resend", { defaultValue: "resend OTP" })}
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -458,7 +458,7 @@ export const useRegistration = () => {
|
|||
const transformedData = transformRegistrationData(sanitizedData, category, userData, instituteId);
|
||||
|
||||
const response = await postRegistration(transformedData);
|
||||
|
||||
console.log("PPPP", transformedData)
|
||||
if (response?.error) {
|
||||
throw new Error(response.message || "Registration failed");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -566,6 +566,8 @@
|
|||
"polda": "Official coverage sourced from Polri activities at Polda",
|
||||
"satker": "Official coverage sourced from Polri activities at Satker",
|
||||
"resending": "Resending",
|
||||
"resend": "Resend",
|
||||
"otpHelp": "Didn't receive the code? Check your spam folder or",
|
||||
"regionNews": "Region Police News",
|
||||
"divisionNews": "Division Police News",
|
||||
"areaCoverage": "Area Coverage & Divison",
|
||||
|
|
|
|||
|
|
@ -353,6 +353,8 @@
|
|||
"versionHistory": "VERSION HISTORY"
|
||||
},
|
||||
"LandingPage": {
|
||||
"resend": "Kirim Ulang",
|
||||
"otpHelp": "Tidak menerima kode? Periksa folder spam Anda atau",
|
||||
"content": "Konten",
|
||||
"new": "Terbaru",
|
||||
"schedule": "Jadwal",
|
||||
|
|
|
|||
|
|
@ -117,10 +117,7 @@ export async function saveInstitutes(data: any) {
|
|||
|
||||
export async function postRegistration(data: any) {
|
||||
const url = "public/users/save";
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
return httpPost(url, headers, data);
|
||||
return httpPost(url, data);
|
||||
}
|
||||
|
||||
export async function requestOTP(data: any) {
|
||||
|
|
@ -176,4 +173,4 @@ export async function getDataJournalist(cert: any) {
|
|||
export async function getDataPersonil(nrp: any) {
|
||||
const url = `public/users/search-personil?nrp=${nrp}`;
|
||||
return httpGetInterceptor(url);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue