From aff407f3cefff01398b8be89dce241c2f5951227 Mon Sep 17 00:00:00 2001 From: Anang Yusman Date: Wed, 9 Apr 2025 14:55:30 +0800 Subject: [PATCH] feat:login OTP, fix performance polda,polres,fix sidebar polda, satker --- components/landing-page/hero.tsx | 7 +- components/partials/auth/login-form.tsx | 197 +++++++++-------- .../visualization/performance-polda.tsx | 4 +- .../visualization/performance-polres.tsx | 6 +- lib/menus.ts | 199 ++++++++++-------- messages/en.json | 2 +- messages/in.json | 2 +- service/auth.ts | 9 +- .../http-config/http-interceptor-service.ts | 7 +- 9 files changed, 231 insertions(+), 202 deletions(-) diff --git a/components/landing-page/hero.tsx b/components/landing-page/hero.tsx index 5aebe217..42a849ac 100644 --- a/components/landing-page/hero.tsx +++ b/components/landing-page/hero.tsx @@ -194,10 +194,7 @@ const options = { const SurveyFormModal = ({ onClose }: { onClose: () => void }) => { useEffect(() => { - // Lock body scroll when modal is open document.body.style.overflow = "hidden"; - - // Clean up when modal closes return () => { document.body.style.overflow = ""; }; @@ -359,7 +356,7 @@ const SurveyFormModal = ({ onClose }: { onClose: () => void }) => { ); }; -const ONE_HOUR = 60 * 60 * 1000; +const FIVE_MINUTES = 5 * 60 * 1000; const Hero: React.FC = () => { const router = useRouter(); @@ -394,7 +391,7 @@ const Hero: React.FC = () => { const now = new Date().getTime(); - if (roleId && (!lastShown || now - parseInt(lastShown) > ONE_HOUR)) { + if (roleId && (!lastShown || now - parseInt(lastShown) > FIVE_MINUTES)) { setShowSurveyModal(true); Cookies.set("surveyLastShown", now.toString(), { expires: 1 }); } diff --git a/components/partials/auth/login-form.tsx b/components/partials/auth/login-form.tsx index 9dfbb146..68e0983c 100644 --- a/components/partials/auth/login-form.tsx +++ b/components/partials/auth/login-form.tsx @@ -17,6 +17,7 @@ import { postEmailValidation, postSetupEmail, requestOTP, + verifyOTPByUsername, } from "@/service/auth"; import { toast } from "sonner"; import { useRouter } from "@/components/navigation"; @@ -30,6 +31,7 @@ import { InputOTPSlot, } from "@/components/ui/input-otp"; import { error, loading } from "@/config/swal"; +import { data } from "jquery"; // Schema validasi menggunakan zod const schema = z.object({ @@ -57,22 +59,13 @@ const LoginForm = () => { const [email, setEmail] = useState(); const [category, setCategory] = useState("5"); - // const handleSignInClick = () => { - // handleSendOTP(); - // setIsOtpStep(true); - // }; - const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); const [oldEmail, setOldEmail] = useState(""); const [oldEmailValidate, setOldEmailValidate] = useState(""); const [newEmail, setNewEmail] = useState(""); const [newEmailValidate, setNewEmailValidate] = useState(""); - - // const handleSignInClick = () => { - // handleSendOTP(); - // setIsOtpStep(true); - // }; + const [otpValidate, setOtpValidate] = useState(""); const [otp1, setOtp1] = useState(); const [otp2, setOtp2] = useState(); @@ -90,6 +83,7 @@ const LoginForm = () => { const { register, handleSubmit, + getValues, formState: { errors }, } = useForm({ resolver: zodResolver(schema), @@ -103,37 +97,8 @@ const LoginForm = () => { event.preventDefault(); }; - // const handleNextStep = () => { - // setIsOtpStep(true); - // }; - - const handleSendOTP = async () => { - console.log(userIdentity, email); - - 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(); - } - }; - - // Fungsi submit form const onSubmit: SubmitHandler = async (data) => { try { - // const response = null; const response = await login({ ...data, grantType: "password", @@ -193,6 +158,13 @@ const LoginForm = () => { Cookies.set("state", profile?.data?.data?.userLevel?.name, { expires: 1, }); + Cookies.set( + "state-prov", + profile.data?.data?.userLevel?.province?.provName, + { + expires: 1, + } + ); setCookiesEncrypt("uie", profile?.data?.data?.id, { expires: 1, }); @@ -278,19 +250,16 @@ const LoginForm = () => { }; const handleEmailValidation = async () => { - const data = { - username: username, - password: password, - }; + const data = getValues(); - loading(); + // loading(); const response = await postEmailValidation(data); - close(); - if (response.error) { - error(response.message); + + if (response?.error) { + error(response?.message); return false; } - const msg = response.data?.message; + const msg = response?.data?.message; if (msg == "Continue to setup email") { setStep(2); } else if (msg == "Email is valid and OTP has been sent") { @@ -298,26 +267,27 @@ const LoginForm = () => { } else if (msg == "Username & password valid") { onSubmit(data); } else { - error("Username / password incorrect"); + setStep(2); } }; const handleSetupEmail = async () => { + const values = getValues(); const data = { - username: username, - password: password, + username: values.username, + password: values.password, oldEmail: oldEmail, newEmail: newEmail, }; - loading(); + // loading(); const response = await postSetupEmail(data); - close(); - if (response.error) { + // close(); + if (response?.error) { error(response.message); return false; } - const msg = response.data?.message; + const msg = response?.data?.message; if (msg == "Email is valid and OTP has been sent") { setStep(3); } else if (msg == "The old email is not same") { @@ -325,6 +295,52 @@ const LoginForm = () => { } }; + const checkEmail = (state: any, e: any) => { + const regEmail = + /^(([^\s"(),.:;<>@[\\\]]+(\.[^\s"(),.:;<>@[\\\]]+)*)|(".+"))@((\[(?:\d{1,3}\.){3}\d{1,3}])|(([\dA-Za-z\-]+\.)+[A-Za-z]{2,}))$/; + + if (regEmail.test(e)) { + if (state == "old") { + setOldEmailValidate(""); + setOldEmail(e); + } else { + setNewEmailValidate(""); + setNewEmail(e); + } + } else { + if (state == "old") { + setOldEmailValidate("Email tidak valid"); + setOldEmail(""); + } else { + setNewEmailValidate("Email tidak valid"); + setNewEmail(""); + } + } + }; + + const handleLoginOTP = async () => { + // const otp = `${otp1}${otp2}${otp3}${otp4}${otp5}${otp6}`; + const values = getValues(); + + if (otpValue.length === 6) { + loading(); + const response = await verifyOTPByUsername(values.username, otpValue); + + if (response?.error) { + error(response.message); + return false; + } + + close(); + + if (response?.message === "success") { + onSubmit(values); + } else { + setOtpValidate("Kode OTP Tidak Valid"); + } + } + }; + return (
{step === 1 ? ( @@ -391,7 +407,7 @@ const LoginForm = () => { ) : ( @@ -466,49 +489,37 @@ const LoginForm = () => {
- setOtpValue(e)}> + setOtpValue(val)} + > - setOtp1(e.target.value)} - onKeyUp={handleTypeOTP} - /> - setOtp2(e.target.value)} - onKeyUp={handleTypeOTP} - /> + + - setOtp3(e.target.value)} - onKeyUp={handleTypeOTP} - /> - setOtp4(e.target.value)} - onKeyUp={handleTypeOTP} - /> + + - setOtp5(e.target.value)} - onKeyUp={handleTypeOTP} - /> - setOtp6(e.target.value)} - onKeyUp={handleTypeOTP} - /> + + +

+ {otpValidate} +

- )} diff --git a/components/visualization/performance-polda.tsx b/components/visualization/performance-polda.tsx index fe4c72df..2bee1ac7 100644 --- a/components/visualization/performance-polda.tsx +++ b/components/visualization/performance-polda.tsx @@ -33,8 +33,8 @@ export default function PerformancePoldaViz() { levelName == "MABES POLRI" ? isInternational[0] ? "views/2023_04_MediaHUB-Viz_INTL_Rev202/db-konten-top10?" - : "views/2023_04_MediaHUB-Viz-POLDA_Rev201/db-ranking-polda?" - : `views/2023_09_db-ranking-polda_rev100/db-ranking-13?`; + : "views/2023_04_MediaHUB-Viz-POLDA_Rev201/db-konten-top10?" + : `/views/2023_09_db-ranking-polres-by-polda_rev100/db-ranking-by-polda?polda-selected=${poldaState}&`; const param = ":embed=yes&:toolbar=yes&:iframeSizedToWindow=true"; diff --git a/components/visualization/performance-polres.tsx b/components/visualization/performance-polres.tsx index 29d3dd96..257e3556 100644 --- a/components/visualization/performance-polres.tsx +++ b/components/visualization/performance-polres.tsx @@ -27,7 +27,7 @@ export default function PerformancePolresViz() { ? isInternational[0] ? "views/2023_04_MediaHUB-Viz_INTL_Rev202/db-konten-top10?" : "views/2023_04_MediaHUB-Viz-POLDA_Rev201/db-konten-top10?" - : `/views/2023_09_db-ranking-polres-by-polda_rev100/db-ranking-by-polda?polda-selected=${provState}&`; + : `/views/2023_09_db-ranking-polres-by-polda_rev100/db-ranking-by-polda?polda-selected=${poldaState}&`; const param = ":embed=yes&:toolbar=yes&:iframeSizedToWindow=true"; @@ -59,9 +59,7 @@ export default function PerformancePolresViz() {

- {isInternational[0] - ? "POLRES PERFORMANCE" - : "POLFORMANCE POLRES"} + {isInternational[0] ? "POLRES PERFORMANCE" : "POLFORMANCE POLRES"}

diff --git a/lib/menus.ts b/lib/menus.ts index 43fd02de..8cf7137d 100644 --- a/lib/menus.ts +++ b/lib/menus.ts @@ -3001,20 +3001,7 @@ export function getMenuList(pathname: string, t: any): Group[] { }, ], }, - // { - // groupLabel: "", - // id: "agenda-setting", - // menus: [ - // { - // id: "agenda-setting", - // href: "/contributor/agenda-setting", - // label: t("agenda-setting"), - // active: pathname.includes("/agenda-setting"), - // icon: "iconoir:journal-page", - // submenus: [], - // }, - // ], - // }, + { groupLabel: "", id: "management-user", @@ -3057,6 +3044,20 @@ export function getMenuList(pathname: string, t: any): Group[] { }, ], }, + // { + // groupLabel: "", + // id: "agenda-setting", + // menus: [ + // { + // id: "agenda-setting", + // href: "/contributor/agenda-setting", + // label: t("agenda-setting"), + // active: pathname.includes("/agenda-setting"), + // icon: "iconoir:journal-page", + // submenus: [], + // }, + // ], + // }, { groupLabel: "", id: "performance-polda", @@ -3352,20 +3353,20 @@ export function getMenuList(pathname: string, t: any): Group[] { }, ], }, - // { - // groupLabel: "", - // id: "agenda-setting", - // menus: [ - // { - // id: "agenda-setting", - // href: "/contributor/agenda-setting", - // label: t("agenda-setting"), - // active: pathname.includes("/agenda-setting"), - // icon: "iconoir:journal-page", - // submenus: [], - // }, - // ], - // }, + { + groupLabel: "", + id: "agenda-setting", + menus: [ + { + id: "agenda-setting", + href: "/contributor/agenda-setting", + label: t("agenda-setting"), + active: pathname.includes("/agenda-setting"), + icon: "iconoir:journal-page", + submenus: [], + }, + ], + }, { groupLabel: "", id: "performance-polres", @@ -3437,70 +3438,70 @@ export function getMenuList(pathname: string, t: any): Group[] { }, ], }, - { - groupLabel: "", - id: "settings", - menus: [ - { - id: "settings", - href: "/admin/settings", - label: t("settings"), - active: pathname.includes("/settinng"), - icon: "material-symbols:settings", - submenus: [ - { - href: "/admin/settings/category", - label: t("category"), - active: pathname === "/admin/settings/category", - icon: "heroicons:arrow-trending-up", - children: [], - }, - { - href: "/admin/settings/tag", - label: "Tag", - active: pathname === "/admin/settings/tag", - icon: "heroicons:arrow-trending-up", - children: [], - }, - { - href: "/admin/settings/banner", - label: "Banner", - active: pathname === "/admin/settings/banner", - icon: "heroicons:arrow-trending-up", - children: [], - }, - { - href: "/admin/settings/feedback", - label: "Feedback", - active: pathname === "/admin/settings/feedback", - icon: "heroicons:arrow-trending-up", - children: [], - }, - { - href: "/admin/settings/faq", - label: "FAQ", - active: pathname === "/admin/settings/faq", - icon: "heroicons:arrow-trending-up", - children: [], - }, - { - href: "https://nat-mediahub.polri.go.id/", - label: "Mediahub 2022", - active: pathname === "/admin/settings/mediahub-2022", - icon: "heroicons:arrow-trending-up", - children: [], - }, - { - href: "/admin/settings/privacy", - label: t("privacy"), - active: pathname === "/admin/settings/privacy", - icon: "heroicons:arrow-trending-up", - children: [], - }, - ], - }, - ], - }, + // { + // groupLabel: "", + // id: "settings", + // menus: [ + // { + // id: "settings", + // href: "/admin/settings", + // label: t("settings"), + // active: pathname.includes("/settinng"), + // icon: "material-symbols:settings", + // submenus: [ + // { + // href: "/admin/settings/category", + // label: t("category"), + // active: pathname === "/admin/settings/category", + // icon: "heroicons:arrow-trending-up", + // children: [], + // }, + // { + // href: "/admin/settings/tag", + // label: "Tag", + // active: pathname === "/admin/settings/tag", + // icon: "heroicons:arrow-trending-up", + // children: [], + // }, + // { + // href: "/admin/settings/banner", + // label: "Banner", + // active: pathname === "/admin/settings/banner", + // icon: "heroicons:arrow-trending-up", + // children: [], + // }, + // { + // href: "/admin/settings/feedback", + // label: "Feedback", + // active: pathname === "/admin/settings/feedback", + // icon: "heroicons:arrow-trending-up", + // children: [], + // }, + // { + // href: "/admin/settings/faq", + // label: "FAQ", + // active: pathname === "/admin/settings/faq", + // icon: "heroicons:arrow-trending-up", + // children: [], + // }, + // { + // href: "https://nat-mediahub.polri.go.id/", + // label: "Mediahub 2022", + // active: pathname === "/admin/settings/mediahub-2022", + // icon: "heroicons:arrow-trending-up", + // children: [], + // }, + // { + // href: "/admin/settings/privacy", + // label: t("privacy"), + // active: pathname === "/admin/settings/privacy", + // icon: "heroicons:arrow-trending-up", + // children: [], + // }, + // ], + // }, + // ], + // }, ]; } else { menusSelected = [ @@ -3632,6 +3633,20 @@ export function getMenuList(pathname: string, t: any): Group[] { }, ], }, + { + groupLabel: "", + id: "experts", + menus: [ + { + id: "experts", + href: "/admin/add-experts", + label: t("add-experts"), + active: pathname.includes("/add-experts"), + icon: "majesticons:user", + submenus: [], + }, + ], + }, { groupLabel: "", id: "settings", diff --git a/messages/en.json b/messages/en.json index 676beb89..bf6918a4 100644 --- a/messages/en.json +++ b/messages/en.json @@ -328,7 +328,7 @@ "performance-satker": "Performance Satker", "analysis": "Analysis", "management-content": "Content Management ", - "add-experts": "Add Experts", + "add-experts": "Experts", "category": "Category", "add-category": "Add Category", "tags": "Tags", diff --git a/messages/in.json b/messages/in.json index edaf14cc..dab71d24 100644 --- a/messages/in.json +++ b/messages/in.json @@ -329,7 +329,7 @@ "performance-satker": "Performa Satker", "analysis": "Analisa", "management-content": "Manajemen Konten", - "add-experts": "Tambah Tenaga Ahli", + "add-experts": "Tenaga Ahli", "category": "Kategori", "add-category": "Tambah Kategori", "tags": "Tag", diff --git a/service/auth.ts b/service/auth.ts index 3ed42e6f..ac094adb 100644 --- a/service/auth.ts +++ b/service/auth.ts @@ -70,12 +70,17 @@ export async function getProfile(token: any) { export async function postEmailValidation(data: any) { const url = "public/users/email-validation"; - return postAPIWithJson(url, data); + return httpPostInterceptor(url, data); } export async function postSetupEmail(data: any) { const url = "public/users/setup-email"; - return httpGetInterceptorWithToken({ url, data }); + return httpPostInterceptor(url, data); +} + +export async function verifyOTPByUsername(username: any, otp: any) { + const url = `public/users/verify-otp?username=${username}&otp=${otp}`; + return httpPostInterceptor(url); } export async function getSubjects() { diff --git a/service/http-config/http-interceptor-service.ts b/service/http-config/http-interceptor-service.ts index fed6665b..c695d280 100644 --- a/service/http-config/http-interceptor-service.ts +++ b/service/http-config/http-interceptor-service.ts @@ -175,10 +175,13 @@ export async function httpGetInterceptorWithToken(pathUrl: any, headers?: any) { } } -export async function postAPIWithJson(url: any, data: any, headers?: any) { +export async function postAPIWithJson(url: any, data: any, token: any) { + const headers = { + Authorization: `Bearer ${token}`, + }; const response = await axiosInstanceJson .post(url, data, { headers }) - .catch((error: any) => error.response); + .catch((error) => error.response); if (response?.status > 300) { return { error: true,