feat:userlevel form
This commit is contained in:
parent
e4dd1da844
commit
66aaa5f0b3
|
|
@ -1,12 +1,34 @@
|
|||
import { AddIcon } from "@/components/icons";
|
||||
import MappingUserLevel from "@/components/table/master/master-user-level/mapping-user-level";
|
||||
import MasterUserLevelTable from "@/components/table/master/master-user-level/master-user-level-table";
|
||||
import { Button } from "@heroui/button";
|
||||
import Link from "next/link";
|
||||
import React from "react";
|
||||
|
||||
const AdminMasterUserLevel = () => {
|
||||
return (
|
||||
// <div><MasterUserLevelTable /></div>
|
||||
<div>
|
||||
<MappingUserLevel />
|
||||
// <div>
|
||||
// <MasterUserLevelTable />
|
||||
// </div>
|
||||
// <div>
|
||||
// <MappingUserLevel />
|
||||
// </div>
|
||||
<div className="overflow-x-hidden overflow-y-scroll">
|
||||
<div className="px-2 md:px-4 md:py-4 w-full">
|
||||
<div className="bg-white shadow-lg dark:bg-[#18181b] rounded-xl py-3">
|
||||
<Link href="/admin/master-user-level/create" className="mx-3">
|
||||
<Button
|
||||
size="md"
|
||||
color="primary"
|
||||
className="bg-[#F07C00] text-white"
|
||||
>
|
||||
Pengguna Baru
|
||||
<AddIcon />
|
||||
</Button>
|
||||
</Link>
|
||||
<MasterUserLevelTable />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
import CreateMasterUserLevelForm from "@/components/form/master/master-user-level/master-user-level-form";
|
||||
import React from "react";
|
||||
|
||||
const AdminMasterUserLevelCreate = () => {
|
||||
return (
|
||||
<div>
|
||||
<CreateMasterUserLevelForm />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AdminMasterUserLevelCreate;
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
import EditUserLevelForm from "@/components/form/master/master-user-level/edit-user-level-form";
|
||||
import React from "react";
|
||||
|
||||
const AdminMasterUserLevelCreate = () => {
|
||||
return <EditUserLevelForm />;
|
||||
};
|
||||
|
||||
export default AdminMasterUserLevelCreate;
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
import { AddIcon } from "@/components/icons";
|
||||
import MappingUserLevel from "@/components/table/master/master-user-level/mapping-user-level";
|
||||
import MasterUserLevelTable from "@/components/table/master/master-user-level/master-user-level-table";
|
||||
import { Button } from "@heroui/button";
|
||||
import Link from "next/link";
|
||||
import React from "react";
|
||||
|
||||
const AdminMasterUserLevel = () => {
|
||||
return (
|
||||
// <div>
|
||||
// <MasterUserLevelTable />
|
||||
// </div>
|
||||
// <div>
|
||||
// <MappingUserLevel />
|
||||
// </div>
|
||||
<div className="overflow-x-hidden overflow-y-scroll">
|
||||
<div className="px-2 md:px-4 md:py-4 w-full">
|
||||
<div className="bg-white shadow-lg dark:bg-[#18181b] rounded-xl py-3">
|
||||
<Link href="/admin/user-level/create" className="mx-3">
|
||||
<Button
|
||||
size="md"
|
||||
color="primary"
|
||||
className="bg-[#F07C00] text-white"
|
||||
>
|
||||
Pengguna Baru
|
||||
<AddIcon />
|
||||
</Button>
|
||||
</Link>
|
||||
<MasterUserLevelTable />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AdminMasterUserLevel;
|
||||
|
|
@ -29,6 +29,7 @@ import {
|
|||
import ReactSelect from "react-select";
|
||||
import makeAnimated from "react-select/animated";
|
||||
import {
|
||||
Calendar,
|
||||
Checkbox,
|
||||
Chip,
|
||||
Modal,
|
||||
|
|
@ -36,13 +37,16 @@ import {
|
|||
ModalContent,
|
||||
ModalFooter,
|
||||
ModalHeader,
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
Select,
|
||||
SelectItem,
|
||||
SelectSection,
|
||||
useDisclosure,
|
||||
} from "@heroui/react";
|
||||
import GenerateSingleArticleForm from "./generate-ai-single-form";
|
||||
import { htmlToString } from "@/utils/global";
|
||||
import { convertDateFormatNoTime, htmlToString } from "@/utils/global";
|
||||
import { close, error, loading } from "@/config/swal";
|
||||
import { useRouter } from "next/navigation";
|
||||
import Link from "next/link";
|
||||
|
|
@ -130,10 +134,7 @@ export default function CreateArticleForm() {
|
|||
const [isScheduled, setIsScheduled] = useState(false);
|
||||
const [timeValue, setTimeValue] = useState("");
|
||||
|
||||
const [startDateValue, setStartDateValue] = useState({
|
||||
startDate: null,
|
||||
endDate: null,
|
||||
});
|
||||
const [startDateValue, setStartDateValue] = useState<any>(null);
|
||||
|
||||
const { getRootProps, getInputProps } = useDropzone({
|
||||
onDrop: (acceptedFiles) => {
|
||||
|
|
@ -766,15 +767,15 @@ export default function CreateArticleForm() {
|
|||
{errors?.tags && (
|
||||
<p className="text-red-400 text-sm mb-3">{errors.tags?.message}</p>
|
||||
)}
|
||||
{/* <div className="flex flex-col gap-2 mt-3">
|
||||
<div className="flex flex-col gap-2 mt-3">
|
||||
<Switch isSelected={isScheduled} onValueChange={setIsScheduled}>
|
||||
Publish dengan Jadwal
|
||||
<p className="text-black">Publish dengan Jadwal</p>
|
||||
</Switch>
|
||||
{isScheduled && (
|
||||
<div className="flex flex-col lg:flex-row gap-3">
|
||||
<div className="w-full lg:w-[140px] flex flex-col gal-2 ">
|
||||
<p className="text-sm">Tanggal</p>
|
||||
<Datepicker
|
||||
{/* <Datepicker
|
||||
value={startDateValue}
|
||||
displayFormat="DD/MM/YYYY"
|
||||
popoverDirection="down"
|
||||
|
|
@ -782,9 +783,30 @@ export default function CreateArticleForm() {
|
|||
useRange={false}
|
||||
onChange={(e: any) => setStartDateValue(e)}
|
||||
inputClassName="z-50 w-full text-xs lg:text-sm bg-white dark bg-black border-1 border-gray-200 px-2 py-[6px] rounded-sm lg:rounded-lg h-[30px] lg:h-[40px] text-gray-600 dark:text-gray-300"
|
||||
/>
|
||||
/> */}
|
||||
<Popover
|
||||
placement="bottom"
|
||||
classNames={{ content: ["!bg-transparent", "p-0"] }}
|
||||
>
|
||||
<PopoverTrigger>
|
||||
<Button
|
||||
className="w-full !h-[30px] lg:h-[40px] border-1 rounded-lg text-black"
|
||||
variant="bordered"
|
||||
>
|
||||
{startDateValue
|
||||
? convertDateFormatNoTime(startDateValue)
|
||||
: "-"}
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="bg-transparent">
|
||||
<Calendar
|
||||
value={startDateValue}
|
||||
onChange={setStartDateValue}
|
||||
/>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</div>
|
||||
<div className="w-[140px] flex flex-col gal-2 ">
|
||||
{/* <div className="w-[140px] flex flex-col gal-2 ">
|
||||
<p className="text-sm">Waktu</p>
|
||||
<Input
|
||||
type="time"
|
||||
|
|
@ -802,10 +824,10 @@ export default function CreateArticleForm() {
|
|||
],
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
)}
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-row justify-end gap-3">
|
||||
|
|
@ -813,7 +835,7 @@ export default function CreateArticleForm() {
|
|||
color="primary"
|
||||
type="submit"
|
||||
isDisabled={
|
||||
(isScheduled && startDateValue.startDate == null) ||
|
||||
(isScheduled && startDateValue == null) ||
|
||||
(isScheduled && timeValue == "")
|
||||
}
|
||||
onClick={() =>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,358 @@
|
|||
"use client";
|
||||
import {
|
||||
Button,
|
||||
Input,
|
||||
Radio,
|
||||
RadioGroup,
|
||||
Select,
|
||||
SelectItem,
|
||||
SelectSection,
|
||||
Slider,
|
||||
Switch,
|
||||
Tab,
|
||||
Table,
|
||||
Tabs,
|
||||
Textarea,
|
||||
User,
|
||||
} from "@heroui/react";
|
||||
import React, {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import { TimesIcon } from "@/components/icons";
|
||||
import Link from "next/link";
|
||||
import { useParams, useRouter } from "next/navigation";
|
||||
import { close, error, loading } from "@/config/swal";
|
||||
import Swal from "sweetalert2";
|
||||
import withReactContent from "sweetalert2-react-content";
|
||||
import dynamic from "next/dynamic";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import * as z from "zod";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import {
|
||||
createUserLevels,
|
||||
editUserLevels,
|
||||
getAllUserLevels,
|
||||
getUserLevels,
|
||||
} from "@/services/user-levels/user-levels-service";
|
||||
import ReactSelect from "react-select";
|
||||
import makeAnimated from "react-select/animated";
|
||||
|
||||
const createArticleSchema = z.object({
|
||||
name: z.string().min(2, {
|
||||
message: "Required",
|
||||
}),
|
||||
aliasName: z.string().optional(),
|
||||
group: z.string().min(2, {
|
||||
message: "Required",
|
||||
}),
|
||||
});
|
||||
|
||||
const groups = [
|
||||
{ id: 1, name: "Mabes", value: "mabes", level: 1 },
|
||||
{ id: 2, name: "Polda", value: "polda", level: 2 },
|
||||
{ id: 3, name: "Satker", value: "satker", level: 2 },
|
||||
{ id: 4, name: "Polres", value: "polres", level: 3 },
|
||||
{ id: 5, name: "Subdiv", value: "subdiv", level: 3 },
|
||||
];
|
||||
|
||||
export default function EditUserLevelForm() {
|
||||
const router = useRouter();
|
||||
const MySwal = withReactContent(Swal);
|
||||
const animatedComponents = makeAnimated();
|
||||
const [needApproval, setNeedApproval] = useState(false);
|
||||
const [parentList, setParentList] = useState<any>([]);
|
||||
const [selectedParent, setSelectedParent] = useState<any>();
|
||||
const params = useParams();
|
||||
const id = params?.id;
|
||||
|
||||
const formOptions = {
|
||||
resolver: zodResolver(createArticleSchema),
|
||||
defaultValues: { name: "", group: "" },
|
||||
};
|
||||
type UserSettingSchema = z.infer<typeof createArticleSchema>;
|
||||
const {
|
||||
register,
|
||||
control,
|
||||
handleSubmit,
|
||||
formState: { errors, isValid },
|
||||
setValue,
|
||||
getValues,
|
||||
watch,
|
||||
setError,
|
||||
clearErrors,
|
||||
} = useForm<UserSettingSchema>(formOptions);
|
||||
|
||||
const watchName = watch("name");
|
||||
const generateSlug = (title: string) => {
|
||||
return title
|
||||
.toLowerCase()
|
||||
.trim()
|
||||
.replace(/[^\w\s-]/g, "")
|
||||
.replace(/\s+/g, "-");
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setValue("aliasName", generateSlug(watchName));
|
||||
}, [watchName]);
|
||||
|
||||
const findSelectedLevel = (group: string) => {
|
||||
const selectedLevel = groups.find((a) => a.value === group);
|
||||
return selectedLevel ? selectedLevel : null;
|
||||
};
|
||||
|
||||
const save = async (data: any) => {
|
||||
const findParent = (group: string) => {
|
||||
if (group === "mabes") {
|
||||
return 0;
|
||||
} else if (group === "polda" || group === "satker") {
|
||||
if (group === "polda") {
|
||||
return 1;
|
||||
} else {
|
||||
return 555;
|
||||
}
|
||||
} else {
|
||||
return selectedParent?.id;
|
||||
}
|
||||
};
|
||||
|
||||
const request = {
|
||||
name: data.name,
|
||||
aliasName: data.aliasName,
|
||||
levelNumber: findSelectedLevel(data.group)?.level,
|
||||
isActive: true,
|
||||
group: data.group,
|
||||
parentLevelId: findParent(data.group),
|
||||
provinceId: 0,
|
||||
isApprovalActive: needApproval,
|
||||
};
|
||||
|
||||
loading();
|
||||
const res = await editUserLevels(String(id), request);
|
||||
if (res.error) {
|
||||
error(res.message);
|
||||
return false;
|
||||
}
|
||||
close();
|
||||
successSubmit("/admin/user-level");
|
||||
};
|
||||
|
||||
async function onSubmit(data: any) {
|
||||
MySwal.fire({
|
||||
title: "Save Data",
|
||||
text: "",
|
||||
icon: "warning",
|
||||
showCancelButton: true,
|
||||
cancelButtonColor: "#d33",
|
||||
confirmButtonColor: "#3085d6",
|
||||
confirmButtonText: "Save",
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
save(data);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function successSubmit(redirect: string) {
|
||||
MySwal.fire({
|
||||
title: "Sukses",
|
||||
icon: "success",
|
||||
confirmButtonColor: "#3085d6",
|
||||
confirmButtonText: "OK",
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
router.push(redirect);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
fetchCategory();
|
||||
}, []);
|
||||
|
||||
const fetchCategory = async () => {
|
||||
loading();
|
||||
const request = {
|
||||
limit: 10,
|
||||
};
|
||||
const res = await getAllUserLevels(request);
|
||||
close();
|
||||
if (res?.data?.data) {
|
||||
setupParent(res?.data?.data);
|
||||
}
|
||||
};
|
||||
|
||||
const setupParent = (data: any) => {
|
||||
const temp = [];
|
||||
for (const element of data) {
|
||||
temp.push({
|
||||
id: element.id,
|
||||
label: element.name,
|
||||
value: element.aliasName,
|
||||
});
|
||||
}
|
||||
setParentList(temp);
|
||||
};
|
||||
|
||||
const selectedGroup = watch("group");
|
||||
|
||||
useEffect(() => {
|
||||
initFetch();
|
||||
}, [parentList]);
|
||||
|
||||
const initFetch = async () => {
|
||||
const res = await getUserLevels(String(id));
|
||||
const data = res?.data?.data;
|
||||
setValue("name", data?.name);
|
||||
setValue("aliasName", data?.aliasName);
|
||||
setValue("group", data?.group);
|
||||
const parentId = parentList.find((a: any) => a.id === data?.parentLevelId);
|
||||
setSelectedParent(parentId);
|
||||
};
|
||||
|
||||
return (
|
||||
<form
|
||||
className="flex flex-col lg:flex-row gap-8 text-black p-4 lg:p-8"
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
>
|
||||
<div className="w-full lg:w-1/2 bg-white rounded-lg p-4 lg:p-8 flex flex-col gap-1 shadow-lg">
|
||||
<p className="text-sm">
|
||||
Name<span className="text-danger">*</span>
|
||||
</p>
|
||||
<Controller
|
||||
control={control}
|
||||
name="name"
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<Input
|
||||
type="text"
|
||||
id="name"
|
||||
placeholder=""
|
||||
label=""
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
labelPlacement="outside"
|
||||
className="w-full "
|
||||
classNames={{
|
||||
inputWrapper: [
|
||||
"border-1 rounded-lg",
|
||||
"dark:group-data-[focused=false]:bg-transparent !border-1 dark:!border-gray-400",
|
||||
],
|
||||
}}
|
||||
variant="bordered"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{errors?.name && (
|
||||
<p className="text-red-400 text-sm mb-3">{errors.name?.message}</p>
|
||||
)}
|
||||
<p className="text-sm mt-3">Alias Name</p>
|
||||
<Controller
|
||||
control={control}
|
||||
name="aliasName"
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<Input
|
||||
type="text"
|
||||
id="alias"
|
||||
placeholder=""
|
||||
label=""
|
||||
isReadOnly
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
labelPlacement="outside"
|
||||
className="w-full "
|
||||
classNames={{
|
||||
inputWrapper: [
|
||||
"border-1 rounded-lg",
|
||||
"dark:group-data-[focused=false]:bg-transparent !border-1 dark:!border-gray-400",
|
||||
],
|
||||
}}
|
||||
variant="bordered"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{errors?.aliasName && (
|
||||
<p className="text-red-400 text-sm mb-3">
|
||||
{errors.aliasName?.message}
|
||||
</p>
|
||||
)}
|
||||
<p className="text-sm mt-3">
|
||||
Group<span className="text-danger">*</span>
|
||||
</p>
|
||||
<Controller
|
||||
control={control}
|
||||
name="group"
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<Select
|
||||
variant="bordered"
|
||||
label=""
|
||||
labelPlacement="outside"
|
||||
selectedKeys={[value]}
|
||||
onChange={onChange}
|
||||
classNames={{
|
||||
trigger: [
|
||||
"border-1 rounded-lg",
|
||||
"dark:group-data-[focused=false]:bg-transparent !border-1 dark:!border-gray-400",
|
||||
],
|
||||
}}
|
||||
>
|
||||
{groups.map((group) => (
|
||||
<SelectItem key={group.value}>{group.name}</SelectItem>
|
||||
))}
|
||||
</Select>
|
||||
)}
|
||||
/>
|
||||
{errors?.name && (
|
||||
<p className="text-red-400 text-sm mb-3">{errors.name?.message}</p>
|
||||
)}
|
||||
|
||||
<p className="text-sm mt-3">Need Approval</p>
|
||||
<Switch isSelected={needApproval} onValueChange={setNeedApproval}>
|
||||
<p className="text-sm text-black">
|
||||
{needApproval ? "Active" : "Inactive"}
|
||||
</p>
|
||||
</Switch>
|
||||
{findSelectedLevel(selectedGroup)?.level === 3 && (
|
||||
<>
|
||||
<p className="text-sm mt-3">Parent</p>
|
||||
<ReactSelect
|
||||
className="basic-single text-black z-50"
|
||||
classNames={{
|
||||
control: (state: any) =>
|
||||
"!rounded-lg bg-white !border-1 !border-gray-200 dark:!border-stone-500",
|
||||
}}
|
||||
classNamePrefix="select"
|
||||
value={selectedParent}
|
||||
onChange={setSelectedParent}
|
||||
closeMenuOnSelect={false}
|
||||
components={animatedComponents}
|
||||
isClearable={true}
|
||||
isSearchable={true}
|
||||
isMulti={false}
|
||||
placeholder=""
|
||||
name="sub-module"
|
||||
options={parentList}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
<div className="flex flex-row gap-3 mt-5">
|
||||
<Button
|
||||
color="primary"
|
||||
type="submit"
|
||||
isDisabled={
|
||||
findSelectedLevel(selectedGroup)?.level === 3 && !selectedParent
|
||||
}
|
||||
>
|
||||
Simpan
|
||||
</Button>
|
||||
<Link href="/admin/master-user-level">
|
||||
<Button color="danger">Kembali</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,413 +1,339 @@
|
|||
'use client'
|
||||
import { Button } from "@heroui/button";
|
||||
import { Card, Checkbox, CheckboxGroup, Divider, Image, Input, Radio, RadioGroup, Select, SelectItem, SelectSection, Slider, Switch, Tab, Table, Tabs, Textarea, User } from "@heroui/react";
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
"use client";
|
||||
import {
|
||||
Button,
|
||||
Input,
|
||||
Radio,
|
||||
RadioGroup,
|
||||
Select,
|
||||
SelectItem,
|
||||
SelectSection,
|
||||
Slider,
|
||||
Switch,
|
||||
Tab,
|
||||
Table,
|
||||
Tabs,
|
||||
Textarea,
|
||||
User,
|
||||
} from "@heroui/react";
|
||||
import React, {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import { TimesIcon } from "@/components/icons";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { close, error, loading } from "@/config/swal";
|
||||
import Swal from 'sweetalert2';
|
||||
import withReactContent from 'sweetalert2-react-content';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { useForm } from "react-hook-form";
|
||||
import Swal from "sweetalert2";
|
||||
import withReactContent from "sweetalert2-react-content";
|
||||
import dynamic from "next/dynamic";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import * as z from "zod";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { createUserLevels } from "@/services/user-levels/user-levels-service";
|
||||
import {
|
||||
createUserLevels,
|
||||
getAllUserLevels,
|
||||
} from "@/services/user-levels/user-levels-service";
|
||||
import ReactSelect from "react-select";
|
||||
import makeAnimated from "react-select/animated";
|
||||
|
||||
const LevelList = [
|
||||
{ label: "Admin", value: "admin", id: 1 },
|
||||
{ label: "Super-Admin", value: "super-admin", id: 2 },
|
||||
{ label: "Kurator", value: "kurator", id: 3 },
|
||||
{ label: "Supervisor", value: "supervisor", id: 4 },
|
||||
];
|
||||
const createArticleSchema = z.object({
|
||||
name: z.string().min(2, {
|
||||
message: "Required",
|
||||
}),
|
||||
aliasName: z.string().optional(),
|
||||
group: z.string().min(2, {
|
||||
message: "Required",
|
||||
}),
|
||||
});
|
||||
|
||||
const moduleList = [
|
||||
{ label: "Article", value: "article", id: 1 },
|
||||
{ label: "Caption", value: "caption", id: 2 },
|
||||
{ label: "Meme", value: "meme", id: 3 },
|
||||
{ label: "Video", value: "video", id: 4 },
|
||||
{ label: "Master Data", value: "master-data", id: 5 },
|
||||
];
|
||||
|
||||
const provinceList = [
|
||||
{ label: "NTT", value: "1", id: 1 },
|
||||
{ label: "NTB", value: "2", id: 2 },
|
||||
{ label: "Aceh", value: "3", id: 3 },
|
||||
{ label: "Jawa Timur", value: "4", id: 4 },
|
||||
{ label: "Jawa Barat", value: "5", id: 5 },
|
||||
const groups = [
|
||||
{ id: 1, name: "Mabes", value: "mabes", level: 1 },
|
||||
{ id: 2, name: "Polda", value: "polda", level: 2 },
|
||||
{ id: 3, name: "Satker", value: "satker", level: 2 },
|
||||
{ id: 4, name: "Polres", value: "polres", level: 3 },
|
||||
{ id: 5, name: "Subdiv", value: "subdiv", level: 3 },
|
||||
];
|
||||
|
||||
export default function CreateMasterUserLevelForm() {
|
||||
const router = useRouter();
|
||||
const JoditEditor = dynamic(() => import('jodit-react'), { ssr: false });
|
||||
const MySwal = withReactContent(Swal);
|
||||
const [isVisible, setIsVisible] = useState(false);
|
||||
const [tabs, setTabs] = useState<string>("personal-info")
|
||||
const editor = useRef(null);
|
||||
const [content, setContent] = useState('');
|
||||
const [haveChildren, setHaveChildren] = useState("no");
|
||||
const [active, setTrue] = useState("true");
|
||||
const [levelValue, setLevelValue] = useState<any>("");
|
||||
const handleTab = (tab: any) => {
|
||||
setTabs(tab);
|
||||
};
|
||||
const router = useRouter();
|
||||
const MySwal = withReactContent(Swal);
|
||||
const animatedComponents = makeAnimated();
|
||||
const [needApproval, setNeedApproval] = useState(false);
|
||||
const [parentList, setParentList] = useState<any>([]);
|
||||
const [selectedParent, setSelectedParent] = useState<any>();
|
||||
|
||||
const handleActive = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setTrue(e.target.value);
|
||||
};
|
||||
const formOptions = {
|
||||
resolver: zodResolver(createArticleSchema),
|
||||
defaultValues: { name: "", group: "" },
|
||||
};
|
||||
type UserSettingSchema = z.infer<typeof createArticleSchema>;
|
||||
const {
|
||||
register,
|
||||
control,
|
||||
handleSubmit,
|
||||
formState: { errors, isValid },
|
||||
setValue,
|
||||
getValues,
|
||||
watch,
|
||||
setError,
|
||||
clearErrors,
|
||||
} = useForm<UserSettingSchema>(formOptions);
|
||||
|
||||
const handleHaveChildren = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setHaveChildren(e.target.value);
|
||||
};
|
||||
const watchName = watch("name");
|
||||
const generateSlug = (title: string) => {
|
||||
return title
|
||||
.toLowerCase()
|
||||
.trim()
|
||||
.replace(/[^\w\s-]/g, "")
|
||||
.replace(/\s+/g, "-");
|
||||
};
|
||||
|
||||
let [files, setFiles] = useState<File[]>([]);
|
||||
useEffect(() => {
|
||||
setValue("aliasName", generateSlug(watchName));
|
||||
}, [watchName]);
|
||||
|
||||
const removeFile = (name: string) => {
|
||||
const arrayFile: File[] = [];
|
||||
for (const element of files) {
|
||||
if (element.name !== name) {
|
||||
arrayFile.push(element);
|
||||
}
|
||||
const findSelectedLevel = (group: string) => {
|
||||
const selectedLevel = groups.find((a) => a.value === group);
|
||||
return selectedLevel ? selectedLevel : null;
|
||||
};
|
||||
|
||||
const save = async (data: any) => {
|
||||
const findParent = (group: string) => {
|
||||
if (group === "mabes") {
|
||||
return 0;
|
||||
} else if (group === "polda" || group === "satker") {
|
||||
if (group === "polda") {
|
||||
return 1;
|
||||
} else {
|
||||
return 555;
|
||||
}
|
||||
setFiles(arrayFile);
|
||||
} else {
|
||||
return selectedParent?.id;
|
||||
}
|
||||
};
|
||||
|
||||
const handleFileChange = (event: any) => {
|
||||
const newFiles: FileList | null = event.target.files;
|
||||
if (newFiles) {
|
||||
const allowedExtensions = ['.doc', '.docx', '.pdf', '.ppt', '.pptx', '.xlsx', '.csv'];
|
||||
let temp: File[] = [...files]; // Salin file-file yang sudah ada
|
||||
for (let i = 0; i < newFiles.length; i++) {
|
||||
const file = newFiles[i];
|
||||
const fileExtension = file.name.split('.').pop()?.toLowerCase();
|
||||
if (fileExtension && allowedExtensions.includes(`.${fileExtension}`)) {
|
||||
temp.push(file);
|
||||
} else {
|
||||
alert('Format file tidak valid. Hanya file .doc, .docx, .ppt, .pptx, .xlsx, .csv atau .pdf yang diperbolehkan.');
|
||||
}
|
||||
}
|
||||
setFiles(temp);
|
||||
}
|
||||
const request = {
|
||||
name: data.name,
|
||||
aliasName: data.aliasName,
|
||||
levelNumber: findSelectedLevel(data.group)?.level,
|
||||
isActive: true,
|
||||
group: data.group,
|
||||
parentLevelId: findParent(data.group),
|
||||
provinceId: 0,
|
||||
isApprovalActive: needApproval,
|
||||
};
|
||||
|
||||
const toggleVisibility = () => setIsVisible(!isVisible);
|
||||
loading();
|
||||
const res = await createUserLevels(request);
|
||||
if (res.error) {
|
||||
error(res.message);
|
||||
return false;
|
||||
}
|
||||
close();
|
||||
successSubmit("/admin/user-level");
|
||||
};
|
||||
|
||||
const validationSchema = z.object({
|
||||
name: z.string().min(1, { message: "Required" }),
|
||||
aliasName: z.string().min(1, { message: "Required" }),
|
||||
// levelNumber: z.string().min(1, { message: "Required" }),
|
||||
async function onSubmit(data: any) {
|
||||
MySwal.fire({
|
||||
title: "Save Data",
|
||||
text: "",
|
||||
icon: "warning",
|
||||
showCancelButton: true,
|
||||
cancelButtonColor: "#d33",
|
||||
confirmButtonColor: "#3085d6",
|
||||
confirmButtonText: "Save",
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
save(data);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const formOptions = { resolver: zodResolver(validationSchema) };
|
||||
type ArticleSchema = z.infer<typeof validationSchema>;
|
||||
function successSubmit(redirect: string) {
|
||||
MySwal.fire({
|
||||
title: "Sukses",
|
||||
icon: "success",
|
||||
confirmButtonColor: "#3085d6",
|
||||
confirmButtonText: "OK",
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
router.push(redirect);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const { register, handleSubmit, formState: { errors }, formState, setValue } = useForm<ArticleSchema>(formOptions);
|
||||
useEffect(() => {
|
||||
fetchCategory();
|
||||
}, []);
|
||||
|
||||
const save = async (data: any) => {
|
||||
const selectedLevel = Number(Array.from(levelValue).pop());
|
||||
const request = {
|
||||
name: data.name,
|
||||
aliasName: data.aliasName,
|
||||
levelNumber: selectedLevel,
|
||||
isActive: active,
|
||||
};
|
||||
|
||||
console.log(request);
|
||||
loading();
|
||||
const res = await createUserLevels(request);
|
||||
if (res.error) {
|
||||
error(res.message);
|
||||
return false;
|
||||
}
|
||||
close();
|
||||
successSubmit("/admin/master/master-user-level")
|
||||
const fetchCategory = async () => {
|
||||
loading();
|
||||
const request = {
|
||||
limit: 10,
|
||||
};
|
||||
const res = await getAllUserLevels(request);
|
||||
close();
|
||||
if (res?.data?.data) {
|
||||
setupParent(res?.data?.data);
|
||||
}
|
||||
};
|
||||
|
||||
async function onSubmit(data: any) {
|
||||
MySwal.fire({
|
||||
title: "Save Data",
|
||||
text: "",
|
||||
icon: "warning",
|
||||
showCancelButton: true,
|
||||
cancelButtonColor: "#d33",
|
||||
confirmButtonColor: "#3085d6",
|
||||
confirmButtonText: "Save",
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
save(data);
|
||||
const setupParent = (data: any) => {
|
||||
const temp = [];
|
||||
for (const element of data) {
|
||||
temp.push({
|
||||
id: element.id,
|
||||
label: element.name,
|
||||
value: element.aliasName,
|
||||
});
|
||||
}
|
||||
setParentList(temp);
|
||||
};
|
||||
|
||||
const selectedGroup = watch("group");
|
||||
|
||||
return (
|
||||
<form
|
||||
className="flex flex-col lg:flex-row gap-8 text-black p-8"
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
>
|
||||
<div className="w-full lg:w-1/2 bg-white rounded-lg p-8 flex flex-col gap-1 shadow-lg">
|
||||
<p className="text-sm">
|
||||
Name<span className="text-danger">*</span>
|
||||
</p>
|
||||
<Controller
|
||||
control={control}
|
||||
name="name"
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<Input
|
||||
type="text"
|
||||
id="name"
|
||||
placeholder=""
|
||||
label=""
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
labelPlacement="outside"
|
||||
className="w-full "
|
||||
classNames={{
|
||||
inputWrapper: [
|
||||
"border-1 rounded-lg",
|
||||
"dark:group-data-[focused=false]:bg-transparent !border-1 dark:!border-gray-400",
|
||||
],
|
||||
}}
|
||||
variant="bordered"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{errors?.name && (
|
||||
<p className="text-red-400 text-sm mb-3">{errors.name?.message}</p>
|
||||
)}
|
||||
<p className="text-sm mt-3">Alias Name</p>
|
||||
<Controller
|
||||
control={control}
|
||||
name="aliasName"
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<Input
|
||||
type="text"
|
||||
id="alias"
|
||||
placeholder=""
|
||||
label=""
|
||||
isReadOnly
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
labelPlacement="outside"
|
||||
className="w-full "
|
||||
classNames={{
|
||||
inputWrapper: [
|
||||
"border-1 rounded-lg",
|
||||
"dark:group-data-[focused=false]:bg-transparent !border-1 dark:!border-gray-400",
|
||||
],
|
||||
}}
|
||||
variant="bordered"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{errors?.aliasName && (
|
||||
<p className="text-red-400 text-sm mb-3">
|
||||
{errors.aliasName?.message}
|
||||
</p>
|
||||
)}
|
||||
<p className="text-sm mt-3">
|
||||
Group<span className="text-danger">*</span>
|
||||
</p>
|
||||
<Controller
|
||||
control={control}
|
||||
name="group"
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<Select
|
||||
variant="bordered"
|
||||
label=""
|
||||
labelPlacement="outside"
|
||||
selectedKeys={[value]}
|
||||
onChange={onChange}
|
||||
classNames={{
|
||||
trigger: [
|
||||
"border-1 rounded-lg",
|
||||
"dark:group-data-[focused=false]:bg-transparent !border-1 dark:!border-gray-400",
|
||||
],
|
||||
}}
|
||||
>
|
||||
{groups.map((group) => (
|
||||
<SelectItem key={group.value}>{group.name}</SelectItem>
|
||||
))}
|
||||
</Select>
|
||||
)}
|
||||
/>
|
||||
{errors?.name && (
|
||||
<p className="text-red-400 text-sm mb-3">{errors.name?.message}</p>
|
||||
)}
|
||||
|
||||
<p className="text-sm mt-3">Need Approval</p>
|
||||
<Switch isSelected={needApproval} onValueChange={setNeedApproval}>
|
||||
<p className="text-sm text-black">
|
||||
{needApproval ? "Active" : "Inactive"}
|
||||
</p>
|
||||
</Switch>
|
||||
{findSelectedLevel(selectedGroup)?.level === 3 && (
|
||||
<>
|
||||
<p className="text-sm mt-3">Parent</p>
|
||||
<ReactSelect
|
||||
className="basic-single text-black z-50"
|
||||
classNames={{
|
||||
control: (state: any) =>
|
||||
"!rounded-lg bg-white !border-1 !border-gray-200 dark:!border-stone-500",
|
||||
}}
|
||||
classNamePrefix="select"
|
||||
onChange={setSelectedParent}
|
||||
closeMenuOnSelect={false}
|
||||
components={animatedComponents}
|
||||
isClearable={true}
|
||||
isSearchable={true}
|
||||
isMulti={false}
|
||||
placeholder=""
|
||||
name="sub-module"
|
||||
options={parentList}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
<div className="flex flex-row gap-3 mt-5">
|
||||
<Button
|
||||
color="primary"
|
||||
type="submit"
|
||||
isDisabled={
|
||||
findSelectedLevel(selectedGroup)?.level === 3 && !selectedParent
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function successSubmit(redirect: string) {
|
||||
MySwal.fire({
|
||||
title: 'Sukses',
|
||||
icon: 'success',
|
||||
confirmButtonColor: '#3085d6',
|
||||
confirmButtonText: 'OK',
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
router.push(redirect);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mx-3 my-5">
|
||||
<div className="flex flex-col gap-3 mb-4">
|
||||
<Card className="w-full bg-white">
|
||||
<div className="w-full mr-2 p-5 ">
|
||||
<form method="POST" onSubmit={handleSubmit(onSubmit)}>
|
||||
<>
|
||||
<div className="flex flex-row gap-1">
|
||||
<div className="w-6/12 justify-start items-start mt-2 gap-3">
|
||||
<div className="flex flex-col ">
|
||||
<Input
|
||||
type="text"
|
||||
label="Nama"
|
||||
id="name"
|
||||
{...register("name")}
|
||||
placeholder="Input Name"
|
||||
labelPlacement="outside"
|
||||
className=" font-semibold"
|
||||
classNames={{
|
||||
label: "!text-black",
|
||||
input: "!text-black hover:!text-white focus:!text-white",
|
||||
inputWrapper: "max-h-[40px] bg-transparant border text-white",
|
||||
}}
|
||||
startContent={
|
||||
<div className="pointer-events-none flex items-center">
|
||||
<span className="text-default-400 text-small"></span>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
{errors.name?.message && (
|
||||
<p className="text-red-400 text-sm">
|
||||
{errors.name?.message}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex flex-col mt-3">
|
||||
<Input
|
||||
type="text"
|
||||
label="Alias Name"
|
||||
id="aliasName"
|
||||
{...register("aliasName")}
|
||||
placeholder="Input Name"
|
||||
labelPlacement="outside"
|
||||
className=" font-semibold"
|
||||
classNames={{
|
||||
label: "!text-black",
|
||||
input: "!text-black hover:!text-white focus:!text-white",
|
||||
inputWrapper: "max-h-[40px] bg-transparant border text-white",
|
||||
}}
|
||||
startContent={
|
||||
<div className="pointer-events-none flex items-center">
|
||||
<span className="text-default-400 text-small"></span>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
{errors.aliasName?.message && (
|
||||
<p className="text-red-400 text-sm">
|
||||
{errors.aliasName?.message}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="mt-3 ">
|
||||
<p className="text-black text-sm mb-1 font-semibold">Level Number</p>
|
||||
<Select
|
||||
variant="bordered"
|
||||
labelPlacement="outside"
|
||||
placeholder="Select Polda"
|
||||
selectedKeys={levelValue}
|
||||
onSelectionChange={setLevelValue}
|
||||
className="w-full"
|
||||
classNames={{
|
||||
mainWrapper: "rounded",
|
||||
listboxWrapper:
|
||||
"bg-white w-full !text-indigo-500 text-center font-bold",
|
||||
popoverContent: "bg-white !text-indigo-500",
|
||||
trigger:
|
||||
"border-1 border-gray-200 hover:!bg-gray-100 !text-black",
|
||||
}}
|
||||
listboxProps={{
|
||||
itemClasses: {
|
||||
base: [
|
||||
"!text-left",
|
||||
"!bg-white",
|
||||
"text-indigo-500 ",
|
||||
"data-[selectable=true]:!text-indigo-500",
|
||||
"data-[pressed=true]:text-indigo-500",
|
||||
"data-[hover=true]:!text-indigo-300",
|
||||
],
|
||||
wrapper: ["!bg-white border-none"],
|
||||
},
|
||||
}}
|
||||
>
|
||||
<SelectSection showDivider title="List Level">
|
||||
{LevelList.map((list: any) => (
|
||||
<SelectItem key={list.id} value={list.id}>
|
||||
{list.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectSection>
|
||||
</Select>
|
||||
</div>
|
||||
{/* <div className="mt-3 ">
|
||||
<p className="text-black text-sm mb-1 font-semibold">Parent LevelId</p>
|
||||
<Select
|
||||
variant="bordered"
|
||||
selectionMode="single"
|
||||
labelPlacement="outside"
|
||||
placeholder="Select"
|
||||
className="font-semibold"
|
||||
items={moduleList}
|
||||
classNames={{
|
||||
mainWrapper: "rounded",
|
||||
listboxWrapper:
|
||||
"bg-white w-full !text-indigo-500 text-center font-bold",
|
||||
popoverContent: "bg-white !text-indigo-500",
|
||||
trigger:
|
||||
"border-1 border-gray-200 hover:!bg-gray-100 !text-black",
|
||||
}}
|
||||
listboxProps={{
|
||||
itemClasses: {
|
||||
base: [
|
||||
"!text-left",
|
||||
"!bg-white",
|
||||
"text-indigo-500 ",
|
||||
"data-[selectable=true]:!text-indigo-500",
|
||||
"data-[pressed=true]:text-indigo-500",
|
||||
"data-[hover=true]:!text-indigo-300",
|
||||
],
|
||||
wrapper: ["!bg-white border-none"],
|
||||
},
|
||||
}}
|
||||
renderValue={(items) => {
|
||||
return items.map((item) => (
|
||||
<span key={item.props?.value} className="text-black text-xs">
|
||||
{item.textValue}
|
||||
</span>
|
||||
));
|
||||
}}
|
||||
>
|
||||
<SelectSection showDivider title="Module">
|
||||
{moduleList.map((list) => (
|
||||
<SelectItem key={list.id} value={list.id}>
|
||||
{list.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectSection>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="mt-3 ">
|
||||
<p className="text-black text-sm mb-1 font-semibold">Provinsi</p>
|
||||
<Select
|
||||
variant="bordered"
|
||||
selectionMode="single"
|
||||
labelPlacement="outside"
|
||||
placeholder="Select"
|
||||
className="font-semibold"
|
||||
items={provinceList}
|
||||
classNames={{
|
||||
mainWrapper: "rounded",
|
||||
listboxWrapper:
|
||||
"bg-white w-full !text-indigo-500 text-center font-bold",
|
||||
popoverContent: "bg-white !text-indigo-500",
|
||||
trigger:
|
||||
"border-1 border-gray-200 hover:!bg-gray-100 !text-black",
|
||||
}}
|
||||
listboxProps={{
|
||||
itemClasses: {
|
||||
base: [
|
||||
"!text-left",
|
||||
"!bg-white",
|
||||
"text-indigo-500 ",
|
||||
"data-[selectable=true]:!text-indigo-500",
|
||||
"data-[pressed=true]:text-indigo-500",
|
||||
"data-[hover=true]:!text-indigo-300",
|
||||
],
|
||||
wrapper: ["!bg-white border-none"],
|
||||
},
|
||||
}}
|
||||
renderValue={(items) => {
|
||||
return items.map((item) => (
|
||||
<span key={item.props?.value} className="text-black text-xs">
|
||||
{item.textValue}
|
||||
</span>
|
||||
));
|
||||
}}
|
||||
>
|
||||
<SelectSection showDivider title="Provinsi">
|
||||
{provinceList.map((list) => (
|
||||
<SelectItem key={list.id} value={list.id}>
|
||||
{list.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectSection>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="text-black">
|
||||
<p className=" text-black ">Status</p>
|
||||
<RadioGroup
|
||||
orientation="horizontal"
|
||||
id="radio-banned"
|
||||
className="text-gray-950 mb-2"
|
||||
onChange={handleActive}
|
||||
defaultValue={active}
|
||||
>
|
||||
<Radio
|
||||
classNames={{
|
||||
label: "!text-black",
|
||||
}}
|
||||
value="true"
|
||||
>
|
||||
Active
|
||||
</Radio>
|
||||
<Radio
|
||||
classNames={{
|
||||
label: "!text-black",
|
||||
}}
|
||||
value="false"
|
||||
>
|
||||
Inactive
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
</div> */}
|
||||
<div className="flex flex-row gap-3 my-3">
|
||||
<Link href="/admin/master/master-user-level">
|
||||
<Button
|
||||
variant="bordered"
|
||||
className="bg-white border-grey-100 rounded-full text-[#8E5C18] mr-5"
|
||||
>
|
||||
Cancel
|
||||
</Button>{" "}
|
||||
</Link>
|
||||
<Button
|
||||
className="w-[50px]"
|
||||
color="primary"
|
||||
size="md"
|
||||
type="submit">
|
||||
Submit
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-6/12 ">
|
||||
<div className="flex items-center justify-center justify-items-center h-full">
|
||||
<Image
|
||||
width={400}
|
||||
alt="NextUI hero Image"
|
||||
src="/account-category.jpg"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
</form>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</div >
|
||||
|
||||
)
|
||||
>
|
||||
Simpan
|
||||
</Button>
|
||||
<Link href="/admin/master-user-level">
|
||||
<Button color="danger">Kembali</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -385,6 +385,26 @@ export const MasterRoleIcon = ({
|
|||
/>
|
||||
</svg>
|
||||
);
|
||||
export const MasterUserLevelIcon = ({
|
||||
size,
|
||||
height = 24,
|
||||
width = 24,
|
||||
fill = "currentColor",
|
||||
...props
|
||||
}: IconSvgProps) => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={size || width}
|
||||
height={size || height}
|
||||
viewBox="0 0 640 512"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M192 256c61.9 0 112-50.1 112-112S253.9 32 192 32S80 82.1 80 144s50.1 112 112 112m76.8 32h-8.3c-20.8 10-43.9 16-68.5 16s-47.6-6-68.5-16h-8.3C51.6 288 0 339.6 0 403.2V432c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48v-28.8c0-63.6-51.6-115.2-115.2-115.2M480 256c53 0 96-43 96-96s-43-96-96-96s-96 43-96 96s43 96 96 96m48 32h-3.8c-13.9 4.8-28.6 8-44.2 8s-30.3-3.2-44.2-8H432c-20.4 0-39.2 5.9-55.7 15.4c24.4 26.3 39.7 61.2 39.7 99.8v38.4c0 2.2-.5 4.3-.6 6.4H592c26.5 0 48-21.5 48-48c0-61.9-50.1-112-112-112"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
export const MasterCategoryIcon = ({
|
||||
size,
|
||||
height = 24,
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import {
|
|||
MagazineIcon,
|
||||
MasterCategoryIcon,
|
||||
MasterRoleIcon,
|
||||
MasterUserLevelIcon,
|
||||
MasterUsersIcon,
|
||||
MinusCircleIcon,
|
||||
StaticPageIcon,
|
||||
|
|
@ -243,6 +244,20 @@ const sideBarDummyData = [
|
|||
statusName: "Active",
|
||||
childModule: null,
|
||||
},
|
||||
{
|
||||
id: 23,
|
||||
name: "Master User Level",
|
||||
moduleId: 656,
|
||||
moduleName: "Form Validation",
|
||||
modulePathUrl: "/admin/user-level",
|
||||
parentId: -1,
|
||||
icon: <MasterUserLevelIcon />,
|
||||
position: 1,
|
||||
statusId: 1,
|
||||
childMenu: [],
|
||||
statusName: "Active",
|
||||
childModule: null,
|
||||
},
|
||||
];
|
||||
|
||||
const SidebarMobile: React.FC<SidebarProps> = ({ updateSidebarData }) => {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import {
|
|||
MagazineIcon,
|
||||
MasterCategoryIcon,
|
||||
MasterRoleIcon,
|
||||
MasterUserLevelIcon,
|
||||
MasterUsersIcon,
|
||||
MinusCircleIcon,
|
||||
StaticPageIcon,
|
||||
|
|
@ -319,6 +320,20 @@ const sideBarDummyData = [
|
|||
statusName: "Active",
|
||||
childModule: null,
|
||||
},
|
||||
{
|
||||
id: 23,
|
||||
name: "Master User Level",
|
||||
moduleId: 656,
|
||||
moduleName: "Form Validation",
|
||||
modulePathUrl: "/admin/user-level",
|
||||
parentId: -1,
|
||||
icon: <MasterUserLevelIcon />,
|
||||
position: 1,
|
||||
statusId: 1,
|
||||
childMenu: [],
|
||||
statusName: "Active",
|
||||
childModule: null,
|
||||
},
|
||||
];
|
||||
|
||||
const Sidebar: React.FC<SidebarProps> = ({ updateSidebarData }) => {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import {
|
|||
} from "@/components/icons";
|
||||
import Link from "next/link";
|
||||
import { getAllUserLevels } from "@/services/user-levels/user-levels-service";
|
||||
import { close, loading } from "@/config/swal";
|
||||
|
||||
type UserObject = {
|
||||
id: number;
|
||||
|
|
@ -41,12 +42,6 @@ type UserObject = {
|
|||
status: string;
|
||||
};
|
||||
|
||||
const statusColorMap = {
|
||||
active: "success",
|
||||
paused: "danger",
|
||||
vacation: "warning",
|
||||
};
|
||||
|
||||
export default function MasterUserLevelTable() {
|
||||
const [totalPage, setTotalPage] = useState(1);
|
||||
const [masterUserLevelTable, setmasterUserLevel] = useState<UserObject[]>([]);
|
||||
|
|
@ -56,11 +51,11 @@ export default function MasterUserLevelTable() {
|
|||
const columns = [
|
||||
{ name: "No", uid: "no" },
|
||||
{ name: "Name", uid: "name" },
|
||||
{ name: "User Name", uid: "alias_name" },
|
||||
{ name: "Level Number", uid: "level_number" },
|
||||
{ name: "Parent Level", uid: "parent_level_id" },
|
||||
{ name: "Province", uid: "province_id" },
|
||||
{ name: "Status", uid: "is_active" },
|
||||
{ name: "User Name", uid: "aliasName" },
|
||||
{ name: "Level Number", uid: "levelNumber" },
|
||||
{ name: "Parent", uid: "parentLevelId" },
|
||||
// { name: "Province", uid: "province_id" },
|
||||
// { name: "Status", uid: "is_active" },
|
||||
{ name: "Action", uid: "actions" },
|
||||
];
|
||||
|
||||
|
|
@ -71,6 +66,7 @@ export default function MasterUserLevelTable() {
|
|||
}, []);
|
||||
|
||||
async function fetchData() {
|
||||
loading();
|
||||
const request = {
|
||||
page: page,
|
||||
limit: 10,
|
||||
|
|
@ -78,10 +74,11 @@ export default function MasterUserLevelTable() {
|
|||
const res = await getAllUserLevels(request);
|
||||
const data = res?.data?.data;
|
||||
setTotalPage(Math.ceil(res?.data?.total / 10));
|
||||
initUserData(10, data);
|
||||
await initUserData(10, data);
|
||||
close();
|
||||
}
|
||||
|
||||
function initUserData(limit: number, data?: any) {
|
||||
async function initUserData(limit: number, data?: any) {
|
||||
if (data) {
|
||||
console.log(data);
|
||||
const startIndex = limit * (page - 1);
|
||||
|
|
@ -91,43 +88,34 @@ export default function MasterUserLevelTable() {
|
|||
value.no = startIndex + iterate;
|
||||
return value;
|
||||
});
|
||||
console.log("Data ::", newData);
|
||||
setmasterUserLevel(newData);
|
||||
}
|
||||
}
|
||||
|
||||
const findParentName = (data: string | number) => {
|
||||
let name = "-";
|
||||
|
||||
for (let i = 9; i < masterUserLevelTable?.length; i++) {
|
||||
const temp = masterUserLevelTable[i];
|
||||
if (temp.id === Number(data)) {
|
||||
name = temp.name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return name;
|
||||
};
|
||||
|
||||
const renderCell = useCallback(
|
||||
(masterUserLevel: TableRow, columnKey: Key) => {
|
||||
const cellValue = masterUserLevel[columnKey as keyof UserObject];
|
||||
const statusColorMap: Record<string, ChipProps["color"]> = {
|
||||
active: "success",
|
||||
cancel: "danger",
|
||||
pending: "warning",
|
||||
};
|
||||
|
||||
switch (columnKey) {
|
||||
case "no":
|
||||
return <div>{masterUserLevel.id}</div>;
|
||||
|
||||
case "name":
|
||||
return <div className="w-[150px]">{masterUserLevel.name}</div>;
|
||||
|
||||
case "alias_Name":
|
||||
return <div className="">{masterUserLevel.aliasName}</div>;
|
||||
case "is_active":
|
||||
return (
|
||||
<Chip
|
||||
className="capitalize "
|
||||
color={statusColorMap[masterUserLevel.status]}
|
||||
size="lg"
|
||||
variant="flat"
|
||||
>
|
||||
<div className="flex flex-row items-center gap-2 justify-center">
|
||||
{cellValue}
|
||||
</div>
|
||||
</Chip>
|
||||
);
|
||||
|
||||
case "parentLevelId":
|
||||
return <p className="text-black">{findParentName(cellValue)}</p>;
|
||||
case "actions":
|
||||
return (
|
||||
<div className="relative flex justify-star items-center gap-2">
|
||||
|
|
@ -138,14 +126,14 @@ export default function MasterUserLevelTable() {
|
|||
</Button>
|
||||
</DropdownTrigger>
|
||||
<DropdownMenu>
|
||||
<DropdownItem key="Detail">
|
||||
{/* <DropdownItem key="Detail">
|
||||
<Link href={`/admin/magazine/detail`}>
|
||||
<EyeIconMdi className="inline mr-2 mb-1" />
|
||||
Detail
|
||||
</Link>
|
||||
</DropdownItem>
|
||||
</DropdownItem> */}
|
||||
<DropdownItem key="Edit">
|
||||
<Link href={`#`}>
|
||||
<Link href={`/admin/user-level/edit/${masterUserLevel.id}`}>
|
||||
<CreateIconIon className="inline mr-2 mb-1" />
|
||||
Edit
|
||||
</Link>
|
||||
|
|
@ -169,18 +157,18 @@ export default function MasterUserLevelTable() {
|
|||
return cellValue;
|
||||
}
|
||||
},
|
||||
[]
|
||||
[masterUserLevelTable]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="mx-3 my-5">
|
||||
<Link href="/admin/master/master-user-level/create">
|
||||
{/* <Link href="/admin/master/master-user-level/create">
|
||||
<Button className="my-3 bg-blue-600 text-white">
|
||||
<CreateIconIon />
|
||||
Create New User Level
|
||||
</Button>
|
||||
</Link>
|
||||
</Link> */}
|
||||
<div className="flex flex-col items-center rounded-2xl">
|
||||
<Table
|
||||
// selectionMode="multiple"
|
||||
|
|
|
|||
|
|
@ -1,12 +1,21 @@
|
|||
import { httpGet, httpPost } from "../http-config/http-base-services";
|
||||
|
||||
|
||||
import {
|
||||
httpDeleteInterceptor,
|
||||
httpGet,
|
||||
httpPost,
|
||||
httpPut,
|
||||
} from "@/service/http-config/axios-base-service";
|
||||
|
||||
export async function getAllUserLevels(data: any) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
return await httpGet(`user-levels`, headers,);
|
||||
return await httpGet(`user-levels?limit=${data.limit || ""}`, headers);
|
||||
}
|
||||
export async function getUserLevels(id: string) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
return await httpGet(`user-levels/${id}`, headers);
|
||||
}
|
||||
|
||||
export async function getAccountById(id: string) {
|
||||
|
|
@ -14,7 +23,6 @@ export async function getAccountById(id: string) {
|
|||
"content-type": "application/json",
|
||||
};
|
||||
return await httpGet(`user-account/findById/${id}`, headers);
|
||||
|
||||
}
|
||||
|
||||
export async function createUserLevels(request: any) {
|
||||
|
|
@ -24,3 +32,9 @@ export async function createUserLevels(request: any) {
|
|||
return await httpPost(`user-levels`, headers, request);
|
||||
}
|
||||
|
||||
export async function editUserLevels(id: string, request: any) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
return await httpPut(`user-levels/${id}`, headers, request);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue