From 16e62c7c09405a71ba324068b210fc3e46063926 Mon Sep 17 00:00:00 2001 From: amel Date: Mon, 28 Oct 2024 16:56:30 +0800 Subject: [PATCH] fix: fixing super admin Deskripsi: - tugas divisi - kegiatan - home - filter No Issues --- src/app/api/project/[id]/route.ts | 4 +- src/app/api/version-app/route.ts | 2 +- src/module/_global/view/view_filter.tsx | 27 ++-- src/module/home/ui/list_project.tsx | 15 +- src/module/home/ui/view_home.tsx | 14 +- .../position/ui/drawer_detail_position.tsx | 2 +- .../position/ui/drawer_list_position.tsx | 2 +- .../project/ui/add_detail_task_project.tsx | 96 ++++++++--- .../project/ui/create_date_end_task.tsx | 153 +++++++++++------- .../project/ui/edit_detail_task_project.tsx | 89 +++++++--- src/module/project/ui/edit_task_project.tsx | 2 +- src/module/task/ui/add_detail_task.tsx | 101 +++++++++--- src/module/task/ui/add_file_detail_task.tsx | 12 +- src/module/task/ui/add_member_detail_task.tsx | 12 +- src/module/task/ui/cancel_task.tsx | 10 +- src/module/task/ui/create_date_end_task.tsx | 123 +++++++++----- .../task/ui/detail_list_anggota_task.tsx | 12 +- src/module/task/ui/detail_list_file_task.tsx | 12 +- src/module/task/ui/detail_list_tugas_task.tsx | 74 +++++---- src/module/task/ui/detail_progress_task.tsx | 2 +- src/module/task/ui/edit_detail_task.tsx | 47 ++++-- src/module/task/ui/edit_task.tsx | 12 +- 22 files changed, 560 insertions(+), 263 deletions(-) diff --git a/src/app/api/project/[id]/route.ts b/src/app/api/project/[id]/route.ts index 1c114df..1685139 100644 --- a/src/app/api/project/[id]/route.ts +++ b/src/app/api/project/[id]/route.ts @@ -49,8 +49,8 @@ export async function GET(request: Request, context: { params: { id: string } }) const progress = Math.ceil((selesai / semua) * 100) allData = { - progress: progress, - lastUpdate: moment(dataProgress[0].updatedAt).format("DD MMMM YYYY"), + progress: (_.isNaN(progress)) ? 0 : progress, + lastUpdate: moment(dataProgress[0]?.updatedAt).format("DD MMMM YYYY"), } } else if (kategori == "task") { const dataProgress = await prisma.projectTask.findMany({ diff --git a/src/app/api/version-app/route.ts b/src/app/api/version-app/route.ts index 5b34bd1..789cbbd 100644 --- a/src/app/api/version-app/route.ts +++ b/src/app/api/version-app/route.ts @@ -2,7 +2,7 @@ import { NextResponse } from "next/server"; export async function GET(request: Request) { try { - return NextResponse.json({ success: true, version: "0.1.6", mode: "staging" }, { status: 200 }); + return NextResponse.json({ success: true, version: "0.1.7", mode: "staging" }, { status: 200 }); } catch (error) { console.error(error); return NextResponse.json({ success: false, version: "Gagal mendapatkan version, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 }); diff --git a/src/module/_global/view/view_filter.tsx b/src/module/_global/view/view_filter.tsx index b15fb72..4b54c24 100644 --- a/src/module/_global/view/view_filter.tsx +++ b/src/module/_global/view/view_filter.tsx @@ -1,15 +1,15 @@ 'use client' -import { Box, Group, Divider, Button, Text, Skeleton, rem } from "@mantine/core"; -import { useState } from "react"; -import { FaCheck } from "react-icons/fa6"; -import { WARNA } from "../fun/WARNA"; -import LayoutNavbarNew from "../layout/layout_navbar_new"; -import { useRouter, useSearchParams } from "next/navigation"; import { funGetAllGroup, IDataGroup } from "@/module/group"; -import { useShallowEffect } from "@mantine/hooks"; -import toast from "react-hot-toast"; import { useHookstate } from "@hookstate/core"; +import { Box, Button, Divider, Group, rem, Skeleton, Text } from "@mantine/core"; +import { useShallowEffect } from "@mantine/hooks"; +import { useRouter, useSearchParams } from "next/navigation"; +import { useState } from "react"; +import toast from "react-hot-toast"; +import { FaCheck } from "react-icons/fa6"; import { TEMA } from "../bin/val_global"; +import LayoutNavbarNew from "../layout/layout_navbar_new"; +import { funGetUserByCookies } from "@/module/auth"; export default function ViewFilter({ linkFilter }: { linkFilter: string }) { const [selectedFilter, setSelectedFilter] = useState(''); @@ -38,8 +38,17 @@ export default function ViewFilter({ linkFilter }: { linkFilter: string }) { } } + async function dataUser() { + const user = await funGetUserByCookies() + setSelectedFilter(user.idGroup) + } + useShallowEffect(() => { - setSelectedFilter(group) + if (group == "null" || group == "undefined" || group == '') { + dataUser() + } else { + setSelectedFilter(group) + } }, [group]); diff --git a/src/module/home/ui/list_project.tsx b/src/module/home/ui/list_project.tsx index 7d5957f..e1c8767 100644 --- a/src/module/home/ui/list_project.tsx +++ b/src/module/home/ui/list_project.tsx @@ -1,17 +1,15 @@ 'use client' -import { TEMA, WARNA } from "@/module/_global"; +import { TEMA } from "@/module/_global"; +import { useHookstate } from "@hookstate/core"; import { Carousel } from "@mantine/carousel"; -import { Box, Card, Flex, Title, Text, Progress, Stack, Skeleton, ActionIcon } from "@mantine/core"; +import { Box, Card, Flex, Progress, Skeleton, Stack, Text, Title } from "@mantine/core"; import { useMediaQuery, useShallowEffect } from "@mantine/hooks"; +import _ from "lodash"; import { useRouter } from "next/navigation"; import { useState } from "react"; import toast from "react-hot-toast"; import { funGetHome } from "../lib/api_home"; import { IDataHomeKegiatan } from "../lib/type_home"; -import _ from "lodash"; -import { useHookstate } from "@hookstate/core"; -import { MdMoreVert } from "react-icons/md"; -import { IoIosArrowDropright } from "react-icons/io"; export default function ListProjects() { const router = useRouter() @@ -24,7 +22,6 @@ export default function ListProjects() { setData([]); setLoading(true); const response = await funGetHome('?cat=kegiatan') - if (response.success) { setData(response.data) } else { @@ -78,8 +75,8 @@ export default function ListProjects() { - - {v.progress}% + + {_.isNull(v.progress) ? 0 : v.progress}% {v.createdAt} diff --git a/src/module/home/ui/view_home.tsx b/src/module/home/ui/view_home.tsx index 3879290..24e239a 100644 --- a/src/module/home/ui/view_home.tsx +++ b/src/module/home/ui/view_home.tsx @@ -1,16 +1,14 @@ "use client" -import { ReloadButtonTop } from '@/module/_global'; import { Box, Stack } from '@mantine/core'; -import React from 'react'; import Carosole from './carosole'; -import Features from './features'; -import ListProjects from './list_project'; -import ListDivisi from './list_divisi'; -import ListDiscussion from './list_discussion'; -import ListEventHome from './list_event'; -import ChartProgressHome from './chart_progress_tugas'; import ChartDocumentHome from './chart_document'; +import ChartProgressHome from './chart_progress_tugas'; +import Features from './features'; import HeaderHome from './header_home'; +import ListDiscussion from './list_discussion'; +import ListDivisi from './list_divisi'; +import ListEventHome from './list_event'; +import ListProjects from './list_project'; export default function ViewHome() { diff --git a/src/module/position/ui/drawer_detail_position.tsx b/src/module/position/ui/drawer_detail_position.tsx index d81ad4e..aff4f6b 100644 --- a/src/module/position/ui/drawer_detail_position.tsx +++ b/src/module/position/ui/drawer_detail_position.tsx @@ -207,7 +207,7 @@ export default function DrawerDetailPosition({ onUpdated, id, isActive }: { onChange={(e) => { onValidation('name', e.target.value) }} error={ touched.name && - (data.name == "" ? "Error! harus memasukkan Nama Jabatan" : + (data.name == "" ? "Nama Jabatan Tidak Boleh Kosong" : data.name.length < 3 ? "Masukkan Minimal 3 karakter" : "" ) } diff --git a/src/module/position/ui/drawer_list_position.tsx b/src/module/position/ui/drawer_list_position.tsx index 390d685..100de23 100644 --- a/src/module/position/ui/drawer_list_position.tsx +++ b/src/module/position/ui/drawer_list_position.tsx @@ -202,7 +202,7 @@ export default function DrawerListPosition({ onCreated }: { onCreated: (val: boo placeholder="Nama Jabatan" error={ touched.name && - (listData.name == "" ? "Error! harus memasukkan Nama Jabatan" : + (listData.name == "" ? "Nama Jabatan Tidak Boleh Kosong" : listData.name.length < 3 ? "Masukkan Minimal 3 karakter" : "" ) } diff --git a/src/module/project/ui/add_detail_task_project.tsx b/src/module/project/ui/add_detail_task_project.tsx index 3860665..0308454 100644 --- a/src/module/project/ui/add_detail_task_project.tsx +++ b/src/module/project/ui/add_detail_task_project.tsx @@ -2,7 +2,7 @@ import { keyWibu, LayoutNavbarNew, TEMA } from '@/module/_global'; import LayoutModal from '@/module/_global/layout/layout_modal'; import { useHookstate } from '@hookstate/core'; -import { Box, Button, Group, rem, SimpleGrid, Stack, Text, TextInput } from '@mantine/core'; +import { Box, Button, Flex, Group, rem, SimpleGrid, Stack, Text, TextInput } from '@mantine/core'; import { DatePicker } from '@mantine/dates'; import moment from 'moment'; import { useParams, useRouter } from 'next/navigation'; @@ -10,6 +10,7 @@ import { useState } from 'react'; import toast from 'react-hot-toast'; import { useWibuRealtime } from 'wibu-realtime'; import { funCreateDetailProject } from '../lib/api_project'; +import { useShallowEffect } from '@mantine/hooks'; export default function AddDetailTaskProject() { const [value, setValue] = useState<[Date | null, Date | null]>([null, null]); @@ -19,24 +20,16 @@ export default function AddDetailTaskProject() { const [loadingModal, setLoadingModal] = useState(false) const param = useParams<{ id: string }>() const tema = useHookstate(TEMA) + const [acuan, setAcuan] = useState(false) const [touched, setTouched] = useState({ - name: false, + title: false, + date: false }); const [dataRealTime, setDataRealtime] = useWibuRealtime({ WIBU_REALTIME_TOKEN: keyWibu, project: "sdm" }) - function onVerification() { - if (value[0] == null || value[1] == null) - return toast.error("Error! harus memilih tanggal") - - if (name == "") - return toast.error("Error! harus memasukkan judul tugas") - - setOpenModal(true) - } - async function onSubmit() { try { setLoadingModal(true) @@ -65,9 +58,59 @@ export default function AddDetailTaskProject() { } } + function onCheck() { + const cek = checkAll() + if (!cek) + return false + setOpenModal(true) + } + + function checkAll() { + let nilai = true + + if (name == "") { + setTouched(touched => ({ ...touched, title: true })) + nilai = false + } + + if (value[0] == null || value[1] == null) { + setTouched(touched => ({ ...touched, date: true })) + nilai = false + } + + return nilai + + } + + function onValidation(kategori: string, val: string) { + if (kategori == 'title') { + setName(val) + if (val === "") { + setTouched({ ...touched, title: true }) + } else { + setTouched({ ...touched, title: false }) + } + } else if (kategori == 'date') { + const array = val.split(",") + if (array[0] == '' || array[1] == '') { + setTouched({ ...touched, date: true }) + } else { + setTouched({ ...touched, date: false }) + } + } + } + + useShallowEffect(() => { + if (acuan) { + onValidation('date', String(value)) + } else { + setAcuan(true) + } + }, [value]) + return ( - + - Tanggal Mulai + + Tanggal Mulai * + - Tanggal Berakhir + + Tanggal Berakhir * + + { + (touched && touched.date) + ? Tanggal Tidak Boleh Kosong + : <> + } { - setName(e.target.value) - setTouched({ ...touched, name: false }) + onValidation('title', e.target.value) }} - onBlur={() => setTouched({ ...touched, name: true })} error={ - touched.name && ( - name == "" ? "Judul Tidak Boleh Kosong" : null + touched.title && ( + name == "" ? "Judul Tugas Tidak Boleh Kosong" : null ) } /> @@ -145,7 +195,7 @@ export default function AddDetailTaskProject() { size="lg" radius={30} fullWidth - onClick={() => { onVerification() }} + onClick={() => { onCheck() }} > Simpan diff --git a/src/module/project/ui/create_date_end_task.tsx b/src/module/project/ui/create_date_end_task.tsx index d5b6155..116f510 100644 --- a/src/module/project/ui/create_date_end_task.tsx +++ b/src/module/project/ui/create_date_end_task.tsx @@ -1,36 +1,24 @@ "use client"; import { LayoutNavbarNew, TEMA } from "@/module/_global"; -import { - ActionIcon, - Avatar, - Box, - Button, - Flex, - Group, - Input, - rem, - SimpleGrid, - Stack, - Text, - TextInput, -} from "@mantine/core"; -import React, { useState } from "react"; -import { DatePicker } from "@mantine/dates"; -import { useRouter } from "next/navigation"; -import toast from "react-hot-toast"; -import moment from "moment"; -import { IFormDateProject } from "../lib/type_project"; -import { HiChevronLeft } from "react-icons/hi2"; import { useHookstate } from "@hookstate/core"; +import { ActionIcon, Box, Button, Flex, Group, rem, SimpleGrid, Stack, Text, TextInput } from "@mantine/core"; +import { DatePicker } from "@mantine/dates"; +import moment from "moment"; +import { useState } from "react"; +import toast from "react-hot-toast"; +import { HiChevronLeft } from "react-icons/hi2"; +import { IFormDateProject } from "../lib/type_project"; +import { useShallowEffect } from "@mantine/hooks"; -export default function ViewDateEndTask({ onClose, onSet }: {onClose: (val: boolean) => void, onSet: (val: IFormDateProject) => void }) { +export default function ViewDateEndTask({ onClose, onSet }: { onClose: (val: boolean) => void, onSet: (val: IFormDateProject) => void }) { const [value, setValue] = useState<[Date | null, Date | null]>([null, null]); - const router = useRouter() const [title, setTitle] = useState("") const tema = useHookstate(TEMA) + const [acuan, setAcuan] = useState(false) const [touched, setTouched] = useState({ - title: false + title: false, + date: false }); function onSubmit() { @@ -40,16 +28,64 @@ export default function ViewDateEndTask({ onClose, onSet }: {onClose: (val: bool if (title == "") return toast.error("Error! harus memasukkan judul tugas") - onSet( - { - dateStart: value[0], - dateEnd: value[1], - title: title - } - ) + onSet({ + dateStart: value[0], + dateEnd: value[1], + title: title + }) + } + + function onCheck() { + const cek = checkAll() + if (!cek) + return false + onSubmit() + } + + function checkAll() { + let nilai = true + + if (title == "") { + setTouched(touched => ({ ...touched, title: true })) + nilai = false + } + + if (value[0] == null || value[1] == null) { + setTouched(touched => ({ ...touched, date: true })) + nilai = false + } + + return nilai } + + function onValidation(kategori: string, val: string) { + if (kategori == 'title') { + setTitle(val) + if (val === "") { + setTouched({ ...touched, title: true }) + } else { + setTouched({ ...touched, title: false }) + } + } else if (kategori == 'date') { + const array = val.split(",") + if (array[0] == '' || array[1] == '') { + setTouched({ ...touched, date: true }) + } else { + setTouched({ ...touched, date: false }) + } + } + } + + useShallowEffect(() => { + if (acuan) { + onValidation('date', String(value)) + } else { + setAcuan(true) + } + }, [value]) + return ( - Tanggal Mulai + + Tanggal Mulai * + - Tanggal Berakhir + + Tanggal Berakhir * + + { + (touched && touched.date) + ? Tanggal Tidak Boleh Kosong + : <> + } { - setTitle(e.target.value) - setTouched({ ...touched, title: false }) + onValidation('title', e.target.value) }} - onBlur={() => setTouched({ ...touched, title: true })} error={ touched.title && ( - title == "" ? "Judul Tahapan Tidak Boleh Kosong" : null + title == "" ? "Judul Tugas Tidak Boleh Kosong" : null ) } /> - - - + + + ); } diff --git a/src/module/project/ui/edit_detail_task_project.tsx b/src/module/project/ui/edit_detail_task_project.tsx index 5421bb8..7bab401 100644 --- a/src/module/project/ui/edit_detail_task_project.tsx +++ b/src/module/project/ui/edit_detail_task_project.tsx @@ -1,15 +1,15 @@ "use client" -import { useParams, useRouter } from 'next/navigation'; -import React, { useState } from 'react'; -import toast from 'react-hot-toast'; -import { funEditDetailProject, funGetDetailProject } from '../lib/api_project'; -import moment from 'moment'; -import { useShallowEffect } from '@mantine/hooks'; -import { Box, Button, Group, Input, rem, SimpleGrid, Skeleton, Stack, Text, TextInput } from '@mantine/core'; import { LayoutNavbarNew, TEMA } from '@/module/_global'; -import { DatePicker } from '@mantine/dates'; import LayoutModal from '@/module/_global/layout/layout_modal'; import { useHookstate } from '@hookstate/core'; +import { Box, Button, Flex, Group, rem, SimpleGrid, Skeleton, Stack, Text, TextInput } from '@mantine/core'; +import { DatePicker } from '@mantine/dates'; +import { useShallowEffect } from '@mantine/hooks'; +import moment from 'moment'; +import { useParams, useRouter } from 'next/navigation'; +import { useState } from 'react'; +import toast from 'react-hot-toast'; +import { funEditDetailProject, funGetDetailProject } from '../lib/api_project'; export default function EditDetailTaskProject() { const [value, setValue] = useState<[Date | null, Date | null]>([null, null]); @@ -18,9 +18,11 @@ export default function EditDetailTaskProject() { const param = useParams<{ id: string }>() const [openModal, setOpenModal] = useState(false) const [loading, setLoading] = useState(true) + const [loadingModal, setLoadingModal] = useState(false) const tema = useHookstate(TEMA) const [touched, setTouched] = useState({ title: false, + date: false, }); const router = useRouter() @@ -32,6 +34,7 @@ export default function EditDetailTaskProject() { return toast.error("Error! harus memasukkan judul tugas") try { + setLoadingModal(true) const res = await funEditDetailProject(param.id, { title: name, dateStart: value[0], @@ -48,6 +51,9 @@ export default function EditDetailTaskProject() { } catch (error) { console.error(error); toast.error("Gagal edit detail tugas Kegiatan, coba lagi nanti"); + } finally { + setLoadingModal(false) + setOpenModal(false) } } @@ -78,6 +84,36 @@ export default function EditDetailTaskProject() { getOneData(); }, [param.id]) + function onCheck() { + if (Object.values(touched).some((v) => v == true)) + return false + setOpenModal(true) + } + + + function onValidation(kategori: string, val: string) { + if (kategori == 'title') { + setName(val) + if (val === "") { + setTouched({ ...touched, title: true }) + } else { + setTouched({ ...touched, title: false }) + } + } else if (kategori == 'date') { + const array = val.split(",") + if (array[0] == '' || array[1] == '') { + setTouched({ ...touched, date: true }) + } else { + setTouched({ ...touched, date: false }) + } + } + } + + + useShallowEffect(() => { + onValidation('date', String(value)) + }, [value]) + return ( @@ -103,7 +139,9 @@ export default function EditDetailTaskProject() { : <> - Tanggal Mulai + + Tanggal Mulai * + : <> - Tanggal Berakhir + + Tanggal Berakhir * + + { + (!loading && touched && touched.date) + ? Tanggal Tidak Boleh Kosong + : <> + } {loading ? @@ -144,16 +189,15 @@ export default function EditDetailTaskProject() { borderRadius: 10, }, }} - placeholder="Input Judul Tahapan" - label="Judul Tahapan" + placeholder="Input Judul Tugas" + label="Judul Tugas" required size="md" value={name} - onChange={(e) => { setName(e.target.value) }} - onBlur={() => setTouched({ ...touched, title: true })} + onChange={(e) => { onValidation('title', e.target.value) }} error={ touched.title && ( - name == "" ? "Judul Tahapan Tidak Boleh Kosong" : null + name == "" ? "Judul Tugas Tidak Boleh Kosong" : null ) } /> @@ -174,28 +218,21 @@ export default function EditDetailTaskProject() { size="lg" radius={30} fullWidth - onClick={() => { - if ( - name !== "" - ) { - setOpenModal(true) - } else { - toast.error("Judul Tidak Boleh Kosong") - } - }} + onClick={() => { onCheck() }} > Simpan } - setOpenModal(false)} + setOpenModal(false)} description="Apakah Anda yakin ingin mengubah data?" onYes={(val) => { if (val) { onSubmit() + } else { + setOpenModal(false) } - setOpenModal(false) }} /> ); diff --git a/src/module/project/ui/edit_task_project.tsx b/src/module/project/ui/edit_task_project.tsx index 58503b1..6b26687 100644 --- a/src/module/project/ui/edit_task_project.tsx +++ b/src/module/project/ui/edit_task_project.tsx @@ -7,8 +7,8 @@ import { useShallowEffect } from '@mantine/hooks'; import { useParams, useRouter } from 'next/navigation'; import { useState } from 'react'; import toast from 'react-hot-toast'; -import { funEditProject, funGetOneProjectById } from '../lib/api_project'; import { useWibuRealtime } from 'wibu-realtime'; +import { funEditProject, funGetOneProjectById } from '../lib/api_project'; export default function EditTaskProject() { const router = useRouter() diff --git a/src/module/task/ui/add_detail_task.tsx b/src/module/task/ui/add_detail_task.tsx index eea33f3..dead6ab 100644 --- a/src/module/task/ui/add_detail_task.tsx +++ b/src/module/task/ui/add_detail_task.tsx @@ -2,43 +2,61 @@ import { keyWibu, LayoutNavbarNew, TEMA } from "@/module/_global"; import LayoutModal from "@/module/_global/layout/layout_modal"; import { useHookstate } from "@hookstate/core"; -import { Box, Button, Group, rem, SimpleGrid, Stack, Text, TextInput } from "@mantine/core"; +import { Box, Button, Flex, Group, rem, SimpleGrid, Stack, Text, TextInput } from "@mantine/core"; import { DatePicker } from "@mantine/dates"; import moment from "moment"; import { useParams, useRouter } from "next/navigation"; import { useState } from "react"; import toast from "react-hot-toast"; -import { funCreateDetailTask } from "../lib/api_task"; import { useWibuRealtime } from "wibu-realtime"; +import { funCreateDetailTask } from "../lib/api_task"; +import { useShallowEffect } from "@mantine/hooks"; export default function AddDetailTask() { const [value, setValue] = useState<[Date | null, Date | null]>([null, null]); const router = useRouter() const [title, setTitle] = useState("") const [openModal, setOpenModal] = useState(false) + const [loadingModal, setLoadingModal] = useState(false) const param = useParams<{ id: string, detail: string }>() const tema = useHookstate(TEMA) + const [acuan, setAcuan] = useState(false) const [touched, setTouched] = useState({ title: false, + date: false }); const [dataRealTime, setDataRealtime] = useWibuRealtime({ WIBU_REALTIME_TOKEN: keyWibu, project: "sdm" }) - - function onVerification() { - if (value[0] == null || value[1] == null) - return toast.error("Error! harus memilih tanggal") - - if (title == "") - return toast.error("Error! harus memasukkan judul tugas") - + function onCheck() { + const cek = checkAll() + if (!cek) + return false setOpenModal(true) } + function checkAll() { + let nilai = true + + if (title == "") { + setTouched(touched => ({ ...touched, title: true })) + nilai = false + } + + if (value[0] == null || value[1] == null) { + setTouched(touched => ({ ...touched, date: true })) + nilai = false + } + + return nilai + + } + async function onSubmit() { try { + setLoadingModal(true) const res = await funCreateDetailTask(param.detail, { title, dateStart: (value[0] != null) ? value[0] : new Date, @@ -52,7 +70,6 @@ export default function AddDetailTask() { id: param.detail, }]) toast.success(res.message) - setOpenModal(false) router.push(`/division/${param.id}/task/${param.detail}`) } else { toast.error(res.message) @@ -60,10 +77,39 @@ export default function AddDetailTask() { } catch (error) { console.error(error) toast.error("Gagal menambahkan tugas, coba lagi nanti") + } finally { + setLoadingModal(false) + setOpenModal(false) } } + function onValidation(kategori: string, val: string) { + if (kategori == 'title') { + setTitle(val) + if (val === "") { + setTouched({ ...touched, title: true }) + } else { + setTouched({ ...touched, title: false }) + } + } else if (kategori == 'date') { + const array = val.split(",") + if (array[0] == '' || array[1] == '') { + setTouched({ ...touched, date: true }) + } else { + setTouched({ ...touched, date: false }) + } + } + } + + useShallowEffect(() => { + if (acuan) { + onValidation('date', String(value)) + } else { + setAcuan(true) + } + }, [value]) + return ( @@ -86,7 +132,9 @@ export default function AddDetailTask() { - Tanggal Mulai + + Tanggal Mulai * + - Tanggal Berakhir + + Tanggal Berakhir * + + { + (touched && touched.date) + ? Tanggal Tidak Boleh Kosong + : <> + } { - setTitle(e.target.value) - setTouched({ ...touched, title: false }) - } - } - onBlur={() => setTouched({ ...touched, title: true })} + onChange={(e) => { onValidation('title', e.target.value) }} error={ touched.title && ( - title == "" ? "Judul Tahapan Tidak Boleh Kosong" : null + title == "" ? "Judul Tugas Tidak Boleh Kosong" : null ) } /> @@ -146,19 +196,20 @@ export default function AddDetailTask() { size="lg" radius={30} fullWidth - onClick={() => { onVerification() }} + onClick={() => { onCheck() }} > Simpan - setOpenModal(false)} + setOpenModal(false)} description="Apakah Anda yakin ingin menambahkan tugas?" onYes={(val) => { if (val) { onSubmit() + } else { + setOpenModal(false) } - setOpenModal(false) }} /> ); diff --git a/src/module/task/ui/add_file_detail_task.tsx b/src/module/task/ui/add_file_detail_task.tsx index 72d09cb..cce9d78 100644 --- a/src/module/task/ui/add_file_detail_task.tsx +++ b/src/module/task/ui/add_file_detail_task.tsx @@ -10,15 +10,16 @@ import { useRef, useState } from "react"; import toast from "react-hot-toast"; import { FaTrash } from "react-icons/fa6"; import { IoIosArrowDropright } from "react-icons/io"; +import { useWibuRealtime } from "wibu-realtime"; import { funAddFileTask, funCekNamFileUploadTask } from "../lib/api_task"; import { IListFileTask } from "../lib/type_task"; import ResultsFile from "./results_file"; -import { useWibuRealtime } from "wibu-realtime"; export default function AddFileDetailTask() { const router = useRouter() const [openModal, setOpenModal] = useState(false) + const [loadingModal, setLoadingModal] = useState(false) const [fileForm, setFileForm] = useState([]) const [listFile, setListFile] = useState([]) const param = useParams<{ id: string, detail: string }>() @@ -57,6 +58,7 @@ export default function AddFileDetailTask() { async function onSubmit() { try { + setLoadingModal(true) const fd = new FormData(); for (let i = 0; i < fileForm.length; i++) { fd.append(`file${i}`, fileForm[i]); @@ -78,6 +80,9 @@ export default function AddFileDetailTask() { } catch (error) { console.error(error) toast.error("Gagal menambahkan tugas divisi, coba lagi nanti"); + } finally { + setLoadingModal(false) + setOpenModal(false) } } @@ -182,13 +187,14 @@ export default function AddFileDetailTask() { - setOpenModal(false)} + setOpenModal(false)} description="Apakah Anda yakin ingin menambahkan file?" onYes={(val) => { if (val) { onSubmit() + } else { + setOpenModal(false) } - setOpenModal(false) }} /> diff --git a/src/module/task/ui/add_member_detail_task.tsx b/src/module/task/ui/add_member_detail_task.tsx index a19b9f1..f95b546 100644 --- a/src/module/task/ui/add_member_detail_task.tsx +++ b/src/module/task/ui/add_member_detail_task.tsx @@ -12,9 +12,9 @@ import toast from "react-hot-toast"; import { FaCheck } from "react-icons/fa6"; import { HiMagnifyingGlass } from "react-icons/hi2"; import { IoArrowBackOutline, IoClose } from "react-icons/io5"; +import { useWibuRealtime } from "wibu-realtime"; import { funAddMemberTask, funGetTaskDivisionById } from "../lib/api_task"; import { IDataMemberTaskDivision } from "../lib/type_task"; -import { useWibuRealtime } from "wibu-realtime"; export default function AddMemberDetailTask() { const router = useRouter() @@ -25,6 +25,7 @@ export default function AddMemberDetailTask() { const [selectAll, setSelectAll] = useState(false) const [openModal, setOpenModal] = useState(false) const [loading, setLoading] = useState(true) + const [loadingModal, setLoadingModal] = useState(false) const [onClickSearch, setOnClickSearch] = useState(false) const [searchQuery, setSearchQuery] = useState('') const tema = useHookstate(TEMA) @@ -106,6 +107,7 @@ export default function AddMemberDetailTask() { async function onSubmit() { try { + setLoadingModal(true) const res = await funAddMemberTask(param.detail, { idDivision: param.id, member: selectedFiles }); if (res.success) { setDataRealtime([{ @@ -120,6 +122,9 @@ export default function AddMemberDetailTask() { } catch (error) { console.error(error) toast.error("Gagal menambahkan anggota, coba lagi nanti"); + } finally { + setLoadingModal(false) + setOpenModal(false) } } @@ -317,13 +322,14 @@ export default function AddMemberDetailTask() { - setOpenModal(false)} + setOpenModal(false)} description="Apakah Anda yakin ingin menambahkan anggota?" onYes={(val) => { if (val) { onSubmit() + } else { + setOpenModal(false) } - setOpenModal(false) }} /> ); diff --git a/src/module/task/ui/cancel_task.tsx b/src/module/task/ui/cancel_task.tsx index ac034bf..a460a41 100644 --- a/src/module/task/ui/cancel_task.tsx +++ b/src/module/task/ui/cancel_task.tsx @@ -14,6 +14,7 @@ export default function CancelTask() { const router = useRouter() const [alasan, setAlasan] = useState("") const [openModal, setOpenModal] = useState(false) + const [loadingModal, setLoadingModal] = useState(false) const tema = useHookstate(TEMA) const param = useParams<{ id: string, detail: string }>() const [touched, setTouched] = useState({ @@ -53,6 +54,7 @@ export default function CancelTask() { async function onSubmit() { try { + setLoadingModal(true) const res = await funCancelTask(param.detail, { reason: alasan }) if (res.success) { setDataRealtime([{ @@ -67,6 +69,9 @@ export default function CancelTask() { } catch (error) { console.error(error) toast.error("Gagal membatalkan tugas, coba lagi nanti") + } finally { + setLoadingModal(false) + setOpenModal(false) } } @@ -109,13 +114,14 @@ export default function CancelTask() { - setOpenModal(false)} + setOpenModal(false)} description="Apakah Anda yakin ingin membatalkan tugas ini? Pembatalan tugas bersifat permanen" onYes={(val) => { if (val) { onSubmit() + } else { + setOpenModal(false) } - setOpenModal(false) }} /> ); diff --git a/src/module/task/ui/create_date_end_task.tsx b/src/module/task/ui/create_date_end_task.tsx index f4f9ec7..613b58c 100644 --- a/src/module/task/ui/create_date_end_task.tsx +++ b/src/module/task/ui/create_date_end_task.tsx @@ -1,37 +1,24 @@ "use client"; import { LayoutNavbarNew, TEMA } from "@/module/_global"; -import { - ActionIcon, - Avatar, - Box, - Button, - Flex, - Group, - Input, - rem, - SimpleGrid, - Stack, - Text, - TextInput, -} from "@mantine/core"; -import React, { useState } from "react"; -import { DatePicker } from "@mantine/dates"; -import { useParams, useRouter } from "next/navigation"; -import toast from "react-hot-toast"; -import { IFormDateTask } from "../lib/type_task"; -import moment from "moment"; -import { HiChevronLeft } from "react-icons/hi2"; import { useHookstate } from "@hookstate/core"; +import { ActionIcon, Box, Button, Flex, Group, rem, SimpleGrid, Stack, Text, TextInput } from "@mantine/core"; +import { DatePicker } from "@mantine/dates"; +import { useShallowEffect } from "@mantine/hooks"; +import moment from "moment"; +import { useState } from "react"; +import toast from "react-hot-toast"; +import { HiChevronLeft } from "react-icons/hi2"; +import { IFormDateTask } from "../lib/type_task"; -export default function ViewDateEndTask({ onClose, onSet }: {onClose: (val: boolean) => void, onSet: (val: IFormDateTask) => void }) { +export default function ViewDateEndTask({ onClose, onSet }: { onClose: (val: boolean) => void, onSet: (val: IFormDateTask) => void }) { const [value, setValue] = useState<[Date | null, Date | null]>([null, null]); - const router = useRouter() - const param = useParams<{ id: string }>() const [title, setTitle] = useState("") + const [acuan, setAcuan] = useState(false) const tema = useHookstate(TEMA) const [touched, setTouched] = useState({ title: false, + date: false }); function onSubmit() { @@ -41,16 +28,65 @@ export default function ViewDateEndTask({ onClose, onSet }: {onClose: (val: bool if (title == "") return toast.error("Error! harus memasukkan judul tugas") - onSet( - { - dateStart: value[0], - dateEnd: value[1], - title: title - } - ) + onSet({ + dateStart: value[0], + dateEnd: value[1], + title: title + }) } + function onCheck() { + const cek = checkAll() + if (!cek) + return false + onSubmit() + } + + function checkAll() { + let nilai = true + + if (title == "") { + setTouched(touched => ({ ...touched, title: true })) + nilai = false + } + + if (value[0] == null || value[1] == null) { + setTouched(touched => ({ ...touched, date: true })) + nilai = false + } + + return nilai + + } + + + function onValidation(kategori: string, val: string) { + if (kategori == 'title') { + setTitle(val) + if (val === "") { + setTouched({ ...touched, title: true }) + } else { + setTouched({ ...touched, title: false }) + } + } else if (kategori == 'date') { + const array = val.split(",") + if (array[0] == '' || array[1] == '') { + setTouched({ ...touched, date: true }) + } else { + setTouched({ ...touched, date: false }) + } + } + } + + useShallowEffect(() => { + if (acuan) { + onValidation('date', String(value)) + } else { + setAcuan(true) + } + }, [value]) + return ( - Tanggal Mulai + + Tanggal Mulai * + - Tanggal Berakhir + + Tanggal Berakhir * + + { + (touched && touched.date) + ? Tanggal Tidak Boleh Kosong + : <> + } { - setTitle(e.target.value) - setTouched({ ...touched, title: false }) + onValidation('title', e.target.value) }} - onBlur={() => setTouched({ ...touched, title: true })} - error={touched.title && title == "" ? "Judul Tahapan Tidak Boleh Kosong" : null} + error={touched.title && title == "" ? "Judul Tugas Tidak Boleh Kosong" : null} /> @@ -133,7 +176,7 @@ export default function ViewDateEndTask({ onClose, onSet }: {onClose: (val: bool size="lg" radius={30} fullWidth - onClick={() => { onSubmit() }} + onClick={() => { onCheck() }} > Simpan diff --git a/src/module/task/ui/detail_list_anggota_task.tsx b/src/module/task/ui/detail_list_anggota_task.tsx index b461880..415f6c1 100644 --- a/src/module/task/ui/detail_list_anggota_task.tsx +++ b/src/module/task/ui/detail_list_anggota_task.tsx @@ -10,9 +10,9 @@ import { useState } from "react"; import toast from "react-hot-toast"; import { FaUser } from "react-icons/fa6"; import { IoIosCloseCircle } from "react-icons/io"; +import { useWibuRealtime } from "wibu-realtime"; import { funDeleteMemberTask, funGetTaskDivisionById } from "../lib/api_task"; import { IDataMemberTaskDivision } from "../lib/type_task"; -import { useWibuRealtime } from "wibu-realtime"; export default function ListAnggotaDetailTask() { @@ -21,6 +21,7 @@ export default function ListAnggotaDetailTask() { const param = useParams<{ id: string, detail: string }>() const [openDrawer, setOpenDrawer] = useState(false) const [isOpenModal, setOpenModal] = useState(false) + const [loadingModal, setLoadingModal] = useState(false) const [dataChoose, setDataChoose] = useState({ id: '', name: '' }) const router = useRouter() const roleLogin = useHookstate(globalRole) @@ -86,6 +87,7 @@ export default function ListAnggotaDetailTask() { async function onSubmit() { try { + setLoadingModal(true) const res = await funDeleteMemberTask(param.detail, { idUser: dataChoose.id }); if (res.success) { setDataRealtime([{ @@ -102,6 +104,9 @@ export default function ListAnggotaDetailTask() { } catch (error) { console.error(error); toast.error("Gagal menghapus anggota tugas divisi, coba lagi nanti"); + } finally { + setLoadingModal(false) + setOpenModal(false) } } @@ -201,13 +206,14 @@ export default function ListAnggotaDetailTask() { - setOpenModal(false)} + setOpenModal(false)} description="Apakah Anda yakin ingin mengeluarkan anggota?" onYes={(val) => { if (val) { onSubmit() + } else { + setOpenModal(false) } - setOpenModal(false) }} /> ) diff --git a/src/module/task/ui/detail_list_file_task.tsx b/src/module/task/ui/detail_list_file_task.tsx index 2bc5299..8182695 100644 --- a/src/module/task/ui/detail_list_file_task.tsx +++ b/src/module/task/ui/detail_list_file_task.tsx @@ -9,9 +9,9 @@ import { useState } from "react"; import toast from "react-hot-toast"; import { BsFileTextFill, BsFiletypeCsv, BsFiletypeHeic, BsFiletypeJpg, BsFiletypePdf, BsFiletypePng } from "react-icons/bs"; import { FaTrash } from "react-icons/fa6"; +import { useWibuRealtime } from "wibu-realtime"; import { funDeleteFileTask, funGetTaskDivisionById } from "../lib/api_task"; import { IDataFileTaskDivision } from "../lib/type_task"; -import { useWibuRealtime } from "wibu-realtime"; export default function ListFileDetailTask() { const [isData, setData] = useState([]) @@ -19,6 +19,7 @@ export default function ListFileDetailTask() { const param = useParams<{ id: string, detail: string }>() const [openDrawer, setOpenDrawer] = useState(false) const [isOpenModal, setOpenModal] = useState(false) + const [loadingModal, setLoadingModal] = useState(false) const [idData, setIdData] = useState('') const [idDataStorage, setIdDataStorage] = useState('') const [nameStorage, setNameStorage] = useState('') @@ -75,6 +76,7 @@ export default function ListFileDetailTask() { async function onDelete() { try { + setLoadingModal(true) const res = await funDeleteFileTask(idData); if (res.success) { setDataRealtime([{ @@ -92,6 +94,9 @@ export default function ListFileDetailTask() { } catch (error) { console.error(error); toast.error("Gagal menghapus file, coba lagi nanti"); + } finally { + setLoadingModal(false) + setOpenModal(false) } } @@ -207,13 +212,14 @@ export default function ListFileDetailTask() { - setOpenModal(false)} + setOpenModal(false)} description="Apakah Anda yakin ingin menghapus file ini? File yang dihapus tidak dapat dikembalikan" onYes={(val) => { if (val) { onDelete() + } else { + setOpenModal(false) } - setOpenModal(false) }} /> setOpenModalView(false)} file={idDataStorage} extension={isExtension} fitur='task' /> diff --git a/src/module/task/ui/detail_list_tugas_task.tsx b/src/module/task/ui/detail_list_tugas_task.tsx index ddca576..f3586b4 100644 --- a/src/module/task/ui/detail_list_tugas_task.tsx +++ b/src/module/task/ui/detail_list_tugas_task.tsx @@ -19,6 +19,7 @@ export default function ListTugasDetailTask() { const [openDrawer, setOpenDrawer] = useState(false) const [openDrawerStatus, setOpenDrawerStatus] = useState(false) const [isOpenModal, setOpenModal] = useState(false) + const [loadingHapus, setLoadingHapus] = useState(false) const [isData, setData] = useState([]) const [loading, setLoading] = useState(true) const param = useParams<{ id: string, detail: string }>() @@ -77,6 +78,7 @@ export default function ListTugasDetailTask() { async function onDelete() { try { + setLoadingHapus(true) const res = await funDeleteDetailTask(idData, { idProject: param.detail }); if (res.success) { setDataRealtime([{ @@ -94,6 +96,9 @@ export default function ListTugasDetailTask() { } catch (error) { console.error(error); toast.error("Gagal menghapus tugas divisi, coba lagi nanti"); + } finally { + setLoadingHapus(false) + setOpenModal(false) } } @@ -140,8 +145,9 @@ export default function ListTugasDetailTask() { style={{ borderRadius: 10, border: `1px solid ${"#D6D8F6"}`, - padding: 20 }} + pl={20} + pr={20} > { loading ? @@ -261,51 +267,49 @@ export default function ListTugasDetailTask() { - setOpenModal(false)} + setOpenModal(false)} description="Apakah Anda yakin ingin menghapus tugas ini?" onYes={(val) => { if (val) { onDelete() + } else { + setOpenModal(false) } - setOpenModal(false) }} /> setOpenDrawerStatus(false)}> - - { - valStatusDetailTask.map((item, index) => { - return ( - { onUpdateStatus(item.value) }}> - - - - {item.name} - - - - {statusData === item.value ? : ""} + { + valStatusDetailTask.map((item, index) => { + return ( + { onUpdateStatus(item.value) }}> + + + + {item.name} - - - - ) - }) - } - - + + + {statusData === item.value ? : ""} + + + + + ) + }) + } diff --git a/src/module/task/ui/detail_progress_task.tsx b/src/module/task/ui/detail_progress_task.tsx index 0609774..5aa840d 100644 --- a/src/module/task/ui/detail_progress_task.tsx +++ b/src/module/task/ui/detail_progress_task.tsx @@ -90,7 +90,7 @@ export default function ProgressDetailTask() { return ( {loading ? "" : - reason !== null ? + (reason !== null && reason != "") ? ( () const [openModal, setOpenModal] = useState(false) const [loading, setLoading] = useState(true) + const [loadingModal, setLoadingModal] = useState(false) const [idTugas, setIdTugas] = useState("") const tema = useHookstate(TEMA) const [touched, setTouched] = useState({ title: false, + date: false }); async function onSubmit() { @@ -33,6 +35,7 @@ export default function EditDetailTask() { return toast.error("Error! harus memasukkan judul tugas") try { + setLoadingModal(true) const res = await funEditDetailTask(param.detail, { title: title, dateStart: value[0], @@ -48,6 +51,9 @@ export default function EditDetailTask() { } catch (error) { console.error(error); toast.error("Gagal edit detail tugas divisi, coba lagi nanti"); + } finally { + setOpenModal(false) + setLoadingModal(false) } } @@ -94,9 +100,22 @@ export default function EditDetailTask() { } else { setTouched({ ...touched, title: false }) } + } else if (kategori == 'date') { + const array = val.split(",") + if (array[0] == '' || array[1] == '') { + setTouched({ ...touched, date: true }) + } else { + setTouched({ ...touched, date: false }) + } } } + + useShallowEffect(() => { + onValidation('date', String(value)) + }, [value]) + + return ( @@ -122,7 +141,9 @@ export default function EditDetailTask() { : <> - Tanggal Mulai + + Tanggal Mulai * + : <> - Tanggal Berakhir + + Tanggal Berakhir * + + { + (!loading && touched && touched.date) + ? Tanggal Tidak Boleh Kosong + : <> + } + {loading ? @@ -163,15 +192,14 @@ export default function EditDetailTask() { borderRadius: 10, }, }} - label={"Judul Tahapan"} + label={"Judul Tugas"} required - placeholder="Input Judul Tahapan" + placeholder="Input Judul Tugas" size="md" value={title} error={ touched.title && - (title == "" ? "Error! harus memasukkan Judul Tahapan" : "" - ) + (title == "" ? "Judul Tugas Tidak Boleh Kosong" : "") } onChange={(e) => { onValidation('title', e.target.value) @@ -201,13 +229,14 @@ export default function EditDetailTask() { } - setOpenModal(false)} + setOpenModal(false)} description="Apakah Anda yakin ingin mengubah data?" onYes={(val) => { if (val) { onSubmit() + } else { + setOpenModal(false) } - setOpenModal(false) }} /> ); diff --git a/src/module/task/ui/edit_task.tsx b/src/module/task/ui/edit_task.tsx index fe56537..957f508 100644 --- a/src/module/task/ui/edit_task.tsx +++ b/src/module/task/ui/edit_task.tsx @@ -7,14 +7,15 @@ import { useShallowEffect } from "@mantine/hooks"; import { useParams, useRouter } from "next/navigation"; import { useState } from "react"; import toast from "react-hot-toast"; -import { funEditTask, funGetTaskDivisionById } from "../lib/api_task"; import { useWibuRealtime } from "wibu-realtime"; +import { funEditTask, funGetTaskDivisionById } from "../lib/api_task"; export default function EditTask() { const router = useRouter() const [title, setTitle] = useState("") const [openModal, setOpenModal] = useState(false) + const [loadingModal, setLoadingModal] = useState(false) const param = useParams<{ id: string, detail: string }>() const [loading, setLoading] = useState(true) const tema = useHookstate(TEMA) @@ -45,6 +46,7 @@ export default function EditTask() { async function onSubmit() { try { + setLoadingModal(true) const res = await funEditTask(param.detail, { title }) if (res.success) { setDataRealtime([{ @@ -59,6 +61,9 @@ export default function EditTask() { } catch (error) { console.error(error) toast.error("Gagal mengedit tugas, coba lagi nanti") + } finally { + setLoadingModal(false) + setOpenModal(false) } } @@ -139,13 +144,14 @@ export default function EditTask() { - setOpenModal(false)} + setOpenModal(false)} description="Apakah Anda yakin ingin mengedit tugas ini?" onYes={(val) => { if (val) { onSubmit() + } else { + setOpenModal(false) } - setOpenModal(false) }} /> );