diff --git a/app/(admin)/admin/master-role/create/page.tsx b/app/(admin)/admin/master-role/create/page.tsx index ab2c6f9..bbf1ff8 100644 --- a/app/(admin)/admin/master-role/create/page.tsx +++ b/app/(admin)/admin/master-role/create/page.tsx @@ -1,10 +1,10 @@ -import FormMasterUserRole from '@/components/form/form-master-user-role' -import { Card } from '@nextui-org/react' +import FormMasterUserRole from "@/components/form/form-master-user-role"; +import { Card } from "@nextui-org/react"; export default function CreateMasterUserRolePage() { - return ( - - - - ) + return ( + + + + ); } diff --git a/components/form/form-master-user-role.tsx b/components/form/form-master-user-role.tsx index 0d2a685..5c75a26 100644 --- a/components/form/form-master-user-role.tsx +++ b/components/form/form-master-user-role.tsx @@ -1,164 +1,308 @@ -'use client' -import { error } from '@/config/swal'; -import { createMasterUser } from '@/service/master-user'; -import { createMasterUserRole } from '@/service/master-user-role'; -import { MasterUser } from '@/types/globals'; -import { zodResolver } from '@hookform/resolvers/zod'; -import { Button, Card, Input, Radio, RadioGroup, Select, SelectItem, Selection, Textarea } from '@nextui-org/react' -import Link from 'next/link'; -import { useRouter } from 'next/navigation'; -import React, { useState } from 'react' -import { useForm } from 'react-hook-form'; -import Swal from 'sweetalert2'; -import withReactContent from 'sweetalert2-react-content'; -import { z } from 'zod'; +"use client"; +import { error } from "@/config/swal"; +import { createMasterUser } from "@/service/master-user"; +import { createMasterUserRole } from "@/service/master-user-role"; +import { MasterUser } from "@/types/globals"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { + Button, + Card, + Checkbox, + Input, + Radio, + RadioGroup, + Select, + SelectItem, + Selection, + Textarea, +} from "@nextui-org/react"; +import Link from "next/link"; +import { useRouter } from "next/navigation"; +import React, { useEffect, useState } from "react"; +import { Controller, useFieldArray, useForm } from "react-hook-form"; +import Swal from "sweetalert2"; +import withReactContent from "sweetalert2-react-content"; +import { z } from "zod"; const masterUserSchema = z.object({ - code: z.string().min(1, { message: "Required" }), - description: z.string().min(1, { message: "Required" }), - levelNumber: z.string().min(1, { message: "Required" }), - name: z.string().min(1, { message: "Required" }), + code: z.string().min(1, { message: "Required" }), + description: z.string().min(1, { message: "Required" }), + name: z.string().min(1, { message: "Required" }), + userLevelId: z.string().min(1, { message: "Required" }), + userRoleAccess: z.array( + z.object({ + isAdminEnabled: z.boolean(), + isApprovalEnabled: z.boolean(), + isDeleteEnabled: z.boolean(), + isInsertEnabled: z.boolean(), + isUpdateEnabled: z.boolean(), + isViewEnabled: z.boolean(), + menuId: z.number(), + menuTitle: z.string(), + }) + ), }); +const menus = [{ id: 1, title: "Menu 1" }]; + export default function FormMasterUserRole() { - const router = useRouter(); - const MySwal = withReactContent(Swal); - const [code, setCode] = useState(); - const [description, setDescription] = useState(); - const [levelNumber, setLevelNumber] = useState(1); - const [name, setName] = useState(); + const router = useRouter(); + const MySwal = withReactContent(Swal); - const formOptions = { resolver: zodResolver(masterUserSchema) }; - type MicroIssueSchema = z.infer; - const { - register, - control, - handleSubmit, - setValue, - formState: { errors }, - } = useForm(formOptions); + const formOptions = { + resolver: zodResolver(masterUserSchema), + }; + type MicroIssueSchema = z.infer; + const { + register, + control, + handleSubmit, + setValue, + getValues, + formState: { errors }, + } = useForm(formOptions); + const { fields, append, remove } = useFieldArray({ + control, + name: "userRoleAccess", + }); + useEffect(() => { + const data: any = []; + menus.map((menu) => { + data.push({ + menuId: menu.id, + isAdminEnabled: false, + isApprovalEnabled: false, + isDeleteEnabled: false, + isInsertEnabled: false, + isUpdateEnabled: false, + isViewEnabled: false, + menuTitle: menu.title, + }); + }); + setValue("userRoleAccess", data); + }, []); - async function save(data: any) { - const formData = { - code: code, - description: description, - level_number: levelNumber, - name: name, + async function save(data: z.infer) { + const formData = { + code: data.code, + description: data.description, + statusId: 1, + userLevelIds: [Number(data.userLevelId)], + name: data.name, + userRoleAccess: data.userRoleAccess.map((roleAccess) => { + return { + isAdminEnabled: roleAccess.isAdminEnabled, + isApprovalEnabled: roleAccess.isApprovalEnabled, + isDeleteEnabled: roleAccess.isDeleteEnabled, + isInsertEnabled: roleAccess.isInsertEnabled, + isUpdateEnabled: roleAccess.isUpdateEnabled, + isViewEnabled: roleAccess.isViewEnabled, + menuId: roleAccess.menuId, }; - - console.log("Form MasterUser:", formData); - const response = await createMasterUserRole(formData); - - if (response?.error) { - error(response.message); - return false; - } - - successSubmit("/admin/master-role"); + }), }; - function successSubmit(redirect: any) { - MySwal.fire({ - title: "Sukses", - icon: "success", - confirmButtonColor: "#3085d6", - confirmButtonText: "OK", - }).then((result) => { - if (result.isConfirmed) { - router.push(redirect); - } - }); + console.log("Form MasterUser:", formData); + const response = await createMasterUserRole(formData); + + if (response?.error) { + error(response.message); + return false; } - async function onSubmit(data: any) { - MySwal.fire({ - title: "Simpan Data", - text: "", - icon: "warning", - showCancelButton: true, - cancelButtonColor: "#d33", - confirmButtonColor: "#3085d6", - confirmButtonText: "Simpan", - }).then((result) => { - if (result.isConfirmed) { - save(data); - } - }); - } + successSubmit("/admin/master-role"); + } - return ( - - - - - setCode(e.target.value)} - /> - {errors.code?.message} - - - setName(e.target.value)} - /> - {errors.name?.message} - - - - - - - {errors.code?.message} - - - - - Cancel - - - - Save - - - - - - ) + function successSubmit(redirect: any) { + MySwal.fire({ + title: "Sukses", + icon: "success", + confirmButtonColor: "#3085d6", + confirmButtonText: "OK", + }).then((result) => { + if (result.isConfirmed) { + router.push(redirect); + } + }); + } + + async function onSubmit(data: z.infer) { + MySwal.fire({ + title: "Simpan Data", + text: "", + icon: "warning", + showCancelButton: true, + cancelButtonColor: "#d33", + confirmButtonColor: "#3085d6", + confirmButtonText: "Simpan", + }).then((result) => { + if (result.isConfirmed) { + save(data); + } + }); + } + + return ( + + + + ( + + )} + /> + {errors.code?.message && ( + {errors.code?.message} + )} + ( + + )} + /> + {errors.name?.message && ( + {errors.name?.message} + )} + ( + + )} + /> + {errors.description?.message && ( + + {errors.description?.message} + + )} + ( + + )} + /> + {errors.userLevelId?.message && ( + + {errors.userLevelId?.message} + + )} + Menus + {fields.map((field, index) => ( + + {field.menuTitle} + + {/* Option */} + ( + + isAdminEnabled + + )} + /> + ( + + isApprovalEnabled + + )} + /> + ( + + isDeleteEnabled + + )} + /> + ( + + isInsertEnabled + + )} + /> + ( + + isUpdateEnabled + + )} + /> + ( + + isViewEnabled + + )} + /> + + + ))} + + + + Cancel + + + + Save + + + + + + ); } diff --git a/components/form/form-master-user.tsx b/components/form/form-master-user.tsx index df8cbfc..1803621 100644 --- a/components/form/form-master-user.tsx +++ b/components/form/form-master-user.tsx @@ -27,7 +27,20 @@ import { EyeFilledIcon, EyeSlashFilledIcon } from "../icons"; const masterUserSchema = z.object({ fullname: z.string().min(1, { message: "Required" }), username: z.string().min(1, { message: "Required" }), - password: z.string().min(1, { message: "Required" }), + password: z + .string() + .min(8, "Password harus memiliki minimal 8 karakter.") + .refine((password) => /[A-Z]/.test(password), { + message: "Password harus memiliki minimal satu huruf kapital.", + }) + .refine((password) => /[0-9]/.test(password), { + message: "Password harus memiliki minimal satu angka.", + }) + .refine((password) => /[!@#$%^&*(),.?":{}|<>]/.test(password), { + message: "Password harus memiliki minimal satu simbol.", + }), + passwordValidate: z.string().min(1, { message: "Required" }), + email: z.string().min(1, { message: "Required" }), identityType: z.string().min(1, { message: "Required" }), identityNumber: z.string().min(1, { message: "Required" }), @@ -114,8 +127,12 @@ const educationGrade = [ export default function FormMasterUser() { const router = useRouter(); const MySwal = withReactContent(Swal); - const [isVisible, setIsVisible] = useState(false); - const toggleVisibility = () => setIsVisible(!isVisible); + const [isVisible, setIsVisible] = useState([false, false]); + const toggleVisibility = (type: number) => { + setIsVisible( + type === 0 ? [!isVisible[0], isVisible[1]] : [isVisible[0], !isVisible[1]] + ); + }; const formOptions = { resolver: zodResolver(masterUserSchema), @@ -129,6 +146,7 @@ export default function FormMasterUser() { control, handleSubmit, formState: { errors }, + setError, } = useForm(formOptions); async function save(data: z.infer) { @@ -173,19 +191,26 @@ export default function FormMasterUser() { } async function onSubmit(data: z.infer) { - MySwal.fire({ - title: "Simpan Data", - text: "", - icon: "warning", - showCancelButton: true, - cancelButtonColor: "#d33", - confirmButtonColor: "#3085d6", - confirmButtonText: "Simpan", - }).then((result) => { - if (result.isConfirmed) { - save(data); - } - }); + if (data.password === data.passwordValidate) { + MySwal.fire({ + title: "Simpan Data", + text: "", + icon: "warning", + showCancelButton: true, + cancelButtonColor: "#d33", + confirmButtonColor: "#3085d6", + confirmButtonText: "Simpan", + }).then((result) => { + if (result.isConfirmed) { + save(data); + } + }); + } else { + setError("passwordValidate", { + type: "manual", + message: "Password harus sama.", + }); + } } return ( @@ -237,7 +262,7 @@ export default function FormMasterUser() { name="password" render={({ field: { onChange, value } }) => ( toggleVisibility(0)} > - {isVisible ? ( + {isVisible[0] ? ( ) : ( @@ -265,6 +290,42 @@ export default function FormMasterUser() { {errors.password?.message && ( {errors.password?.message} )} + ( + toggleVisibility(1)} + > + {isVisible[1] ? ( + + ) : ( + + )} + + } + /> + )} + /> + {errors.passwordValidate?.message && ( + + {errors.passwordValidate?.message} + + )} + - Laki-laki - Perempuan + Laki-laki + Perempuan )} />
{errors.code?.message}
{errors.name?.message}
+ {errors.description?.message} +
+ {errors.userLevelId?.message} +
Menus
{field.menuTitle}
{errors.password?.message}
+ {errors.passwordValidate?.message} +