Merge branch 'main' of https://gitlab.com/hanifsalafi/web-humas-polri into dev-new-ahmad

This commit is contained in:
amd123 2024-04-24 17:43:32 +07:00
commit 5881b97109
30 changed files with 3498 additions and 1173 deletions

28
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,28 @@
stages:
- build
- deploy
build-dev:
stage: build
when: on_success
only:
- main
image: docker:stable
services:
- docker:dind
script:
- docker logout
- docker login -u $DEPLOY_USERNAME -p $DEPLOY_TOKEN registry.gitlab.com
- docker build -t registry.gitlab.com/hanifsalafi/web-humas-polri:dev .
- docker push registry.gitlab.com/hanifsalafi/web-humas-polri:dev
auto-deploy:
stage: deploy
when: on_success
only:
- main
image: curlimages/curl:latest
services:
- docker:dind
script:
- curl --user cekmedsos:$JENKINS_PWD http://103.82.242.92:8080/job/autodeploy-humas/build?token=autodeployhumas

24
Dockerfile Normal file
View File

@ -0,0 +1,24 @@
FROM node:21-alpine
ENV PORT 4000
# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
# Installing dependencies
COPY package*.json /usr/src/app/
# RUN npm install --force
RUN npm install -g npm@latest
RUN npm install
# Copying source files
COPY . /usr/src/app
# Building app
RUN npm run build
EXPOSE 4000
# Running the app
CMD "npm" "run" "start"

View File

@ -0,0 +1,11 @@
import CreateMagazineForm from '@/components/form/magazine/magazine-form'
import MagazineTable from '@/components/table/magazine/magazine-table'
import React from 'react'
const AdminMagazineCreate = () => {
return (
<div><CreateMagazineForm /></div>
)
}
export default AdminMagazineCreate

View File

@ -0,0 +1,11 @@
import CreateMagazineForm from '@/components/form/magazine/magazine-form'
import MagazineTable from '@/components/table/magazine/magazine-table'
import React from 'react'
const AdminMagazineDetail = () => {
return (
<div><CreateMagazineForm /></div>
)
}
export default AdminMagazineDetail

View File

@ -0,0 +1,10 @@
import MagazineTable from '@/components/table/magazine/magazine-table'
import React from 'react'
const AdminMagazine = () => {
return (
<div><MagazineTable /></div>
)
}
export default AdminMagazine

View File

@ -0,0 +1,12 @@
import CreateMagazineForm from '@/components/form/magazine/magazine-form'
import CreateMenuDataForm from '@/components/form/master/master-menu/menu-data/menu-data-form'
import MagazineTable from '@/components/table/magazine/magazine-table'
import React from 'react'
const AdminMenuDataCreate = () => {
return (
<div><CreateMenuDataForm /></div>
)
}
export default AdminMenuDataCreate

View File

@ -0,0 +1,11 @@
import MagazineTable from '@/components/table/magazine/magazine-table'
import MenuDataTable from '@/components/table/master/master-menu/menu-data/menu-data-table'
import React from 'react'
const AdminMenuData = () => {
return (
<div><MenuDataTable /></div>
)
}
export default AdminMenuData

View File

@ -0,0 +1,13 @@
import CreateMagazineForm from '@/components/form/magazine/magazine-form'
import CreateMenuDataForm from '@/components/form/master/master-menu/menu-data/menu-data-form'
import CreateMasterModuleForm from '@/components/form/master/master-module/master-module-form'
import MagazineTable from '@/components/table/magazine/magazine-table'
import React from 'react'
const AdminMasterModuleCreate = () => {
return (
<div><CreateMasterModuleForm /></div>
)
}
export default AdminMasterModuleCreate

View File

@ -0,0 +1,12 @@
import MagazineTable from '@/components/table/magazine/magazine-table'
import MenuDataTable from '@/components/table/master/master-menu/menu-data/menu-data-table'
import MasterModuleTable from '@/components/table/master/master-module/master-module-table'
import React from 'react'
const AdminMasterModule = () => {
return (
<div><MasterModuleTable /></div>
)
}
export default AdminMasterModule

View File

@ -0,0 +1,14 @@
import CreateMagazineForm from '@/components/form/magazine/magazine-form'
import CreateMenuDataForm from '@/components/form/master/master-menu/menu-data/menu-data-form'
import CreateMasterModuleForm from '@/components/form/master/master-module/master-module-form'
import CreateMasterUserLevelForm from '@/components/form/master/master-user-level/master-user-level-form'
import MagazineTable from '@/components/table/magazine/magazine-table'
import React from 'react'
const AdminMasterUserLevelCreate = () => {
return (
<div><CreateMasterUserLevelForm /></div>
)
}
export default AdminMasterUserLevelCreate

View File

@ -0,0 +1,13 @@
import MagazineTable from '@/components/table/magazine/magazine-table'
import MenuDataTable from '@/components/table/master/master-menu/menu-data/menu-data-table'
import MasterModuleTable from '@/components/table/master/master-module/master-module-table'
import MasterUserLevelTable from '@/components/table/master/master-user-level/master-user-level-table'
import React from 'react'
const AdminMasterUserLevel = () => {
return (
<div><MasterUserLevelTable /></div>
)
}
export default AdminMasterUserLevel

10
app/admin/page.tsx Normal file
View File

@ -0,0 +1,10 @@
import React from 'react'
export default function AdminHumasPage() {
return (
<div className=''>
<div>1</div>
<div>1</div>
</div>
)
}

View File

@ -0,0 +1,267 @@
'use client'
import { Button } from "@nextui-org/button";
import { Card, Checkbox, CheckboxGroup, Divider, Input, Radio, RadioGroup, Select, SelectItem, Slider, Switch, Tab, Table, Tabs, Textarea, User } from "@nextui-org/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 * as z from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import parse from 'html-react-parser';
export default function CreateMagazineForm() {
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 handleTab = (tab: any) => {
setTabs(tab);
};
let [files, setFiles] = useState<File[]>([]);
const removeFile = (name: string) => {
const arrayFile: File[] = [];
for (const element of files) {
if (element.name !== name) {
arrayFile.push(element);
}
}
setFiles(arrayFile);
};
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 toggleVisibility = () => setIsVisible(!isVisible);
const validationSchema = z.object({
title: z.string().min(1, { message: "Required" }),
slug: z.string().min(1, { message: "Required" }),
});
const formOptions = { resolver: zodResolver(validationSchema) };
type ArticleSchema = z.infer<typeof validationSchema>;
const { register, handleSubmit, formState: { errors }, formState, setValue } = useForm<ArticleSchema>(formOptions);
const save = async (data: any) => {
const parsedContent = parse(content);
console.log(parsedContent);
const request = {
title: data.title,
slug: data.slug,
articleBody: data.articleBody,
status: 1,
};
console.log(request);
// loading();
// // const res = await saveManualContext(request);
// if (res.error) {
// error(res.message);
// return false;
// }
close();
successSubmit("/admin/magazine")
}
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);
}
});
}
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-col gap-1">
<div className="flex flex-row justify-between items-center mt-[24px] gap-3">
<div className="flex flex-col w-6/12">
<Input
type="text"
label="Title"
id="title"
{...register("title")}
placeholder="...."
labelPlacement="outside"
className="w-9/12 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.title?.message && (
<p className="text-red-400 text-sm">
{errors.title?.message}
</p>
)}
</div>
<div className="flex flex-col w-6/12">
<Input
type="text"
label="Slug"
id="slug"
{...register("slug")}
placeholder="....."
labelPlacement="outside"
className="w-9/12 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.slug?.message && (
<p className="text-red-400 text-sm">
{errors.slug?.message}
</p>
)}
</div>
</div>
<div className="mt-1">
<p className="text-black text-sm font-semibold my-2">Description</p>
<JoditEditor
ref={editor}
value={content}
onChange={(newContent) => setContent(newContent)}
className="dark:text-black"
/>
</div>
<p className="text-sm text-black mt-2 pb-1 pt-3">Upload File (Opsional)</p>
<div className="w-full bg-transparent">
<div className="flex items-center justify-center w-full ">
<label
htmlFor="dropzone-file"
className="flex flex-col items-center justify-center w-full h-32 border-2 border-gray-100 border-dashed rounded-lg cursor-pointer bg-gray-50 dark:hover:bg-bray-800 hover:bg-gray-100 dark:border-gray-600 dark:hover:border-gray-500 dark:hover:bg-gray-600"
>
<div className="flex flex-col items-center justify-center pt-5 pb-6 ">
<svg
className="w-10 h-10 mb-3 text-gray-400"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"
></path>
</svg>
{/* <p className="mb-2 text-sm text-gray-500 dark:text-gray-400">
Drag and drop files here
</p> */}
<p className="mb-2 text-sm text-gray-500 dark:text-gray-400">
{/* or{" "} */}
<span className="font-semibold underline text-amber-800">
Click to upload
</span>
</p>
</div>
<input id="dropzone-file" type="file" multiple accept=".doc,.docx,.pdf,.ppt,.pptx,.xlsx,.csv" className="hidden" onChange={handleFileChange} />
</label>
</div>
</div>
<p className="text-tiny text-default ">Support file format in word, excel, ppt and pdf</p>
<div className="flex flex-wrap gap-3">
{files?.length > 0 &&
files?.map((list: File) => (
<div key={list.name} className="text-black text-sm py-2 px-4 border-1 border-black w-auto rounded-lg flex justify-between gap-5">
{list.name}
<a className="cursor-pointer" onClick={() => removeFile(list.name)}><TimesIcon /></a>
</div>
))
}
</div>
<div className="flex flex-row gap-3 my-3">
<Link href="/admin/magazine">
<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>
</>
</form>
</div>
</Card>
</div>
</div >
)
}

View File

@ -0,0 +1,397 @@
'use client'
import { Button } from "@nextui-org/button";
import { Card, Checkbox, CheckboxGroup, Divider, Image, Input, Radio, RadioGroup, Select, SelectItem, SelectSection, Slider, Switch, Tab, Table, Tabs, Textarea, User } from "@nextui-org/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 * as z from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
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 },
];
export default function CreateMenuDataForm() {
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, setActive] = useState("1");
const handleTab = (tab: any) => {
setTabs(tab);
};
const handleActive = (e: React.ChangeEvent<HTMLInputElement>) => {
setActive(e.target.value);
};
const handleHaveChildren = (e: React.ChangeEvent<HTMLInputElement>) => {
setHaveChildren(e.target.value);
};
let [files, setFiles] = useState<File[]>([]);
const removeFile = (name: string) => {
const arrayFile: File[] = [];
for (const element of files) {
if (element.name !== name) {
arrayFile.push(element);
}
}
setFiles(arrayFile);
};
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 toggleVisibility = () => setIsVisible(!isVisible);
const validationSchema = z.object({
name: z.string().min(1, { message: "Required" }),
description: z.string().min(1, { message: "Required" }),
});
const formOptions = { resolver: zodResolver(validationSchema) };
type ArticleSchema = z.infer<typeof validationSchema>;
const { register, handleSubmit, formState: { errors }, formState, setValue } = useForm<ArticleSchema>(formOptions);
const save = async (data: any) => {
const request = {
name: data.name,
description: data.description,
moduleList: moduleList,
status: 1,
};
console.log(request);
// loading();
// // const res = await saveManualContext(request);
// if (res.error) {
// error(res.message);
// return false;
// }
close();
successSubmit("/admin/master/master-menu/menu-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);
}
});
}
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="Name"
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="Description"
id="description"
{...register("description")}
placeholder="Input Description"
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.description?.message && (
<p className="text-red-400 text-sm">
{errors.description?.message}
</p>
)}
</div>
<div className="mt-3 ">
<p className="text-black text-sm mb-1 font-semibold">Main Module</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="text-black mt-3">
<label className="text-black text-sm dark:text-black">Have sub module ?</label>
<RadioGroup
orientation="horizontal"
id="radio-banned"
className="text-gray-950 pt-2"
onChange={handleHaveChildren}
defaultValue={haveChildren}
classNames={{
label: "!text-black",
description: "!text-black",
base: "!text-black",
wrapper: "!text-black",
}}
>
<Radio
classNames={{
label: "!text-black",
}}
value="no"
>
No
</Radio>
<Radio
classNames={{
label: "!text-black",
}}
value="yes"
>
Yes
</Radio>
</RadioGroup>
</div>
{haveChildren === "yes" && (
<div className="mt-3 ">
<p className="text-black text-sm mb-1 font-semibold">Sub Module</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="text-black mt-3">
<label className="text-black text-sm dark:text-black">Status</label>
<RadioGroup
orientation="horizontal"
id="radio-banned"
className="text-gray-950 pt-2"
onChange={handleActive}
defaultValue={active}
classNames={{
label: "!text-black",
description: "!text-black",
base: "!text-black",
wrapper: "!text-black",
}}
>
<Radio
classNames={{
label: "!text-black",
}}
value="1"
>
Active
</Radio>
<Radio
classNames={{
label: "!text-black",
}}
value="2"
>
Inactive
</Radio>
</RadioGroup>
</div>
<div className="flex flex-row gap-3 my-3">
<Link href="/admin/master/master-menu/menu-data">
<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 >
)
}

View File

@ -0,0 +1,294 @@
'use client'
import { Button } from "@nextui-org/button";
import { Card, Checkbox, CheckboxGroup, Divider, Image, Input, Radio, RadioGroup, Select, SelectItem, SelectSection, Slider, Switch, Tab, Table, Tabs, Textarea, User } from "@nextui-org/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 * as z from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
const platform = [
{ 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 },
];
export default function CreateMasterModuleForm() {
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, setActive] = useState("1");
const handleTab = (tab: any) => {
setTabs(tab);
};
const handleActive = (e: React.ChangeEvent<HTMLInputElement>) => {
setActive(e.target.value);
};
const handleHaveChildren = (e: React.ChangeEvent<HTMLInputElement>) => {
setHaveChildren(e.target.value);
};
let [files, setFiles] = useState<File[]>([]);
const removeFile = (name: string) => {
const arrayFile: File[] = [];
for (const element of files) {
if (element.name !== name) {
arrayFile.push(element);
}
}
setFiles(arrayFile);
};
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 toggleVisibility = () => setIsVisible(!isVisible);
const validationSchema = z.object({
name: z.string().min(1, { message: "Required" }),
description: z.string().min(1, { message: "Required" }),
pathUrl: z.string().min(1, { message: "Required" }),
});
const formOptions = { resolver: zodResolver(validationSchema) };
type ArticleSchema = z.infer<typeof validationSchema>;
const { register, handleSubmit, formState: { errors }, formState, setValue } = useForm<ArticleSchema>(formOptions);
const save = async (data: any) => {
const request = {
name: data.name,
description: data.description,
pathUrl: data.pathUrl,
status: 1,
};
console.log(request);
// loading();
// // const res = await saveManualContext(request);
// if (res.error) {
// error(res.message);
// return false;
// }
close();
successSubmit("/admin/master/master-module")
}
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);
}
});
}
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="Name"
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="Description"
id="description"
{...register("description")}
placeholder="Input Description"
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.description?.message && (
<p className="text-red-400 text-sm">
{errors.description?.message}
</p>
)}
</div>
<div className="flex flex-col mt-3">
<Input
type="text"
label="pathUrl"
id="pathUrl"
{...register("pathUrl")}
placeholder="Input PathUrl"
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.description?.message && (
<p className="text-red-400 text-sm">
{errors.description?.message}
</p>
)}
</div>
<div className="text-black mt-3">
<label className="text-black text-sm dark:text-black">Status</label>
<RadioGroup
orientation="horizontal"
id="radio-banned"
className="text-gray-950 pt-2"
onChange={handleActive}
defaultValue={active}
classNames={{
label: "!text-black",
description: "!text-black",
base: "!text-black",
wrapper: "!text-black",
}}
>
<Radio
classNames={{
label: "!text-black",
}}
value="1"
>
Active
</Radio>
<Radio
classNames={{
label: "!text-black",
}}
value="2"
>
Inactive
</Radio>
</RadioGroup>
</div>
<div className="flex flex-row gap-3 my-3">
<Link href="/admin/master/master-module">
<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 >
)
}

View File

@ -0,0 +1,413 @@
'use client'
import { Button } from "@nextui-org/button";
import { Card, Checkbox, CheckboxGroup, Divider, Image, Input, Radio, RadioGroup, Select, SelectItem, SelectSection, Slider, Switch, Tab, Table, Tabs, Textarea, User } from "@nextui-org/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 * as z from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import { createUserLevels } from "@/services/user-levels/user-levels-service";
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 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 },
];
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 handleActive = (e: React.ChangeEvent<HTMLInputElement>) => {
setTrue(e.target.value);
};
const handleHaveChildren = (e: React.ChangeEvent<HTMLInputElement>) => {
setHaveChildren(e.target.value);
};
let [files, setFiles] = useState<File[]>([]);
const removeFile = (name: string) => {
const arrayFile: File[] = [];
for (const element of files) {
if (element.name !== name) {
arrayFile.push(element);
}
}
setFiles(arrayFile);
};
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 toggleVisibility = () => setIsVisible(!isVisible);
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" }),
});
const formOptions = { resolver: zodResolver(validationSchema) };
type ArticleSchema = z.infer<typeof validationSchema>;
const { register, handleSubmit, formState: { errors }, formState, setValue } = useForm<ArticleSchema>(formOptions);
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")
}
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);
}
});
}
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 >
)
}

View File

@ -0,0 +1,222 @@
"use client";
import {
TableCell,
TableRow,
Table,
TableHeader,
TableColumn,
TableBody,
Pagination,
Dropdown,
DropdownTrigger,
DropdownMenu,
DropdownItem,
Input,
User,
Card,
Divider,
Chip,
ChipProps,
} from "@nextui-org/react";
import { Button } from "@nextui-org/button";
import React, { Key, useCallback, useMemo, useState } from "react";
import {
AddIcon,
CreateIconIon,
DeleteIcon,
DotsYIcon,
EyeFilledIcon,
EyeIconMdi,
} from "@/components/icons";
import Link from "next/link";
type UserObject = {
id: number;
title: string;
status: string;
description: string;
avatar: string;
};
const statusColorMap = {
active: "success",
paused: "danger",
vacation: "warning",
};
export default function MagazineTable() {
type TableRow = (typeof magazineTable)[0];
const columns = [
{ name: "Title", uid: "title" },
{ name: "Description", uid: "description" },
{ name: "Action", uid: "actions" },
];
const magazineTable = [
{
id: 1,
title: "Proses pembuatan website humas ",
status: "active",
description: "Pembuatan website Humas adalah sebuah proses yang strategis untuk membangun identitas digital sebuah organisasi atau entitas, yang bertujuan untuk menyebarkan informasi kepada publik, memperkuat citra merek, serta menjaga keterbukaan dan transparansi. Proses ini melibatkan beberapa tahapan yang terstruktur dan terkoordinasi dengan baik",
avatar: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSa8Luglga9J2R3Bxt_PsWZISUHQWODD6_ZTAJ5mIQgxYCAE-YbkY81faTqp-hSA_jVPTs&usqp=CAU",
},
{
id: 2,
title: "Proses pembuatan website humas ",
status: "active",
description: "Pembuatan website Humas adalah sebuah proses yang strategis untuk membangun identitas digital sebuah organisasi atau entitas, yang bertujuan untuk menyebarkan informasi kepada publik, memperkuat citra merek, serta menjaga keterbukaan dan transparansi. Proses ini melibatkan beberapa tahapan yang terstruktur dan terkoordinasi dengan baik",
avatar: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSa8Luglga9J2R3Bxt_PsWZISUHQWODD6_ZTAJ5mIQgxYCAE-YbkY81faTqp-hSA_jVPTs&usqp=CAU",
},
{
id: 3,
title: "Proses pembuatan website humas ",
status: "active",
description: "Pembuatan website Humas adalah sebuah proses yang strategis untuk membangun identitas digital sebuah organisasi atau entitas, yang bertujuan untuk menyebarkan informasi kepada publik, memperkuat citra merek, serta menjaga keterbukaan dan transparansi. Proses ini melibatkan beberapa tahapan yang terstruktur dan terkoordinasi dengan baik",
avatar: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSa8Luglga9J2R3Bxt_PsWZISUHQWODD6_ZTAJ5mIQgxYCAE-YbkY81faTqp-hSA_jVPTs&usqp=CAU",
},
{
id: 4,
title: "Proses pembuatan website humas ",
status: "active",
description: "Pembuatan website Humas adalah sebuah proses yang strategis untuk membangun identitas digital sebuah organisasi atau entitas, yang bertujuan untuk menyebarkan informasi kepada publik, memperkuat citra merek, serta menjaga keterbukaan dan transparansi. Proses ini melibatkan beberapa tahapan yang terstruktur dan terkoordinasi dengan baik",
avatar: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSa8Luglga9J2R3Bxt_PsWZISUHQWODD6_ZTAJ5mIQgxYCAE-YbkY81faTqp-hSA_jVPTs&usqp=CAU",
},
{
id: 5,
title: "Proses pembuatan website humas ",
status: "active",
description: "Pembuatan website Humas adalah sebuah proses yang strategis untuk membangun identitas digital sebuah organisasi atau entitas, yang bertujuan untuk menyebarkan informasi kepada publik, memperkuat citra merek, serta menjaga keterbukaan dan transparansi. Proses ini melibatkan beberapa tahapan yang terstruktur dan terkoordinasi dengan baik",
avatar: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSa8Luglga9J2R3Bxt_PsWZISUHQWODD6_ZTAJ5mIQgxYCAE-YbkY81faTqp-hSA_jVPTs&usqp=CAU",
},
];
const renderCell = useCallback((magazine: TableRow, columnKey: Key) => {
const cellValue = magazine[columnKey as keyof UserObject];
const statusColorMap: Record<string, ChipProps["color"]> = {
active: "primary",
cancel: "danger",
pending: "success",
};
switch (columnKey) {
case "no":
return (
<div>{magazine.id}</div>
)
case "title":
return (
<div className="w-[350px]">{magazine.title}</div>
)
case "description":
return (
<div className="">{magazine.description}</div>
)
case "status":
return (
<Chip
className="capitalize "
color={statusColorMap[magazine.status]}
size="lg"
variant="flat"
>
<div className="flex flex-row items-center gap-2 justify-center">
{cellValue}
</div>
</Chip>
);
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>
<DropdownItem
>
<Link
href={`/admin/magazine/detail`}
>
<EyeIconMdi className="inline mr-2 mb-1" />
Detail
</Link>
</DropdownItem>
<DropdownItem
>
<Link
href={`#`}
>
<CreateIconIon className="inline mr-2 mb-1" />
Edit
</Link>
</DropdownItem>
<DropdownItem
>
<Link
href={`#`}
>
<DeleteIcon
width={20}
height={16}
className="inline mr-2 mb-1"
/>
Delete
</Link>
</DropdownItem>
</DropdownMenu>
</Dropdown>
</div>
);
default:
return cellValue;
}
}, []);
return (
<>
<div className="mx-3 my-5">
<Link href="/admin/magazine/create" >
<Button className="my-3 bg-blue-600 text-white" ><CreateIconIon />Create New Magazine</Button>
</Link>
<div className="flex flex-col items-center rounded-2xl">
<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 ",
}}
>
<TableHeader columns={columns}>
{(column) => (
<TableColumn key={column.uid}>{column.name}</TableColumn>
)}
</TableHeader>
<TableBody items={magazineTable} emptyContent={"No data to display."}>
{(item) => (
<TableRow key={item.id}>
{(columnKey) => (
<TableCell>{renderCell(item, columnKey)}</TableCell>
)}
</TableRow>
)}
</TableBody>
</Table>
</div>
</div>
</>
);
}

View File

@ -0,0 +1,231 @@
"use client";
import {
TableCell,
TableRow,
Table,
TableHeader,
TableColumn,
TableBody,
Pagination,
Dropdown,
DropdownTrigger,
DropdownMenu,
DropdownItem,
Input,
User,
Card,
Divider,
Chip,
ChipProps,
} from "@nextui-org/react";
import { Button } from "@nextui-org/button";
import React, { Key, useCallback, useMemo, useState } from "react";
import {
AddIcon,
CreateIconIon,
DeleteIcon,
DotsYIcon,
EyeFilledIcon,
EyeIconMdi,
} from "@/components/icons";
import Link from "next/link";
type UserObject = {
id: number;
name: string;
status: string;
description: string;
moduleName: string;
pathUrl: string;
};
const statusColorMap = {
active: "success",
paused: "danger",
vacation: "warning",
};
export default function MenuDataTable() {
type TableRow = (typeof menuDataTable)[0];
const columns = [
{ name: "No", uid: "no" },
{ name: "Name", uid: "name" },
{ name: "Description", uid: "description" },
{ name: "Module Name", uid: "moduleName" },
{ name: "Path URL", uid: "pathUrl" },
{ name: "Status", uid: "status" },
{ name: "Action", uid: "actions" },
];
const menuDataTable = [
{
id: 1,
name: "AI Journalist ",
status: "active",
description: "AI Journalist",
moduleName: "Multipool Acts",
pathUrl: "/admin/acts",
},
{
id: 2,
name: "AI Journalist ",
status: "active",
description: "AI Journalist",
moduleName: "Multipool Acts",
pathUrl: "/admin/acts",
},
{
id: 3,
name: "AI Journalist ",
status: "active",
description: "AI Journalist",
moduleName: "Multipool Acts",
pathUrl: "/admin/acts",
},
{
id: 4,
name: "AI Journalist ",
status: "active",
description: "AI Journalist",
moduleName: "Multipool Acts",
pathUrl: "/admin/acts",
},
{
id: 5,
name: "AI Journalist ",
status: "active",
description: "AI Journalist",
moduleName: "Multipool Acts",
pathUrl: "/admin/acts",
},
];
const renderCell = useCallback((menuData: TableRow, columnKey: Key) => {
const cellValue = menuData[columnKey as keyof UserObject];
const statusColorMap: Record<string, ChipProps["color"]> = {
active: "success",
cancel: "danger",
pending: "warning",
};
switch (columnKey) {
case "no":
return (
<div>{menuData.id}</div>
)
case "name":
return (
<div className="w-[150px]">{menuData.name}</div>
)
case "description":
return (
<div className="">{menuData.description}</div>
)
case "status":
return (
<Chip
className="capitalize "
color={statusColorMap[menuData.status]}
size="lg"
variant="flat"
>
<div className="flex flex-row items-center gap-2 justify-center">
{cellValue}
</div>
</Chip>
);
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>
<DropdownItem
>
<Link
href={`/admin/magazine/detail`}
>
<EyeIconMdi className="inline mr-2 mb-1" />
Detail
</Link>
</DropdownItem>
<DropdownItem
>
<Link
href={`#`}
>
<CreateIconIon className="inline mr-2 mb-1" />
Edit
</Link>
</DropdownItem>
<DropdownItem
>
<Link
href={`#`}
>
<DeleteIcon
width={20}
height={16}
className="inline mr-2 mb-1"
/>
Delete
</Link>
</DropdownItem>
</DropdownMenu>
</Dropdown>
</div>
);
default:
return cellValue;
}
}, []);
return (
<>
<div className="mx-3 my-5">
<Link href="/admin/master/master-menu/menu-data/create" >
<Button className="my-3 bg-blue-600 text-white" ><CreateIconIon />Add Master Menu</Button>
</Link>
<div className="flex flex-col items-center rounded-2xl">
<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 ",
}}
>
<TableHeader columns={columns}>
{(column) => (
<TableColumn key={column.uid}>{column.name}</TableColumn>
)}
</TableHeader>
<TableBody items={menuDataTable} emptyContent={"No data to display."}>
{(item) => (
<TableRow key={item.id}>
{(columnKey) => (
<TableCell>{renderCell(item, columnKey)}</TableCell>
)}
</TableRow>
)}
</TableBody>
</Table>
</div>
</div>
</>
);
}

View File

@ -0,0 +1,224 @@
"use client";
import {
TableCell,
TableRow,
Table,
TableHeader,
TableColumn,
TableBody,
Pagination,
Dropdown,
DropdownTrigger,
DropdownMenu,
DropdownItem,
Input,
User,
Card,
Divider,
Chip,
ChipProps,
} from "@nextui-org/react";
import { Button } from "@nextui-org/button";
import React, { Key, useCallback, useMemo, useState } from "react";
import {
AddIcon,
CreateIconIon,
DeleteIcon,
DotsYIcon,
EyeFilledIcon,
EyeIconMdi,
} from "@/components/icons";
import Link from "next/link";
type UserObject = {
id: number;
name: string;
status: string;
description: string;
pathUrl: string;
};
const statusColorMap = {
active: "success",
paused: "danger",
vacation: "warning",
};
export default function MasterModuleTable() {
type TableRow = (typeof masterModuleTable)[0];
const columns = [
{ name: "No", uid: "no" },
{ name: "Name", uid: "name" },
{ name: "Description", uid: "description" },
{ name: "Path URL", uid: "pathUrl" },
{ name: "Status", uid: "status" },
{ name: "Action", uid: "actions" },
];
const masterModuleTable = [
{
id: 1,
name: "AI Journalist ",
status: "active",
description: "AI Journalist",
pathUrl: "/admin/acts",
},
{
id: 2,
name: "AI Journalist ",
status: "active",
description: "AI Journalist",
pathUrl: "/admin/acts",
},
{
id: 3,
name: "AI Journalist ",
status: "active",
description: "AI Journalist",
pathUrl: "/admin/acts",
},
{
id: 4,
name: "AI Journalist ",
status: "active",
description: "AI Journalist",
pathUrl: "/admin/acts",
},
{
id: 5,
name: "AI Journalist ",
status: "active",
description: "AI Journalist",
pathUrl: "/admin/acts",
},
];
const renderCell = useCallback((masterModule: TableRow, columnKey: Key) => {
const cellValue = masterModule[columnKey as keyof UserObject];
const statusColorMap: Record<string, ChipProps["color"]> = {
active: "success",
cancel: "danger",
pending: "warning",
};
switch (columnKey) {
case "no":
return (
<div>{masterModule.id}</div>
)
case "name":
return (
<div className="w-[150px]">{masterModule.name}</div>
)
case "description":
return (
<div className="">{masterModule.description}</div>
)
case "status":
return (
<Chip
className="capitalize "
color={statusColorMap[masterModule.status]}
size="lg"
variant="flat"
>
<div className="flex flex-row items-center gap-2 justify-center">
{cellValue}
</div>
</Chip>
);
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>
<DropdownItem
>
<Link
href={`/admin/magazine/detail`}
>
<EyeIconMdi className="inline mr-2 mb-1" />
Detail
</Link>
</DropdownItem>
<DropdownItem
>
<Link
href={`#`}
>
<CreateIconIon className="inline mr-2 mb-1" />
Edit
</Link>
</DropdownItem>
<DropdownItem
>
<Link
href={`#`}
>
<DeleteIcon
width={20}
height={16}
className="inline mr-2 mb-1"
/>
Delete
</Link>
</DropdownItem>
</DropdownMenu>
</Dropdown>
</div>
);
default:
return cellValue;
}
}, []);
return (
<>
<div className="mx-3 my-5">
<Link href="/admin/master/master-module/create" >
<Button className="my-3 bg-blue-600 text-white" ><CreateIconIon />Add Master Module</Button>
</Link>
<div className="flex flex-col items-center rounded-2xl">
<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 ",
}}
>
<TableHeader columns={columns}>
{(column) => (
<TableColumn key={column.uid}>{column.name}</TableColumn>
)}
</TableHeader>
<TableBody items={masterModuleTable} emptyContent={"No data to display."}>
{(item) => (
<TableRow key={item.id}>
{(columnKey) => (
<TableCell>{renderCell(item, columnKey)}</TableCell>
)}
</TableRow>
)}
</TableBody>
</Table>
</div>
</div>
</>
);
}

View File

@ -0,0 +1,241 @@
"use client";
import {
TableCell,
TableRow,
Table,
TableHeader,
TableColumn,
TableBody,
Pagination,
Dropdown,
DropdownTrigger,
DropdownMenu,
DropdownItem,
Input,
User,
Card,
Divider,
Chip,
ChipProps,
} from "@nextui-org/react";
import { Button } from "@nextui-org/button";
import React, { Key, useCallback, useEffect, useMemo, useState } from "react";
import {
AddIcon,
CreateIconIon,
DeleteIcon,
DotsYIcon,
EyeFilledIcon,
EyeIconMdi,
} from "@/components/icons";
import Link from "next/link";
import { getAllUserLevels } from "@/services/user-levels/user-levels-service";
type UserObject = {
id: number;
name: string;
levelNumber: string;
aliasName: string;
parentLevelId: string;
provinceId: string;
status: string;
};
const statusColorMap = {
active: "success",
paused: "danger",
vacation: "warning",
};
export default function MasterUserLevelTable() {
const [totalPage, setTotalPage] = useState(1);
const [masterUserLevelTable, setmasterUserLevel] = useState<UserObject[]>([]);
type TableRow = (typeof masterUserLevelTable)[0];
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: "Action", uid: "actions" },
];
const [page, setPage] = useState(1);
useEffect(() => {
fetchData();
}, []);
async function fetchData() {
const request = {
page: page,
limit: 10,
};
const res = await getAllUserLevels(request);
const data = res?.data?.data;
setTotalPage(Math.ceil(res?.data?.total / 10));
initUserData(10, data);
}
function initUserData(limit: number, data?: any) {
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;
});
console.log("Data ::", newData);
setmasterUserLevel(newData);
}
}
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 "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>
<DropdownItem
>
<Link
href={`/admin/magazine/detail`}
>
<EyeIconMdi className="inline mr-2 mb-1" />
Detail
</Link>
</DropdownItem>
<DropdownItem
>
<Link
href={`#`}
>
<CreateIconIon className="inline mr-2 mb-1" />
Edit
</Link>
</DropdownItem>
<DropdownItem
>
<Link
href={`#`}
>
<DeleteIcon
width={20}
height={16}
className="inline mr-2 mb-1"
/>
Delete
</Link>
</DropdownItem>
</DropdownMenu>
</Dropdown>
</div>
);
default:
return cellValue;
}
}, []);
return (
<>
<div className="mx-3 my-5">
<Link href="/admin/master/master-user-level/create" >
<Button className="my-3 bg-blue-600 text-white" ><CreateIconIon />Create New User Level</Button>
</Link>
<div className="flex flex-col items-center rounded-2xl">
<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 ",
}}
>
<TableHeader columns={columns}>
{(column) => (
<TableColumn key={column.uid}>{column.name}</TableColumn>
)}
</TableHeader>
<TableBody items={masterUserLevelTable} emptyContent={"No data to display."}>
{(item) => (
<TableRow key={item.id}>
{(columnKey) => (
<TableCell>{renderCell(item, columnKey)}</TableCell>
)}
</TableRow>
)}
</TableBody>
</Table>
<div className="mt-2">
<Pagination
isCompact
showControls
showShadow
color="primary"
classNames={{
base: "bg-transparent",
wrapper: "bg-transparent",
}}
page={page}
total={totalPage}
onChange={(page) => setPage(page)}
/>
</div>
</div>
</div>
</>
);
}

View File

@ -5,91 +5,91 @@ import { useRouter } from "next/navigation";
const MySwal = withReactContent(Swal); const MySwal = withReactContent(Swal);
const Toast = MySwal.mixin({ const Toast = MySwal.mixin({
toast: true, toast: true,
position: "top-end", position: "top-end",
showConfirmButton: false, showConfirmButton: false,
timer: 3000, timer: 3000,
timerProgressBar: true, timerProgressBar: true,
didOpen: (toast) => { didOpen: (toast) => {
toast.addEventListener("mouseenter", Swal.stopTimer); toast.addEventListener("mouseenter", Swal.stopTimer);
toast.addEventListener("mouseleave", Swal.resumeTimer); toast.addEventListener("mouseleave", Swal.resumeTimer);
}, },
}); });
export function loading(msg?: any) { export function loading(msg?: any) {
let timerInterval: any; let timerInterval: any;
MySwal.fire({ MySwal.fire({
title: msg || "Loading...", title: msg || "Loading...",
allowOutsideClick: false, allowOutsideClick: false,
timerProgressBar: true, timerProgressBar: true,
didOpen: () => { didOpen: () => {
MySwal.showLoading(); MySwal.showLoading();
timerInterval = setInterval(() => { }, 100); timerInterval = setInterval(() => { }, 100);
}, },
willClose: () => { willClose: () => {
clearInterval(timerInterval); clearInterval(timerInterval);
}, },
}); });
} }
export function error(msg?: any) { export function error(msg?: any) {
MySwal.fire({ MySwal.fire({
icon: "error", icon: "error",
title: "Failed...", title: "Failed...",
text: msg || "Unknown Error", text: msg || "Unknown Error",
}); });
} }
export function successRouter(redirect: string, router?: any) { export function successRouter(redirect: string, router?: any) {
MySwal.fire({ MySwal.fire({
title: "Success!", title: "Success!",
icon: "success", icon: "success",
confirmButtonColor: "#3085d6", confirmButtonColor: "#3085d6",
confirmButtonText: "Ok", confirmButtonText: "Ok",
allowOutsideClick: false, allowOutsideClick: false,
}).then((result) => { }).then((result) => {
if (result.isConfirmed) { if (result.isConfirmed) {
router.push(redirect); router.push(redirect);
} }
}); });
} }
export function success(title: string) { export function success(title: string) {
MySwal.fire({ MySwal.fire({
title: title || "Success!", title: title || "Success!",
icon: "success", icon: "success",
confirmButtonColor: "#3085d6", confirmButtonColor: "#3085d6",
confirmButtonText: "OK", confirmButtonText: "OK",
}).then((result) => { }).then((result) => {
if (result.isConfirmed) { if (result.isConfirmed) {
return true; return true;
} }
}); });
} }
export function close() { export function close() {
MySwal.close(); MySwal.close();
} }
export function warning(text: string, redirect: string, router?: any) { export function warning(text: string, redirect: string, router?: any) {
MySwal.fire({ MySwal.fire({
title: text, title: text,
icon: "warning", icon: "warning",
confirmButtonColor: "#3085d6", confirmButtonColor: "#3085d6",
confirmButtonText: "OK", confirmButtonText: "OK",
}).then((result) => { }).then((result) => {
if (result.isConfirmed) { if (result.isConfirmed) {
router.push(redirect); router.push(redirect);
} }
}); });
} }
export function successToast(title: string, text: string) { export function successToast(title: string, text: string) {
Toast.fire({ Toast.fire({
icon: "success", icon: "success",
title: title, title: title,
text: text, text: text,
}); });
} }

1817
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,7 @@
"scripts": { "scripts": {
"dev": "next dev", "dev": "next dev",
"build": "next build", "build": "next build",
"start": "next start", "start": "next start -p 4000",
"lint": "next lint" "lint": "next lint"
}, },
"dependencies": { "dependencies": {
@ -24,6 +24,7 @@
"@nextui-org/theme": "2.1.17", "@nextui-org/theme": "2.1.17",
"@react-aria/ssr": "^3.8.0", "@react-aria/ssr": "^3.8.0",
"@react-aria/visually-hidden": "^3.8.6", "@react-aria/visually-hidden": "^3.8.6",
"@types/js-cookie": "^3.0.6",
"@types/node": "20.5.7", "@types/node": "20.5.7",
"@types/react": "18.2.21", "@types/react": "18.2.21",
"@types/react-datepicker": "^6.0.1", "@types/react-datepicker": "^6.0.1",
@ -35,6 +36,7 @@
"eslint": "8.48.0", "eslint": "8.48.0",
"eslint-config-next": "14.0.2", "eslint-config-next": "14.0.2",
"framer-motion": "^10.18.0", "framer-motion": "^10.18.0",
"html-react-parser": "^5.1.10",
"intl-messageformat": "^10.5.0", "intl-messageformat": "^10.5.0",
"jodit-react": "^4.0.25", "jodit-react": "^4.0.25",
"next": "14.0.2", "next": "14.0.2",
@ -55,6 +57,6 @@
"tailwind-variants": "^0.1.18", "tailwind-variants": "^0.1.18",
"tailwindcss": "3.3.5", "tailwindcss": "3.3.5",
"typescript": "5.0.4", "typescript": "5.0.4",
"zod": "^3.22.4" "zod": "^1.11.17"
} }
} }

BIN
public/account-category.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -0,0 +1,12 @@
import axios from "axios";
const baseURL = "http://103.82.242.92:8888";
const axiosBaseInstance = axios.create({
baseURL,
headers: {
"content-type": "application/json",
},
});
export default axiosBaseInstance;

View File

@ -0,0 +1,33 @@
import axios from "axios";
import Cookies from "js-cookie";
const baseURL = "http://103.82.242.92:8800";
const refreshToken = Cookies.get("refresh_token");
const axiosInterceptorInstance = axios.create({
baseURL,
headers: {
"content-type": "application/json",
},
});
// Request interceptor
axiosInterceptorInstance.interceptors.request.use(
(config) => {
const accessToken = Cookies.get("access_token");
if (accessToken) {
if (config.headers)
config.headers.Authorization = "Bearer " + accessToken;
}
return config;
},
(error) => {
return Promise.reject(error);
},
);
// Response interceptor
export default axiosInterceptorInstance;

View File

@ -0,0 +1,44 @@
import axiosBaseInstance from "./axios-base-instance";
export async function httpGet(pathUrl: any, headers: any) {
const response = await axiosBaseInstance
.get(pathUrl, { headers })
.catch((error) => error.response);
console.log("Response base svc : ", response);
if (response?.data.success) {
return {
error: false,
message: "success",
data: response?.data,
};
} else {
return {
error: true,
message: response?.data?.message || null,
data: null,
};
}
}
export async function httpPost(pathUrl: any, headers: any, data: any) {
const response = await axiosBaseInstance
.post(pathUrl, data, { headers })
.catch(function (error) {
console.log(error);
return error.response;
});
console.log("Response base svc : ", response);
if (response?.status == 200 || response?.status == 201) {
return {
error: false,
message: "success",
data: response?.data,
};
} else {
return {
error: true,
message: response?.data?.message || response?.data || null,
data: null,
};
}
}

View File

@ -0,0 +1,70 @@
import axiosDisestagesInstance2 from "./axios-disestages-instance-2";
export async function httpPostDisestages(pathUrl: any, headers: any, data?: any) {
const response = await axiosDisestagesInstance2
.post(pathUrl, data, { headers })
.catch(function (error) {
console.log(error);
return error.response;
});
console.log("Response base svc : ", response);
if (response?.status == 200 || response?.status == 201) {
return {
error: false,
message: "success",
data: response?.data,
};
} else {
return {
error: true,
message: response?.data?.message || response?.data || null,
data: null,
};
}
}
export async function httpGetDisestages(pathUrl: any, headers: any) {
const response = await axiosDisestagesInstance2
.get(pathUrl, { headers })
.catch(function (error) {
console.log(error);
return error.response;
});
console.log("Response base svc : ", response);
if (response?.status == 200 || response?.status == 201) {
return {
error: false,
message: "success",
data: response?.data,
};
} else {
return {
error: true,
message: response?.data?.message || response?.data || null,
data: null,
};
}
}
// export async function httpDelete(pathUrl: any) {
// const response = await axiosDisestagesInstance
// .delete(pathUrl, data, { headers })
// .catch(function (error) {
// console.log(error);
// return error.response;
// });
// console.log("Response base svc : ", response);
// if (response?.status == 200 || response?.status == 201) {
// return {
// error: false,
// message: "success",
// data: response?.data,
// };
// } else {
// return {
// error: true,
// message: response?.data?.message || response?.data || null,
// data: null,
// };
// }
// }

View File

@ -0,0 +1,75 @@
import { useRouter } from "next/navigation";
import axiosInterceptorInstance from "./axios-interceptor-instance";
import Cookies from "js-cookie";
export async function httpGetInterceptor(pathUrl: any) {
const response = await axiosInterceptorInstance
.get(pathUrl)
.catch((error) => error.response);
console.log("Response interceptor : ", response);
if (response?.status == 200 || response?.status == 201) {
return {
error: false,
message: "success",
data: response?.data,
};
} else if (response?.status == 401) {
Cookies.set("is_logout", "true");
window.location.href = "/";
return {
error: true,
};
} else {
return {
error: true,
message: response?.data?.message || response?.data || null,
data: null,
};
}
}
export async function httpPostInterceptor(pathUrl: any, data: any, headers?: any) {
const response = await axiosInterceptorInstance
.post(pathUrl, data, { headers })
.catch((error) => error.response);
console.log("Response interceptor : ", response);
if (response?.status == 200 || response?.status == 201) {
return {
error: false,
message: "success",
data: response?.data,
};
} else if (response?.status == 401) {
Cookies.set("is_logout", "true");
window.location.href = "/";
} else {
return {
error: true,
message: response?.data?.message || response?.data || null,
data: null,
};
}
}
export async function httpDeleteInterceptor(pathUrl: any) {
const response = await axiosInterceptorInstance
.delete(pathUrl)
.catch((error) => error.response);
console.log("Response interceptor : ", response);
if (response?.status == 200 || response?.status == 201) {
return {
error: false,
message: "success",
data: response?.data,
};
} else if (response?.status == 401) {
Cookies.set("is_logout", "true");
window.location.href = "/";
} else {
return {
error: true,
message: response?.data?.message || response?.data || null,
data: null,
};
}
}

View File

@ -0,0 +1,26 @@
import { httpGet, httpPost } from "../http-config/http-base-services";
export async function getAllUserLevels(data: any) {
const headers = {
"content-type": "application/json",
};
return await httpGet(`user-levels`, headers,);
}
export async function getAccountById(id: string) {
const headers = {
"content-type": "application/json",
};
return await httpGet(`user-account/findById/${id}`, headers);
}
export async function createUserLevels(request: any) {
const headers = {
"content-type": "application/json",
};
return await httpPost(`user-levels`, headers, request);
}