Fix: validasi

Deksripsi:
- Penambahan fitur kirim ulang kode
## No Issue
This commit is contained in:
2024-11-06 13:57:54 +08:00
parent 8cedf7db61
commit a6548f7b36
11 changed files with 580 additions and 484 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "hipmi", "name": "hipmi",
"version": "1.0.12", "version": "1.1.0",
"private": true, "private": true,
"prisma": { "prisma": {
"seed": "npx tsx prisma/seed.ts" "seed": "npx tsx prisma/seed.ts"
@@ -88,7 +88,6 @@
"utf-8-validate": "^6.0.3", "utf-8-validate": "^6.0.3",
"uuid": "^9.0.1", "uuid": "^9.0.1",
"wibu": "bipproduction/wibu", "wibu": "bipproduction/wibu",
"wibu-realtime": "bipproduction/wibu-realtime",
"yaml": "^2.3.2" "yaml": "^2.3.2"
} }
} }

View File

@@ -6,7 +6,7 @@ import { RouterAuth } from "@/app/lib/router_hipmi/router_auth";
export default async function Page({ params }: { params: { id: string } }) { export default async function Page({ params }: { params: { id: string } }) {
let kodeId = params.id; let kodeId = params.id;
const dataOtp = await auth_getCodeOtpByNumber({ kodeId: kodeId }); const dataOtp = await auth_getCodeOtpByNumber({ kodeId: kodeId });
if (dataOtp === null) return redirect(RouterAuth.login); // if (dataOtp === null) return redirect(RouterAuth.login);
return <Validasi dataOtp={dataOtp} />; return <Validasi dataOtp={dataOtp as any} />;
} }

View File

@@ -1,16 +1,17 @@
import ComponentGlobal_HeaderTamplate from "@/app_modules/_global/header_tamplate"; import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
import UIGlobal_LayoutTamplate from "@/app_modules/_global/ui/ui_layout_tamplate"; import { CobaRealtime } from "@/app_modules/zCoba/coba_realtime";
import Coba_TestLoading from "@/app_modules/zCoba";
import { Text } from "@mantine/core";
export default async function Page() { export default async function Page() {
await new Promise((a, b) => { await new Promise((a, b) => {
setTimeout(a, 3000); setTimeout(a, 3000);
}); });
const userLoginId = await funGetUserIdByToken();
return ( return (
<> <>
<Coba_TestLoading /> <CobaRealtime userLoginId={userLoginId} />
{/* <Coba_TestLoading userLoginId={userLoginId} /> */}
{/* <ComponentGlobal_UI_LayoutTamplate /> */} {/* <ComponentGlobal_UI_LayoutTamplate /> */}
</> </>
); );

View File

@@ -0,0 +1,40 @@
"use server";
import { prisma } from "@/app/lib";
import { randomOTP } from "./rondom_otp";
export async function auth_funResendCode({ nomor }: { nomor: string }) {
const codeOtp = randomOTP();
try {
const res = await fetch(
`https://wa.wibudev.com/code?nom=${nomor}&text=HIPMI - Kode ini bersifat RAHASIA dan JANGAN DI BAGIKAN KEPADA SIAPAPUN, termasuk anggota ataupun pengurus HIPMI lainnya.
\n
>> Kode OTP anda: ${codeOtp}.
`
);
const sendWa = await res.json();
if (sendWa.status !== "success")
return { status: 400, message: "WA Tidak Terdaftar", kodeId: {} };
const createOtpId = await prisma.kodeOtp.create({
data: {
nomor: nomor,
otp: codeOtp,
},
});
if (!createOtpId)
return { status: 400, message: "Gagal Membuat Kode OTP", kodeId: {} };
return {
status: 200,
message: "Kode Verifikasi Dikirim",
kodeId: createOtpId.id,
};
} catch (error) {
console.log(error);
return { status: 500, message: "Server Error !!!", kodeId: {} };
}
}

View File

@@ -0,0 +1,3 @@
import { auth_funResendCode } from "./fun_resend_code";
export { auth_funResendCode };

View File

@@ -3,15 +3,16 @@
import { RouterAdminDashboard } from "@/app/lib/router_hipmi/router_admin"; import { RouterAdminDashboard } from "@/app/lib/router_hipmi/router_admin";
import { RouterAuth } from "@/app/lib/router_hipmi/router_auth"; import { RouterAuth } from "@/app/lib/router_hipmi/router_auth";
import { RouterHome } from "@/app/lib/router_hipmi/router_home"; import { RouterHome } from "@/app/lib/router_hipmi/router_home";
import { GlobalEnv } from "@/app/lib/token";
import { import {
AccentColor, AccentColor,
MainColor, MainColor,
} from "@/app_modules/_global/color/color_pallet"; } from "@/app_modules/_global/color/color_pallet";
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil"; import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil";
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global/notifikasi_peringatan"; import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global/notifikasi_peringatan";
import { UIGlobal_LayoutDefault } from "@/app_modules/_global/ui";
import { import {
ActionIcon, ActionIcon,
BackgroundImage,
Box, Box,
Button, Button,
Center, Center,
@@ -20,23 +21,33 @@ import {
Text, Text,
Title, Title,
} from "@mantine/core"; } from "@mantine/core";
import { useFocusTrap } from "@mantine/hooks"; import { useFocusTrap, useShallowEffect } from "@mantine/hooks";
import { Prisma } from "@prisma/client";
import { IconChevronLeft } from "@tabler/icons-react"; import { IconChevronLeft } from "@tabler/icons-react";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { useState } from "react"; import { useState } from "react";
import { auth_funResendCode } from "../fun";
import { auth_funDeleteAktivasiKodeOtpById } from "../fun/fun_edit_aktivasi_kode_otp_by_id"; import { auth_funDeleteAktivasiKodeOtpById } from "../fun/fun_edit_aktivasi_kode_otp_by_id";
import { auth_funValidasi } from "../fun/fun_validasi"; import { auth_funValidasi } from "../fun/fun_validasi";
import { GlobalEnv } from "@/app/lib/token";
import { UIGlobal_LayoutDefault } from "@/app_modules/_global/ui";
export default function Validasi({ dataOtp }: { dataOtp: any }) { export default function Validasi({
dataOtp,
}: {
dataOtp: Prisma.KodeOtpSelect;
}) {
const router = useRouter(); const router = useRouter();
const [nomor, setnomor] = useState(dataOtp.nomor); const nomor = dataOtp.nomor as any;
const [code, setCode] = useState(dataOtp.otp); const code = dataOtp.otp as any;
const [inputCode, setInputOtp] = useState(""); const [inputCode, setInputOtp] = useState("");
const focusTrapRef = useFocusTrap(); const focusTrapRef = useFocusTrap();
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [counter, setCounter] = useState(60);
useShallowEffect(() => {
counter > 0 && setTimeout(() => setCounter(counter - 1), 1000);
}, [counter]);
async function onVerifikasi() { async function onVerifikasi() {
if (!inputCode) if (!inputCode)
return ComponentGlobal_NotifikasiPeringatan("Lengkapi Kode"); return ComponentGlobal_NotifikasiPeringatan("Lengkapi Kode");
@@ -48,7 +59,9 @@ export default function Validasi({ dataOtp }: { dataOtp: any }) {
HIPMI_PWD: GlobalEnv.value?.WIBU_PWD as string, HIPMI_PWD: GlobalEnv.value?.WIBU_PWD as string,
}); });
if (res.status === 200) { if (res.status === 200) {
const resAktivasi = await auth_funDeleteAktivasiKodeOtpById(dataOtp.id); const resAktivasi = await auth_funDeleteAktivasiKodeOtpById(
dataOtp.id as any
);
if (resAktivasi.status === 200) { if (resAktivasi.status === 200) {
if (res.role === "1") { if (res.role === "1") {
ComponentGlobal_NotifikasiBerhasil(res.message); ComponentGlobal_NotifikasiBerhasil(res.message);
@@ -85,6 +98,16 @@ export default function Validasi({ dataOtp }: { dataOtp: any }) {
router.back(); router.back();
} }
async function onResendCode() {
const res = await auth_funResendCode({ nomor: nomor });
if (res.status === 200) {
ComponentGlobal_NotifikasiBerhasil(res.message, 2000);
router.push(RouterAuth.validasi + res.kodeId, { scroll: false });
} else {
ComponentGlobal_NotifikasiPeringatan(res.message);
}
}
return ( return (
<> <>
<UIGlobal_LayoutDefault> <UIGlobal_LayoutDefault>
@@ -102,24 +125,25 @@ export default function Validasi({ dataOtp }: { dataOtp: any }) {
</ActionIcon> </ActionIcon>
</Box> </Box>
<Stack align="center" justify="center" h={"100vh"} spacing={70}> <Stack align="center" justify="center" h={"100vh"} spacing={50}>
<Title order={2} color={MainColor.yellow}> <Title order={2} color={MainColor.yellow}>
Verifikasi Kode OTP Verifikasi Kode OTP
</Title> </Title>
<Stack spacing={0} align="center"> <Stack spacing={"md"} align="center">
<Text fz={"xs"} c={"white"}> <Stack spacing={0} align="center">
Masukan 4 digit kode otp <Text c={"white"}>Masukan 4 digit kode otp</Text>
</Text> <Text c={"white"}>
<Text fz={"xs"} c={"white"}> Yang dikirim ke{" "}
Yang dikirim ke{" "} <Text span inherit fw={"bold"}>
<Text span inherit fw={"bold"}> {" "}
{" "} +{nomor}
+{nomor} </Text>
</Text> </Text>
</Text> </Stack>
<Center> <Center>
<PinInput <PinInput
size="xl"
type={"number"} type={"number"}
ref={focusTrapRef} ref={focusTrapRef}
spacing={"md"} spacing={"md"}
@@ -129,6 +153,19 @@ export default function Validasi({ dataOtp }: { dataOtp: any }) {
}} }}
/> />
</Center> </Center>
<Text fs="italic" mt={"sm"} c={"white"}>
Tidak menerima kode ?{" "}
{counter > 0 ? (
<Text fw={"bold"} inherit span>
{counter + "s"}
</Text>
) : (
<Text inherit span onClick={() => onResendCode()}>
Kirim ulang
</Text>
)}
</Text>
</Stack> </Stack>
<Button <Button
w={300} w={300}

View File

@@ -11,15 +11,15 @@ export function CheckCookies_UiLayout({
}) { }) {
const router = useRouter(); const router = useRouter();
useShallowEffect(() => { // useShallowEffect(() => {
onCheckCookies(); // onCheckCookies();
}, []); // }, []);
async function onCheckCookies() { async function onCheckCookies() {
const cek = await fetch("/api/check-cookies"); const cek = await fetch("/api/check-cookies");
const result = await cek.json(); const result = await cek.json();
if (result.success === false) { if (result.success === false) {
router.push(RouterAuth.login); router.push(RouterAuth.login, { scroll: false });
} }
} }

View File

@@ -0,0 +1,48 @@
"use client";
import { useWibuRealtime, WibuRealtime } from "wibu";
import { v4 } from "uuid";
import { Stack, Title, Button } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import Countdown from "react-countdown";
export function CobaRealtime({ userLoginId }: { userLoginId: string }) {
const WIBU_REALTIME_TOKEN: any = process.env.NEXT_PUBLIC_WIBU_REALTIME_TOKEN;
// const [dataRealTime, setDataRealTime] = useWibuRealtime({
// WIBU_REALTIME_TOKEN: WIBU_REALTIME_TOKEN,
// project: "hipmi",
// });
useShallowEffect(() => {
// WibuRealtime.init({
// WIBU_REALTIME_TOKEN: WIBU_REALTIME_TOKEN,
// project: "hipmi",
// onData(data) {
// console.log(data);
// },
// });
// return () => {
// WibuRealtime.cleanup();
// };
}, []);
return (
<>
<Stack w={200} p={"lg"}>
<Title order={6}>User {userLoginId}</Title>
<Button
onClick={() => {
// WibuRealtime.setData({
// id: v4(),
// name: "bagas",
// age: 28,
// });
}}
>
Cek
</Button>
</Stack>
</>
);
}

View File

@@ -1,17 +1,14 @@
"use client"; "use client";
import { import { ActionIcon, Box, Button, Stack, Title } from "@mantine/core";
ActionIcon,
Box,
Button,
Stack
} from "@mantine/core";
import { useState } from "react"; import { useState } from "react";
import { IconPencilPlus } from "@tabler/icons-react"; import { IconPencilPlus } from "@tabler/icons-react";
import _ from "lodash"; import _ from "lodash";
import UIGlobal_LayoutTamplate from "../_global/ui/ui_layout_tamplate"; import UIGlobal_LayoutTamplate from "../_global/ui/ui_layout_tamplate";
import { useShallowEffect } from "@mantine/hooks";
import { WibuRealtime } from "wibu";
import { v4 } from "uuid";
const newData = Array(20) const newData = Array(20)
.fill(0) .fill(0)
@@ -35,89 +32,84 @@ const data2 = [
}, },
]; ];
export default function Coba_TestLoading() { export default function Coba_TestLoading({
const [data, setData] = useState(data2); userLoginId,
}: {
userLoginId: string;
}) {
// const [data, setData] = useState(data2);
const [openDrawer, setOpenDrawer] = useState(false); const [openDrawer, setOpenDrawer] = useState(false);
const [newData, setNewData] = useState({});
useShallowEffect(() => {
WibuRealtime.init({
WIBU_REALTIME_TOKEN: process.env.WIBU_REALTIME_KEY as any,
project: "hipmi",
onData(data) {
console.log(data);
},
});
return () => {
WibuRealtime.cleanup();
};
}, []);
return ( return (
<> <>
<UIGlobal_LayoutTamplate> <Stack w={200} p={"lg"}>
{/* <CreateButton /> */} <Title>User {userLoginId}</Title>
<Button onClick={() => setOpenDrawer(true)}>Click</Button> <Button
</UIGlobal_LayoutTamplate> onClick={() => {
WibuRealtime.setData({
id: v4(),
userId: userLoginId,
data: `Ini dari user ${userLoginId}`,
});
}}
>
Cek
</Button>
</Stack>
</> </>
); );
// return (
// <>
// <UIGlobal_LayoutTamplate>
// {/* <CreateButton /> */}
// <Button onClick={() => setOpenDrawer(true)}>Click</Button>
// </UIGlobal_LayoutTamplate>
// </>
// );
// Clone data // Clone data
return ( // return (
<> // <>
<Box mt={"lg"}> // <Box mt={"lg"}>
<Stack> // <Stack>
<Button // <Button
onClick={() => { // onClick={() => {
const clone = _.clone(data); // const clone = _.clone(data);
const dataBaru = clone.map( // const dataBaru = clone.map(
(e) => ( // (e) => (
e.id === 1, // e.id === 1,
{ // {
...e, // ...e,
name: e.id === 1 ? "firman" : e.name, // name: e.id === 1 ? "firman" : e.name,
age: e.id === 1 ? 30 : e.age, // age: e.id === 1 ? 30 : e.age,
} // }
) // )
); // );
setData(dataBaru); // setData(dataBaru);
}} // }}
> // >
Update // Update
</Button> // </Button>
</Stack> // </Stack>
<pre>{JSON.stringify(data, null, 2)}</pre> // <pre>{JSON.stringify(data, null, 2)}</pre>
</Box> // </Box>
</> // </>
); // );
}
function CreateButton() {
return (
<>
<ActionIcon
p={3}
variant="filled"
radius={"xl"}
size={"xl"}
style={{
position: "absolute",
zIndex: 1,
bottom: 150,
right: 30,
}}
>
<IconPencilPlus size={30} />
</ActionIcon>
{/* <Affix
bg={"blue"}
withinPortal
portalProps={{}}
position={{ bottom: rem(150), right: rem(30) }}
>
<ActionIcon
style={{
transition: "0.5s",
border: `1px solid ${AccentColor.skyblue}`,
}}
bg={AccentColor.blue}
size={"xl"}
radius={"xl"}
variant="transparent"
onClick={() => {}}
>
<IconPencilPlus color="white" />
</ActionIcon>
</Affix> */}
</>
);
} }

View File

@@ -5,5 +5,5 @@ Client_KEY : process.env.Client_KEY,
Server_KEY : process.env.Server_KEY, Server_KEY : process.env.Server_KEY,
MAPBOX_TOKEN : process.env.MAPBOX_TOKEN, MAPBOX_TOKEN : process.env.MAPBOX_TOKEN,
WS_APIKEY : process.env.WS_APIKEY, WS_APIKEY : process.env.WS_APIKEY,
WIBU_REALTIME_KEY : process.env.WIBU_REALTIME_KEY NEXT_PUBLIC_WIBU_REALTIME_TOKEN : process.env.NEXT_PUBLIC_WIBU_REALTIME_TOKEN
} }

710
yarn.lock

File diff suppressed because it is too large Load Diff