refactor : divisi
Deskripsi: - folder management divisi No Issues
This commit is contained in:
37
src/module/division_new/ui/carousel_division.tsx
Normal file
37
src/module/division_new/ui/carousel_division.tsx
Normal file
@@ -0,0 +1,37 @@
|
||||
'use client'
|
||||
import React, { useRef } from 'react';
|
||||
import { Carousel } from '@mantine/carousel';
|
||||
import { WARNA } from '@/module/_global';
|
||||
import Autoplay from 'embla-carousel-autoplay';
|
||||
import { Flex, Text } from '@mantine/core';
|
||||
export default function CarouselDivision() {
|
||||
const autoplay = useRef(Autoplay({ delay: 5000 }));
|
||||
return (
|
||||
<>
|
||||
<Carousel
|
||||
withIndicators
|
||||
height={150}
|
||||
plugins={[autoplay.current]}
|
||||
onMouseEnter={autoplay.current.stop}
|
||||
onMouseLeave={autoplay.current.reset}
|
||||
>
|
||||
<Carousel.Slide bg={WARNA.biruTua} style={{ borderRadius: 10 }}>
|
||||
<Flex justify={'center'} h={"100%"} align={'center'}>
|
||||
<Text c={"white"}>INFORMASI DARMASABA</Text>
|
||||
</Flex>
|
||||
</Carousel.Slide>
|
||||
<Carousel.Slide bg={WARNA.biruTua} style={{ borderRadius: 10 }}>
|
||||
<Flex justify={'center'} h={"100%"} align={'center'}>
|
||||
<Text c={"white"}>INFORMASI DARMASABA</Text>
|
||||
</Flex>
|
||||
</Carousel.Slide>
|
||||
<Carousel.Slide bg={WARNA.biruTua} style={{ borderRadius: 10 }}>
|
||||
<Flex justify={'center'} h={"100%"} align={'center'}>
|
||||
<Text c={"white"}>INFORMASI DARMASABA</Text>
|
||||
</Flex>
|
||||
</Carousel.Slide>
|
||||
</Carousel>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
9
src/module/division_new/ui/create_admin_division.tsx
Normal file
9
src/module/division_new/ui/create_admin_division.tsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import React from 'react';
|
||||
import NavbarAdminDivision from './navbar_admin_division';
|
||||
|
||||
export default function CreateAdminDivision({ data }: { data: any }) {
|
||||
return (
|
||||
<NavbarAdminDivision data={data} onSuccess={() => { }} />
|
||||
);
|
||||
}
|
||||
|
||||
184
src/module/division_new/ui/create_anggota_division.tsx
Normal file
184
src/module/division_new/ui/create_anggota_division.tsx
Normal file
@@ -0,0 +1,184 @@
|
||||
"use client"
|
||||
import { API_ADDRESS, LayoutNavbarNew, WARNA } from '@/module/_global';
|
||||
import LayoutModal from '@/module/_global/layout/layout_modal';
|
||||
import { funGetUserByCookies } from '@/module/auth';
|
||||
import { TypeUser } from '@/module/user';
|
||||
import { useHookstate } from '@hookstate/core';
|
||||
import { Avatar, Box, Button, Divider, Group, Stack, Text, TextInput } from '@mantine/core';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
import React, { useState } from 'react';
|
||||
import toast from 'react-hot-toast';
|
||||
import { FaCheck } from 'react-icons/fa6';
|
||||
import { HiMagnifyingGlass } from 'react-icons/hi2';
|
||||
import { globalMemberDivision } from '../lib/val_division';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { funGetAllmember } from '@/module/user/member/lib/api_member';
|
||||
import { IDataMemberDivision } from '../lib/type_division';
|
||||
import { funAddDivisionMember, funGetDivisionById } from '../lib/api_division';
|
||||
|
||||
const dataUser = [
|
||||
{
|
||||
id: 1,
|
||||
img: "https://i.pravatar.cc/1000?img=3",
|
||||
name: "Doni Setiawan",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
img: "https://i.pravatar.cc/1000?img=10",
|
||||
name: "Ilham Udin",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
img: "https://i.pravatar.cc/1000?img=11",
|
||||
name: "Didin Anang",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
img: "https://i.pravatar.cc/1000?img=21",
|
||||
name: "Angga Saputra",
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
img: "https://i.pravatar.cc/1000?img=32",
|
||||
name: "Marcel Widianto",
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
img: "https://i.pravatar.cc/1000?img=37",
|
||||
name: "Bagas Nusantara",
|
||||
},
|
||||
];
|
||||
|
||||
export default function CreateAnggotaDivision() {
|
||||
const router = useRouter()
|
||||
const [selectedFiles, setSelectedFiles] = useState<any>([]);
|
||||
const [dataMember, setDataMember] = useState<TypeUser>([])
|
||||
const [memberDb, setMemberDb] = useState<IDataMemberDivision[]>([])
|
||||
const [group, setGroup] = useState("")
|
||||
const [isOpen, setOpen] = useState(false)
|
||||
const param = useParams<{ id: string }>()
|
||||
|
||||
const handleFileClick = (index: number) => {
|
||||
if (selectedFiles.some((i: any) => i.idUser == dataMember[index].id)) {
|
||||
setSelectedFiles(selectedFiles.filter((i: any) => i.idUser != dataMember[index].id))
|
||||
} else {
|
||||
setSelectedFiles([...selectedFiles, { idUser: dataMember[index].id, name: dataMember[index].name }])
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
async function loadMember(group: string, search: string) {
|
||||
const res = await funGetAllmember('?active=true&group=' + group + '&search=' + search);
|
||||
const user = await funGetUserByCookies();
|
||||
|
||||
if (res.success) {
|
||||
setDataMember(res.data.filter((i: any) => i.id != user.id))
|
||||
} else {
|
||||
toast.error(res.message)
|
||||
}
|
||||
}
|
||||
|
||||
async function loadFirst() {
|
||||
const respon = await funGetDivisionById(param.id);
|
||||
if (respon.success) {
|
||||
setMemberDb(respon.data.member)
|
||||
setGroup(respon.data.division.idGroup)
|
||||
loadMember(respon.data.division.idGroup, "")
|
||||
} else {
|
||||
toast.error(respon.message);
|
||||
}
|
||||
}
|
||||
|
||||
async function addMember() {
|
||||
try {
|
||||
const res = await funAddDivisionMember(param.id, selectedFiles)
|
||||
if (res.success) {
|
||||
toast.success(res.message)
|
||||
router.push("/division/info/" + param.id)
|
||||
} else {
|
||||
toast.error(res.message)
|
||||
}
|
||||
setOpen(false)
|
||||
} catch (error) {
|
||||
setOpen(false)
|
||||
console.log(error);
|
||||
toast.error("Gagal menambahkan anggota divisi, coba lagi nanti");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
useShallowEffect(() => {
|
||||
loadFirst()
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<LayoutNavbarNew back="" title="tambah anggota"
|
||||
menu
|
||||
/>
|
||||
<Box p={20}>
|
||||
<Stack>
|
||||
<TextInput
|
||||
styles={{
|
||||
input: {
|
||||
color: WARNA.biruTua,
|
||||
borderRadius: '#A3A3A3',
|
||||
borderColor: '#A3A3A3',
|
||||
},
|
||||
}}
|
||||
size="md"
|
||||
radius={30}
|
||||
leftSection={<HiMagnifyingGlass size={20} />}
|
||||
placeholder="Pencarian"
|
||||
onChange={(e: any) => loadMember(group, e.target.value)}
|
||||
/>
|
||||
</Stack>
|
||||
<Box mt={20}>
|
||||
{dataMember.map((v: any, index: any) => {
|
||||
const isSelected = selectedFiles.some((i: any) => i.idUser == dataMember[index].id)
|
||||
const found = memberDb.some((i: any) => i.idUser == v.id)
|
||||
return (
|
||||
<Box my={10} key={index} onClick={() => (!found) ? handleFileClick(index) : null}>
|
||||
<Group justify='space-between' align='center'>
|
||||
<Group>
|
||||
<Avatar src={"v.img"} alt="it's me" size="lg" />
|
||||
<Stack align="flex-start" justify="flex-start">
|
||||
<Text>{v.name}</Text>
|
||||
<Text c={"dimmed"}>{(found) ? "sudah menjadi anggota divisi" : ""}</Text>
|
||||
</Stack>
|
||||
</Group>
|
||||
{isSelected ? <FaCheck /> : null}
|
||||
</Group>
|
||||
<Box mt={10}>
|
||||
<Divider size={"xs"} />
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
})}
|
||||
</Box>
|
||||
<Box mt="xl">
|
||||
<Button
|
||||
color="white"
|
||||
bg={WARNA.biruTua}
|
||||
size="lg"
|
||||
radius={30}
|
||||
fullWidth
|
||||
onClick={() => { setOpen(true) }}
|
||||
>
|
||||
Simpan
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
<LayoutModal opened={isOpen} onClose={() => setOpen(false)}
|
||||
description="Apakah Anda yakin ingin menambahkan anggota divisi?"
|
||||
onYes={(val) => {
|
||||
if (val) {
|
||||
addMember()
|
||||
} else {
|
||||
setOpen(false)
|
||||
}
|
||||
}} />
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
216
src/module/division_new/ui/create_division.tsx
Normal file
216
src/module/division_new/ui/create_division.tsx
Normal file
@@ -0,0 +1,216 @@
|
||||
"use client";
|
||||
import { API_ADDRESS, LayoutNavbarNew, WARNA } from "@/module/_global";
|
||||
import { useHookstate } from "@hookstate/core";
|
||||
import {
|
||||
Avatar,
|
||||
Box,
|
||||
Button,
|
||||
Flex,
|
||||
Group,
|
||||
Select,
|
||||
Stack,
|
||||
Text,
|
||||
Textarea,
|
||||
TextInput,
|
||||
} from "@mantine/core";
|
||||
import { useShallowEffect } from "@mantine/hooks";
|
||||
import { useRouter } from "next/navigation";
|
||||
import React, { useState } from "react";
|
||||
import { IoIosArrowDropright } from "react-icons/io";
|
||||
import { globalMemberDivision } from "../lib/val_division";
|
||||
import toast from "react-hot-toast";
|
||||
import { funGetUserByCookies } from "@/module/auth";
|
||||
import { funGetAllGroup, IDataGroup } from "@/module/group";
|
||||
import NavbarAdminDivision from "./navbar_admin_division";
|
||||
import NavbarCreateUsers from "./navbar_create_users";
|
||||
|
||||
export default function CreateDivision() {
|
||||
const router = useRouter();
|
||||
const [dataGroup, setDataGroup] = useState<IDataGroup[]>([]);
|
||||
const [roleUser, setRoleUser] = useState<any>("")
|
||||
const [isChooseAnggota, setChooseAnggota] = useState(false)
|
||||
const [isChooseAdmin, setChooseAdmin] = useState(false)
|
||||
const member = useHookstate(globalMemberDivision)
|
||||
const [body, setBody] = useState<any>({
|
||||
idGroup: "",
|
||||
name: "",
|
||||
desc: "",
|
||||
});
|
||||
|
||||
async function loadData() {
|
||||
const loadGroup = await funGetAllGroup('?active=true')
|
||||
if (loadGroup.success) {
|
||||
setDataGroup(loadGroup.data);
|
||||
} else {
|
||||
toast.error(loadGroup.message);
|
||||
}
|
||||
|
||||
const loadUser = await funGetUserByCookies();
|
||||
setRoleUser(loadUser.idUserRole)
|
||||
}
|
||||
|
||||
function onSubmit() {
|
||||
if (roleUser == "supadmin" && (body.idGroup == "" || body.idGroup == null)) {
|
||||
return toast.error("Error! grup harus diisi")
|
||||
}
|
||||
|
||||
if (body.name == "") {
|
||||
return toast.error("Error! nama divisi harus diisi")
|
||||
}
|
||||
|
||||
if (member.length == 0) {
|
||||
return toast.error("Error! belum ada anggota yang terdaftar")
|
||||
}
|
||||
|
||||
|
||||
|
||||
setChooseAdmin(true)
|
||||
|
||||
}
|
||||
|
||||
function onToChooseAnggota() {
|
||||
if (roleUser == "supadmin" && body.idGroup == "")
|
||||
return toast.error("Error! grup harus diisi")
|
||||
setChooseAnggota(true)
|
||||
}
|
||||
|
||||
|
||||
function onChooseGroup(val: any) {
|
||||
member.set([])
|
||||
setBody({ ...body, idGroup: val })
|
||||
}
|
||||
|
||||
|
||||
|
||||
useShallowEffect(() => {
|
||||
loadData();
|
||||
}, []);
|
||||
|
||||
|
||||
|
||||
if (isChooseAdmin) return <NavbarAdminDivision data={body} onSuccess={(val) => {
|
||||
if (val) {
|
||||
member.set([])
|
||||
setBody({
|
||||
...body,
|
||||
idGroup: "",
|
||||
name: "",
|
||||
desc: "",
|
||||
})
|
||||
}
|
||||
|
||||
setChooseAdmin(false)
|
||||
}} />
|
||||
|
||||
if (isChooseAnggota) return <NavbarCreateUsers grup={body.idGroup} onClose={() => { setChooseAnggota(false) }} />
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<LayoutNavbarNew back="/division" title="Tambah Divisi" menu />
|
||||
<Box p={20}>
|
||||
<Stack>
|
||||
{
|
||||
(roleUser == "supadmin") && (
|
||||
<Select
|
||||
placeholder="Grup"
|
||||
label="Grup"
|
||||
size="md"
|
||||
required
|
||||
radius={40}
|
||||
data={dataGroup?.map((pro: any) => ({
|
||||
value: String(pro.id),
|
||||
label: pro.name
|
||||
}))}
|
||||
onChange={(val) => {
|
||||
onChooseGroup(val)
|
||||
}}
|
||||
|
||||
value={body.idGroup}
|
||||
/>
|
||||
)
|
||||
}
|
||||
<TextInput
|
||||
placeholder="Nama Divisi"
|
||||
label="Nama Divisi"
|
||||
size="md"
|
||||
required
|
||||
radius={40}
|
||||
value={body.name}
|
||||
onChange={(val) => { setBody({ ...body, name: val.target.value }) }}
|
||||
/>
|
||||
<Textarea size="md" placeholder="Deskripsi" label="Deskripsi" value={body.desc} radius={10} onChange={(val) => { setBody({ ...body, desc: val.currentTarget.value }) }} />
|
||||
<Box onClick={() => { onToChooseAnggota() }}>
|
||||
<Group
|
||||
justify="space-between"
|
||||
p={10}
|
||||
style={{
|
||||
border: `1px solid ${"#D6D8F6"}`,
|
||||
borderRadius: 10,
|
||||
}}
|
||||
>
|
||||
<Text>Pilih Anggota</Text>
|
||||
<IoIosArrowDropright size={25} />
|
||||
</Group>
|
||||
</Box>
|
||||
<Box pt={20}>
|
||||
<Group justify="space-between">
|
||||
<Text c={WARNA.biruTua}>Anggota Terpilih</Text>
|
||||
<Text c={WARNA.biruTua}>Total {member.length} Anggota</Text>
|
||||
</Group>
|
||||
<Box pt={10}>
|
||||
<Box mb={20}>
|
||||
<Box
|
||||
style={{
|
||||
border: `1px solid ${"#C7D6E8"}`,
|
||||
borderRadius: 10,
|
||||
}}
|
||||
px={20}
|
||||
py={10}
|
||||
>
|
||||
{(member.length === 0) ? (
|
||||
<Text c="dimmed" ta={"center"} fs={"italic"}>Belum ada anggota</Text>
|
||||
) : member.get().map((v: any, i: any) => {
|
||||
return (
|
||||
<Flex
|
||||
justify={"space-between"}
|
||||
align={"center"}
|
||||
mt={20}
|
||||
key={i}
|
||||
>
|
||||
<Group>
|
||||
<Avatar src={v.img} alt="it's me" size="lg" />
|
||||
<Box>
|
||||
<Text c={WARNA.biruTua} fw={"bold"}>
|
||||
{v.name}
|
||||
</Text>
|
||||
</Box>
|
||||
</Group>
|
||||
<Text c={WARNA.biruTua} fw={"bold"}>
|
||||
Anggota
|
||||
</Text>
|
||||
</Flex>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box mt="xl">
|
||||
<Button
|
||||
color="white"
|
||||
bg={WARNA.biruTua}
|
||||
size="lg"
|
||||
radius={30}
|
||||
fullWidth
|
||||
onClick={() => {
|
||||
onSubmit()
|
||||
}}
|
||||
>
|
||||
Simpan
|
||||
</Button>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
86
src/module/division_new/ui/create_report.tsx
Normal file
86
src/module/division_new/ui/create_report.tsx
Normal file
@@ -0,0 +1,86 @@
|
||||
"use client";
|
||||
import { LayoutNavbarNew, WARNA } from "@/module/_global";
|
||||
import { Box, Select, Stack, Text } from "@mantine/core";
|
||||
import { DateInput } from "@mantine/dates";
|
||||
import React, { useState } from "react";
|
||||
import EchartPaiReport from "./echart_pai_report";
|
||||
import EchartBarReport from "./echart_bar_report";
|
||||
import EventReport from "./event_report";
|
||||
import DiscussionReport from "./discussion_report";
|
||||
|
||||
export default function CreateReport() {
|
||||
const [value, setValue] = useState<Date | null>(null);
|
||||
return (
|
||||
<Box>
|
||||
<LayoutNavbarNew back="/division" title="Report Divisi" menu />
|
||||
<Box p={20}>
|
||||
<Stack>
|
||||
<Select
|
||||
placeholder="Grup"
|
||||
label="Grup"
|
||||
size="md"
|
||||
required
|
||||
radius={10}
|
||||
/>
|
||||
<DateInput
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
radius={10}
|
||||
size="md"
|
||||
required
|
||||
label="Date input"
|
||||
placeholder="Date input"
|
||||
/>
|
||||
<Box pt={10}>
|
||||
<Box
|
||||
bg={"white"}
|
||||
style={{
|
||||
border: `1px solid ${WARNA.borderBiruMuda}`,
|
||||
borderRadius: 10,
|
||||
padding: 10,
|
||||
}}
|
||||
>
|
||||
<EchartPaiReport />
|
||||
</Box>
|
||||
</Box>
|
||||
<Box pt={10}>
|
||||
<Box
|
||||
bg={"white"}
|
||||
style={{
|
||||
border: `1px solid ${WARNA.borderBiruMuda}`,
|
||||
borderRadius: 10,
|
||||
padding: 10,
|
||||
}}
|
||||
>
|
||||
<EchartBarReport />
|
||||
</Box>
|
||||
</Box>
|
||||
<Box pt={10}>
|
||||
<Box
|
||||
bg={"white"}
|
||||
style={{
|
||||
border: `1px solid ${WARNA.borderBiruMuda}`,
|
||||
borderRadius: 10,
|
||||
padding: 10,
|
||||
}}
|
||||
>
|
||||
<EventReport />
|
||||
</Box>
|
||||
</Box>
|
||||
<Box pt={10}>
|
||||
<Box
|
||||
bg={"white"}
|
||||
style={{
|
||||
border: `1px solid ${WARNA.borderBiruMuda}`,
|
||||
borderRadius: 10,
|
||||
padding: 10,
|
||||
}}
|
||||
>
|
||||
<DiscussionReport />
|
||||
</Box>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
9
src/module/division_new/ui/create_users.tsx
Normal file
9
src/module/division_new/ui/create_users.tsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import React from 'react';
|
||||
import NavbarCreateUsers from './navbar_create_users';
|
||||
|
||||
export default function CreateUsers({ grup }: { grup: string }) {
|
||||
return (
|
||||
<NavbarCreateUsers grup={grup} onClose={() => {}}/>
|
||||
);
|
||||
}
|
||||
|
||||
67
src/module/division_new/ui/discussion_report.tsx
Normal file
67
src/module/division_new/ui/discussion_report.tsx
Normal file
@@ -0,0 +1,67 @@
|
||||
import { WARNA } from "@/module/_global";
|
||||
import { Box, Group, Text } from "@mantine/core";
|
||||
import { GoDiscussionClosed } from "react-icons/go";
|
||||
import { CiClock2, CiUser } from "react-icons/ci";
|
||||
|
||||
const dataDiskusi = [
|
||||
{
|
||||
id: 1,
|
||||
judul: 'Mengatasi Limbah Makanan ',
|
||||
user: 'Fibra Marcell',
|
||||
date: '21 Juni 2024'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
judul: 'Pentingnya Menjaga Kelestarian Hutan ',
|
||||
user: 'Bayu Tegar',
|
||||
date: '15 Juni 2024'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
judul: 'Mengatasi Limbah Industri ',
|
||||
user: 'Nian Putri',
|
||||
date: '11 Mei 2024'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
judul: 'Manfaat Sampah Plastik',
|
||||
user: 'Budi Prasetyo',
|
||||
date: '10 Mei 2024'
|
||||
},
|
||||
]
|
||||
export default function DiscussionReport() {
|
||||
return (
|
||||
<Box pt={10}>
|
||||
<Text ta={"center"} mb={20} fw={'bold'}>DISKUSI</Text>
|
||||
{dataDiskusi.map((v, i) => {
|
||||
return (
|
||||
<Box key={i} m={10}>
|
||||
<Box style={{
|
||||
borderRadius: 10,
|
||||
border: `1px solid ${"#D6D8F6"}`,
|
||||
padding: 15
|
||||
}} mb={10}>
|
||||
<Group align="center">
|
||||
<GoDiscussionClosed size={25} />
|
||||
<Box w={{ base: 230, md: 300 }}>
|
||||
<Text truncate="end" fw={'bold'}>{v.judul}</Text>
|
||||
</Box>
|
||||
</Group>
|
||||
<Group justify="space-between" align="center" mt={20} c={'#8C8C8C'}>
|
||||
<Group gap={5} align="center">
|
||||
<CiUser size={18} />
|
||||
<Text fz={13}>{v.user}</Text>
|
||||
</Group>
|
||||
<Group gap={5} align="center">
|
||||
<CiClock2 size={18} />
|
||||
<Text fz={13}>{v.date}</Text>
|
||||
</Group>
|
||||
</Group>
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
})
|
||||
}
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
41
src/module/division_new/ui/drawer_detail_division.tsx
Normal file
41
src/module/division_new/ui/drawer_detail_division.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
"use client"
|
||||
import { WARNA } from "@/module/_global";
|
||||
import { Box, Stack, SimpleGrid, Flex, Text } from "@mantine/core";
|
||||
import { useParams, useRouter } from "next/navigation";
|
||||
import { BsInfoCircle } from "react-icons/bs";
|
||||
import { FaPencil } from "react-icons/fa6";
|
||||
import { TbReportAnalytics } from "react-icons/tb";
|
||||
|
||||
export default function DrawerDetailDivision() {
|
||||
const param = useParams<{ id: string }>()
|
||||
const router = useRouter()
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Stack pt={10}>
|
||||
<SimpleGrid
|
||||
cols={{ base: 2, sm: 2, lg: 3 }}
|
||||
>
|
||||
<Flex onClick={() => router.push('/division/info/' + param.id)} justify={'center'} align={'center'} direction={'column'} >
|
||||
<Box>
|
||||
<BsInfoCircle size={30} color={WARNA.biruTua} />
|
||||
</Box>
|
||||
<Box>
|
||||
<Text c={WARNA.biruTua}>Informasi Divisi</Text>
|
||||
</Box>
|
||||
</Flex>
|
||||
<Flex onClick={() => {
|
||||
router.push('/division/report/' + param.id)
|
||||
}} justify={'center'} align={'center'} direction={'column'} >
|
||||
<Box>
|
||||
<TbReportAnalytics size={30} color={WARNA.biruTua} />
|
||||
</Box>
|
||||
<Box>
|
||||
<Text c={WARNA.biruTua}>Report Divisi</Text>
|
||||
</Box>
|
||||
</Flex>
|
||||
</SimpleGrid>
|
||||
</Stack>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
50
src/module/division_new/ui/drawer_division.tsx
Normal file
50
src/module/division_new/ui/drawer_division.tsx
Normal file
@@ -0,0 +1,50 @@
|
||||
"use client"
|
||||
import { WARNA } from '@/module/_global';
|
||||
import { Box, Flex, SimpleGrid, Stack, Text } from '@mantine/core';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import React, { useState } from 'react';
|
||||
import { HiOutlineFilter } from 'react-icons/hi';
|
||||
import { IoAddCircle } from 'react-icons/io5';
|
||||
import { TbReportAnalytics } from "react-icons/tb";
|
||||
|
||||
export default function DrawerDivision() {
|
||||
const router = useRouter()
|
||||
return (
|
||||
<Box>
|
||||
<Stack pt={10}>
|
||||
<SimpleGrid
|
||||
cols={{ base: 3, sm: 3, lg: 3 }}
|
||||
>
|
||||
<Flex onClick={() => router.push('/division/create')} justify={'center'} align={'center'} direction={'column'} >
|
||||
<Box>
|
||||
<IoAddCircle size={30} color={WARNA.biruTua} />
|
||||
</Box>
|
||||
<Box>
|
||||
<Text c={WARNA.biruTua}>Tambah Divisi</Text>
|
||||
</Box>
|
||||
</Flex>
|
||||
<Flex onClick={() => {
|
||||
router.push('/division?page=filter')
|
||||
}} justify={'center'} align={'center'} direction={'column'} >
|
||||
<Box>
|
||||
<HiOutlineFilter size={30} color={WARNA.biruTua} />
|
||||
</Box>
|
||||
<Box>
|
||||
<Text c={WARNA.biruTua}>Filter</Text>
|
||||
</Box>
|
||||
</Flex>
|
||||
<Flex onClick={() => {
|
||||
router.push('/division?page=report')
|
||||
}} justify={'center'} align={'center'} direction={'column'} >
|
||||
<Box>
|
||||
<TbReportAnalytics size={30} color={WARNA.biruTua} />
|
||||
</Box>
|
||||
<Box>
|
||||
<Text c={WARNA.biruTua}>Report</Text>
|
||||
</Box>
|
||||
</Flex>
|
||||
</SimpleGrid>
|
||||
</Stack>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
105
src/module/division_new/ui/echart_bar_report.tsx
Normal file
105
src/module/division_new/ui/echart_bar_report.tsx
Normal file
@@ -0,0 +1,105 @@
|
||||
import React, { useState } from 'react';
|
||||
import { EChartsOption, color } from "echarts";
|
||||
import EChartsReact from "echarts-for-react";
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import * as echarts from 'echarts';
|
||||
import { Box } from '@mantine/core';
|
||||
import { WARNA } from '@/module/_global';
|
||||
|
||||
export default function EchartBarReport() {
|
||||
const [options, setOptions] = useState<EChartsOption>({});
|
||||
|
||||
useShallowEffect(() => {
|
||||
loadData()
|
||||
}, [])
|
||||
|
||||
const loadData = () => {
|
||||
const option: EChartsOption = {
|
||||
title: {
|
||||
text: "DOKUMEN",
|
||||
top: '2%',
|
||||
left: 'center',
|
||||
textStyle: {
|
||||
color: WARNA.biruTua
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow'
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '3%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: [
|
||||
{
|
||||
type: 'category',
|
||||
data: ['File', 'Folder', 'Documen'],
|
||||
axisLabel: {
|
||||
fontSize: 14
|
||||
},
|
||||
axisTick: {
|
||||
alignWithLabel: true
|
||||
},
|
||||
axisLine: {
|
||||
show: true,
|
||||
},
|
||||
}
|
||||
],
|
||||
yAxis: [
|
||||
{
|
||||
type: 'value',
|
||||
show: true,
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: "gray",
|
||||
opacity: 0.1
|
||||
}
|
||||
},
|
||||
}
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: 'Direct',
|
||||
type: 'bar',
|
||||
barWidth: '70%',
|
||||
data: [
|
||||
{
|
||||
value: 78,
|
||||
name: 'Confidence',
|
||||
itemStyle: {
|
||||
color: "#F3C96B"
|
||||
}
|
||||
},
|
||||
{
|
||||
value: 35,
|
||||
name: 'Supportive',
|
||||
itemStyle: {
|
||||
color: "#9EC97F"
|
||||
}
|
||||
},
|
||||
{
|
||||
value: 58,
|
||||
name: 'Positive',
|
||||
itemStyle: {
|
||||
color: "#5971C0"
|
||||
}
|
||||
},
|
||||
|
||||
],
|
||||
}
|
||||
]
|
||||
};
|
||||
setOptions(option);
|
||||
}
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<EChartsReact style={{ height: 400, width: "auto" }} option={options} />
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
69
src/module/division_new/ui/echart_pai_report.tsx
Normal file
69
src/module/division_new/ui/echart_pai_report.tsx
Normal file
@@ -0,0 +1,69 @@
|
||||
import React, { useState } from 'react';
|
||||
import { EChartsOption, color } from "echarts";
|
||||
import EChartsReact from "echarts-for-react";
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import * as echarts from 'echarts';
|
||||
import { Box } from '@mantine/core';
|
||||
import { WARNA } from '@/module/_global';
|
||||
|
||||
export default function EchartPaiReport() {
|
||||
const [options, setOptions] = useState<EChartsOption>({});
|
||||
|
||||
useShallowEffect(() => {
|
||||
loadData()
|
||||
}, [])
|
||||
|
||||
const loadData = () => {
|
||||
const option: EChartsOption = {
|
||||
title: {
|
||||
text: "PROGRES TUGAS",
|
||||
top: '2%',
|
||||
left: 'center',
|
||||
textStyle: {
|
||||
color: WARNA.biruTua
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
top: 'bottom',
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'Progres Tugas',
|
||||
type: 'pie',
|
||||
radius: '70%',
|
||||
avoidLabelOverlap: false,
|
||||
itemStyle: {
|
||||
borderRadius: 2,
|
||||
borderWidth: 2
|
||||
},
|
||||
label: {
|
||||
position: "inner",
|
||||
formatter: (a) => {
|
||||
return `${a.value + "%"}`;
|
||||
},
|
||||
},
|
||||
data: [
|
||||
{ value: 25, name: 'Dikerjakan' },
|
||||
{ value: 35, name: 'Selesai dikerjakan' },
|
||||
{ value: 10, name: 'Segera dikerjakan' },
|
||||
{ value: 30, name: 'Batal dikerjakan' },
|
||||
],
|
||||
emphasis: {
|
||||
itemStyle: {
|
||||
shadowBlur: 10,
|
||||
shadowOffsetX: 0,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
setOptions(option);
|
||||
}
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<EChartsReact style={{ height: 400, width: "auto" }} option={options} />
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
130
src/module/division_new/ui/edit_division.tsx
Normal file
130
src/module/division_new/ui/edit_division.tsx
Normal file
@@ -0,0 +1,130 @@
|
||||
"use client"
|
||||
import { LayoutNavbarNew, WARNA } from '@/module/_global';
|
||||
import LayoutModal from '@/module/_global/layout/layout_modal';
|
||||
import { Box, Button, Select, Stack, Textarea, TextInput } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
import React, { useState } from 'react';
|
||||
import toast from 'react-hot-toast';
|
||||
import { funEditDivision, funGetDivisionById } from '../lib/api_division';
|
||||
import { funGetAllGroup, IDataGroup } from '@/module/group';
|
||||
import { funGetUserByCookies } from '@/module/auth';
|
||||
|
||||
|
||||
export default function EditDivision() {
|
||||
const [openModal, setOpenModal] = useState(false)
|
||||
const router = useRouter()
|
||||
const param = useParams<{ id: string }>()
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [body, setBody] = useState<any>({
|
||||
idGroup: "",
|
||||
name: "",
|
||||
desc: "",
|
||||
});
|
||||
|
||||
function onTrue(val: boolean) {
|
||||
if (val) {
|
||||
toast.success("Sukses! Data tersimpan");
|
||||
}
|
||||
setOpenModal(false)
|
||||
}
|
||||
|
||||
|
||||
async function getOneData() {
|
||||
try {
|
||||
setLoading(true);
|
||||
const res = await funGetDivisionById(param.id);
|
||||
if (res.success) {
|
||||
setBody({
|
||||
...body,
|
||||
idGroup: res.data.division.idGroup,
|
||||
name: res.data.division.name,
|
||||
desc: res.data.division.desc
|
||||
})
|
||||
} else {
|
||||
toast.error(res.message);
|
||||
}
|
||||
setLoading(false);
|
||||
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
toast.error("Gagal mendapatkan divisi, coba lagi nanti");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function onUpdate() {
|
||||
try {
|
||||
const res = await funEditDivision(param.id, body)
|
||||
if (res.success) {
|
||||
toast.success(res.message)
|
||||
} else {
|
||||
toast.error(res.message)
|
||||
}
|
||||
setOpenModal(false)
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
setOpenModal(false)
|
||||
toast.error("Gagal mengedit divisi, coba lagi nanti");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
useShallowEffect(() => {
|
||||
getOneData();
|
||||
}, [param.id])
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<LayoutNavbarNew back="" title="Edit Divisi" menu />
|
||||
<Box p={20}>
|
||||
|
||||
<Stack>
|
||||
{/* <Select
|
||||
placeholder="Grup"
|
||||
label="Grup"
|
||||
size="md"
|
||||
required
|
||||
radius={40}
|
||||
/> */}
|
||||
<TextInput
|
||||
placeholder="Judul"
|
||||
label="Judul"
|
||||
size="md"
|
||||
required
|
||||
radius={40}
|
||||
value={body.name}
|
||||
onChange={(e) => { setBody({ ...body, name: e.target.value }) }}
|
||||
/>
|
||||
<Textarea placeholder="Deskripsi" label="Deskripsi" size="md" radius={10}
|
||||
value={body.desc}
|
||||
onChange={(e) => { setBody({ ...body, desc: e.currentTarget.value }) }}
|
||||
/>
|
||||
<Box mt="xl">
|
||||
<Button
|
||||
color="white"
|
||||
bg={WARNA.biruTua}
|
||||
size="lg"
|
||||
radius={30}
|
||||
fullWidth
|
||||
onClick={() => { setOpenModal(true) }}
|
||||
>
|
||||
Simpan
|
||||
</Button>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Box>
|
||||
<LayoutModal opened={openModal} onClose={() => setOpenModal(false)} description='Apakah Anda yakin ingin edit data'
|
||||
onYes={(val) => {
|
||||
if (val) {
|
||||
onUpdate()
|
||||
} else {
|
||||
setOpenModal(false)
|
||||
}
|
||||
}} />
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
62
src/module/division_new/ui/event_report.tsx
Normal file
62
src/module/division_new/ui/event_report.tsx
Normal file
@@ -0,0 +1,62 @@
|
||||
import { Box, Divider, Group, ScrollArea, Stack, Text } from '@mantine/core';
|
||||
import React from 'react';
|
||||
|
||||
const dataEvent = [
|
||||
{
|
||||
id: 1,
|
||||
title: 'Pembahasan Mengenai Darmasaba',
|
||||
jamAwal: "10.00",
|
||||
jamAkhir: "11.00",
|
||||
dibuat: "Jhon"
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Pembahasan Mengenai Darmasaba',
|
||||
jamAwal: "11.00",
|
||||
jamAkhir: "12.00",
|
||||
dibuat: "Jhon"
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: 'Pembahasan Mengenai Darmasaba',
|
||||
jamAwal: "13.00",
|
||||
jamAkhir: "14.00",
|
||||
dibuat: "Jhon"
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
title: 'Pembahasan Mengenai Darmasaba',
|
||||
jamAwal: "15.00",
|
||||
jamAkhir: "16.00",
|
||||
dibuat: "Jhon"
|
||||
},
|
||||
]
|
||||
|
||||
export default function EventReport() {
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Text mb={20} mt={10} ta={'center'} fw={"bold"}>EVENT SELESAI DILAKSANAKAN</Text>
|
||||
{dataEvent.map((event, index) => {
|
||||
const bgColor = ['#D8D8F1', '#FED6C5'][index % 2]
|
||||
const colorDivider = ['#535FCA', '#A7A7A7'][index % 2]
|
||||
return (
|
||||
<Box key={event.id} m={10}>
|
||||
<Box bg={bgColor} pl={15} p={10} style={{
|
||||
borderRadius: 10
|
||||
}} h={113}>
|
||||
<Group>
|
||||
<Divider h={92} size="lg" orientation="vertical" color={colorDivider} />
|
||||
<Box>
|
||||
<Text>{event.jamAwal} - {event.jamAkhir}</Text>
|
||||
<Text fw={"bold"}>{event.title}</Text>
|
||||
<Text>Dibuat oleh : {event.dibuat}</Text>
|
||||
</Box>
|
||||
</Group>
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
})}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
157
src/module/division_new/ui/feature_detail_division.tsx
Normal file
157
src/module/division_new/ui/feature_detail_division.tsx
Normal file
@@ -0,0 +1,157 @@
|
||||
"use client"
|
||||
import { WARNA } from '@/module/_global';
|
||||
import { ActionIcon, Box, Center, Grid, Group, SimpleGrid, Text } from '@mantine/core';
|
||||
import React, { useState } from 'react';
|
||||
import { HiMiniUserGroup } from 'react-icons/hi2';
|
||||
import { IoIosArrowRoundForward } from 'react-icons/io';
|
||||
import { LuClipboardEdit } from "react-icons/lu";
|
||||
import { GoCommentDiscussion } from "react-icons/go";
|
||||
import { BsFileEarmarkText } from "react-icons/bs";
|
||||
import { IoCalendarOutline } from "react-icons/io5";
|
||||
import { LuFileSignature } from "react-icons/lu";
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
import { funGetDetailDivisionById } from '../lib/api_division';
|
||||
import toast from 'react-hot-toast';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IDataJumlahDetailDivision } from '../lib/type_division';
|
||||
|
||||
export default function FeatureDetailDivision() {
|
||||
const param = useParams<{ id: string }>()
|
||||
const router = useRouter()
|
||||
const [feature, setFeature] = useState<IDataJumlahDetailDivision>()
|
||||
|
||||
async function fetchData() {
|
||||
try {
|
||||
const res = await funGetDetailDivisionById(param.id, 'jumlah');
|
||||
if (res.success) {
|
||||
setFeature(res.data)
|
||||
} else {
|
||||
toast.error(res.message);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
toast.error("Gagal mendapatkan divisi, coba lagi nanti");
|
||||
}
|
||||
}
|
||||
|
||||
useShallowEffect(() => {
|
||||
fetchData()
|
||||
}, [param.id])
|
||||
|
||||
|
||||
return (
|
||||
<Box pt={10}>
|
||||
<Text c={WARNA.biruTua} mb={10} fw={'bold'} fz={16}>Features</Text>
|
||||
<SimpleGrid
|
||||
cols={{ base: 2, sm: 2, lg: 2 }}
|
||||
style={{
|
||||
alignItems: "center",
|
||||
alignContent: "center"
|
||||
}}
|
||||
>
|
||||
<Box bg={'white'} style={{
|
||||
border: `1px solid ${WARNA.bgHijauMuda}`,
|
||||
borderRadius: 10,
|
||||
padding: 10
|
||||
}} onClick={() => router.push(param.id + '/task')}>
|
||||
<Grid justify='center' align='center'>
|
||||
<Grid.Col span={"auto"}>
|
||||
<ActionIcon variant="filled"
|
||||
size={"xl"}
|
||||
aria-label="Gradient action icon"
|
||||
radius={100}
|
||||
color={WARNA.bgHijauMuda}
|
||||
>
|
||||
<LuClipboardEdit size={25} color={WARNA.biruTua} />
|
||||
</ActionIcon>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={{ base: 7, md: 9 }}>
|
||||
<Text fz={15} c={WARNA.biruTua} fw={"bold"}>Tugas</Text>
|
||||
<Group justify='space-between' align='center'>
|
||||
<Text fz={10} c={"gray"}>{feature?.tugas} Tugas</Text>
|
||||
<IoIosArrowRoundForward size={20} color='gray' />
|
||||
</Group>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
</Box>
|
||||
<Box bg={'white'} style={{
|
||||
border: `1px solid ${WARNA.bgHijauMuda}`,
|
||||
borderRadius: 10,
|
||||
padding: 10
|
||||
}} onClick={() => router.push(param.id + '/document')}>
|
||||
<Grid justify='center' align='center'>
|
||||
<Grid.Col span={"auto"}>
|
||||
<ActionIcon variant="filled"
|
||||
size={"xl"}
|
||||
aria-label="Gradient action icon"
|
||||
radius={100}
|
||||
color={WARNA.bgHijauMuda}
|
||||
>
|
||||
<BsFileEarmarkText size={25} color={WARNA.biruTua} />
|
||||
</ActionIcon>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={{ base: 7, md: 9 }}>
|
||||
<Text fz={15} c={WARNA.biruTua} fw={"bold"}>Dokumen</Text>
|
||||
<Group justify='space-between' align='center'>
|
||||
<Text fz={10} c={"gray"}>{feature?.dokumen} File</Text>
|
||||
<IoIosArrowRoundForward size={20} color='gray' />
|
||||
</Group>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
</Box>
|
||||
<Box bg={'white'} style={{
|
||||
border: `1px solid ${WARNA.bgHijauMuda}`,
|
||||
borderRadius: 10,
|
||||
padding: 10
|
||||
}} onClick={() => router.push(param.id + '/discussion')}>
|
||||
<Grid justify='center' align='center'>
|
||||
<Grid.Col span={"auto"}>
|
||||
<ActionIcon variant="filled"
|
||||
size={"xl"}
|
||||
aria-label="Gradient action icon"
|
||||
radius={100}
|
||||
color={WARNA.bgHijauMuda}
|
||||
>
|
||||
<GoCommentDiscussion size={25} color={WARNA.biruTua} />
|
||||
</ActionIcon>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={{ base: 7, md: 9 }}>
|
||||
<Text fz={15} c={WARNA.biruTua} fw={"bold"}>Diskusi</Text>
|
||||
<Group justify='space-between' align='center'>
|
||||
<Text fz={10} c={"gray"}>{feature?.diskusi} Diskusi</Text>
|
||||
<IoIosArrowRoundForward size={20} color='gray' />
|
||||
</Group>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
</Box>
|
||||
<Box bg={'white'} style={{
|
||||
border: `1px solid ${WARNA.bgHijauMuda}`,
|
||||
borderRadius: 10,
|
||||
padding: 10
|
||||
}} onClick={() => router.push(param.id + '/calender')}>
|
||||
<Grid justify='center' align='center'>
|
||||
<Grid.Col span={"auto"}>
|
||||
<ActionIcon variant="filled"
|
||||
size={"xl"}
|
||||
aria-label="Gradient action icon"
|
||||
radius={100}
|
||||
color={WARNA.bgHijauMuda}
|
||||
>
|
||||
<IoCalendarOutline size={25} color={WARNA.biruTua} />
|
||||
</ActionIcon>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={{ base: 7, md: 9 }}>
|
||||
<Text fz={15} c={WARNA.biruTua} fw={"bold"}>Kalender</Text>
|
||||
<Group justify='space-between' align='center'>
|
||||
<Text fz={10} c={"gray"}>{feature?.kalender} Acara</Text>
|
||||
<IoIosArrowRoundForward size={20} color='gray' />
|
||||
</Group>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
</Box>
|
||||
</SimpleGrid>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
219
src/module/division_new/ui/information_division.tsx
Normal file
219
src/module/division_new/ui/information_division.tsx
Normal file
@@ -0,0 +1,219 @@
|
||||
"use client"
|
||||
import { LayoutDrawer, LayoutNavbarNew, SkeletonSingle, WARNA } from '@/module/_global';
|
||||
import { ActionIcon, Avatar, Box, Button, Divider, Flex, Group, Skeleton, Stack, Text } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
import React, { useState } from 'react';
|
||||
import toast from 'react-hot-toast';
|
||||
import { AiOutlineUserAdd } from 'react-icons/ai';
|
||||
import { FaUserTie } from 'react-icons/fa6';
|
||||
import { IoIosCloseCircle } from 'react-icons/io';
|
||||
import { LuClipboardEdit } from 'react-icons/lu';
|
||||
import { funDeleteMemberDivision, funEditStatusAdminDivision, funGetDivisionById } from '../lib/api_division';
|
||||
import { IDataMemberDivision } from '../lib/type_division';
|
||||
import LayoutModal from '@/module/_global/layout/layout_modal';
|
||||
|
||||
|
||||
export default function InformationDivision() {
|
||||
const router = useRouter()
|
||||
const [openDrawer, setDrawer] = useState(false)
|
||||
const param = useParams<{ id: string }>()
|
||||
const [name, setName] = useState('')
|
||||
const [deskripsi, setDeskripsi] = useState('')
|
||||
const [member, setMember] = useState<IDataMemberDivision[]>([])
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [valChooseMember, setChooseMember] = useState("")
|
||||
const [valChooseMemberStatus, setChooseMemberStatus] = useState<boolean>(false)
|
||||
const [valChooseMemberName, setChooseMemberName] = useState("")
|
||||
const [isOpenModal, setOpenModal] = useState(false)
|
||||
|
||||
async function getOneData() {
|
||||
try {
|
||||
setLoading(true);
|
||||
const res = await funGetDivisionById(param.id);
|
||||
if (res.success) {
|
||||
setName(res.data.division.name);
|
||||
setDeskripsi(res.data.division.desc);
|
||||
setMember(res.data.member)
|
||||
} else {
|
||||
toast.error(res.message);
|
||||
}
|
||||
setLoading(false);
|
||||
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
toast.error("Gagal mendapatkan divisi, coba lagi nanti");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
useShallowEffect(() => {
|
||||
getOneData();
|
||||
}, [param.id])
|
||||
|
||||
|
||||
async function onClickMember(id: string, status: boolean) {
|
||||
setChooseMember(id)
|
||||
setChooseMemberStatus(status)
|
||||
setDrawer(true)
|
||||
}
|
||||
|
||||
|
||||
async function deleteMember() {
|
||||
try {
|
||||
const res = await funDeleteMemberDivision(param.id, { id: valChooseMember })
|
||||
if (res.success) {
|
||||
toast.success(res.message)
|
||||
setDrawer(false)
|
||||
getOneData()
|
||||
} else {
|
||||
toast.error(res.message)
|
||||
}
|
||||
setOpenModal(false)
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
setOpenModal(false)
|
||||
toast.error("Gagal mendapatkan divisi, coba lagi nanti");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function editStatusAdmin() {
|
||||
try {
|
||||
const res = await funEditStatusAdminDivision(param.id, { id: valChooseMember, isAdmin: valChooseMemberStatus })
|
||||
if (res.success) {
|
||||
toast.success(res.message)
|
||||
getOneData()
|
||||
} else {
|
||||
toast.error(res.message)
|
||||
}
|
||||
setDrawer(false)
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
toast.error("Gagal mendapatkan divisi, coba lagi nanti");
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<LayoutNavbarNew back={""} title={name}
|
||||
menu={
|
||||
<ActionIcon variant="light" onClick={() => {
|
||||
router.push('/division/edit/' + param.id)
|
||||
}} bg={WARNA.bgIcon} size="lg" radius="lg" aria-label="Settings">
|
||||
<LuClipboardEdit size={20} color='white' />
|
||||
</ActionIcon>}
|
||||
/>
|
||||
<Box p={20}>
|
||||
<Box>
|
||||
<Text fw={"bold"}>Deskripsi Divisi</Text>
|
||||
<Box p={20} bg={"white"} style={{
|
||||
borderRadius: 10,
|
||||
border: `1px solid ${WARNA.borderBiruMuda}`,
|
||||
}}>
|
||||
{
|
||||
loading ?
|
||||
Array(3)
|
||||
.fill(null)
|
||||
.map((_, i) => (
|
||||
<Stack align="stretch" justify="center" key={i} mb={10}>
|
||||
<Skeleton height={10} radius="md" m={0} />
|
||||
</Stack>
|
||||
))
|
||||
:
|
||||
(deskripsi != null && deskripsi != undefined) ?
|
||||
<Text ta={"justify"}>{deskripsi}</Text>
|
||||
: <></>
|
||||
}
|
||||
</Box>
|
||||
</Box>
|
||||
<Box mt={20}>
|
||||
<Box p={20} bg={"white"} style={{
|
||||
borderRadius: 10,
|
||||
border: `1px solid ${WARNA.borderBiruMuda}`,
|
||||
}}>
|
||||
<Box>
|
||||
<Text>{member.length} Anggota</Text>
|
||||
</Box>
|
||||
<Box mt={15}>
|
||||
<Group align='center' onClick={() => router.push('/division/add-member/' + param.id)}>
|
||||
<Avatar size="lg">
|
||||
<AiOutlineUserAdd size={30} color={WARNA.biruTua} />
|
||||
</Avatar>
|
||||
<Text>Tambah Anggota</Text>
|
||||
</Group>
|
||||
</Box>
|
||||
<Box pt={10}>
|
||||
<Box mb={10}>
|
||||
{loading
|
||||
? Array(3)
|
||||
.fill(null)
|
||||
.map((_, i) => (
|
||||
<Box key={i}>
|
||||
<SkeletonSingle />
|
||||
</Box>
|
||||
))
|
||||
: member.map((v, i) => {
|
||||
return (
|
||||
<Box key={i}>
|
||||
<Flex
|
||||
justify={"space-between"}
|
||||
align={"center"}
|
||||
mt={10}
|
||||
onClick={() => { onClickMember(v.id, (v.isAdmin) ? true : false), setChooseMemberName(v.name) }}
|
||||
>
|
||||
<Group>
|
||||
<Avatar src={"v.img"} alt="it's me" size="lg" />
|
||||
<Box>
|
||||
<Text c={WARNA.biruTua} fw={"bold"}>
|
||||
{v.name}
|
||||
</Text>
|
||||
</Box>
|
||||
</Group>
|
||||
<Text c={WARNA.biruTua} fw={"bold"}>
|
||||
{(v.isAdmin) ? 'Admin' : 'Anggota'}
|
||||
</Text>
|
||||
</Flex>
|
||||
<Box mt={10}>
|
||||
<Divider size={"xs"} />
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
})
|
||||
}
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<LayoutDrawer opened={openDrawer} onClose={() => setDrawer(false)} title={valChooseMemberName}>
|
||||
<Box>
|
||||
<Group align='center' mb={20} onClick={() => editStatusAdmin()}>
|
||||
<ActionIcon variant="light" size={60} aria-label="admin" radius="xl">
|
||||
<FaUserTie size={30} color={WARNA.biruTua} />
|
||||
</ActionIcon>
|
||||
<Text c={WARNA.biruTua}>{(valChooseMemberStatus == false) ? "Jadikan admin" : "Memberhentikan sebagai admin"}</Text>
|
||||
</Group>
|
||||
<Group align='center' onClick={() => setOpenModal(true)}>
|
||||
<ActionIcon variant="light" size={60} aria-label="admin" radius="xl">
|
||||
<IoIosCloseCircle size={40} color={WARNA.biruTua} />
|
||||
</ActionIcon>
|
||||
<Text c={WARNA.biruTua}>Keluarkan dari divisi</Text>
|
||||
</Group>
|
||||
</Box>
|
||||
</LayoutDrawer>
|
||||
|
||||
<LayoutModal opened={isOpenModal} onClose={() => setOpenModal(false)}
|
||||
description="Apakah Anda yakin ingin mengeluarkan anggota?"
|
||||
onYes={(val) => {
|
||||
if (!val) {
|
||||
setOpenModal(false)
|
||||
} else {
|
||||
deleteMember()
|
||||
}
|
||||
}} />
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
140
src/module/division_new/ui/list_discussion.tsx
Normal file
140
src/module/division_new/ui/list_discussion.tsx
Normal file
@@ -0,0 +1,140 @@
|
||||
"use client"
|
||||
import { WARNA } from "@/module/_global";
|
||||
import { Box, Group, Skeleton, Stack, Text } from "@mantine/core";
|
||||
import { useShallowEffect } from "@mantine/hooks";
|
||||
import { useParams, useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
import { CiUser, CiClock2 } from "react-icons/ci";
|
||||
import { GoDiscussionClosed } from "react-icons/go";
|
||||
import { funGetDetailDivisionById } from "../lib/api_division";
|
||||
import { IDataDiscussionOnDetailDivision } from "../lib/type_division";
|
||||
|
||||
const dataDiskusi = [
|
||||
{
|
||||
id: 1,
|
||||
judul: "Mengatasi Limbah Makanan ",
|
||||
user: "Fibra Marcell",
|
||||
date: "21 Juni 2024",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
judul: "Pentingnya Menjaga Kelestarian Hutan ",
|
||||
user: "Bayu Tegar",
|
||||
date: "15 Juni 2024",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
judul: "Mengatasi Limbah Industri ",
|
||||
user: "Nian Putri",
|
||||
date: "11 Mei 2024",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
judul: "Manfaat Sampah Plastik",
|
||||
user: "Budi Prasetyo",
|
||||
date: "10 Mei 2024",
|
||||
},
|
||||
];
|
||||
|
||||
export default function ListDiscussionOnDetailDivision() {
|
||||
const router = useRouter();
|
||||
const param = useParams<{ id: string }>()
|
||||
const [data, setData] = useState<IDataDiscussionOnDetailDivision[]>([])
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
async function fetchData() {
|
||||
try {
|
||||
setLoading(true);
|
||||
const res = await funGetDetailDivisionById(param.id, 'new-discussion');
|
||||
if (res.success) {
|
||||
setData(res.data)
|
||||
} else {
|
||||
toast.error(res.message);
|
||||
}
|
||||
setLoading(false);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
toast.error("Gagal mendapatkan divisi, coba lagi nanti");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
useShallowEffect(() => {
|
||||
fetchData()
|
||||
}, [param.id])
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box pt={10}>
|
||||
<Text c={WARNA.biruTua} mb={10} fw={"bold"} fz={16}>
|
||||
Diskusi Terbaru
|
||||
</Text>
|
||||
<Box
|
||||
bg={"white"}
|
||||
style={{
|
||||
borderRadius: 10,
|
||||
border: `1px solid ${"#D6D8F6"}`,
|
||||
padding: 20,
|
||||
}}
|
||||
>
|
||||
|
||||
{
|
||||
loading ?
|
||||
Array(2)
|
||||
.fill(null)
|
||||
.map((_, i) => (
|
||||
<Stack align="stretch" justify="center" key={i} pb={10}>
|
||||
<Skeleton height={80} radius="md" m={0} />
|
||||
<Group justify="space-between">
|
||||
<Skeleton height={10} radius="md" m={0} w={100} />
|
||||
<Skeleton height={10} radius="md" m={0} w={100} />
|
||||
</Group>
|
||||
</Stack>
|
||||
))
|
||||
:
|
||||
(data.length === 0) ?
|
||||
<Stack align="stretch" justify="center" w={"100%"}>
|
||||
<Text c="dimmed" ta={"center"} fs={"italic"}>Belum ada diskusi</Text>
|
||||
</Stack>
|
||||
: <></>
|
||||
}
|
||||
{data.map((v, i) => {
|
||||
return (
|
||||
<Box
|
||||
key={i}
|
||||
style={{
|
||||
borderRadius: 10,
|
||||
border: `1px solid ${"#D6D8F6"}`,
|
||||
padding: 10,
|
||||
}}
|
||||
mb={10}
|
||||
onClick={() => router.push(`/discussion/${v.id}`)}
|
||||
>
|
||||
<Group>
|
||||
<GoDiscussionClosed size={25} />
|
||||
<Box w={{ base: 230, md: 400 }}>
|
||||
<Text fw={"bold"} truncate="end">
|
||||
{v.title}
|
||||
</Text>
|
||||
</Box>
|
||||
</Group>
|
||||
<Group justify="space-between" mt={20} c={"#8C8C8C"}>
|
||||
<Group gap={5} align="center">
|
||||
<CiUser size={18} />
|
||||
<Text fz={13}>{v.user}</Text>
|
||||
</Group>
|
||||
<Group gap={5} align="center">
|
||||
<CiClock2 size={18} />
|
||||
<Text fz={13}>{v.date}</Text>
|
||||
</Group>
|
||||
</Group>
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
}
|
||||
165
src/module/division_new/ui/list_division.tsx
Normal file
165
src/module/division_new/ui/list_division.tsx
Normal file
@@ -0,0 +1,165 @@
|
||||
'use client'
|
||||
import { API_ADDRESS, LayoutDrawer, LayoutNavbarNew, WARNA } from '@/module/_global';
|
||||
import { ActionIcon, Avatar, Box, Card, Center, Divider, Flex, Grid, Group, Text, TextInput, Title } from '@mantine/core';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import React, { useState } from 'react';
|
||||
import { HiMenu } from 'react-icons/hi';
|
||||
import { HiMagnifyingGlass, HiMiniPresentationChartBar, HiMiniUserGroup, HiOutlineListBullet, HiSquares2X2 } from 'react-icons/hi2';
|
||||
import { MdAccountCircle } from 'react-icons/md';
|
||||
import DrawerDivision from './drawer_division';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { IDataDivison } from '../lib/type_division';
|
||||
import { funGetAllDivision } from '../lib/api_division';
|
||||
import toast from 'react-hot-toast';
|
||||
|
||||
export default function ListDivision() {
|
||||
const [isList, setIsList] = useState(false)
|
||||
const router = useRouter()
|
||||
const [openDrawer, setOpenDrawer] = useState(false)
|
||||
const [data, setData] = useState<IDataDivison[]>([])
|
||||
const [jumlah, setJumlah] = useState(0)
|
||||
const [searchQuery, setSearchQuery] = useState('')
|
||||
|
||||
const handleList = () => {
|
||||
setIsList(!isList)
|
||||
}
|
||||
|
||||
const fetchData = async (search: string) => {
|
||||
try {
|
||||
setData([]);
|
||||
const response = await funGetAllDivision('?search=' + search)
|
||||
|
||||
if (response.success) {
|
||||
setData(response.data)
|
||||
setJumlah(response.data.length)
|
||||
} else {
|
||||
toast.error(response.message);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
toast.error("Gagal mendapatkan divisi, coba lagi nanti");
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
function searchDivision(search: string) {
|
||||
setSearchQuery(search)
|
||||
fetchData(search)
|
||||
}
|
||||
|
||||
useShallowEffect(() => {
|
||||
fetchData(searchQuery)
|
||||
}, [searchQuery])
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<LayoutNavbarNew back='/home' title='Divisi'
|
||||
menu={<ActionIcon variant="light" onClick={() => (setOpenDrawer(true))} bg={WARNA.bgIcon} size="lg" radius="lg" aria-label="Settings">
|
||||
<HiMenu size={20} color='white' />
|
||||
</ActionIcon>} />
|
||||
<Box p={20}>
|
||||
<Grid justify='center' align='center'>
|
||||
<Grid.Col span={10}>
|
||||
<TextInput
|
||||
styles={{
|
||||
input: {
|
||||
color: WARNA.biruTua,
|
||||
borderRadius: '#A3A3A3',
|
||||
borderColor: '#A3A3A3',
|
||||
},
|
||||
}}
|
||||
size="md"
|
||||
radius={30}
|
||||
leftSection={<HiMagnifyingGlass size={20} />}
|
||||
placeholder="Pencarian"
|
||||
value={searchQuery}
|
||||
onChange={(val) => { searchDivision(val.target.value) }}
|
||||
/>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={'auto'}>
|
||||
<Flex justify={'center'}>
|
||||
{isList ? (
|
||||
<HiOutlineListBullet size={35} color={WARNA.biruTua} onClick={handleList} />
|
||||
) : (
|
||||
<HiSquares2X2 size={35} color={WARNA.biruTua} onClick={handleList} />
|
||||
)}
|
||||
</Flex>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
<Box pt={20}>
|
||||
<Box bg={WARNA.biruTua} p={10} style={{ borderRadius: 10 }}>
|
||||
<Text fw={'bold'} c={'white'}>Total Divisi</Text>
|
||||
<Flex justify={'center'} align={'center'} h={'100%'}>
|
||||
<Text fz={40} fw={'bold'} c={'white'}>{jumlah}</Text>
|
||||
</Flex>
|
||||
</Box>
|
||||
</Box>
|
||||
{isList ? (
|
||||
<Box pt={20}>
|
||||
{data?.map((v: any, i: any) => {
|
||||
return (
|
||||
<Box key={i}>
|
||||
<Group justify="space-between" mb={10} onClick={() => router.push(`/division/${v.id}`)}>
|
||||
<Group>
|
||||
<Center>
|
||||
<ActionIcon
|
||||
variant="gradient"
|
||||
size={50}
|
||||
aria-label="Gradient action icon"
|
||||
radius={100}
|
||||
gradient={{
|
||||
from: '#DFDA7C',
|
||||
to: '#F2AF46',
|
||||
deg: 174
|
||||
}}
|
||||
>
|
||||
<HiMiniUserGroup size={25} color={WARNA.biruTua} />
|
||||
</ActionIcon>
|
||||
</Center>
|
||||
<Text>{v.name}</Text>
|
||||
</Group>
|
||||
</Group>
|
||||
<Divider my="sm" />
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
) : (
|
||||
<Box pt={20}>
|
||||
{data?.map((v: any, i: any) => {
|
||||
return (
|
||||
<Box key={i} mb={20}>
|
||||
<Card shadow="sm" padding="md" component="a" radius={10} onClick={() => router.push(`/division/${v.id}`)}>
|
||||
<Card.Section>
|
||||
<Box h={120} bg={WARNA.biruTua}>
|
||||
<Flex justify={'center'} align={'center'} h={"100%"}>
|
||||
<Title order={3} c={"white"}>{v.name}</Title>
|
||||
</Flex>
|
||||
</Box>
|
||||
</Card.Section>
|
||||
<Box pt={10}>
|
||||
<Text>{v.desc}</Text>
|
||||
<Group align='center' pt={10} justify='flex-end'>
|
||||
<Avatar.Group>
|
||||
<Avatar>
|
||||
<MdAccountCircle size={32} color={WARNA.biruTua} />
|
||||
</Avatar>
|
||||
<Avatar>+{v.jumlah_member - 1}</Avatar>
|
||||
</Avatar.Group>
|
||||
</Group>
|
||||
</Box>
|
||||
</Card>
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
<LayoutDrawer opened={openDrawer} title={'Menu'} onClose={() => setOpenDrawer(false)}>
|
||||
<DrawerDivision />
|
||||
</LayoutDrawer>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
86
src/module/division_new/ui/list_document.tsx
Normal file
86
src/module/division_new/ui/list_document.tsx
Normal file
@@ -0,0 +1,86 @@
|
||||
'use client'
|
||||
import { WARNA } from "@/module/_global";
|
||||
import { Carousel } from "@mantine/carousel";
|
||||
import { Box, Image, Text, Center, Paper, Stack, UnstyledButton, Skeleton, Group } from "@mantine/core";
|
||||
import * as ICON from '../../division/lib/file_icon'
|
||||
import { useParams, useRouter } from "next/navigation";
|
||||
import { useShallowEffect } from "@mantine/hooks";
|
||||
import toast from "react-hot-toast";
|
||||
import { funGetDetailDivisionById } from "../lib/api_division";
|
||||
import { IDataKalenderOnDetailDivision } from "../lib/type_division";
|
||||
import { useState } from "react";
|
||||
|
||||
const iconContainer = (icon: string) => 'data:image/svg+xml;base64,' + btoa(icon)
|
||||
|
||||
export default function ListDocumentOnDetailDivision() {
|
||||
const router = useRouter()
|
||||
const param = useParams<{ id: string }>()
|
||||
const [data, setData] = useState<IDataKalenderOnDetailDivision[]>([])
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
async function fetchData() {
|
||||
try {
|
||||
setLoading(true);
|
||||
const res = await funGetDetailDivisionById(param.id, 'new-file');
|
||||
if (res.success) {
|
||||
setData(res.data)
|
||||
} else {
|
||||
toast.error(res.message);
|
||||
}
|
||||
setLoading(false);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
toast.error("Gagal mendapatkan divisi, coba lagi nanti");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
useShallowEffect(() => {
|
||||
fetchData()
|
||||
}, [param.id])
|
||||
|
||||
return (
|
||||
<Box pt={10}>
|
||||
<Text c={WARNA.biruTua} mb={10} fw={'bold'} fz={16}>Dokumen Terbaru</Text>
|
||||
<Group justify="center" grow>
|
||||
{
|
||||
loading
|
||||
?
|
||||
Array(4)
|
||||
.fill(null)
|
||||
.map((_, i) => (
|
||||
<Stack align="stretch" justify="center" key={i}>
|
||||
<Skeleton height={80} radius="md" m={0} />
|
||||
<Skeleton height={10} radius="md" m={0} />
|
||||
</Stack>
|
||||
))
|
||||
: (data.length === 0) ?
|
||||
<Stack align="stretch" justify="center" w={"100%"}>
|
||||
<Text c="dimmed" ta={"center"} fs={"italic"}>Belum ada file</Text>
|
||||
</Stack>
|
||||
: <></>
|
||||
}
|
||||
</Group>
|
||||
<Carousel dragFree slideGap={"xs"} align="start" slideSize={"xs"} withIndicators withControls={false}>
|
||||
{
|
||||
data.map((v) =>
|
||||
<Carousel.Slide key={v.id}>
|
||||
<UnstyledButton onClick={() => router.push(`/document`)}>
|
||||
<Stack gap={0}>
|
||||
<Paper withBorder shadow="sm" radius={12} >
|
||||
<Center p={"md"}>
|
||||
<Image w={"75"} src={(v.extension == "pdf") ? iconContainer(ICON.PDF) : iconContainer(ICON.IMAGE)} alt="image" />
|
||||
</Center>
|
||||
</Paper>
|
||||
<Box p={"sm"}>
|
||||
<Text c={"dimmed"} truncate="end" ta={"center"}>{v.name + '.' + v.extension}</Text>
|
||||
</Box>
|
||||
</Stack>
|
||||
</UnstyledButton>
|
||||
</Carousel.Slide>
|
||||
)}
|
||||
</Carousel>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
89
src/module/division_new/ui/list_task.tsx
Normal file
89
src/module/division_new/ui/list_task.tsx
Normal file
@@ -0,0 +1,89 @@
|
||||
'use client'
|
||||
import { WARNA } from "@/module/_global";
|
||||
import { Carousel } from "@mantine/carousel";
|
||||
import { Avatar, Box, Group, Skeleton, Stack, Text } from "@mantine/core";
|
||||
import { useShallowEffect } from "@mantine/hooks";
|
||||
import { useParams, useRouter } from "next/navigation";
|
||||
import toast from "react-hot-toast";
|
||||
import { CiClock2 } from "react-icons/ci";
|
||||
import { funGetDetailDivisionById } from "../lib/api_division";
|
||||
import { useState } from "react";
|
||||
import { IDataTaskOnDetailDivision } from "../lib/type_division";
|
||||
|
||||
|
||||
export default function ListTaskOnDetailDivision() {
|
||||
const router = useRouter()
|
||||
const param = useParams<{ id: string }>()
|
||||
const [data, setData] = useState<IDataTaskOnDetailDivision[]>([])
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
async function fetchData() {
|
||||
try {
|
||||
setLoading(true);
|
||||
const res = await funGetDetailDivisionById(param.id, 'today-task');
|
||||
if (res.success) {
|
||||
setData(res.data)
|
||||
} else {
|
||||
toast.error(res.message);
|
||||
}
|
||||
setLoading(false);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
toast.error("Gagal mendapatkan divisi, coba lagi nanti");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
useShallowEffect(() => {
|
||||
fetchData()
|
||||
}, [param.id])
|
||||
|
||||
return (
|
||||
<Box pt={10}>
|
||||
<Text c={WARNA.biruTua} mb={10} fw={'bold'} fz={16}>Tugas Hari Ini</Text>
|
||||
<Group justify="center" grow>
|
||||
{
|
||||
loading ?
|
||||
Array(2)
|
||||
.fill(null)
|
||||
.map((_, i) => (
|
||||
<Stack align="stretch" justify="center" key={i}>
|
||||
<Skeleton height={80} radius="md" m={0} />
|
||||
<Skeleton height={10} radius="md" m={0} />
|
||||
</Stack>
|
||||
))
|
||||
:
|
||||
(data.length === 0) ?
|
||||
<Stack align="stretch" justify="center" w={"100%"}>
|
||||
<Text c="dimmed" ta={"center"} fs={"italic"}>Belum ada tugas hari ini</Text>
|
||||
</Stack>
|
||||
: <></>
|
||||
}
|
||||
</Group>
|
||||
<Carousel dragFree slideGap={"xs"} align="start" slideSize={"xs"} withIndicators withControls={false}>
|
||||
{data.map((v, i) =>
|
||||
<Carousel.Slide key={v.id}>
|
||||
<Box p={20} w={{ base: 300, md: 400 }} onClick={() => router.push(`/task/${v.id}`)} bg={WARNA.biruTua} style={{ borderRadius: 10, border: `1px solid ${"#D6D8F6"}` }}>
|
||||
<Text fw={'bold'} c={WARNA.bgWhite} truncate="end">{v.title}</Text>
|
||||
<Group justify="space-between" mt={20} c={'#aeaeae'}>
|
||||
<Group gap={5} align="center">
|
||||
<CiClock2 size={18} />
|
||||
<Text fz={13}>{v.dateStart}</Text>
|
||||
</Group >
|
||||
<Group gap={5} align="center">
|
||||
{/* <Avatar.Group>
|
||||
<Avatar>
|
||||
<MdAccountCircle size={32} color={WARNA.biruTua} />
|
||||
</Avatar>
|
||||
<Avatar>+{v.jumlah}</Avatar>
|
||||
</Avatar.Group> */}
|
||||
</Group>
|
||||
</Group>
|
||||
</Box>
|
||||
</Carousel.Slide>
|
||||
)}
|
||||
</Carousel>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
132
src/module/division_new/ui/navbar_admin_division.tsx
Normal file
132
src/module/division_new/ui/navbar_admin_division.tsx
Normal file
@@ -0,0 +1,132 @@
|
||||
"use client"
|
||||
import { API_ADDRESS, LayoutNavbarNew, WARNA } from '@/module/_global';
|
||||
import { useHookstate } from '@hookstate/core';
|
||||
import { Avatar, Box, Button, Checkbox, Divider, Flex, Group, Stack, Text, TextInput } from '@mantine/core';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import React, { useState } from 'react';
|
||||
import { HiMagnifyingGlass } from 'react-icons/hi2';
|
||||
import toast from 'react-hot-toast';
|
||||
import { globalMemberDivision } from '../lib/val_division';
|
||||
import { funCreateDivision } from '../lib/api_division';
|
||||
import { IFormMemberDivision } from '../lib/type_division';
|
||||
|
||||
export default function NavbarAdminDivision({ data, onSuccess }: { data: any, onSuccess: (val: any) => void }) {
|
||||
const router = useRouter()
|
||||
const member = useHookstate(globalMemberDivision)
|
||||
const memberValue = member.get() as IFormMemberDivision[]
|
||||
const [value, setValue] = useState<string[]>([]);
|
||||
|
||||
async function onSubmit() {
|
||||
if (value.length === 0) {
|
||||
return toast.error("Error! Silahkan pilih admin divisi")
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await funCreateDivision({ data: data, member: memberValue, admin: value })
|
||||
|
||||
if (response.success) {
|
||||
toast.success(response.message);
|
||||
onSuccess(true)
|
||||
} else {
|
||||
toast.error(response.message)
|
||||
onSuccess(false)
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
onSuccess(false)
|
||||
toast.error("Gagal menambahkan grup, coba lagi nanti");
|
||||
}
|
||||
|
||||
|
||||
|
||||
// try {
|
||||
// const res = await fetch(API_ADDRESS.apiCreateDivision, {
|
||||
// method: 'POST',
|
||||
// headers: {
|
||||
// 'Content-Type': 'application/json'
|
||||
// },
|
||||
// body: JSON.stringify({
|
||||
// data: data,
|
||||
// member: member.get(),
|
||||
// admin: value
|
||||
// })
|
||||
// })
|
||||
|
||||
// const errorData = await res.json();
|
||||
|
||||
// if (res.status == 201) {
|
||||
// toast.success('Sukses! data tersimpan')
|
||||
// onSuccess(true)
|
||||
// } else {
|
||||
// toast.error(errorData.message);
|
||||
// onSuccess(false)
|
||||
// }
|
||||
// } catch (error) {
|
||||
// toast.error('Error')
|
||||
// onSuccess(false)
|
||||
// }
|
||||
}
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<LayoutNavbarNew title="Pilih Admin Divisi" menu />
|
||||
<Box p={20}>
|
||||
<TextInput
|
||||
styles={{
|
||||
input: {
|
||||
color: WARNA.biruTua,
|
||||
borderRadius: '#A3A3A3',
|
||||
borderColor: '#A3A3A3',
|
||||
},
|
||||
}}
|
||||
size="md"
|
||||
radius={30}
|
||||
leftSection={<HiMagnifyingGlass size={20} />}
|
||||
placeholder="Pencarian"
|
||||
/>
|
||||
<Box pt={20}>
|
||||
<Checkbox.Group value={value} onChange={setValue}>
|
||||
{
|
||||
(member.length === 0) ? (
|
||||
<Text c="dimmed" ta={"center"} fs={"italic"}>Belum ada anggota</Text>
|
||||
) : member.get().map((v: any, i: any) => {
|
||||
return (
|
||||
<Box key={i}>
|
||||
<Flex
|
||||
justify={"space-between"}
|
||||
align={"center"}
|
||||
>
|
||||
<Group>
|
||||
<Avatar src={v.img} alt="it's me" size="lg" />
|
||||
<Box>
|
||||
<Text c={WARNA.biruTua} fw={"bold"}>
|
||||
{v.name}
|
||||
</Text>
|
||||
</Box>
|
||||
</Group>
|
||||
<Checkbox value={v.idUser} />
|
||||
</Flex>
|
||||
<Divider my={20} />
|
||||
</Box>
|
||||
);
|
||||
})
|
||||
}
|
||||
</Checkbox.Group>
|
||||
</Box>
|
||||
<Box mt="xl">
|
||||
<Button
|
||||
color="white"
|
||||
bg={WARNA.biruTua}
|
||||
size="lg"
|
||||
radius={30}
|
||||
fullWidth
|
||||
onClick={() => { onSubmit() }}
|
||||
>
|
||||
Simpan
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
121
src/module/division_new/ui/navbar_create_users.tsx
Normal file
121
src/module/division_new/ui/navbar_create_users.tsx
Normal file
@@ -0,0 +1,121 @@
|
||||
"use client"
|
||||
import { API_ADDRESS, LayoutNavbarNew, WARNA } from '@/module/_global';
|
||||
import { useHookstate } from '@hookstate/core';
|
||||
import { Avatar, Box, Button, Center, Input, SimpleGrid, Stack, Text, TextInput } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import React, { useState } from 'react';
|
||||
import { HiMagnifyingGlass } from 'react-icons/hi2';
|
||||
import { TypeUser } from '@/module/user';
|
||||
import { funGetUserByCookies } from '@/module/auth';
|
||||
import toast from 'react-hot-toast';
|
||||
import { globalMemberDivision } from '../lib/val_division';
|
||||
|
||||
|
||||
export default function NavbarCreateUsers({ grup, onClose }: { grup?: string, onClose: (val: any) => void }) {
|
||||
const router = useRouter()
|
||||
const member = useHookstate(globalMemberDivision)
|
||||
const [selectedFiles, setSelectedFiles] = useState<any>([]);
|
||||
const [dataMember, setDataMember] = useState<TypeUser>([])
|
||||
|
||||
const handleFileClick = (index: number) => {
|
||||
if (selectedFiles.some((i: any) => i.id == dataMember[index].id)) {
|
||||
setSelectedFiles(selectedFiles.filter((i: any) => i.id != dataMember[index].id))
|
||||
} else {
|
||||
setSelectedFiles([...selectedFiles, {idUser: dataMember[index].id, name: dataMember[index].name}])
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
async function loadData() {
|
||||
const loadMember = await fetch(API_ADDRESS.apiGetAllUser + '&active=true&groupID=' + grup);
|
||||
const user = await funGetUserByCookies();
|
||||
const hasil = await loadMember.json()
|
||||
setDataMember(hasil.filter((i: any) => i.id != user.id))
|
||||
|
||||
// cek data member sebelumnya
|
||||
if (member.length > 0) {
|
||||
setSelectedFiles(JSON.parse(JSON.stringify(member.get())))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function onSubmit() {
|
||||
if (selectedFiles.length == 0) {
|
||||
return toast.error("Error! silahkan pilih anggota")
|
||||
}
|
||||
member.set(selectedFiles)
|
||||
onClose(true)
|
||||
}
|
||||
|
||||
useShallowEffect(() => {
|
||||
loadData()
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<LayoutNavbarNew title="Pilih Anggota" menu />
|
||||
<Box p={20}>
|
||||
<Stack>
|
||||
<TextInput
|
||||
styles={{
|
||||
input: {
|
||||
color: WARNA.biruTua,
|
||||
borderRadius: '#A3A3A3',
|
||||
borderColor: '#A3A3A3',
|
||||
},
|
||||
}}
|
||||
size="md"
|
||||
radius={30}
|
||||
leftSection={<HiMagnifyingGlass size={20} />}
|
||||
placeholder="Pencarian"
|
||||
/>
|
||||
<Box pt={10}>
|
||||
<SimpleGrid
|
||||
cols={{ base: 2, sm: 2, lg: 2 }}
|
||||
spacing={{ base: 20, sm: "xl" }}
|
||||
verticalSpacing={{ base: "md", sm: "xl" }}
|
||||
>
|
||||
{dataMember.map((v, index) => {
|
||||
const isSelected = selectedFiles.some((i: any) => i.idUser == dataMember[index].id);
|
||||
return (
|
||||
<Box key={index} mb={10}>
|
||||
<Box
|
||||
bg={isSelected ? WARNA.bgHijauMuda : "white"}
|
||||
style={{
|
||||
border: `1px solid ${WARNA.biruTua}`,
|
||||
borderRadius: 20,
|
||||
}}
|
||||
py={10}
|
||||
onClick={() => handleFileClick(index)}
|
||||
>
|
||||
<Center>
|
||||
<Avatar src={"https://i.pravatar.cc/1000?img=37"} alt="it's me" size="xl" />
|
||||
</Center>
|
||||
<Text mt={20} ta="center">
|
||||
{v.name}
|
||||
</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
</SimpleGrid>
|
||||
</Box>
|
||||
</Stack>
|
||||
<Box mt="xl">
|
||||
<Button
|
||||
color="white"
|
||||
bg={WARNA.biruTua}
|
||||
size="lg"
|
||||
radius={30}
|
||||
fullWidth
|
||||
onClick={() => { onSubmit() }}
|
||||
>
|
||||
Simpan
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
50
src/module/division_new/ui/navbar_detail_division.tsx
Normal file
50
src/module/division_new/ui/navbar_detail_division.tsx
Normal file
@@ -0,0 +1,50 @@
|
||||
'use client'
|
||||
import { LayoutDrawer, LayoutNavbarNew, WARNA } from "@/module/_global";
|
||||
import { ActionIcon, Box } from "@mantine/core";
|
||||
import { useState } from "react";
|
||||
import { HiMenu } from "react-icons/hi";
|
||||
import DrawerDetailDivision from "./drawer_detail_division";
|
||||
import { funGetDivisionById } from "../lib/api_division";
|
||||
import { useParams } from "next/navigation";
|
||||
import toast from "react-hot-toast";
|
||||
import { useShallowEffect } from "@mantine/hooks";
|
||||
|
||||
export default function NavbarDetailDivision() {
|
||||
const [openDrawer, setOpenDrawer] = useState(false)
|
||||
const param = useParams<{ id: string }>()
|
||||
const [name, setName] = useState('')
|
||||
|
||||
async function getOneData() {
|
||||
try {
|
||||
const res = await funGetDivisionById(param.id);
|
||||
if (res.success) {
|
||||
setName(res.data.division.name);
|
||||
} else {
|
||||
toast.error(res.message);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
toast.error("Gagal mendapatkan grup, coba lagi nanti");
|
||||
}
|
||||
}
|
||||
|
||||
useShallowEffect(() => {
|
||||
getOneData();
|
||||
}, [param.id])
|
||||
|
||||
return (
|
||||
<>
|
||||
<LayoutNavbarNew back="" title={name} menu={
|
||||
<ActionIcon variant="light" onClick={() => (setOpenDrawer(true))} bg={WARNA.bgIcon} size="lg" radius="lg" aria-label="Settings">
|
||||
<HiMenu size={20} color='white' />
|
||||
</ActionIcon>
|
||||
} />
|
||||
<LayoutDrawer opened={openDrawer} title={'Menu'} onClose={() => setOpenDrawer(false)}>
|
||||
<DrawerDetailDivision />
|
||||
</LayoutDrawer>
|
||||
</>
|
||||
|
||||
|
||||
);
|
||||
}
|
||||
80
src/module/division_new/ui/report_division_id.tsx
Normal file
80
src/module/division_new/ui/report_division_id.tsx
Normal file
@@ -0,0 +1,80 @@
|
||||
"use client"
|
||||
import { LayoutNavbarNew, WARNA } from '@/module/_global';
|
||||
import { Box, Stack } from '@mantine/core';
|
||||
import { DateInput } from '@mantine/dates';
|
||||
import React, { useState } from 'react';
|
||||
import EchartPaiReport from './echart_pai_report';
|
||||
import EchartBarReport from './echart_bar_report';
|
||||
import EventReport from './event_report';
|
||||
import DiscussionReport from './discussion_report';
|
||||
|
||||
export default function ReportDivisionId() {
|
||||
const [value, setValue] = useState<Date | null>(null);
|
||||
return (
|
||||
<Box>
|
||||
<LayoutNavbarNew back="/division/1" title="Report Divisi" menu />
|
||||
<Box p={20}>
|
||||
<Stack>
|
||||
<DateInput
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
radius={10}
|
||||
size="md"
|
||||
required
|
||||
label="Date input"
|
||||
placeholder="Date input"
|
||||
/>
|
||||
<Box pt={10}>
|
||||
<Box
|
||||
bg={"white"}
|
||||
style={{
|
||||
border: `1px solid ${WARNA.borderBiruMuda}`,
|
||||
borderRadius: 10,
|
||||
padding: 10,
|
||||
}}
|
||||
>
|
||||
<EchartPaiReport />
|
||||
</Box>
|
||||
</Box>
|
||||
<Box pt={10}>
|
||||
<Box
|
||||
bg={"white"}
|
||||
style={{
|
||||
border: `1px solid ${WARNA.borderBiruMuda}`,
|
||||
borderRadius: 10,
|
||||
padding: 10,
|
||||
}}
|
||||
>
|
||||
<EchartBarReport />
|
||||
</Box>
|
||||
</Box>
|
||||
<Box pt={10}>
|
||||
<Box
|
||||
bg={"white"}
|
||||
style={{
|
||||
border: `1px solid ${WARNA.borderBiruMuda}`,
|
||||
borderRadius: 10,
|
||||
padding: 10,
|
||||
}}
|
||||
>
|
||||
<EventReport />
|
||||
</Box>
|
||||
</Box>
|
||||
<Box pt={10}>
|
||||
<Box
|
||||
bg={"white"}
|
||||
style={{
|
||||
border: `1px solid ${WARNA.borderBiruMuda}`,
|
||||
borderRadius: 10,
|
||||
padding: 10,
|
||||
}}
|
||||
>
|
||||
<DiscussionReport />
|
||||
</Box>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user