web-humas-fe/components/table/master/master-user-level/master-user-level-table.tsx

397 lines
11 KiB
TypeScript
Raw Normal View History

"use client";
import {
2025-02-13 04:53:53 +00:00
TableCell,
TableRow,
Table,
TableHeader,
TableColumn,
TableBody,
Pagination,
Dropdown,
DropdownTrigger,
DropdownMenu,
DropdownItem,
Input,
User,
Card,
Divider,
Chip,
ChipProps,
2025-03-06 10:40:54 +00:00
Checkbox,
2025-04-16 08:51:12 +00:00
Switch,
2025-02-13 08:25:39 +00:00
} from "@heroui/react";
import { Button } from "@heroui/button";
2024-04-23 05:17:21 +00:00
import React, { Key, useCallback, useEffect, useMemo, useState } from "react";
import {
2025-02-13 04:53:53 +00:00
AddIcon,
CreateIconIon,
DeleteIcon,
DotsYIcon,
EyeFilledIcon,
EyeIconMdi,
2025-03-03 02:58:33 +00:00
SearchIcon,
} from "@/components/icons";
import Link from "next/link";
2025-04-16 08:51:12 +00:00
import {
changeIsApproval,
getAllUserLevels,
} from "@/services/user-levels/user-levels-service";
import { close, error, loading } from "@/config/swal";
2025-03-06 10:40:54 +00:00
import { stringify } from "querystring";
2025-05-28 06:56:41 +00:00
import { getUnixTimestamp } from "@/utils/global";
type UserObject = {
2025-02-13 04:53:53 +00:00
id: number;
name: string;
levelNumber: string;
aliasName: string;
parentLevelId: string;
provinceId: string;
status: string;
2025-04-16 08:51:12 +00:00
isApprovalActive: boolean;
};
export default function MasterUserLevelTable() {
2025-02-13 04:53:53 +00:00
const [totalPage, setTotalPage] = useState(1);
2025-03-06 10:40:54 +00:00
const [masterUserLevelTable, setMasterUserLevel] = useState<UserObject[]>([]);
2025-03-03 02:58:33 +00:00
const [search, setSearch] = useState("");
2025-03-06 10:40:54 +00:00
const [doSetup, setDoSetup] = useState(false);
const [userLevelAll, setUserLevelAll] = useState<UserObject[]>([]);
const [selectAllLevel, setSelectAllLevel] = useState(false);
const [selectedLevel, setSelectedLevel] = useState<string[]>([]);
2025-04-16 08:51:12 +00:00
const [isSelected, setIsSelected] = useState(true);
2025-02-13 04:53:53 +00:00
const columns = [
{ name: "No", uid: "no" },
{ name: "Name", uid: "name" },
2025-02-18 05:17:41 +00:00
{ name: "User Name", uid: "aliasName" },
{ name: "Level Number", uid: "levelNumber" },
{ name: "Parent", uid: "parentLevelId" },
2025-03-06 10:40:54 +00:00
{ name: "Action", uid: "actions" },
];
const columns2 = [
{ name: "No", uid: "no" },
{ name: "Setup", uid: "setup" },
{ name: "Name", uid: "name" },
{ name: "User Name", uid: "aliasName" },
{ name: "Level Number", uid: "levelNumber" },
{ name: "Parent", uid: "parentLevelId" },
2025-04-16 08:51:12 +00:00
{ name: "Need Approval", uid: "approvalActive" },
2025-02-13 04:53:53 +00:00
{ name: "Action", uid: "actions" },
];
const [page, setPage] = useState(1);
2025-04-16 08:51:12 +00:00
useEffect(() => {
console.log("level", selectedLevel);
}, [selectedLevel]);
2025-02-13 04:53:53 +00:00
useEffect(() => {
fetchData();
2025-03-06 10:40:54 +00:00
}, [page, selectedLevel]);
useEffect(() => {
fetchDataAll();
}, []);
2025-02-13 04:53:53 +00:00
async function fetchData() {
2025-02-18 05:17:41 +00:00
loading();
2025-02-13 04:53:53 +00:00
const request = {
page: page,
limit: 10,
2025-03-03 02:58:33 +00:00
search: search,
2025-05-28 06:56:41 +00:00
timeStamp: getUnixTimestamp(),
2025-02-13 04:53:53 +00:00
};
const res = await getAllUserLevels(request);
const data = res?.data?.data;
2025-04-16 08:51:12 +00:00
setTotalPage(Math.ceil(res?.data?.meta?.totalPage));
2025-02-18 05:17:41 +00:00
await initUserData(10, data);
close();
2025-02-13 04:53:53 +00:00
}
2025-03-06 10:40:54 +00:00
async function fetchDataAll() {
loading();
const request = {
page: 1,
limit: -1,
search: "",
2025-05-28 06:56:41 +00:00
timeStamp: getUnixTimestamp(),
2025-03-06 10:40:54 +00:00
};
const res = await getAllUserLevels(request);
const data = res?.data?.data;
setUserLevelAll(data);
2025-03-07 09:08:19 +00:00
const temp = [];
for (const element of data) {
if (element.isApprovalActive) {
temp.push(String(element.id));
}
}
2025-04-16 08:51:12 +00:00
// setSelectedLevel(temp);
2025-03-06 10:40:54 +00:00
close();
}
2025-02-13 04:53:53 +00:00
2025-02-18 05:17:41 +00:00
async function initUserData(limit: number, data?: any) {
2025-02-13 04:53:53 +00:00
if (data) {
console.log(data);
const startIndex = limit * (page - 1);
let iterate = 0;
const newData = data.map((value: any) => {
iterate++;
value.no = startIndex + iterate;
return value;
});
2025-03-06 10:40:54 +00:00
setMasterUserLevel(newData);
2024-04-23 05:17:21 +00:00
}
2025-02-13 04:53:53 +00:00
}
2025-03-03 02:58:33 +00:00
let typingTimer: NodeJS.Timeout;
const doneTypingInterval = 1500;
const handleKeyUp = () => {
clearTimeout(typingTimer);
typingTimer = setTimeout(doneTyping, doneTypingInterval);
};
const handleKeyDown = () => {
clearTimeout(typingTimer);
};
async function doneTyping() {
fetchData();
}
2025-03-06 10:40:54 +00:00
const doMapping = (status: boolean) => {
setSelectAllLevel(status);
if (status) {
const temp = [];
for (const element of userLevelAll) {
temp.push(String(element.id));
}
setSelectedLevel(temp);
} else {
setSelectedLevel([]);
}
};
const handleSelectedLevel = (id: string, checked: boolean) => {
console.log("change", id, checked);
const temp = [...selectedLevel];
if (checked) {
temp.push(id);
setSelectedLevel(temp);
if (temp.length === userLevelAll.length) {
setSelectAllLevel(true);
}
} else {
const newTemp = temp.filter((a) => a !== id);
setSelectedLevel(newTemp);
if (newTemp.length !== userLevelAll.length) {
setSelectAllLevel(false);
}
}
};
2025-02-13 04:53:53 +00:00
const renderCell = useCallback(
2025-03-06 10:40:54 +00:00
(masterUserLevel: UserObject, columnKey: Key) => {
const findParentName = (data: string | number) => {
let name = "-";
2025-02-13 04:53:53 +00:00
2025-03-06 10:40:54 +00:00
for (let i = 9; i < userLevelAll?.length; i++) {
const temp = userLevelAll[i];
if (temp.id === Number(data)) {
name = temp.name;
break;
}
}
return name;
};
const cellValue = masterUserLevel[columnKey as keyof UserObject];
2025-02-13 04:53:53 +00:00
switch (columnKey) {
2025-02-18 05:17:41 +00:00
case "parentLevelId":
2025-04-16 08:51:12 +00:00
return (
<p className="text-black">
{findParentName(masterUserLevel.parentLevelId)}
</p>
);
2025-03-06 10:40:54 +00:00
case "setup":
return (
<Checkbox
key={masterUserLevel.id}
isSelected={selectedLevel?.includes(String(masterUserLevel.id))}
onValueChange={(e) =>
handleSelectedLevel(String(masterUserLevel.id), e)
}
/>
);
2025-04-16 08:51:12 +00:00
case "approvalActive":
return (
<p className="text-black">
{masterUserLevel.isApprovalActive ? "Yes" : "No"}
</p>
);
2025-02-13 04:53:53 +00:00
case "actions":
return (
<div className="relative flex justify-star items-center gap-2">
<Dropdown className="lg:min-w-[150px] bg-black text-white shadow border ">
<DropdownTrigger>
<Button isIconOnly size="lg" variant="light">
<DotsYIcon className="text-default-300" />
</Button>
</DropdownTrigger>
<DropdownMenu>
2025-02-18 05:17:41 +00:00
{/* <DropdownItem key="Detail">
2025-02-13 04:53:53 +00:00
<Link href={`/admin/magazine/detail`}>
<EyeIconMdi className="inline mr-2 mb-1" />
Detail
</Link>
2025-02-18 05:17:41 +00:00
</DropdownItem> */}
2025-02-13 04:53:53 +00:00
<DropdownItem key="Edit">
2025-02-18 05:17:41 +00:00
<Link href={`/admin/user-level/edit/${masterUserLevel.id}`}>
2025-02-13 04:53:53 +00:00
<CreateIconIon className="inline mr-2 mb-1" />
Edit
</Link>
</DropdownItem>
<DropdownItem key="Delete">
<Link href={`#`}>
<DeleteIcon
width={20}
height={16}
className="inline mr-2 mb-1"
/>
Delete
</Link>
</DropdownItem>
</DropdownMenu>
</Dropdown>
</div>
2025-02-13 04:53:53 +00:00
);
default:
return cellValue;
}
},
2025-03-06 10:40:54 +00:00
[selectedLevel, userLevelAll, masterUserLevelTable]
2025-02-13 04:53:53 +00:00
);
2025-04-16 08:51:12 +00:00
const saveApproval = async () => {
const req = { ids: selectedLevel.join(","), isApprovalActive: isSelected };
const res = await changeIsApproval(req);
if (res?.error) {
error(res?.message);
return false;
}
fetchData();
};
2025-02-13 04:53:53 +00:00
return (
<>
<div className="mx-3 my-5">
2025-03-06 10:40:54 +00:00
<div className="flex flex-col items-start rounded-2xl">
2025-03-07 09:08:19 +00:00
<div className="flex flex-row gap-3 mb-3 w-full justify-start items-end">
<div className="flex flex-col gap-1 w-auto justify-start">
2025-03-06 10:40:54 +00:00
<p className="font-semibold text-sm">Pencarian</p>
<Input
aria-label="Search"
classNames={{
inputWrapper: "bg-default-100",
input: "text-sm",
}}
2025-03-07 09:08:19 +00:00
className="w-[300px]"
2025-03-06 10:40:54 +00:00
labelPlacement="outside"
startContent={
<SearchIcon className="text-base text-default-400 pointer-events-none flex-shrink-0" />
}
type="text"
onChange={(e) => setSearch(e.target.value)}
onKeyUp={handleKeyUp}
onKeyDown={handleKeyDown}
/>
</div>
2025-03-07 09:08:19 +00:00
<Button
color="primary"
onPress={() => setDoSetup(!doSetup)}
className="px-2"
>
Settings Approval
2025-03-06 10:40:54 +00:00
</Button>
{doSetup && (
2025-04-16 08:51:12 +00:00
<div className="flex items-center gap-2">
Need Approval?
<Switch isSelected={isSelected} onValueChange={setIsSelected} />
{isSelected ? "Yes" : "No"}
<Button
color="success"
className="text-white"
onPress={saveApproval}
>
Save
</Button>
</div>
2025-03-06 10:40:54 +00:00
)}
2025-03-03 02:58:33 +00:00
</div>
2025-03-06 10:40:54 +00:00
2025-02-13 04:53:53 +00:00
<Table
// selectionMode="multiple"
aria-label="micro issue table"
className="rounded-xl"
classNames={{
th: "bg-white dark:bg-black text-black dark:text-white border-b-1 text-md",
base: "bg-white dark:bg-black border",
wrapper:
"min-h-[50px] bg-transpararent text-black dark:text-white ",
}}
>
2025-03-06 10:40:54 +00:00
<TableHeader columns={doSetup ? columns2 : columns}>
2025-02-13 04:53:53 +00:00
{(column) => (
2025-03-06 10:40:54 +00:00
<TableColumn key={column.uid}>
{column.uid === "setup" ? (
<Checkbox
isSelected={selectAllLevel}
onValueChange={(e) => {
doMapping(e);
}}
></Checkbox>
) : (
column.name
)}
</TableColumn>
2025-02-13 04:53:53 +00:00
)}
</TableHeader>
<TableBody
items={masterUserLevelTable}
emptyContent={"No data to display."}
>
{(item) => (
<TableRow key={item.id}>
{(columnKey) => (
<TableCell>{renderCell(item, columnKey)}</TableCell>
)}
</TableRow>
)}
</TableBody>
</Table>
2025-03-06 10:40:54 +00:00
<div className="mt-2 justify-center flex w-full">
2025-02-13 04:53:53 +00:00
<Pagination
isCompact
showControls
showShadow
color="primary"
classNames={{
base: "bg-transparent",
wrapper: "bg-transparent",
2025-05-31 14:52:58 +00:00
item: "w-fit px-3",
cursor: "w-fit px-3",
2025-02-13 04:53:53 +00:00
}}
page={page}
total={totalPage}
onChange={(page) => setPage(page)}
/>
</div>
</div>
</div>
</>
);
}