1070 lines
42 KiB
TypeScript
1070 lines
42 KiB
TypeScript
"use client";
|
|
|
|
import React from "react";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Checkbox } from "@/components/ui/checkbox";
|
|
import { Input } from "@/components/ui/input";
|
|
import { Label } from "@/components/ui/label";
|
|
import Image from "next/image";
|
|
import { close, error, loading, registerConfirm } from "@/config/swal";
|
|
import { Link, useRouter } from "@/i18n/routing";
|
|
import { getDataByNIK, getDataByNRP, getDataJournalist, getDataPersonil, listCity, listDistricts, listInstitusi, listProvince, postRegistration, requestOTP, saveInstitutes, verifyOTP } from "@/service/auth";
|
|
import { yupResolver } from "@hookform/resolvers/yup";
|
|
import { useParams, useSearchParams } from "next/navigation";
|
|
import { useEffect, useState } from "react";
|
|
import { useForm, SubmitHandler } from "react-hook-form";
|
|
import Swal from "sweetalert2";
|
|
import withReactContent from "sweetalert2-react-content";
|
|
import * as Yup from "yup";
|
|
import { InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot } from "@/components/ui/input-otp";
|
|
import { Textarea } from "@/components/ui/textarea";
|
|
import { Icon } from "@/components/ui/icon";
|
|
import dynamic from "next/dynamic";
|
|
import sanitizeHtml from "sanitize-html";
|
|
import { useTranslations } from "next-intl";
|
|
|
|
type Inputs = {
|
|
example: string;
|
|
exampleRequired: string;
|
|
};
|
|
|
|
const PasswordChecklist = dynamic(() => import("react-password-checklist"), {
|
|
ssr: false,
|
|
});
|
|
|
|
const page = () => {
|
|
const params = useParams();
|
|
const [stepOneActive, setStepOneActive] = useState(true);
|
|
const [stepTwoActive, setStepTwoActive] = useState(false);
|
|
const [stepThreeActive, setStepThreeActive] = useState(false);
|
|
const [typePass, setTypePass] = useState("password");
|
|
const [typePassConf, setTypePassConf] = useState("password");
|
|
const searchParams = useSearchParams();
|
|
const [formProfile, setFormProfile] = useState(false);
|
|
const [journalistCertificate, setJournalistCertificate] = useState();
|
|
const [personilNRP, setPersonilNRP] = useState();
|
|
const [journalistData, setJournalistData] = useState<any>();
|
|
const [personilData, setPersonilData] = useState<any>();
|
|
const [userIdentity] = useState();
|
|
const [userIdentityValidate, setUserIdentityValidate] = useState("");
|
|
const [email, setEmail] = useState<any>();
|
|
const [emailValidate, setEmailValidate] = useState("");
|
|
const [otpValidate, setOtpValidate] = useState("");
|
|
const [password, setPassword] = useState("");
|
|
const [city, setCity] = useState([]);
|
|
const [isValidPassword, setIsValidPassword] = useState(false);
|
|
const MySwal = withReactContent(Swal);
|
|
const [isCustomActive, setIsCustomActive] = useState(false);
|
|
const [institusi, setInstitusi] = useState();
|
|
const [customInstituteName, setCustomInstituteName] = useState("");
|
|
const [institusiAddress, setInstitusiAddress] = useState<any>();
|
|
const [institution, setInstitution] = useState<any>([]);
|
|
const [province, setProvince] = useState<any>([]);
|
|
const router = useRouter();
|
|
const category = searchParams?.get("category");
|
|
const [districts, setDistricts] = useState([]);
|
|
const [, setAssociation] = useState<any>();
|
|
const [warningPassConf] = useState();
|
|
const [otpValue, setOtpValue] = useState("");
|
|
const t = useTranslations("LandingPage");
|
|
|
|
const [otp1, setOtp1] = useState();
|
|
const [otp2, setOtp2] = useState();
|
|
const [otp3, setOtp3] = useState();
|
|
const [otp4, setOtp4] = useState();
|
|
const [otp5, setOtp5] = useState();
|
|
const [otp6, setOtp6] = useState();
|
|
|
|
const nMinuteSeconds = 60;
|
|
const nSecondInMiliseconds = 1000;
|
|
const [, setRefreshTimer] = useState(false);
|
|
|
|
const [passwordType, setPasswordType] = React.useState("password");
|
|
const [passwordConf, setPasswordConf] = React.useState("password");
|
|
|
|
const togglePasswordType = () => {
|
|
setPasswordType((prevType) => (prevType === "password" ? "text" : "password"));
|
|
setPasswordConf((prevType) => (prevType === "same password" ? "text" : "same password"));
|
|
};
|
|
|
|
const validationSchema = Yup.object().shape({
|
|
firstName: Yup.string().required(t("nameEmpty")),
|
|
username: Yup.string().required(t("usernameEmpty")),
|
|
phoneNumber: Yup.string().required(t("numberEmpty")),
|
|
address: Yup.string().required(t("addressEmpty")),
|
|
email: Yup.string().required(t("emailEmpty")),
|
|
provinsi: Yup.string().required(t("provinceEmpty")),
|
|
kota: Yup.string().required(t("cityEmpty")),
|
|
kecamatan: Yup.string().required(t("subdistrictEmpty")),
|
|
password: Yup.string().required(t("passwordEmpty")),
|
|
passwordConf: Yup.string().required(t("confirmEmpty")),
|
|
});
|
|
|
|
const formOptions = {
|
|
resolver: yupResolver(validationSchema),
|
|
};
|
|
|
|
const { register, handleSubmit, formState, setValue } = useForm<any>(formOptions);
|
|
|
|
const convertMinutesToMiliseconds = (minute: any) => minute * nMinuteSeconds * nSecondInMiliseconds;
|
|
|
|
const convertMilisecondsToHour = (miliseconds: any) => new Date(miliseconds).toISOString().slice(17, -5);
|
|
|
|
let [timerCount, setTimerCount] = useState(convertMinutesToMiliseconds(1));
|
|
let interval: any;
|
|
|
|
const setValUsername = (e: any) => {
|
|
const uname = e.replaceAll(/[^\w.-]/g, "");
|
|
setValue("username", uname.toLowerCase());
|
|
};
|
|
|
|
const setValPassword = (e: any) => {
|
|
setValue("password", e);
|
|
setPassword(e);
|
|
};
|
|
|
|
const setValPasswordConf = (e: any) => {
|
|
setPasswordConf(e);
|
|
};
|
|
|
|
const { errors }: any = formState;
|
|
|
|
async function save(data: any) {
|
|
// loading();
|
|
let institutionId = 1;
|
|
|
|
if (Number(category) == 6) {
|
|
const dataInstitution =
|
|
isCustomActive == true
|
|
? {
|
|
name: customInstituteName,
|
|
address: institusiAddress,
|
|
categoryRoleId: Number(category),
|
|
}
|
|
: {
|
|
id: institusi,
|
|
address: institusiAddress,
|
|
};
|
|
|
|
console.log(dataInstitution);
|
|
|
|
const resInstitution = await saveInstitutes(dataInstitution);
|
|
|
|
institutionId = resInstitution?.data?.data?.id;
|
|
if (resInstitution?.error) {
|
|
error(resInstitution?.message);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
const sanitizedFirstName = sanitizeHtml(data.firstName);
|
|
|
|
if (sanitizedFirstName == "") {
|
|
error("Invalid Name");
|
|
} else {
|
|
const datas = {
|
|
firstName: sanitizedFirstName,
|
|
lastName: sanitizedFirstName,
|
|
username: data.username,
|
|
phoneNumber: data.phoneNumber,
|
|
email,
|
|
address: data.address,
|
|
memberIdentity: userIdentity,
|
|
provinceId: Number(data.provinsi),
|
|
cityId: Number(data.kota),
|
|
districtId: Number(data.kecamatan),
|
|
password: data.password,
|
|
instituteId: Number(institutionId),
|
|
roleId: Number(category),
|
|
};
|
|
|
|
const response = await postRegistration(datas);
|
|
console.log(response);
|
|
if (response?.error) {
|
|
error(response?.message);
|
|
return false;
|
|
}
|
|
|
|
registerConfirm();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
const handleSendOTP = async () => {
|
|
console.log(userIdentity, email);
|
|
if (Number(category) == 6) {
|
|
// const journalist = await handleJournalistCertificate();
|
|
console.log(email, journalistCertificate);
|
|
if (email != "" && journalistCertificate != undefined) {
|
|
const data = {
|
|
memberIdentity: journalistCertificate,
|
|
email,
|
|
category: 6,
|
|
};
|
|
|
|
loading();
|
|
const response = await requestOTP(data);
|
|
|
|
if (response?.error) {
|
|
error(response.message);
|
|
return false;
|
|
}
|
|
|
|
close();
|
|
handleJournalistCertificate();
|
|
setStepTwoActive(true);
|
|
} else {
|
|
console.log("identity empty");
|
|
setUserIdentityValidate("Nomor identitas tidak boleh kosong");
|
|
}
|
|
} else if (Number(category) == 7) {
|
|
console.log(email, personilNRP);
|
|
if (email != "" && personilNRP != undefined) {
|
|
const data = {
|
|
memberIdentity: personilNRP,
|
|
email,
|
|
category: 7,
|
|
};
|
|
|
|
loading();
|
|
const response = await requestOTP(data);
|
|
|
|
if (response?.error) {
|
|
error(response?.message);
|
|
return false;
|
|
}
|
|
|
|
close();
|
|
handleDataNRP();
|
|
setStepTwoActive(true);
|
|
} else {
|
|
console.log("identity empty");
|
|
setUserIdentityValidate("Nomor identitas tidak boleh kosong");
|
|
}
|
|
} else {
|
|
console.log("UMUM");
|
|
if (email != "") {
|
|
const data = {
|
|
memberIdentity: null,
|
|
email,
|
|
category,
|
|
};
|
|
|
|
loading();
|
|
const response = await requestOTP(data);
|
|
|
|
if (response?.error) {
|
|
error(response?.message);
|
|
return false;
|
|
}
|
|
|
|
close();
|
|
setStepTwoActive(true);
|
|
}
|
|
}
|
|
};
|
|
|
|
const handleJournalistCertificate = async () => {
|
|
const response = await getDataJournalist(journalistCertificate);
|
|
const data = response?.data?.data;
|
|
console.log(data);
|
|
if (data) {
|
|
setJournalistData(data[0]);
|
|
}
|
|
|
|
console.log("Data jurnalis:", data);
|
|
return data;
|
|
};
|
|
|
|
const handleTypeOTP = (event: any) => {
|
|
const { form } = event.target;
|
|
const index = [...form].indexOf(event.target);
|
|
form.elements[index + 1].focus();
|
|
event.preventDefault();
|
|
};
|
|
|
|
const handleResendOTP = async () => {
|
|
const timer = convertMilisecondsToHour(timerCount);
|
|
|
|
if (timer == "00") {
|
|
handleSendOTP();
|
|
restartTimer();
|
|
}
|
|
};
|
|
|
|
function restartTimer() {
|
|
setTimerCount(60_000);
|
|
setRefreshTimer(true);
|
|
startInterval();
|
|
}
|
|
|
|
function startInterval() {
|
|
interval = setInterval(() => {
|
|
if (timerCount == 1000 && interval) {
|
|
clearInterval(interval);
|
|
console.log("Reset");
|
|
}
|
|
|
|
timerCount = timerCount == 0 ? 60_000 : timerCount;
|
|
setTimerCount((timerCount -= nSecondInMiliseconds));
|
|
}, nSecondInMiliseconds);
|
|
}
|
|
|
|
const handleDataNRP = async () => {
|
|
const response = await getDataPersonil(personilNRP);
|
|
const data = response?.data?.data;
|
|
setPersonilData(data);
|
|
console.log("Data personil:", data);
|
|
return data;
|
|
};
|
|
|
|
const handleInstituteOption = (e: any) => {
|
|
if (e.target.value == "0") {
|
|
setIsCustomActive(true);
|
|
} else {
|
|
setIsCustomActive(false);
|
|
setInstitusi(e.target.value);
|
|
}
|
|
};
|
|
|
|
// const {
|
|
// register,
|
|
// handleSubmit,
|
|
// watch,
|
|
// formState: { errors },
|
|
// } = useForm<Inputs>();
|
|
// const onSubmit: SubmitHandler<Inputs> = (data) => console.log(data);
|
|
// console.log(watch("example"));
|
|
|
|
function setDataToForm() {
|
|
if (Number(category) == 6 && journalistData) {
|
|
setValue("firstName", journalistData.journalistName);
|
|
setValue("memberIdentity", journalistData.certNumber);
|
|
const selectedProvince = province.find((o: any) => o.provName == journalistData.province?.toUpperCase());
|
|
|
|
if (selectedProvince !== undefined) {
|
|
setValue("provinsi", selectedProvince.id);
|
|
}
|
|
} else if (Number(category) == 7 && personilData) {
|
|
setValue("firstName", personilData.lastName);
|
|
setValue("memberIdentity", personilData.nrp);
|
|
}
|
|
}
|
|
|
|
const checkEmail = (e: any) => {
|
|
const regEmail = /^(([^\s"(),.:;<>@[\\\]]+(\.[^\s"(),.:;<>@[\\\]]+)*)|(".+"))@((\[(?:\d{1,3}\.){3}\d{1,3}])|(([\dA-Za-z\-]+\.)+[A-Za-z]{2,}))$/;
|
|
|
|
if (regEmail.test(e)) {
|
|
setEmailValidate("");
|
|
setEmail(e);
|
|
} else {
|
|
setEmailValidate(t("emailValid"));
|
|
setEmail("");
|
|
}
|
|
};
|
|
|
|
async function onSubmit(data: any) {
|
|
console.log("Submit");
|
|
|
|
if (isValidPassword) {
|
|
MySwal.fire({
|
|
title: "Buat akun",
|
|
text: "",
|
|
icon: "warning",
|
|
showCancelButton: true,
|
|
cancelButtonColor: "#d33",
|
|
confirmButtonColor: "#3085d6",
|
|
confirmButtonText: "Buat",
|
|
}).then((result) => {
|
|
if (result.isConfirmed) {
|
|
save(data);
|
|
}
|
|
});
|
|
} else {
|
|
error("Kata Sandi harus sama");
|
|
}
|
|
}
|
|
|
|
const handleIdentity = async (e: any) => {
|
|
const id = e;
|
|
console.log(id);
|
|
await new Promise((resolve) => setTimeout(resolve, 2000)); // 2 sec
|
|
if (Number(category) == 5) {
|
|
const reqId =
|
|
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dlZF9pbiI6ImxvZ2luX3RydWUiLCJpZF91c2VyX2FjY291bnQiOiJJRDExMyIsInVzZXJuYW1lIjoiaXdhbjc0M0BnbWFpbC5jb20iLCJub21lcktUUCI6bnVsbCwicm9sZSI6IjEiLCJyZWRpcmVjdF9sb2dpbl92YWxpZCI6IjM0IiwiY29udHJvbGxlciI6InN5c3RlbXMiLCJuYW1hX2xlbmdrYXAiOiJJd2FuIEphZWxhbmksIFMuS29tIiwiaWRXYXJnYSI6IjIwMTgxMjA2MTMwNTQ1Iiwia29kZV9yYWhhc2lhIjoiWGJqMHRRR2djWXdVMnYiLCJpZF9zZXNzaW9uIjoiMnRwMTZUV2VpTEhQN1o0RGpyYkt2TlVBelhHIiwicGVyc29uYWxfYXRhdV9sZW1iYWdhIjoiTEVNQkFHQSIsImV4cGlyZV9zZXNzaW9uIjoiMjAyMi0wMS0yNyAxNTowMzozNiJ9.Nzq3QqAlKaeKAdDujI9fGuj_mJcIIyWe8lvBI_Ui06o";
|
|
const response = await getDataByNIK(reqId, id);
|
|
const data = response?.data?.data_return[0];
|
|
|
|
console.log(data);
|
|
if (data !== undefined) {
|
|
setValue("firstName", data.nama_lengkap);
|
|
setValue("address", data.alamat);
|
|
const selectedProvince = province.find((o: any) => o.provName == data.prov?.toUpperCase());
|
|
|
|
if (selectedProvince !== undefined) {
|
|
setValue("provinsi", selectedProvince.id);
|
|
}
|
|
|
|
const selectedCity: any = city.find((o: any) => o.cityName == data.kab_kota?.toUpperCase());
|
|
|
|
if (selectedCity !== undefined) {
|
|
setValue("kota", selectedCity?.id);
|
|
}
|
|
|
|
const selectedDistrict: any = districts.find((o: any) => o.disName == data.kec?.toUpperCase());
|
|
|
|
if (selectedDistrict !== undefined) {
|
|
setValue("kecamatan", selectedDistrict?.id);
|
|
}
|
|
}
|
|
} else if (Number(category) == 7) {
|
|
const reqId =
|
|
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dlZF9pbiI6ImxvZ2luX3RydWUiLCJpZF91c2VyX2FjY291bnQiOiJJRDExMyIsInVzZXJuYW1lIjoiaXdhbjc0M0BnbWFpbC5jb20iLCJub21lcktUUCI6bnVsbCwicm9sZSI6IjEiLCJyZWRpcmVjdF9sb2dpbl92YWxpZCI6IjM0IiwiY29udHJvbGxlciI6InN5c3RlbXMiLCJuYW1hX2xlbmdrYXAiOiJJd2FuIEphZWxhbmksIFMuS29tIiwiaWRXYXJnYSI6IjIwMTgxMjA2MTMwNTQ1Iiwia29kZV9yYWhhc2lhIjoiWGJqMHRRR2djWXdVMnYiLCJpZF9zZXNzaW9uIjoiMnRwMTZUV2VpTEhQN1o0RGpyYkt2TlVBelhHIiwicGVyc29uYWxfYXRhdV9sZW1iYWdhIjoiTEVNQkFHQSIsImV4cGlyZV9zZXNzaW9uIjoiMjAyMi0wMS0yNyAxNTowMzozNiJ9.Nzq3QqAlKaeKAdDujI9fGuj_mJcIIyWe8lvBI_Ui06o";
|
|
const response = await getDataByNRP(reqId, id);
|
|
const data = response?.data?.data_return[0];
|
|
|
|
console.log("Data :", data);
|
|
if (data !== undefined) {
|
|
setValue("firstName", data.nama);
|
|
setValue("address", data.lokasi);
|
|
}
|
|
}
|
|
};
|
|
|
|
const getCity = async (e: any) => {
|
|
const res = await listCity(e);
|
|
setCity(res?.data.data);
|
|
};
|
|
|
|
const getDistricts = async (e: any) => {
|
|
const res = await listDistricts(e);
|
|
setDistricts(res?.data.data);
|
|
};
|
|
|
|
const handleVerifyOTP = async () => {
|
|
const otp = `${otp1}${otp2}${otp3}${otp4}${otp5}${otp6}`;
|
|
const dummyOtp = "123456";
|
|
if (email != "" && otpValue.length == 6) {
|
|
console.log("verify otp");
|
|
loading();
|
|
// const response = {
|
|
// message: "success",
|
|
// };
|
|
const response = {
|
|
message: otpValue == dummyOtp ? "success" : "failed",
|
|
};
|
|
|
|
// const response = await verifyOTP(email, otp);
|
|
// if (response?.error) {
|
|
// error(response?.message);
|
|
// return false;
|
|
// }
|
|
close();
|
|
// console.log(response);
|
|
if (response?.message == "success") {
|
|
console.log("success");
|
|
setStepTwoActive(false);
|
|
setStepThreeActive(true);
|
|
setFormProfile(true);
|
|
setOtpValidate("");
|
|
setValue("email", email);
|
|
setValue("memberIdentity", userIdentity);
|
|
handleIdentity(userIdentity);
|
|
setDataToForm();
|
|
} else {
|
|
setOtpValidate("Kode OTP Tidak Valid");
|
|
}
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
async function initState() {
|
|
if (category != undefined) {
|
|
const resInstiution = await listInstitusi(category);
|
|
const res = await listProvince();
|
|
setInstitution(resInstiution?.data?.data);
|
|
setProvince(res?.data?.data);
|
|
}
|
|
}
|
|
|
|
initState();
|
|
}, [category]);
|
|
|
|
useEffect(() => {
|
|
function initState() {
|
|
for (const element of institution) {
|
|
const { id } = element;
|
|
|
|
if (id == institusi) {
|
|
setInstitusiAddress(element.address);
|
|
}
|
|
}
|
|
}
|
|
|
|
initState();
|
|
}, [institusi]);
|
|
|
|
return (
|
|
<div className="overflow-y-auto flex flex-wrap w-full h-dvh">
|
|
<div className="lg:block hidden flex-1 overflow-hidden bg-[#f7f7f7] text-[40px] leading-[48px] text-default-600 relative z-[1]">
|
|
<div className="max-w-[520px] pt-16 ps-20 ">
|
|
<Link href="/" className="mb-6 inline-block">
|
|
<Image src="/assets/mediahub-logo.png" alt="" width={250} height={250} className="mb-10 w-full h-full" />
|
|
</Link>
|
|
</div>
|
|
<div className="absolute left-0 2xl:bottom-[-160px] bottom-[-130px] h-full w-full z-[-1]">
|
|
<Image src="/assets/vector-login.svg" alt="" width={300} height={300} className="mb-10 w-full h-full" />
|
|
</div>
|
|
</div>
|
|
|
|
<form
|
|
className="flex-1 w-full bg-white dark:bg-slate-600"
|
|
onSubmit={handleSubmit(onSubmit)}
|
|
style={
|
|
Number(category) < 5
|
|
? {
|
|
display: "none",
|
|
}
|
|
: {}
|
|
}
|
|
>
|
|
<div className="flex flex-col first-letter:mb-8 ">
|
|
<div className="flex flex-row justify-center py-10">
|
|
<ul className="flex flex-row items-center text-center">
|
|
<li>
|
|
<div className={`flex justify-center items-center text-center text-black bg-[#f32d2d] h-[40px] w-[40px] border rounded-full ${stepOneActive ? "active bg-white border border-[#f32d2d] rounded-full text-[#f32d2d]" : ""}`}>
|
|
<b>1</b>
|
|
</div>
|
|
</li>
|
|
<div className="w-16 h-1 z-[1] bg-[#f32d2d] "></div>
|
|
<li>
|
|
<div className={`flex justify-center items-center text-center text-black bg-[#f32d2d] h-[40px] w-[40px] border rounded-full ${stepTwoActive ? "active bg-white border border-[#f32d2d] rounded-full text-[#f32d2d]" : ""}`}>
|
|
<b>2</b>
|
|
</div>
|
|
</li>
|
|
<div className="w-16 h-1 bg-[#f32d2d]"></div>
|
|
<li>
|
|
<div className={`flex justify-center items-center text-center text-black bg-[#f32d2d] h-[40px] w-[40px] borde rounded-full ${stepThreeActive ? "active bg-white border border-[#f32d2d] rounded-full text-[#f32d2d]" : ""}`}>
|
|
<b>3</b>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div className="flex flex-row ">
|
|
<div
|
|
className="px-8 my-10 gap-3"
|
|
style={
|
|
stepTwoActive && !formProfile
|
|
? {
|
|
display: "none",
|
|
}
|
|
: {}
|
|
}
|
|
>
|
|
<p className="text-2xl lg:text-4xl px-0 lg:px-12 font-bold ">{stepThreeActive ? t("userData") : t("registerFirst")}</p>
|
|
<p className="px-0 lg:px-12 text-sm lg:text-base mt-2">
|
|
{t("alreadyHave")}{" "}
|
|
<Link href="/auth" className="text-red-500">
|
|
<b>{t("logIn")}</b>
|
|
</Link>
|
|
</p>
|
|
</div>
|
|
<div
|
|
className="px-8 lg:px-20 mb-6"
|
|
style={
|
|
!stepTwoActive || (stepOneActive && stepThreeActive)
|
|
? {
|
|
display: "none",
|
|
}
|
|
: {}
|
|
}
|
|
>
|
|
<p className="text-black dark:text-white text-2xl px-0 lg:px-20 font-semibold">{t("enterOTP")}</p>
|
|
<p className="text-red-500 text-sm px-0 lg:px-20">{t("checkInbox")}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className={`flex flex-col gap-3 px-8 lg:px-12 ${formProfile == true || stepTwoActive ? "hidden" : ""}`}>
|
|
<div
|
|
className="flex flex-col px-0 lg:px-8"
|
|
style={
|
|
Number(category) == 6
|
|
? {}
|
|
: {
|
|
display: "none",
|
|
}
|
|
}
|
|
>
|
|
<Label htmlFor="association" className="mb-2">
|
|
{t("member")} <span className="text-red-500">*</span>
|
|
</Label>
|
|
<select
|
|
className={`py-2 px-1 rounded-md border text-sm text-slate-400 border-slate-300 bg-white dark:bg-slate-600 ${errors.association ? "block" : ""}`}
|
|
{...register("association")}
|
|
id="association"
|
|
onChange={(e) => setAssociation(e.target.value)}
|
|
>
|
|
<option disabled selected>
|
|
{t("association")}
|
|
</option>
|
|
<option value="PWI" key="1">
|
|
PWI (Persatuan Wartawan Indonesia)
|
|
</option>
|
|
<option value="IJTI" key="2">
|
|
IJTI (Ikatan Jurnalis Televisi Indonesia)
|
|
</option>
|
|
<option value="PFI" key="3">
|
|
PFI (Pewarta Foto Indonesia)
|
|
</option>
|
|
<option value="AJI" key="4">
|
|
AJI (Asosiasi Jurnalis Indonesia)
|
|
</option>
|
|
<option value="Wartawan" key="5">
|
|
{t("otherIdentity")}
|
|
</option>
|
|
</select>
|
|
<div className="hidden w-full mt-[0.25rem] text-lg text-[#dc3545]">{errors.association?.message}</div>
|
|
</div>
|
|
|
|
{Number(category) == 7 ? (
|
|
<div className="px-0 lg:px-[34px]">
|
|
<label htmlFor="userIdentity" className="mb-3">
|
|
<b>{t("policeNumber")}</b> <span className="text-red-500">*</span>
|
|
</label>
|
|
<Input className="mt-3" autoComplete="off" placeholder="Masukan Nomor Registrasi Polri Anda" type="text" onChange={(event: any) => setPersonilNRP(event.target.value)} />
|
|
<p className="text-red-500">{userIdentityValidate}</p>
|
|
</div>
|
|
) : (
|
|
""
|
|
)}
|
|
{Number(category) == 6 ? (
|
|
<div
|
|
className="px-0 lg:px-[34px]"
|
|
style={
|
|
Number(category) == 6
|
|
? {}
|
|
: {
|
|
display: "none",
|
|
}
|
|
}
|
|
>
|
|
<Label htmlFor="journalistCertificate">
|
|
{t("journalistNumber")} <span className="text-red-500">*</span>
|
|
</Label>
|
|
<Input className="rounded-md py-3" autoComplete="off" placeholder={t("inputJournalist")} type="text" onChange={(event: any) => setJournalistCertificate(event.target.value)} />
|
|
</div>
|
|
) : (
|
|
""
|
|
)}
|
|
<div className="flex flex-col w-full px-0 lg:px-8 gap-2">
|
|
<label htmlFor="email">
|
|
<b>Email</b> <span className="text-red-500">*</span>
|
|
</label>
|
|
<Input className="w-full" autoComplete="off" placeholder={t("inputEmail")} type="email" onChange={(event) => checkEmail(event.target.value)} />
|
|
<p className="text-sm text-red-500 mt-1">{emailValidate}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className={`flex flex-col mt-4 px-8 lg:px-12 ${!stepTwoActive || stepThreeActive ? "hidden" : ""}`}>
|
|
<div className="flex justify-center mb-6">
|
|
<InputOTP maxLength={6} onChange={(e) => setOtpValue(e)}>
|
|
<InputOTPGroup>
|
|
<InputOTPSlot index={0} onChange={(e: any) => setOtp1(e.target.value)} onKeyUp={handleTypeOTP} />
|
|
<InputOTPSlot index={1} onChange={(e: any) => setOtp2(e.target.value)} onKeyUp={handleTypeOTP} />
|
|
</InputOTPGroup>
|
|
<InputOTPSeparator />
|
|
<InputOTPGroup>
|
|
<InputOTPSlot index={2} onChange={(e: any) => setOtp3(e.target.value)} onKeyUp={handleTypeOTP} />
|
|
<InputOTPSlot index={3} onChange={(e: any) => setOtp4(e.target.value)} onKeyUp={handleTypeOTP} />
|
|
</InputOTPGroup>
|
|
<InputOTPSeparator />
|
|
<InputOTPGroup>
|
|
<InputOTPSlot index={4} onChange={(e: any) => setOtp5(e.target.value)} onKeyUp={handleTypeOTP} />
|
|
<InputOTPSlot index={5} onChange={(e: any) => setOtp6(e.target.value)} onKeyUp={handleTypeOTP} />
|
|
</InputOTPGroup>
|
|
</InputOTP>
|
|
</div>
|
|
<p className="text-red-500">
|
|
<b>{otpValidate}</b>
|
|
</p>
|
|
<div className="flex flex-row px-0 lg:px-28 justify-between items-center my-4">
|
|
<a className="bg-slate-300 dark:bg-black text-center rounded-lg mr-1 w-[200px] py-2 text-base cursor-pointer" onClick={() => handleResendOTP()}>
|
|
{t("resending")} ({convertMilisecondsToHour(timerCount)})
|
|
</a>
|
|
<a className="bg-red-700 w-[200px] py-2 text-center text-white rounded-lg ml-1 cursor-pointer" onClick={() => handleVerifyOTP()}>
|
|
{t("next")}
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div className={`flex flex-col px-8 lg:px-12 ${formProfile == false ? "hidden" : ""}`}>
|
|
<div>
|
|
{Number(category) == 6 || Number(category) == 7 ? (
|
|
<div className="px-0 lg:px-[34px]">
|
|
<Label className="mb-2">
|
|
{`${Number(category) == 6 ? t("journalistNumber") : "NRP"}`}
|
|
<span className="text-red-500">*</span>
|
|
</Label>
|
|
<Input
|
|
type="text"
|
|
autoComplete="off"
|
|
className={`mb-3 ${errors.memberIdentity ? "block" : ""}`}
|
|
{...register("memberIdentity")}
|
|
placeholder={t("inputNumberIdentity")}
|
|
onChange={(e) => handleIdentity(e.target.value)}
|
|
disabled
|
|
/>
|
|
<div className="text-red-500">{errors.memberIdentity?.message}</div>
|
|
</div>
|
|
) : (
|
|
""
|
|
)}
|
|
<div className="mb-4 px-0 lg:px-[34px]">
|
|
<Label className="mb-2">
|
|
{t("fullName")} <span className="text-red-500">*</span>
|
|
</Label>
|
|
<Input type="text" autoComplete="off" className={` ${errors.firstName ? "block" : ""}`} {...register("firstName")} placeholder={t("enterFullName")} />
|
|
<div className="text-red-500">{errors.firstName?.message}</div>
|
|
</div>
|
|
<div className="mb-4 px-0 lg:px-[34px]">
|
|
<Label className="mb-2">
|
|
Username <span className="text-red-500">*</span>
|
|
</Label>
|
|
<Input
|
|
id="username"
|
|
type="text"
|
|
autoComplete="off"
|
|
className={`${errors.username ? "block" : ""}`}
|
|
placeholder={t("enterUsername")}
|
|
onChange={(e) => {
|
|
setValUsername(e.target.value.trim());
|
|
}}
|
|
onPaste={(e: any) => {
|
|
setValUsername(e.target.value.trim());
|
|
}}
|
|
onCopy={(e: any) => {
|
|
setValUsername(e.target.value.trim());
|
|
}}
|
|
/>
|
|
<div className="text-red-500">{errors.username?.message}</div>
|
|
</div>
|
|
<div className="mb-4 px-0 lg:px-[34px]">
|
|
<Label className="mb-2">
|
|
Email <span className="text-red-500">*</span>
|
|
</Label>
|
|
<Input type="email" autoComplete="off" className={`${errors.email ? "block" : "text-white"}`} {...register("email")} placeholder="Masukan Email Anda" disabled />
|
|
<div className="text-red-500">{errors.email?.message}</div>
|
|
</div>
|
|
</div>
|
|
<div className="flex flex-col px-0 lg:px-[34px]">
|
|
<Label className="mb-2">
|
|
{t("number")} <span className="text-red-500">*</span>
|
|
</Label>
|
|
<Input type="number" autoComplete="off" className={`mb-3 ${errors.phoneNumber ? "block" : ""}`} {...register("phoneNumber")} placeholder={t("enterNumber")} />
|
|
<div className="text-red-500">{errors.phoneNumber?.message}</div>
|
|
</div>
|
|
<div className="mb-4 px-0 lg:px-[34px]">
|
|
<Label htmlFor="address" className="mb-2">
|
|
{t("address")} <span className="text-red-500">*</span>
|
|
</Label>
|
|
<Textarea className={` ${errors.address ? "block" : ""}`} {...register("address")} placeholder={t("insertAddress")} rows={3} />
|
|
<div className="text-red-500">{errors.address?.message}</div>
|
|
</div>
|
|
{Number(category) == 6 ? (
|
|
<div className="flex flex-col gap-3 px-0 lg:px-[34px]">
|
|
<div className="flex flex-col mb-2">
|
|
<Label htmlFor="provinsi" className="mb-2">
|
|
{t("institutions")} <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" id="provinsi" onChange={(event) => handleInstituteOption(event)}>
|
|
<option disabled selected>
|
|
{t("selectInst")}
|
|
</option>
|
|
{institution?.map((row: any) => (
|
|
<option value={row.id} key={row.id}>
|
|
{row?.name}
|
|
</option>
|
|
))}
|
|
<option value="0" key="0">
|
|
{t("otherInst")}
|
|
</option>
|
|
</select>
|
|
</div>
|
|
<div
|
|
className="px-0 lg:px-[34px]"
|
|
style={
|
|
isCustomActive == false
|
|
? {
|
|
display: "none",
|
|
}
|
|
: {}
|
|
}
|
|
>
|
|
<Label htmlFor="alamat" className="mb-2">
|
|
{t("instName")} <span className="text-red-500">*</span>
|
|
</Label>
|
|
<Input className="mb-3" autoComplete="off" placeholder="Masukan Nama Lengkap Institusi Anda" type="text" onChange={(event) => setCustomInstituteName(event.target.value)} />
|
|
</div>
|
|
<div>
|
|
<Label htmlFor="alamat" className="mb-2">
|
|
{t("instAddress")} <span className="text-red-500">*</span>
|
|
</Label>
|
|
<Textarea className="mb-3" placeholder={t("addressInst")} rows={3} value={institusiAddress} onChange={(event) => setInstitusiAddress(event.target.value)} />
|
|
</div>
|
|
</div>
|
|
) : (
|
|
""
|
|
)}
|
|
<div className="flex flex-col px-0 lg:px-[34px]">
|
|
<label htmlFor="provinsi" className="mb-2 ">
|
|
{t("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 ${errors.provinsi ? "block" : ""}`}
|
|
{...register("provinsi")}
|
|
id="provinsi"
|
|
name="provinsi"
|
|
onChange={(event) => getCity(event.target.value)}
|
|
>
|
|
<option disabled selected>
|
|
{t("selectProv")}
|
|
</option>
|
|
{province?.map((row: any) => (
|
|
<option value={row.id} key={row.id}>
|
|
{row.provName}
|
|
</option>
|
|
))}
|
|
</select>
|
|
<div className="text-red-500">{errors.provinsi?.message}</div>
|
|
</div>
|
|
<div className="flex flex-col px-0 lg:px-[34px]">
|
|
<label htmlFor="kota" className="mb-2">
|
|
{t("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 ${errors.kota ? "block" : ""}`}
|
|
{...register("kota")}
|
|
id="kota"
|
|
onChange={(event) => getDistricts(event.target.value)}
|
|
>
|
|
<option disabled selected>
|
|
{t("selectCity")}
|
|
</option>
|
|
{city?.map((row: any) => (
|
|
<option value={row.id} key={row.id}>
|
|
{row.cityName}
|
|
</option>
|
|
))}
|
|
</select>
|
|
<div className="text-red-500">{errors.kota?.message}</div>
|
|
</div>
|
|
<div className="flex flex-col px-0 lg:px-[34px]">
|
|
<label htmlFor="kecamatan" className="mb-2">
|
|
{t("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 ${errors.kecamatan ? "block" : ""}`} {...register("kecamatan")} id="kecamatan">
|
|
<option disabled selected>
|
|
{t("selectSub")}
|
|
</option>
|
|
{districts?.map((row: any) => (
|
|
<option value={row.id} key={row.id}>
|
|
{row.disName}
|
|
</option>
|
|
))}
|
|
</select>
|
|
<div className="text-red-500">{errors.kecamatan?.message}</div>
|
|
</div>
|
|
{/* <div className="flex flex-col">
|
|
<label htmlFor="password" className="mb-2">
|
|
<b>Kata Sandi</b> <span className="text-red-500">*</span>
|
|
</label>
|
|
<Input
|
|
type={typePass}
|
|
autoComplete="off"
|
|
className={` ${errors.password ? "block" : ""}`}
|
|
{...register("password")}
|
|
placeholder="Masukan Kata Sandi"
|
|
onChange={(e) => {
|
|
setValPassword(e.target.value.trim());
|
|
}}
|
|
onPaste={(e: any) => {
|
|
setValPassword(e.target.value.trim());
|
|
}}
|
|
onCopy={(e: any) => {
|
|
setValPassword(e.target.value.trim());
|
|
}}
|
|
required
|
|
/>{" "}
|
|
<a className={`text-black place-items-end -top-44 ${typePass == "text" ? "hidden" : ""}`} onClick={showPass}>
|
|
<Icon icon="fa:eye" />
|
|
</a>
|
|
<a className={`text-black ${typePass == "password" ? "hidden" : ""}`} onClick={hidePass}>
|
|
<Icon icon="fa:eye-slash" />
|
|
</a>
|
|
<div className="text-red-500">{errors.password?.message}</div>
|
|
</div> */}
|
|
<div className="mt-3.5 space-y-2 px-0 lg:px-[34px]">
|
|
<Label htmlFor="password" className="mb-2 font-medium text-default-600">
|
|
{t("password")} <span className="text-red-500">*</span>
|
|
</Label>
|
|
<div className="relative">
|
|
<Input
|
|
size="lg"
|
|
type={passwordType}
|
|
autoComplete="off"
|
|
className={` ${errors.password ? "block" : ""}`}
|
|
{...register("password")}
|
|
placeholder={t("inputPass")}
|
|
onChange={(e) => {
|
|
setValPassword(e.target.value.trim());
|
|
}}
|
|
onPaste={(e: any) => {
|
|
setValPassword(e.target.value.trim());
|
|
}}
|
|
onCopy={(e: any) => {
|
|
setValPassword(e.target.value.trim());
|
|
}}
|
|
required
|
|
/>
|
|
<div className="absolute top-1/2 -translate-y-1/2 ltr:right-4 rtl:left-4 cursor-pointer" onClick={togglePasswordType}>
|
|
{passwordType === "password" ? <Icon icon="heroicons:eye" className="w-5 h-5 text-default-400" /> : <Icon icon="heroicons:eye-slash" className="w-5 h-5 text-default-400" />}{" "}
|
|
</div>
|
|
</div>
|
|
{errors.password?.message && <div className="text-destructive mt-2 text-sm">{errors.password.message}</div>}
|
|
</div>
|
|
{/* <div className="flex flex-col">
|
|
<label htmlFor="password" className="mb-2">
|
|
<b>Konfirmasi Kata Sandi</b> <span className="text-red-500">*</span>
|
|
</label>
|
|
<Input
|
|
type={typePassConf}
|
|
autoComplete="off"
|
|
className={` ${errors.passwordConf ? "block" : ""}`}
|
|
{...register("passwordConf")}
|
|
placeholder="Masukan Kata Sandi"
|
|
onChange={(e) => {
|
|
setValPasswordConf(e.target.value.trim());
|
|
}}
|
|
onPaste={(e: any) => {
|
|
setValPasswordConf(e.target.value.trim());
|
|
}}
|
|
onCopy={(e: any) => {
|
|
setValPasswordConf(e.target.value.trim());
|
|
}}
|
|
required
|
|
/>
|
|
<div className="text-red-500">{warningPassConf}</div>
|
|
<a className={`text-black ${typePassConf == "text" ? "hidden" : ""}`} onClick={showPassConf}>
|
|
<Icon icon="fa:eye" />
|
|
</a>
|
|
<a className={`text-dark show-pass ${typePassConf == "password" ? "hidden" : ""}`} onClick={hidePassConf}>
|
|
<Icon icon="fa:eye-slash" />
|
|
</a>
|
|
</div> */}
|
|
<div className="mt-3.5 space-y-2 px-0 lg:px-[34px]">
|
|
<Label htmlFor="password" className="mb-2 font-medium text-default-600">
|
|
{t("confirmPass")} <span className="text-red-500">*</span>
|
|
</Label>
|
|
<div className="relative">
|
|
<Input
|
|
size="lg"
|
|
type={passwordConf}
|
|
autoComplete="off"
|
|
className={` ${errors.passwordConf ? "block" : ""}`}
|
|
{...register("passwordConf")}
|
|
placeholder={t("samePass")}
|
|
onChange={(e) => {
|
|
setValPasswordConf(e.target.value.trim());
|
|
}}
|
|
onPaste={(e: any) => {
|
|
setValPasswordConf(e.target.value.trim());
|
|
}}
|
|
onCopy={(e: any) => {
|
|
setValPasswordConf(e.target.value.trim());
|
|
}}
|
|
required
|
|
/>
|
|
<div className="absolute top-1/2 -translate-y-1/2 ltr:right-4 rtl:left-4 cursor-pointer" onClick={togglePasswordType}>
|
|
{passwordConf === "same password" ? <Icon icon="heroicons:eye" className="w-5 h-5 text-default-400" /> : <Icon icon="heroicons:eye-slash" className="w-5 h-5 text-default-400" />}{" "}
|
|
</div>
|
|
</div>
|
|
<div className="text-red-500">{warningPassConf}</div>
|
|
</div>
|
|
<div className="form-group px-0 lg:px-[34px]">
|
|
<PasswordChecklist
|
|
rules={["minLength", "specialChar", "number", "capital", "match"]}
|
|
minLength={8}
|
|
value={password}
|
|
valueAgain={passwordConf}
|
|
onChange={(isValid: any) => {
|
|
setIsValidPassword(isValid);
|
|
}}
|
|
messages={{
|
|
minLength: t("passCharacter"),
|
|
specialChar: t("passSpecial"),
|
|
number: t("passNumber"),
|
|
capital: t("passCapital"),
|
|
match: t("passSame"),
|
|
}}
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
className="flex flex-col mt-8 mb-2"
|
|
style={
|
|
(stepOneActive && !stepTwoActive) || stepThreeActive
|
|
? {}
|
|
: {
|
|
display: "none",
|
|
}
|
|
}
|
|
>
|
|
<div className="text-center mb-2 px-[34px]">
|
|
<p className="text-sm lg:text-base">
|
|
{t("byRegis")} <br />{" "}
|
|
<a href="/privacy" target="_blank" className="text-red-500">
|
|
<b>{t("terms")}</b>
|
|
</a>{" "}
|
|
{t("and")}{" "}
|
|
<a href="/privacy" target="_blank" className="text-red-500">
|
|
<b>{t("privacy")}</b>
|
|
</a>
|
|
</p>
|
|
</div>
|
|
<div className={`mb-5 mt-7 px-[34px] w-full text-center flex justify-center ${formProfile == true || stepTwoActive ? "hidden" : ""}`}>
|
|
{/* <a className="border cursor-pointer border-red-500 px-4 py-3 rounded-lg text-white bg-[#dc3545] w-full" onClick={() => handleSendOTP()}> */}
|
|
<a
|
|
className="border cursor-pointer border-red-500 px-4 py-3 rounded-lg text-white bg-[#dc3545] w-[550px]"
|
|
onClick={() => {
|
|
setStepOneActive(false);
|
|
setStepTwoActive(true);
|
|
}}
|
|
>
|
|
{t("send")} OTP
|
|
</a>
|
|
</div>
|
|
</div>
|
|
<div
|
|
className="flex justify-center items-center mt-2 mb-4 px-[34px]"
|
|
style={
|
|
formProfile == false
|
|
? {
|
|
display: "none",
|
|
}
|
|
: {}
|
|
}
|
|
>
|
|
<Button type="submit" className="border w-[550px] text-center bg-red-700 text-white hover:bg-white hover:text-red-700 ">
|
|
{t("register")}
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default page;
|