upd: detail task
Deskripsi: - detail task divisi - folder manager No Issues
This commit is contained in:
@@ -1,8 +1,17 @@
|
|||||||
import { ViewDetailDivisionTask } from "@/module/division_new"
|
import { NavbarDetailDivisionTask, ProgressDetailTask, ListTugasDetailTask, ListFileDetailTask, ListAnggotaDetailTask } from "@/module/task"
|
||||||
|
import { Box } from "@mantine/core"
|
||||||
|
|
||||||
function Page() {
|
function Page() {
|
||||||
return (
|
return (
|
||||||
<ViewDetailDivisionTask />
|
<Box>
|
||||||
|
<NavbarDetailDivisionTask />
|
||||||
|
<Box p={20}>
|
||||||
|
<ProgressDetailTask />
|
||||||
|
<ListTugasDetailTask />
|
||||||
|
<ListFileDetailTask />
|
||||||
|
<ListAnggotaDetailTask />
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
134
src/app/api/task/[id]/route.ts
Normal file
134
src/app/api/task/[id]/route.ts
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
import { prisma } from "@/module/_global";
|
||||||
|
import { funGetUserByCookies } from "@/module/auth";
|
||||||
|
import _ from "lodash";
|
||||||
|
import moment from "moment";
|
||||||
|
import { NextResponse } from "next/server";
|
||||||
|
|
||||||
|
// GET DETAIL TASK DIVISI / GET ONE
|
||||||
|
export async function GET(request: Request, context: { params: { id: string } }) {
|
||||||
|
try {
|
||||||
|
let allData
|
||||||
|
const { id } = context.params;
|
||||||
|
const user = await funGetUserByCookies()
|
||||||
|
const { searchParams } = new URL(request.url);
|
||||||
|
const kategori = searchParams.get("cat");
|
||||||
|
|
||||||
|
if (user.id == undefined) {
|
||||||
|
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await prisma.divisionProject.findUnique({
|
||||||
|
where: {
|
||||||
|
id: String(id),
|
||||||
|
isActive: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
return NextResponse.json({ success: false, message: "Gagal mendapatkan tugas, data tidak ditemukan", }, { status: 404 });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kategori == "data") {
|
||||||
|
allData = data
|
||||||
|
} else if (kategori == "progress") {
|
||||||
|
const dataProgress = await prisma.divisionProjectTask.findMany({
|
||||||
|
where: {
|
||||||
|
isActive: true,
|
||||||
|
idProject: String(id)
|
||||||
|
},
|
||||||
|
orderBy:{
|
||||||
|
updatedAt: 'desc'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const semua = dataProgress.length
|
||||||
|
const selesai = _.filter(dataProgress, { status: 1 }).length
|
||||||
|
const progress = Math.ceil((selesai / semua) * 100)
|
||||||
|
|
||||||
|
allData = {
|
||||||
|
progress: progress,
|
||||||
|
lastUpdate: moment(dataProgress[0].updatedAt).format("DD MMMM YYYY"),
|
||||||
|
}
|
||||||
|
} else if (kategori == "task") {
|
||||||
|
const dataProgress = await prisma.divisionProjectTask.findMany({
|
||||||
|
where: {
|
||||||
|
isActive: true,
|
||||||
|
idProject: String(id)
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
title: true,
|
||||||
|
status: true,
|
||||||
|
dateStart: true,
|
||||||
|
dateEnd: true,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const fix = dataProgress.map((v: any) => ({
|
||||||
|
..._.omit(v, ["dateStart", "dateEnd"]),
|
||||||
|
dateStart: moment(v.dateStart).format("DD MMMM YYYY"),
|
||||||
|
dateEnd: moment(v.dateEnd).format("DD MMMM YYYY"),
|
||||||
|
}))
|
||||||
|
|
||||||
|
allData = fix
|
||||||
|
|
||||||
|
} else if (kategori == "file") {
|
||||||
|
const dataFile = await prisma.divisionProjectFile.findMany({
|
||||||
|
where: {
|
||||||
|
isActive: true,
|
||||||
|
idProject: String(id)
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
ContainerFileDivision: {
|
||||||
|
select: {
|
||||||
|
name: true,
|
||||||
|
extension: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const fix = dataFile.map((v: any) => ({
|
||||||
|
..._.omit(v, ["ContainerFileDivision"]),
|
||||||
|
name: v.ContainerFileDivision.name,
|
||||||
|
extension: v.ContainerFileDivision.extension,
|
||||||
|
}))
|
||||||
|
|
||||||
|
allData = fix
|
||||||
|
|
||||||
|
} else if (kategori == "member") {
|
||||||
|
const dataMember = await prisma.divisionProjectMember.findMany({
|
||||||
|
where: {
|
||||||
|
isActive: true,
|
||||||
|
idProject: String(id)
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
User: {
|
||||||
|
select: {
|
||||||
|
name: true,
|
||||||
|
email: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
const fix = dataMember.map((v: any) => ({
|
||||||
|
..._.omit(v, ["User"]),
|
||||||
|
name: v.User.name,
|
||||||
|
email: v.User.email,
|
||||||
|
}))
|
||||||
|
|
||||||
|
allData = fix
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json({ success: true, message: "Berhasil mendapatkan tugas divisi", data: allData }, { status: 200 });
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
return NextResponse.json({ success: false, message: "Gagal mendapatkan tugas divisi, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,130 +0,0 @@
|
|||||||
"use client";
|
|
||||||
import { LayoutDrawer, LayoutNavbarNew, WARNA } from "@/module/_global";
|
|
||||||
import { Box, Button, Center, Flex, Group, Input, Stack, Text } from "@mantine/core";
|
|
||||||
import { useRouter } from "next/navigation";
|
|
||||||
import React, { useState } from "react";
|
|
||||||
import { IoIosArrowDropright } from "react-icons/io";
|
|
||||||
import { BsFiletypeCsv } from "react-icons/bs";
|
|
||||||
import ResultsDateAndTask from "@/module/project/components/results_date-and_task";
|
|
||||||
import ResultsFile from "@/module/project/components/results_file";
|
|
||||||
|
|
||||||
export default function CreateTask({ searchParams }: { searchParams: any }) {
|
|
||||||
const router = useRouter();
|
|
||||||
const [openDrawer, setOpenDrawer] = useState(false);
|
|
||||||
return (
|
|
||||||
<Box>
|
|
||||||
<LayoutNavbarNew back="" title="tambah tugas" menu />
|
|
||||||
<Box p={20}>
|
|
||||||
<Stack>
|
|
||||||
<Input
|
|
||||||
styles={{
|
|
||||||
input: {
|
|
||||||
border: `1px solid ${"#D6D8F6"}`,
|
|
||||||
borderRadius: 10,
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
placeholder="Nama Proyek"
|
|
||||||
size="md"
|
|
||||||
/>
|
|
||||||
<Box onClick={() => router.push("/task/create?page=task")}>
|
|
||||||
<Group
|
|
||||||
justify="space-between"
|
|
||||||
p={10}
|
|
||||||
style={{
|
|
||||||
border: `1px solid ${"#D6D8F6"}`,
|
|
||||||
borderRadius: 10,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Text>Tambah Tanggal & Tugas</Text>
|
|
||||||
<IoIosArrowDropright size={25} />
|
|
||||||
</Group>
|
|
||||||
</Box>
|
|
||||||
<Group
|
|
||||||
justify="space-between"
|
|
||||||
p={10}
|
|
||||||
style={{
|
|
||||||
border: `1px solid ${"#D6D8F6"}`,
|
|
||||||
borderRadius: 10,
|
|
||||||
}}
|
|
||||||
onClick={() => setOpenDrawer(true)}
|
|
||||||
>
|
|
||||||
<Text>Upload File</Text>
|
|
||||||
<IoIosArrowDropright size={25} />
|
|
||||||
</Group>
|
|
||||||
</Stack>
|
|
||||||
{
|
|
||||||
(searchParams.anggota == 'yes') &&
|
|
||||||
<>
|
|
||||||
<ResultsDateAndTask />
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
|
|
||||||
{(searchParams.files == 'yes') &&
|
|
||||||
<>
|
|
||||||
<ResultsFile />
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
(searchParams.button == 'yes') &&
|
|
||||||
<>
|
|
||||||
<Box mt="xl">
|
|
||||||
<Button color="white" bg={WARNA.biruTua} size="lg" radius={30} fullWidth onClick={() => router.push('/task')}>
|
|
||||||
Simpan
|
|
||||||
</Button>
|
|
||||||
</Box>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<LayoutDrawer
|
|
||||||
opened={openDrawer}
|
|
||||||
onClose={() => setOpenDrawer(false)}
|
|
||||||
title={"Pilih File"}
|
|
||||||
>
|
|
||||||
<Flex justify={"space-around"}>
|
|
||||||
<Box onClick={() => ""}>
|
|
||||||
<Box
|
|
||||||
bg={"#DCEED8"}
|
|
||||||
style={{
|
|
||||||
border: `1px solid ${"#D6D8F6"}`,
|
|
||||||
padding: 20,
|
|
||||||
borderRadius: 10,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Center>
|
|
||||||
<BsFiletypeCsv size={40} />
|
|
||||||
</Center>
|
|
||||||
</Box>
|
|
||||||
<Text mt={10} ta={"center"}>
|
|
||||||
Pilih file
|
|
||||||
</Text>
|
|
||||||
<Text ta={"center"}>diperangkat</Text>
|
|
||||||
</Box>
|
|
||||||
<Box onClick={() => router.push("/task/create?page=file-save")}>
|
|
||||||
<Box
|
|
||||||
bg={"#DCEED8"}
|
|
||||||
style={{
|
|
||||||
border: `1px solid ${"#D6D8F6"}`,
|
|
||||||
padding: 20,
|
|
||||||
borderRadius: 10,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Center>
|
|
||||||
<BsFiletypeCsv size={40} />
|
|
||||||
</Center>
|
|
||||||
</Box>
|
|
||||||
<Text mt={10} ta={"center"}>
|
|
||||||
Pilih file yang
|
|
||||||
</Text>
|
|
||||||
<Text ta={"center"}>sudah ada</Text>
|
|
||||||
</Box>
|
|
||||||
</Flex>
|
|
||||||
</LayoutDrawer>
|
|
||||||
</Box >
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
import { WARNA } from "@/module/_global";
|
|
||||||
import { Box, Group, Flex, Avatar, Text } from "@mantine/core";
|
|
||||||
|
|
||||||
|
|
||||||
const dataAnggota = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
name: "Iqbal Ramadan",
|
|
||||||
image: "https://i.pravatar.cc/1000?img=5",
|
|
||||||
email: "iqbal.ramadan@gmail.com",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
name: "Doni Setiawan",
|
|
||||||
image: "https://i.pravatar.cc/1000?img=10",
|
|
||||||
email: "doni.setiawan@gmail.com",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
name: "Rangga Agung",
|
|
||||||
image: "https://i.pravatar.cc/1000?img=51",
|
|
||||||
email: "rangga.agung@gmail.com",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
name: "Ramadan Sananta",
|
|
||||||
image: "https://i.pravatar.cc/1000?img=15",
|
|
||||||
email: "ramadan@gmail.com",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
name: "Imam Baroni",
|
|
||||||
image: "https://i.pravatar.cc/1000?img=22",
|
|
||||||
email: "imam.baroni@gmail.com",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
export default function ListAnggotaDetailTask() {
|
|
||||||
return (
|
|
||||||
<Box pt={20}>
|
|
||||||
<Group justify="space-between">
|
|
||||||
<Text c={WARNA.biruTua}>Anggota Terpilih</Text>
|
|
||||||
<Text c={WARNA.biruTua}>Total 10 Anggota</Text>
|
|
||||||
</Group>
|
|
||||||
<Box pt={10}>
|
|
||||||
<Box mb={20}>
|
|
||||||
<Box
|
|
||||||
style={{
|
|
||||||
border: `1px solid ${"#C7D6E8"}`,
|
|
||||||
borderRadius: 10,
|
|
||||||
}}
|
|
||||||
px={20}
|
|
||||||
py={10}
|
|
||||||
>
|
|
||||||
<Text c={WARNA.biruTua} fw={"bold"}>
|
|
||||||
Divisi Kerohanian
|
|
||||||
</Text>
|
|
||||||
{dataAnggota.map((v, i) => {
|
|
||||||
return (
|
|
||||||
<Flex
|
|
||||||
justify={"space-between"}
|
|
||||||
align={"center"}
|
|
||||||
mt={20}
|
|
||||||
key={i}
|
|
||||||
>
|
|
||||||
<Group>
|
|
||||||
<Avatar src={v.image} alt="it's me" size="lg" />
|
|
||||||
<Box>
|
|
||||||
<Text c={WARNA.biruTua} fw={"bold"}>
|
|
||||||
{v.name}
|
|
||||||
</Text>
|
|
||||||
<Text c={"#5A687D"} fz={14}>
|
|
||||||
{v.email}
|
|
||||||
</Text>
|
|
||||||
</Box>
|
|
||||||
</Group>
|
|
||||||
<Text c={WARNA.biruTua} fw={"bold"}>
|
|
||||||
Anggota
|
|
||||||
</Text>
|
|
||||||
</Flex>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
import { WARNA } from "@/module/_global";
|
|
||||||
import { Box, Group, Text } from "@mantine/core";
|
|
||||||
import { BsFiletypeCsv } from "react-icons/bs";
|
|
||||||
|
|
||||||
export default function ListFileDetailTask() {
|
|
||||||
return (
|
|
||||||
<Box pt={20}>
|
|
||||||
<Text fw={'bold'} c={WARNA.biruTua}>File</Text>
|
|
||||||
<Box bg={"white"} style={{
|
|
||||||
borderRadius: 10,
|
|
||||||
border: `1px solid ${"#D6D8F6"}`,
|
|
||||||
padding: 20
|
|
||||||
}}>
|
|
||||||
<Box style={{
|
|
||||||
borderRadius: 10,
|
|
||||||
border: `1px solid ${"#D6D8F6"}`,
|
|
||||||
padding: 10
|
|
||||||
}} mb={10}>
|
|
||||||
<Group>
|
|
||||||
<BsFiletypeCsv size={25} />
|
|
||||||
<Text>Proyek Laporan Permasyarakatan</Text>
|
|
||||||
</Group>
|
|
||||||
</Box>
|
|
||||||
<Box style={{
|
|
||||||
borderRadius: 10,
|
|
||||||
border: `1px solid ${"#D6D8F6"}`,
|
|
||||||
padding: 10
|
|
||||||
}}>
|
|
||||||
<Group>
|
|
||||||
<BsFiletypeCsv size={25} />
|
|
||||||
<Text>Proyek Laporan Permasyarakatan</Text>
|
|
||||||
</Group>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
'use client'
|
|
||||||
|
|
||||||
import { WARNA } from "@/module/_global"
|
|
||||||
import { Box, Grid, Center, Checkbox, Group, SimpleGrid, Text } from "@mantine/core"
|
|
||||||
import { AiOutlineFileSync } from "react-icons/ai"
|
|
||||||
|
|
||||||
export default function ListTugasDetailTask() {
|
|
||||||
return (
|
|
||||||
<Box pt={20}>
|
|
||||||
<Text fw={"bold"} c={WARNA.biruTua}>
|
|
||||||
Tanggal & Tugas
|
|
||||||
</Text>
|
|
||||||
<Box
|
|
||||||
bg={"white"}
|
|
||||||
style={{
|
|
||||||
borderRadius: 10,
|
|
||||||
border: `1px solid ${"#D6D8F6"}`,
|
|
||||||
padding: 20,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Grid>
|
|
||||||
<Grid.Col span={"auto"}>
|
|
||||||
<Center>
|
|
||||||
<Checkbox color="teal" size="md" />
|
|
||||||
</Center>
|
|
||||||
</Grid.Col>
|
|
||||||
<Grid.Col span={10}>
|
|
||||||
<Box
|
|
||||||
style={{
|
|
||||||
borderRadius: 10,
|
|
||||||
border: `1px solid ${"#D6D8F6"}`,
|
|
||||||
padding: 10,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Group>
|
|
||||||
<AiOutlineFileSync size={25} />
|
|
||||||
<Text>Laporan Permasyarakatan</Text>
|
|
||||||
</Group>
|
|
||||||
</Box>
|
|
||||||
<Box>
|
|
||||||
<SimpleGrid cols={{ base: 2, sm: 2, lg: 2 }} mt={20}>
|
|
||||||
<Box>
|
|
||||||
<Text>Tanggal Mulai</Text>
|
|
||||||
<Group
|
|
||||||
justify="center"
|
|
||||||
bg={"white"}
|
|
||||||
h={45}
|
|
||||||
style={{
|
|
||||||
borderRadius: 10,
|
|
||||||
border: `1px solid ${"#D6D8F6"}`,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Text>16 Juni 2024</Text>
|
|
||||||
</Group>
|
|
||||||
</Box>
|
|
||||||
<Box>
|
|
||||||
<Text c={WARNA.biruTua}>Tanggal Berakhir</Text>
|
|
||||||
<Group
|
|
||||||
justify="center"
|
|
||||||
bg={"white"}
|
|
||||||
h={45}
|
|
||||||
style={{
|
|
||||||
borderRadius: 10,
|
|
||||||
border: `1px solid ${"#D6D8F6"}`,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Text>20 Juni 2024</Text>
|
|
||||||
</Group>
|
|
||||||
</Box>
|
|
||||||
</SimpleGrid>
|
|
||||||
</Box>
|
|
||||||
</Grid.Col>
|
|
||||||
</Grid>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
'use client'
|
|
||||||
import { LayoutNavbarNew, WARNA } from "@/module/_global";
|
|
||||||
import { ActionIcon } from "@mantine/core";
|
|
||||||
import { useRouter } from "next/navigation";
|
|
||||||
import { LuClipboardEdit } from "react-icons/lu";
|
|
||||||
|
|
||||||
export default function NavbarDetailDivisionTask() {
|
|
||||||
const router = useRouter()
|
|
||||||
return (
|
|
||||||
<LayoutNavbarNew back="" title="Tugas 1" menu={
|
|
||||||
<ActionIcon
|
|
||||||
variant="light"
|
|
||||||
bg={WARNA.bgIcon}
|
|
||||||
size="lg"
|
|
||||||
radius="lg"
|
|
||||||
aria-label="Settings"
|
|
||||||
onClick={() => router.push("/task/update/1")}
|
|
||||||
>
|
|
||||||
<LuClipboardEdit size={20} color="white" />
|
|
||||||
</ActionIcon>
|
|
||||||
} />
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
import { Box } from "@mantine/core";
|
|
||||||
import NavbarDetailDivisionTask from "../component/navbar_detail_division_task";
|
|
||||||
import ProgressDetailTask from "../component/detail_progress_task";
|
|
||||||
import ListTugasDetailTask from "../component/detail_list_tugas_task";
|
|
||||||
import ListFileDetailTask from "../component/detail_list_file_task";
|
|
||||||
import ListAnggotaDetailTask from "../component/detail_list_anggota_task";
|
|
||||||
|
|
||||||
export default function ViewDetailDivisionTask() {
|
|
||||||
return (
|
|
||||||
<Box>
|
|
||||||
<NavbarDetailDivisionTask />
|
|
||||||
<Box p={20}>
|
|
||||||
<ProgressDetailTask />
|
|
||||||
<ListTugasDetailTask />
|
|
||||||
<ListFileDetailTask />
|
|
||||||
<ListAnggotaDetailTask />
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -9,7 +9,6 @@ import ViewDivisionCalender from "./_division_fitur/calender/view/view_division_
|
|||||||
import ViewHistoryDivisionCalender from "./_division_fitur/calender/view/view_history_division_calender";
|
import ViewHistoryDivisionCalender from "./_division_fitur/calender/view/view_history_division_calender";
|
||||||
import ViewUpdateDivisionCalender from "./_division_fitur/calender/view/view_update_division_calender";
|
import ViewUpdateDivisionCalender from "./_division_fitur/calender/view/view_update_division_calender";
|
||||||
import ViewDocumentDivision from "./_division_fitur/document/view/view_document_division";
|
import ViewDocumentDivision from "./_division_fitur/document/view/view_document_division";
|
||||||
import ViewDetailDivisionTask from "./_division_fitur/task/view/view_detail_division_task";
|
|
||||||
import ViewUpdateProgressDivisionTask from "./_division_fitur/task/view/view_update_progress_division_task";
|
import ViewUpdateProgressDivisionTask from "./_division_fitur/task/view/view_update_progress_division_task";
|
||||||
import CreateAdminDivision from "./ui/create_admin_division";
|
import CreateAdminDivision from "./ui/create_admin_division";
|
||||||
import CreateUsers from "./ui/create_users";
|
import CreateUsers from "./ui/create_users";
|
||||||
@@ -30,7 +29,6 @@ import { funGetDivisionById } from './lib/api_division';
|
|||||||
|
|
||||||
export { CreateUsers };
|
export { CreateUsers };
|
||||||
export { CreateAdminDivision };
|
export { CreateAdminDivision };
|
||||||
export { ViewDetailDivisionTask };
|
|
||||||
export { ViewUpdateProgressDivisionTask };
|
export { ViewUpdateProgressDivisionTask };
|
||||||
export { ViewDivisionCalender };
|
export { ViewDivisionCalender };
|
||||||
export { ViewCreateDivisionCalender };
|
export { ViewCreateDivisionCalender };
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
import ViewDateEndTask from "./ui/create_date_end_task";
|
import ViewDateEndTask from "./ui/create_date_end_task";
|
||||||
import CreateTask from "./ui/create_task";
|
import CreateTask from "./ui/create_task";
|
||||||
import CreateUsersProject from "./ui/create_users_project";
|
import CreateUsersProject from "./ui/create_users_project";
|
||||||
|
import ListAnggotaDetailTask from "./ui/detail_list_anggota_task";
|
||||||
|
import ListFileDetailTask from "./ui/detail_list_file_task";
|
||||||
|
import ListTugasDetailTask from "./ui/detail_list_tugas_task";
|
||||||
|
import ProgressDetailTask from "./ui/detail_progress_task";
|
||||||
import FileSave from "./ui/file_save";
|
import FileSave from "./ui/file_save";
|
||||||
|
import NavbarDetailDivisionTask from "./ui/navbar_detail_division_task";
|
||||||
import NavbarDivisionTask from "./ui/navbar_division_task";
|
import NavbarDivisionTask from "./ui/navbar_division_task";
|
||||||
import TabsDivisionTask from "./ui/tabs_division_task";
|
import TabsDivisionTask from "./ui/tabs_division_task";
|
||||||
|
|
||||||
@@ -11,3 +16,8 @@ export { CreateTask }
|
|||||||
export { ViewDateEndTask }
|
export { ViewDateEndTask }
|
||||||
export { CreateUsersProject }
|
export { CreateUsersProject }
|
||||||
export { FileSave }
|
export { FileSave }
|
||||||
|
export { NavbarDetailDivisionTask }
|
||||||
|
export { ListTugasDetailTask }
|
||||||
|
export { ProgressDetailTask }
|
||||||
|
export { ListFileDetailTask }
|
||||||
|
export { ListAnggotaDetailTask }
|
||||||
@@ -19,3 +19,8 @@ export const funCreateTask = async (data: IFormTaskDivision) => {
|
|||||||
});
|
});
|
||||||
return await response.json().catch(() => null);
|
return await response.json().catch(() => null);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const funGetTaskDivisionById = async (path: string, kategori: string) => {
|
||||||
|
const response = await fetch(`/api/task/${path}?cat=${kategori}`);
|
||||||
|
return await response.json().catch(() => null);
|
||||||
|
}
|
||||||
@@ -32,3 +32,24 @@ export interface IListFileTask {
|
|||||||
name: string,
|
name: string,
|
||||||
extension: string
|
extension: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface IDataListTaskDivision {
|
||||||
|
id: string
|
||||||
|
title: string
|
||||||
|
dateStart: string
|
||||||
|
dateEnd: string
|
||||||
|
status: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IDataMemberTaskDivision {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
email: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IDataFileTaskDivision {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
extension: string
|
||||||
|
}
|
||||||
88
src/module/task/ui/detail_list_anggota_task.tsx
Normal file
88
src/module/task/ui/detail_list_anggota_task.tsx
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
'use client'
|
||||||
|
import { WARNA } from "@/module/_global";
|
||||||
|
import { Box, Group, Flex, Avatar, Text } from "@mantine/core";
|
||||||
|
import { useShallowEffect } from "@mantine/hooks";
|
||||||
|
import { useParams } from "next/navigation";
|
||||||
|
import { useState } from "react";
|
||||||
|
import toast from "react-hot-toast";
|
||||||
|
import { funGetTaskDivisionById } from "../lib/api_task";
|
||||||
|
import { IDataMemberTaskDivision } from "../lib/type_task";
|
||||||
|
|
||||||
|
|
||||||
|
export default function ListAnggotaDetailTask() {
|
||||||
|
const [isData, setData] = useState<IDataMemberTaskDivision[]>([])
|
||||||
|
const [loading, setLoading] = useState(true)
|
||||||
|
const param = useParams<{ id: string, detail: string }>()
|
||||||
|
async function getOneData() {
|
||||||
|
try {
|
||||||
|
setLoading(true)
|
||||||
|
const res = await funGetTaskDivisionById(param.detail, 'member');
|
||||||
|
if (res.success) {
|
||||||
|
setData(res.data)
|
||||||
|
} else {
|
||||||
|
toast.error(res.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
toast.error("Gagal mendapatkan member tugas divisi, coba lagi nanti");
|
||||||
|
} finally {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
getOneData();
|
||||||
|
}, [param.detail])
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box pt={20}>
|
||||||
|
<Group justify="space-between">
|
||||||
|
<Text c={WARNA.biruTua}>Anggota Terpilih</Text>
|
||||||
|
<Text c={WARNA.biruTua}>Total {isData.length} Anggota</Text>
|
||||||
|
</Group>
|
||||||
|
<Box pt={10}>
|
||||||
|
<Box mb={20}>
|
||||||
|
<Box
|
||||||
|
style={{
|
||||||
|
border: `1px solid ${"#C7D6E8"}`,
|
||||||
|
borderRadius: 10,
|
||||||
|
}}
|
||||||
|
px={20}
|
||||||
|
py={10}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
loading ? <Text>loading</Text> :
|
||||||
|
isData.length === 0 ? <Text>Tidak ada anggota</Text> :
|
||||||
|
isData.map((v, i) => {
|
||||||
|
return (
|
||||||
|
<Flex
|
||||||
|
justify={"space-between"}
|
||||||
|
align={"center"}
|
||||||
|
mt={20}
|
||||||
|
key={i}
|
||||||
|
>
|
||||||
|
<Group>
|
||||||
|
<Avatar src={""} alt="it's me" size="lg" />
|
||||||
|
<Box>
|
||||||
|
<Text c={WARNA.biruTua} fw={"bold"}>
|
||||||
|
{v.name}
|
||||||
|
</Text>
|
||||||
|
<Text c={"#5A687D"} fz={14}>
|
||||||
|
{v.email}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
</Group>
|
||||||
|
<Text c={WARNA.biruTua} fw={"bold"}>
|
||||||
|
Anggota
|
||||||
|
</Text>
|
||||||
|
</Flex>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
||||||
76
src/module/task/ui/detail_list_file_task.tsx
Normal file
76
src/module/task/ui/detail_list_file_task.tsx
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
'use client'
|
||||||
|
import { WARNA } from "@/module/_global";
|
||||||
|
import { Box, Group, Text } from "@mantine/core";
|
||||||
|
import { useShallowEffect } from "@mantine/hooks";
|
||||||
|
import { useParams } from "next/navigation";
|
||||||
|
import { useState } from "react";
|
||||||
|
import toast from "react-hot-toast";
|
||||||
|
import { BsFiletypeCsv, BsFiletypeHeic, BsFiletypeJpg, BsFiletypePdf, BsFiletypePng } from "react-icons/bs";
|
||||||
|
import { funGetTaskDivisionById } from "../lib/api_task";
|
||||||
|
import { IDataFileTaskDivision } from "../lib/type_task";
|
||||||
|
|
||||||
|
export default function ListFileDetailTask() {
|
||||||
|
const [isData, setData] = useState<IDataFileTaskDivision[]>([])
|
||||||
|
const [loading, setLoading] = useState(true)
|
||||||
|
const param = useParams<{ id: string, detail: string }>()
|
||||||
|
async function getOneData() {
|
||||||
|
try {
|
||||||
|
setLoading(true)
|
||||||
|
const res = await funGetTaskDivisionById(param.detail, 'file');
|
||||||
|
if (res.success) {
|
||||||
|
setData(res.data)
|
||||||
|
} else {
|
||||||
|
toast.error(res.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
toast.error("Gagal mendapatkan file tugas divisi, coba lagi nanti");
|
||||||
|
} finally {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
getOneData();
|
||||||
|
}, [param.detail])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box pt={20}>
|
||||||
|
<Text fw={'bold'} c={WARNA.biruTua}>File</Text>
|
||||||
|
<Box bg={"white"} style={{
|
||||||
|
borderRadius: 10,
|
||||||
|
border: `1px solid ${"#D6D8F6"}`,
|
||||||
|
padding: 20
|
||||||
|
}}>
|
||||||
|
{
|
||||||
|
|
||||||
|
loading ? <Text>loading</Text> :
|
||||||
|
isData.length === 0 ? <Text>Tidak ada file</Text> :
|
||||||
|
isData.map((item, index) => {
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
key={index}
|
||||||
|
style={{
|
||||||
|
borderRadius: 10,
|
||||||
|
border: `1px solid ${"#D6D8F6"}`,
|
||||||
|
padding: 10
|
||||||
|
}}
|
||||||
|
mb={10}
|
||||||
|
>
|
||||||
|
<Group>
|
||||||
|
{item.extension == "pdf" && <BsFiletypePdf size={25} />}
|
||||||
|
{item.extension == "csv" && <BsFiletypeCsv size={25} />}
|
||||||
|
{item.extension == "png" && <BsFiletypePng size={25} />}
|
||||||
|
{item.extension == "jpg" || item.extension == "jpeg" && <BsFiletypeJpg size={25} />}
|
||||||
|
{item.extension == "heic" && <BsFiletypeHeic size={25} />}
|
||||||
|
<Text>{item.name}</Text>
|
||||||
|
</Group>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
||||||
116
src/module/task/ui/detail_list_tugas_task.tsx
Normal file
116
src/module/task/ui/detail_list_tugas_task.tsx
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
'use client'
|
||||||
|
import { WARNA } from "@/module/_global"
|
||||||
|
import { Box, Grid, Center, Checkbox, Group, SimpleGrid, Text } from "@mantine/core"
|
||||||
|
import { useShallowEffect } from "@mantine/hooks"
|
||||||
|
import { useParams } from "next/navigation"
|
||||||
|
import toast from "react-hot-toast"
|
||||||
|
import { AiOutlineFileSync } from "react-icons/ai"
|
||||||
|
import { funGetTaskDivisionById } from "../lib/api_task"
|
||||||
|
import { useState } from "react"
|
||||||
|
import { IDataListTaskDivision } from "../lib/type_task"
|
||||||
|
|
||||||
|
export default function ListTugasDetailTask() {
|
||||||
|
const [isData, setData] = useState<IDataListTaskDivision[]>([])
|
||||||
|
const [loading, setLoading] = useState(true)
|
||||||
|
const param = useParams<{ id: string, detail: string }>()
|
||||||
|
async function getOneData() {
|
||||||
|
try {
|
||||||
|
setLoading(true)
|
||||||
|
const res = await funGetTaskDivisionById(param.detail, 'task');
|
||||||
|
if (res.success) {
|
||||||
|
setData(res.data)
|
||||||
|
} else {
|
||||||
|
toast.error(res.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
toast.error("Gagal mendapatkan list tugas divisi, coba lagi nanti");
|
||||||
|
} finally {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
getOneData();
|
||||||
|
}, [param.detail])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box pt={20}>
|
||||||
|
<Text fw={"bold"} c={WARNA.biruTua}>
|
||||||
|
Tanggal & Tugas
|
||||||
|
</Text>
|
||||||
|
<Box
|
||||||
|
bg={"white"}
|
||||||
|
style={{
|
||||||
|
borderRadius: 10,
|
||||||
|
border: `1px solid ${"#D6D8F6"}`,
|
||||||
|
padding: 20,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
loading ? <Text>loading</Text> :
|
||||||
|
isData.length === 0 ? <Text>Tidak ada tugas</Text> :
|
||||||
|
isData.map((item, index) => {
|
||||||
|
return (
|
||||||
|
<Grid key={index} style={{ borderBottom: "1px solid #D6D8F6" }} pb={10} mb={10}>
|
||||||
|
<Grid.Col span={"auto"}>
|
||||||
|
<Center>
|
||||||
|
<Checkbox color="teal" size="md" checked={(item.status === 1) ? true : false} disabled />
|
||||||
|
</Center>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={10}>
|
||||||
|
<Box
|
||||||
|
style={{
|
||||||
|
borderRadius: 10,
|
||||||
|
border: `1px solid ${"#D6D8F6"}`,
|
||||||
|
padding: 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Group>
|
||||||
|
<AiOutlineFileSync size={25} />
|
||||||
|
<Text>{item.title}</Text>
|
||||||
|
</Group>
|
||||||
|
</Box>
|
||||||
|
<Box>
|
||||||
|
<SimpleGrid cols={{ base: 2, sm: 2, lg: 2 }} mt={20}>
|
||||||
|
<Box>
|
||||||
|
<Text>Tanggal Mulai</Text>
|
||||||
|
<Group
|
||||||
|
justify="center"
|
||||||
|
bg={"white"}
|
||||||
|
h={45}
|
||||||
|
style={{
|
||||||
|
borderRadius: 10,
|
||||||
|
border: `1px solid ${"#D6D8F6"}`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text>{item.dateStart}</Text>
|
||||||
|
</Group>
|
||||||
|
</Box>
|
||||||
|
<Box>
|
||||||
|
<Text c={WARNA.biruTua}>Tanggal Berakhir</Text>
|
||||||
|
<Group
|
||||||
|
justify="center"
|
||||||
|
bg={"white"}
|
||||||
|
h={45}
|
||||||
|
style={{
|
||||||
|
borderRadius: 10,
|
||||||
|
border: `1px solid ${"#D6D8F6"}`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text>{item.dateEnd}</Text>
|
||||||
|
</Group>
|
||||||
|
</Box>
|
||||||
|
</SimpleGrid>
|
||||||
|
</Box>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,9 +1,37 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import { WARNA } from "@/module/_global";
|
import { WARNA } from "@/module/_global";
|
||||||
import { Box, Grid, ActionIcon, Progress, Text } from "@mantine/core";
|
import { Box, Grid, ActionIcon, Progress, Text } from "@mantine/core";
|
||||||
|
import { useShallowEffect } from "@mantine/hooks";
|
||||||
|
import { useParams } from "next/navigation";
|
||||||
|
import toast from "react-hot-toast";
|
||||||
import { HiMiniPresentationChartBar } from "react-icons/hi2";
|
import { HiMiniPresentationChartBar } from "react-icons/hi2";
|
||||||
|
import { funGetTaskDivisionById } from "../lib/api_task";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
export default function ProgressDetailTask() {
|
export default function ProgressDetailTask() {
|
||||||
|
const [valProgress, setValProgress] = useState(0)
|
||||||
|
const [valLastUpdate, setValLastUpdate] = useState('')
|
||||||
|
const param = useParams<{ id: string, detail: string }>()
|
||||||
|
async function getOneData() {
|
||||||
|
try {
|
||||||
|
const res = await funGetTaskDivisionById(param.detail, 'progress');
|
||||||
|
if (res.success) {
|
||||||
|
setValProgress(res.data.progress);
|
||||||
|
setValLastUpdate(res.data.lastUpdate);
|
||||||
|
} else {
|
||||||
|
toast.error(res.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
toast.error("Gagal mendapatkan progress tugas divisi, coba lagi nanti");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
getOneData();
|
||||||
|
}, [param.detail])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box mt={10}>
|
<Box mt={10}>
|
||||||
<Box
|
<Box
|
||||||
@@ -27,7 +55,7 @@ export default function ProgressDetailTask() {
|
|||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
<Grid.Col span={9}>
|
<Grid.Col span={9}>
|
||||||
<Box>
|
<Box>
|
||||||
<Text>Kemajuan Proyek 60%</Text>
|
<Text>Kemajuan Proyek {valProgress}%</Text>
|
||||||
<Progress
|
<Progress
|
||||||
style={{
|
style={{
|
||||||
border: `1px solid ${"#BDBDBD"}`,
|
border: `1px solid ${"#BDBDBD"}`,
|
||||||
@@ -36,9 +64,9 @@ export default function ProgressDetailTask() {
|
|||||||
color="#FCAA4B"
|
color="#FCAA4B"
|
||||||
radius="md"
|
radius="md"
|
||||||
size="xl"
|
size="xl"
|
||||||
value={60}
|
value={valProgress}
|
||||||
/>
|
/>
|
||||||
<Text>18 Juni 2024</Text>
|
<Text>{valLastUpdate}</Text>
|
||||||
</Box>
|
</Box>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
</Grid>
|
</Grid>
|
||||||
@@ -136,7 +136,7 @@ export default function ListDivisionTask() {
|
|||||||
{isData.map((v, i) => {
|
{isData.map((v, i) => {
|
||||||
return (
|
return (
|
||||||
<Box key={i}>
|
<Box key={i}>
|
||||||
<Group justify="space-between" mb={10} onClick={() => router.push(`/task/${v.id}`)}>
|
<Group justify="space-between" mb={10} onClick={() => router.push(`task/${v.id}`)}>
|
||||||
<Group>
|
<Group>
|
||||||
<Center>
|
<Center>
|
||||||
<ActionIcon
|
<ActionIcon
|
||||||
|
|||||||
50
src/module/task/ui/navbar_detail_division_task.tsx
Normal file
50
src/module/task/ui/navbar_detail_division_task.tsx
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
'use client'
|
||||||
|
import { LayoutNavbarNew, WARNA } from "@/module/_global";
|
||||||
|
import { ActionIcon } from "@mantine/core";
|
||||||
|
import { useParams, useRouter } from "next/navigation";
|
||||||
|
import { useState } from "react";
|
||||||
|
import toast from "react-hot-toast";
|
||||||
|
import { LuClipboardEdit } from "react-icons/lu";
|
||||||
|
import { funGetTaskDivisionById } from "../lib/api_task";
|
||||||
|
import { useShallowEffect } from "@mantine/hooks";
|
||||||
|
|
||||||
|
export default function NavbarDetailDivisionTask() {
|
||||||
|
const router = useRouter()
|
||||||
|
const param = useParams<{ id: string, detail: string }>()
|
||||||
|
const [name, setName] = useState('')
|
||||||
|
|
||||||
|
async function getOneData() {
|
||||||
|
try {
|
||||||
|
const res = await funGetTaskDivisionById(param.detail, 'data');
|
||||||
|
if (res.success) {
|
||||||
|
setName(res.data.title);
|
||||||
|
} else {
|
||||||
|
toast.error(res.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
toast.error("Gagal mendapatkan data tugas divisi, coba lagi nanti");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
getOneData();
|
||||||
|
}, [param.detail])
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LayoutNavbarNew back="" title={name} menu={
|
||||||
|
<ActionIcon
|
||||||
|
variant="light"
|
||||||
|
bg={WARNA.bgIcon}
|
||||||
|
size="lg"
|
||||||
|
radius="lg"
|
||||||
|
aria-label="Settings"
|
||||||
|
onClick={() => router.push("/task/update/1")}
|
||||||
|
>
|
||||||
|
<LuClipboardEdit size={20} color="white" />
|
||||||
|
</ActionIcon>
|
||||||
|
} />
|
||||||
|
)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user