upd: detail task
Deskripsi: - detail task divisi - folder manager No Issues
This commit is contained in:
@@ -1,7 +1,12 @@
|
||||
import ViewDateEndTask from "./ui/create_date_end_task";
|
||||
import CreateTask from "./ui/create_task";
|
||||
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 NavbarDetailDivisionTask from "./ui/navbar_detail_division_task";
|
||||
import NavbarDivisionTask from "./ui/navbar_division_task";
|
||||
import TabsDivisionTask from "./ui/tabs_division_task";
|
||||
|
||||
@@ -10,4 +15,9 @@ export { TabsDivisionTask }
|
||||
export { CreateTask }
|
||||
export { ViewDateEndTask }
|
||||
export { CreateUsersProject }
|
||||
export { FileSave }
|
||||
export { FileSave }
|
||||
export { NavbarDetailDivisionTask }
|
||||
export { ListTugasDetailTask }
|
||||
export { ProgressDetailTask }
|
||||
export { ListFileDetailTask }
|
||||
export { ListAnggotaDetailTask }
|
||||
@@ -18,4 +18,9 @@ export const funCreateTask = async (data: IFormTaskDivision) => {
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
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);
|
||||
}
|
||||
@@ -31,4 +31,25 @@ export interface IFormTaskDivision {
|
||||
export interface IListFileTask {
|
||||
name: 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>
|
||||
)
|
||||
}
|
||||
76
src/module/task/ui/detail_progress_task.tsx
Normal file
76
src/module/task/ui/detail_progress_task.tsx
Normal file
@@ -0,0 +1,76 @@
|
||||
'use client'
|
||||
import { WARNA } from "@/module/_global";
|
||||
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 { funGetTaskDivisionById } from "../lib/api_task";
|
||||
import { useState } from "react";
|
||||
|
||||
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 (
|
||||
<Box mt={10}>
|
||||
<Box
|
||||
p={20}
|
||||
bg={"#DCEED8"}
|
||||
style={{
|
||||
borderRadius: 10,
|
||||
}}
|
||||
>
|
||||
<Grid gutter={"lg"}>
|
||||
<Grid.Col span={3}>
|
||||
<ActionIcon
|
||||
variant="gradient"
|
||||
size={68}
|
||||
aria-label="Gradient action icon"
|
||||
radius={100}
|
||||
gradient={{ from: "#DFDA7C", to: "#F2AF46", deg: 174 }}
|
||||
>
|
||||
<HiMiniPresentationChartBar size={35} color={WARNA.biruTua} />
|
||||
</ActionIcon>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={9}>
|
||||
<Box>
|
||||
<Text>Kemajuan Proyek {valProgress}%</Text>
|
||||
<Progress
|
||||
style={{
|
||||
border: `1px solid ${"#BDBDBD"}`,
|
||||
}}
|
||||
w={"100%"}
|
||||
color="#FCAA4B"
|
||||
radius="md"
|
||||
size="xl"
|
||||
value={valProgress}
|
||||
/>
|
||||
<Text>{valLastUpdate}</Text>
|
||||
</Box>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
@@ -136,7 +136,7 @@ export default function ListDivisionTask() {
|
||||
{isData.map((v, i) => {
|
||||
return (
|
||||
<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>
|
||||
<Center>
|
||||
<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