diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 5e5e3ef..eba8a9d 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -259,8 +259,8 @@ model ProjectTaskDetail { ProjectTask ProjectTask @relation(fields: [idTask], references: [id]) idTask String date DateTime @db.Date - timeStart DateTime? @db.Time() - timeEnd DateTime? @db.Time() + timeStart DateTime? @db.Time() + timeEnd DateTime? @db.Time() isActive Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@ -352,6 +352,19 @@ model DivisionProjectTask { isActive Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt + DivisionProjectTaskDetail DivisionProjectTaskDetail[] +} + +model DivisionProjectTaskDetail { + id String @id @default(cuid()) + DivisionProjectTask DivisionProjectTask @relation(fields: [idTask], references: [id]) + idTask String + date DateTime @db.Date + timeStart DateTime? @db.Time() + timeEnd DateTime? @db.Time() + isActive Boolean @default(true) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt } model DivisionProjectMember { diff --git a/src/app/api/mobile/project/detail/[id]/route.ts b/src/app/api/mobile/project/detail/[id]/route.ts index 8a550da..22c7b94 100644 --- a/src/app/api/mobile/project/detail/[id]/route.ts +++ b/src/app/api/mobile/project/detail/[id]/route.ts @@ -171,12 +171,14 @@ export async function GET(request: Request, context: { params: { id: string } }) const { id } = context.params; const { searchParams } = new URL(request.url); const user = searchParams.get("user"); + const kategori = searchParams.get("cat"); const userMobile = await funGetUserById({ id: String(user) }) if (userMobile.id == "null" || userMobile.id == undefined || userMobile.id == "") { return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 200 }); } + let dataFix const data = await prisma.projectTask.findUnique({ where: { id: String(id), @@ -195,7 +197,29 @@ export async function GET(request: Request, context: { params: { id: string } }) ); } - return NextResponse.json({ success: true, message: "Detail kegiatan berhasil ditemukan", data: fixData }, { status: 200 }); + if (kategori == "detailTask") { + const dataDetail = await prisma.projectTaskDetail.findMany({ + where: { + idTask: String(id) + }, + orderBy: { + date: "asc" + } + }) + + const dataDetailFix = dataDetail.map((data: any) => ({ + ...data, + date: moment(data?.date).format('DD-MM-YYYY'), + timeStart: data.timeStart == null ? "" : moment.utc(data.timeStart).format("HH:mm"), + timeEnd: data.timeEnd == null ? "" : moment.utc(data.timeEnd).format("HH:mm") + })) + + dataFix = dataDetailFix + } else { + dataFix = fixData + } + + return NextResponse.json({ success: true, message: "Detail kegiatan berhasil ditemukan", data: dataFix }, { status: 200 }); } catch (error) { console.error(error); return NextResponse.json({ success: false, message: "Gagal mendapatkan kegiatan, coba lagi nanti (error: 500)", reason: (error as Error).message, }, { status: 500 }); diff --git a/src/app/api/project/[id]/route.ts b/src/app/api/project/[id]/route.ts index 0b687e7..f74afcb 100644 --- a/src/app/api/project/[id]/route.ts +++ b/src/app/api/project/[id]/route.ts @@ -197,10 +197,10 @@ export async function POST(request: Request, context: { params: { id: string } } ...v, idTask: dataCreate.id, date: new Date(v.date), - timeStart: new Date(new Date('1970-01-01 ' + v.timeStart).getTime() - (new Date('1970-01-01 ' + v.timeStart).getTimezoneOffset() * 60000)).toISOString(), - timeEnd: new Date(new Date('1970-01-01 ' + v.timeEnd).getTime() - (new Date('1970-01-01 ' + v.timeEnd).getTimezoneOffset() * 60000)).toISOString(), + timeStart: v.timeStart == null ? null : new Date(new Date('1970-01-01 ' + v.timeStart).getTime() - (new Date('1970-01-01 ' + v.timeStart).getTimezoneOffset() * 60000)).toISOString(), + timeEnd: v.timeEnd == null ? null : new Date(new Date('1970-01-01 ' + v.timeEnd).getTime() - (new Date('1970-01-01 ' + v.timeEnd).getTimezoneOffset() * 60000)).toISOString(), })) - + const dataDetailCreate = await prisma.projectTaskDetail.createMany({ data: dataDetailFix }) diff --git a/src/app/api/project/detail/[id]/route.ts b/src/app/api/project/detail/[id]/route.ts index 1cc6f2f..d29ed5e 100644 --- a/src/app/api/project/detail/[id]/route.ts +++ b/src/app/api/project/detail/[id]/route.ts @@ -261,26 +261,24 @@ export async function POST(request: Request, context: { params: { id: string } } } }) - if (moment(dataTaskLama.dateStart).format('YYYY-MM-DD') != dateStart || moment(dataTaskLama.dateEnd).format('YYYY-MM-DD') != dateEnd) { - const dataDetailDelete = await prisma.projectTaskDetail.deleteMany({ - where: { - idTask: id - } - }) - - if (dataDetail.length > 0) { - const dataDetailFix = dataDetail.map((v: any) => ({ - ...v, - idTask: id, - date: new Date(v.date), - timeStart: new Date(new Date('1970-01-01 ' + v.timeStart).getTime() - (new Date('1970-01-01 ' + v.timeStart).getTimezoneOffset() * 60000)).toISOString(), - timeEnd: new Date(new Date('1970-01-01 ' + v.timeEnd).getTime() - (new Date('1970-01-01 ' + v.timeEnd).getTimezoneOffset() * 60000)).toISOString(), - })) - - const dataDetailCreate = await prisma.projectTaskDetail.createMany({ - data: dataDetailFix - }) + const dataDetailDelete = await prisma.projectTaskDetail.deleteMany({ + where: { + idTask: id } + }) + + if (dataDetail.length > 0) { + const dataDetailFix = dataDetail.map((v: any) => ({ + ...v, + idTask: id, + date: new Date(v.date), + timeStart: v.timeStart == null ? null : new Date(new Date('1970-01-01 ' + v.timeStart).getTime() - (new Date('1970-01-01 ' + v.timeStart).getTimezoneOffset() * 60000)).toISOString(), + timeEnd: v.timeEnd == null ? null : new Date(new Date('1970-01-01 ' + v.timeEnd).getTime() - (new Date('1970-01-01 ' + v.timeEnd).getTimezoneOffset() * 60000)).toISOString(), + })) + + const dataDetailCreate = await prisma.projectTaskDetail.createMany({ + data: dataDetailFix + }) } // create log user diff --git a/src/app/api/project/route.ts b/src/app/api/project/route.ts index ee2a96b..d4e6652 100644 --- a/src/app/api/project/route.ts +++ b/src/app/api/project/route.ts @@ -169,15 +169,34 @@ export async function POST(request: Request) { if (task.length > 0) { const dataProject = task.map((v: any) => ({ - ..._.omit(v, ["dateStart", "dateEnd", "name"]), + ..._.omit(v, ["dateStart", "dateEnd", "name", "dataDetail"]), idProject: data.id, title: v.title, dateStart: new Date(v.dateStart), dateEnd: new Date(v.dateEnd), })) - const insertTask = await prisma.projectTask.createMany({ - data: dataProject + let dataDetailFix = [] + + for (let i = 0; i < dataProject.length; i++) { + const insertTask = await prisma.projectTask.create({ + data: dataProject[i], + select:{ + id: true + } + }) + const dataDetail = task[i].dataDetail.map((v: any) => ({ + ...v, + idTask: insertTask.id, + date: new Date(v.date), + timeStart: v.timeStart == null ? null : new Date(new Date('1970-01-01 ' + v.timeStart).getTime() - (new Date('1970-01-01 ' + v.timeStart).getTimezoneOffset() * 60000)).toISOString(), + timeEnd: v.timeEnd == null ? null : new Date(new Date('1970-01-01 ' + v.timeEnd).getTime() - (new Date('1970-01-01 ' + v.timeEnd).getTimezoneOffset() * 60000)).toISOString(), + })) + dataDetailFix.push(...dataDetail) + } + + const insertDetail = await prisma.projectTaskDetail.createMany({ + data: dataDetailFix }) } diff --git a/src/app/api/task/[id]/route.ts b/src/app/api/task/[id]/route.ts index dbc2ef1..7ef6090 100644 --- a/src/app/api/task/[id]/route.ts +++ b/src/app/api/task/[id]/route.ts @@ -183,7 +183,8 @@ export async function POST(request: Request, context: { params: { id: string } } } const { id } = context.params; - const { title, dateStart, dateEnd, idDivision } = (await request.json()); + const { title, dateStart, dateEnd, idDivision, dataDetail } = (await request.json()); + const data = await prisma.divisionProject.count({ where: { id: id, @@ -213,6 +214,20 @@ export async function POST(request: Request, context: { params: { id: string } } } }); + if(dataDetail.length>0){ + const dataDetailFix = dataDetail.map((v: any) => ({ + ...v, + idTask: create.id, + date: new Date(v.date), + timeStart: v.timeStart == null ? null : new Date(new Date('1970-01-01 ' + v.timeStart).getTime() - (new Date('1970-01-01 ' + v.timeStart).getTimezoneOffset() * 60000)).toISOString(), + timeEnd: v.timeEnd == null ? null : new Date(new Date('1970-01-01 ' + v.timeEnd).getTime() - (new Date('1970-01-01 ' + v.timeEnd).getTimezoneOffset() * 60000)).toISOString(), + })) + + const dataDetailCreate = await prisma.divisionProjectTaskDetail.createMany({ + data: dataDetailFix + }) + } + // const cek progress const dataTask = await prisma.divisionProjectTask.findMany({ where: { diff --git a/src/app/api/task/detail/[id]/route.ts b/src/app/api/task/detail/[id]/route.ts index ddaa1f0..7a55930 100644 --- a/src/app/api/task/detail/[id]/route.ts +++ b/src/app/api/task/detail/[id]/route.ts @@ -2,6 +2,7 @@ import { prisma } from "@/module/_global"; import { funGetUserByCookies } from "@/module/auth"; import { createLogUser } from "@/module/user"; import _ from "lodash"; +import moment from "moment"; import { NextResponse } from "next/server"; @@ -155,12 +156,15 @@ export async function PUT(request: Request, context: { params: { id: string } }) export async function GET(request: Request, context: { params: { id: string } }) { try { const { id } = context.params; + const { searchParams } = new URL(request.url); + const kategori = searchParams.get("cat"); const user = await funGetUserByCookies() if (user.id == undefined) { return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 }); } + let dataFix const data = await prisma.divisionProjectTask.findUnique({ where: { id: String(id), @@ -172,7 +176,28 @@ export async function GET(request: Request, context: { params: { id: string } }) return NextResponse.json({ success: false, message: "Gagal mendapatkan detail tugas, data tidak ditemukan", }, { status: 404 }); } - return NextResponse.json({ success: true, message: "Berhasil mendapatkan detail tugas divisi", data }, { status: 200 }); + if (kategori == "detailTask") { + const dataDetail = await prisma.divisionProjectTaskDetail.findMany({ + where: { + idTask: String(id) + }, + orderBy: { + date: "asc" + } + }) + + const dataDetailFix = dataDetail.map((data: any) => ({ + ...data, + timeStart: moment.utc(data.timeStart).format("HH:mm"), + timeEnd: moment.utc(data.timeEnd).format("HH:mm") + })) + + dataFix = dataDetailFix + } else { + dataFix = data + } + + return NextResponse.json({ success: true, message: "Berhasil mendapatkan detail tugas divisi", data: dataFix }, { status: 200 }); } catch (error) { @@ -192,7 +217,7 @@ export async function POST(request: Request, context: { params: { id: string } } } const { id } = context.params; - const { title, dateStart, dateEnd } = (await request.json()); + const { title, dateStart, dateEnd, dataDetail } = (await request.json()); const data = await prisma.divisionProjectTask.count({ where: { id: id, @@ -220,6 +245,26 @@ export async function POST(request: Request, context: { params: { id: string } } }, }); + const dataDetailDelete = await prisma.divisionProjectTaskDetail.deleteMany({ + where: { + idTask: id + } + }) + + if (dataDetail.length > 0) { + const dataDetailFix = dataDetail.map((v: any) => ({ + ...v, + idTask: id, + date: new Date(v.date), + timeStart: v.timeStart == null ? null : new Date(new Date('1970-01-01 ' + v.timeStart).getTime() - (new Date('1970-01-01 ' + v.timeStart).getTimezoneOffset() * 60000)).toISOString(), + timeEnd: v.timeEnd == null ? null : new Date(new Date('1970-01-01 ' + v.timeEnd).getTime() - (new Date('1970-01-01 ' + v.timeEnd).getTimezoneOffset() * 60000)).toISOString(), + })) + + const dataDetailCreate = await prisma.divisionProjectTaskDetail.createMany({ + data: dataDetailFix + }) + } + // create log user const log = await createLogUser({ act: 'UPDATE', desc: 'User mengupdate data detail task divisi', table: 'divisionProjectTask', data: id }) diff --git a/src/app/api/task/route.ts b/src/app/api/task/route.ts index b55940e..976b941 100644 --- a/src/app/api/task/route.ts +++ b/src/app/api/task/route.ts @@ -140,7 +140,7 @@ export async function POST(request: Request) { if (task.length > 0) { const dataTask = task.map((v: any) => ({ - ..._.omit(v, ["dateStart", "dateEnd", "title"]), + ..._.omit(v, ["dateStart", "dateEnd", "title", "dataDetail"]), idDivision: idDivision, idProject: data.id, title: v.title, @@ -148,8 +148,26 @@ export async function POST(request: Request) { dateEnd: new Date(v.dateEnd), })) - const insertTask = await prisma.divisionProjectTask.createMany({ - data: dataTask + let dataDetailFix = [] + for (let i = 0; i < dataTask.length; i++) { + const insertTask = await prisma.divisionProjectTask.create({ + data: dataTask[i], + select: { + id: true + } + }) + const dataDetail = task[i].dataDetail.map((v: any) => ({ + ...v, + idTask: insertTask.id, + date: new Date(v.date), + timeStart: v.timeStart == null ? null : new Date(new Date('1970-01-01 ' + v.timeStart).getTime() - (new Date('1970-01-01 ' + v.timeStart).getTimezoneOffset() * 60000)).toISOString(), + timeEnd: v.timeEnd == null ? null : new Date(new Date('1970-01-01 ' + v.timeEnd).getTime() - (new Date('1970-01-01 ' + v.timeEnd).getTimezoneOffset() * 60000)).toISOString(), + })) + dataDetailFix.push(...dataDetail) + } + + const insertDetail = await prisma.divisionProjectTaskDetail.createMany({ + data: dataDetailFix }) } diff --git a/src/module/project/lib/type_project.ts b/src/module/project/lib/type_project.ts index e85b6af..8adb847 100644 --- a/src/module/project/lib/type_project.ts +++ b/src/module/project/lib/type_project.ts @@ -56,6 +56,7 @@ export interface NewIFormDateProject { dateStart: string, dateEnd: string, title: string, + dataDetail: any[] } export interface IFormMemberProject { diff --git a/src/module/project/ui/create_date_end_task.tsx b/src/module/project/ui/create_date_end_task.tsx index acecb76..3e2685c 100644 --- a/src/module/project/ui/create_date_end_task.tsx +++ b/src/module/project/ui/create_date_end_task.tsx @@ -1,4 +1,5 @@ "use client"; +import { getDatesInRange } from "@/lib/getDatesInRange"; import { LayoutNavbarNew, TEMA } from "@/module/_global"; import { useHookstate } from "@hookstate/core"; import { ActionIcon, Box, Button, Flex, Group, rem, SimpleGrid, Stack, Text, TextInput } from "@mantine/core"; @@ -9,6 +10,7 @@ import { useState } from "react"; import toast from "react-hot-toast"; import { HiChevronLeft } from "react-icons/hi2"; import { NewIFormDateProject } from "../lib/type_project"; +import { ModalAddDetailTaskProject } from "./modal_add_detail_task_project"; export default function ViewDateEndTask({ onClose, onSet }: { onClose: (val: boolean) => void, onSet: (val: NewIFormDateProject) => void }) { @@ -16,6 +18,8 @@ export default function ViewDateEndTask({ onClose, onSet }: { onClose: (val: boo const [title, setTitle] = useState("") const tema = useHookstate(TEMA) const [acuan, setAcuan] = useState(false) + const [openModalDetailTask, setOpenModalDetailTask] = useState(false) + const [dataDetail, setDataDetail] = useState([]) const [touched, setTouched] = useState({ title: false, date: false @@ -28,10 +32,16 @@ export default function ViewDateEndTask({ onClose, onSet }: { onClose: (val: boo if (title == "") return toast.error("Error! harus memasukkan judul tugas") + const dataDetailFix = dataDetail.map((v: any) => ({ + ...v, + date: moment(v.date).format("YYYY-MM-DD"), + })) + onSet({ dateStart: moment(value[0]).format('YYYY-MM-DD'), dateEnd: moment(value[1]).format('YYYY-MM-DD'), - title: title + title, + dataDetail: dataDetailFix }) } @@ -72,8 +82,15 @@ export default function ViewDateEndTask({ onClose, onSet }: { onClose: (val: boo const array = val.split(",") if (array[0] == '' || array[1] == '') { setTouched({ ...touched, date: true }) + setDataDetail([]) } else { setTouched({ ...touched, date: false }) + const datanya = getDatesInRange(value[0]!, value[1]!) + setDataDetail(datanya.map((data: any) => ({ + date: data, + timeStart: null, + timeEnd: null + }))) } } } @@ -144,6 +161,16 @@ export default function ViewDateEndTask({ onClose, onSet }: { onClose: (val: boo ? Tanggal Tidak Boleh Kosong : <> } + + + setOpenModalDetailTask(false)} + data={dataDetail} + onSubmit={(data) => { + setDataDetail(data) + setOpenModalDetailTask(false) + }} + /> ); } diff --git a/src/module/project/ui/create_project.tsx b/src/module/project/ui/create_project.tsx index 311fcf9..069536a 100644 --- a/src/module/project/ui/create_project.tsx +++ b/src/module/project/ui/create_project.tsx @@ -299,7 +299,7 @@ export default function CreateProject() { setIndexDelTask(i) setOpenDrawerTask(true) }}> - + ) }) diff --git a/src/module/project/ui/edit_detail_task_project.tsx b/src/module/project/ui/edit_detail_task_project.tsx index 1b66c89..4412fc6 100644 --- a/src/module/project/ui/edit_detail_task_project.tsx +++ b/src/module/project/ui/edit_detail_task_project.tsx @@ -44,11 +44,15 @@ export default function EditDetailTaskProject() { try { setLoadingModal(true) + const dataDetailFix = dataDetail.map((v: any) => ({ + ...v, + date: moment(v.date).format("YYYY-MM-DD"), + })) const res = await funEditDetailProject(param.id, { title: name, dateStart: moment(value[0]).format('YYYY-MM-DD'), dateEnd: moment(value[1]).format('YYYY-MM-DD'), - + dataDetail: dataDetailFix }) if (res.success) { @@ -83,8 +87,16 @@ export default function EditDetailTaskProject() { ]) const res2 = await funGetDetailProject(param.id, 'detailTask'); - console.log('detail task',res2) - setDataDetail(res2.data) + if (res2.data.length == 0) { + const datanya = getDatesInRange(new Date(moment(res.data.dateStart).format('YYYY-MM-DD')) , new Date(moment(res.data.dateEnd).format('YYYY-MM-DD'))) + setDataDetail(datanya.map((data: any) => ({ + date: data, + timeStart: null, + timeEnd: null + }))) + } else { + setDataDetail(res2.data) + } } else { toast.error(res.message); } @@ -260,8 +272,7 @@ export default function EditDetailTaskProject() { -{/* TODO */} - {/* setOpenModalDetailTask(false)} data={dataDetail} @@ -269,7 +280,7 @@ export default function EditDetailTaskProject() { setDataDetail(data) setOpenModalDetailTask(false) }} - /> */} + /> setOpenModal(false)} description="Apakah Anda yakin ingin mengubah data?" diff --git a/src/module/project/ui/modal_add_detail_task_project.tsx b/src/module/project/ui/modal_add_detail_task_project.tsx index 1ff9a08..09235f8 100644 --- a/src/module/project/ui/modal_add_detail_task_project.tsx +++ b/src/module/project/ui/modal_add_detail_task_project.tsx @@ -16,7 +16,13 @@ export function ModalAddDetailTaskProject({ open, onClose, data, onSubmit }: { o if (cat == "timeEnd") { if (value == "" || dataDetail.find((data: any) => data.date == date)?.timeStart > value) { setTouched((touched: any) => [...touched, { date: date, timeEnd: true }]) - }else{ + } else { + setTouched((touched: any) => touched.filter((item: any) => item.date != date)) + } + } else { + if (value == "" || dataDetail.find((data: any) => data.date == date)?.timeEnd < value) { + setTouched((touched: any) => [...touched, { date: date, timeEnd: true }]) + } else { setTouched((touched: any) => touched.filter((item: any) => item.date != date)) } } diff --git a/src/module/task/lib/api_task.ts b/src/module/task/lib/api_task.ts index 39755a1..f4d3496 100644 --- a/src/module/task/lib/api_task.ts +++ b/src/module/task/lib/api_task.ts @@ -44,8 +44,8 @@ export const funUpdateStatusDetailTask = async (path: string, data: { status: nu }; -export const funGetDetailTask = async (path: string) => { - const response = await fetch(`/api/task/detail/${path}`); +export const funGetDetailTask = async (path: string, kat?:string) => { + const response = await fetch(`/api/task/detail/${path}${(kat) ? `?cat=${kat}` : ''}`); return await response.json().catch(() => null); } diff --git a/src/module/task/lib/type_task.ts b/src/module/task/lib/type_task.ts index 96dab26..e7c181f 100644 --- a/src/module/task/lib/type_task.ts +++ b/src/module/task/lib/type_task.ts @@ -16,14 +16,16 @@ export interface IFormMemberTask { export interface IFormDateTask { dateStart: string, dateEnd: string, - title: string + title: string, + dataDetail: any[] } export interface IFormAddDetailTask { dateStart: string, dateEnd: string, title: string - idDivision: string + idDivision: string, + dataDetail: any[] } diff --git a/src/module/task/ui/add_detail_task.tsx b/src/module/task/ui/add_detail_task.tsx index 7feae9c..b6af2b9 100644 --- a/src/module/task/ui/add_detail_task.tsx +++ b/src/module/task/ui/add_detail_task.tsx @@ -1,4 +1,5 @@ "use client"; +import { getDatesInRange } from "@/lib/getDatesInRange"; import { keyWibu, LayoutNavbarNew, TEMA } from "@/module/_global"; import LayoutModal from "@/module/_global/layout/layout_modal"; import { useHookstate } from "@hookstate/core"; @@ -11,6 +12,7 @@ import { useState } from "react"; import toast from "react-hot-toast"; import { useWibuRealtime } from "wibu-realtime"; import { funCreateDetailTask } from "../lib/api_task"; +import { ModalAddDetailTugasTask } from "./modal_add_detail_tugas_task"; export default function AddDetailTask() { const [value, setValue] = useState<[Date | null, Date | null]>([null, null]); @@ -18,6 +20,8 @@ export default function AddDetailTask() { const [title, setTitle] = useState("") const [openModal, setOpenModal] = useState(false) const [loadingModal, setLoadingModal] = useState(false) + const [openModalDetailTask, setOpenModalDetailTask] = useState(false) + const [dataDetail, setDataDetail] = useState([]) const param = useParams<{ id: string, detail: string }>() const tema = useHookstate(TEMA) const [acuan, setAcuan] = useState(false) @@ -57,11 +61,17 @@ export default function AddDetailTask() { async function onSubmit() { try { setLoadingModal(true) + const dataDetailFix = dataDetail.map((v: any) => ({ + ...v, + date: moment(v.date).format("YYYY-MM-DD"), + })) + const res = await funCreateDetailTask(param.detail, { title, dateStart: (value[0] != null) ? moment(value[0]).format('YYYY-MM-DD') : moment(new Date).format('YYYY-MM-DD'), dateEnd: (value[1] != null) ? moment(value[1]).format('YYYY-MM-DD') : moment(new Date).format('YYYY-MM-DD'), - idDivision: param.id + idDivision: param.id, + dataDetail: dataDetailFix }) if (res.success) { @@ -96,8 +106,15 @@ export default function AddDetailTask() { const array = val.split(",") if (array[0] == '' || array[1] == '') { setTouched({ ...touched, date: true }) + setDataDetail([]) } else { setTouched({ ...touched, date: false }) + const datanya = getDatesInRange(value[0]!, value[1]!) + setDataDetail(datanya.map((data: any) => ({ + date: data, + timeStart: null, + timeEnd: null + }))) } } } @@ -163,6 +180,16 @@ export default function AddDetailTask() { ? Tanggal Tidak Boleh Kosong : <> } + + setOpenModalDetailTask(false)} + data={dataDetail} + onSubmit={(data) => { + setDataDetail(data) + setOpenModalDetailTask(false) + }} /> + setOpenModal(false)} description="Apakah Anda yakin ingin menambahkan tugas?" onYes={(val) => { diff --git a/src/module/task/ui/create_date_end_task.tsx b/src/module/task/ui/create_date_end_task.tsx index 0b769eb..cd8a31f 100644 --- a/src/module/task/ui/create_date_end_task.tsx +++ b/src/module/task/ui/create_date_end_task.tsx @@ -1,4 +1,5 @@ "use client"; +import { getDatesInRange } from "@/lib/getDatesInRange"; import { LayoutNavbarNew, TEMA } from "@/module/_global"; import { useHookstate } from "@hookstate/core"; import { ActionIcon, Box, Button, Flex, Group, rem, SimpleGrid, Stack, Text, TextInput } from "@mantine/core"; @@ -9,13 +10,16 @@ import { useState } from "react"; import toast from "react-hot-toast"; import { HiChevronLeft } from "react-icons/hi2"; import { IFormDateTask } from "../lib/type_task"; +import { ModalAddDetailTugasTask } from "./modal_add_detail_tugas_task"; 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 [title, setTitle] = useState("") const [acuan, setAcuan] = useState(false) + const [dataDetail, setDataDetail] = useState([]) const tema = useHookstate(TEMA) + const [openModalDetailTask, setOpenModalDetailTask] = useState(false) const [touched, setTouched] = useState({ title: false, date: false @@ -28,10 +32,16 @@ export default function ViewDateEndTask({ onClose, onSet }: { onClose: (val: boo if (title == "") return toast.error("Error! harus memasukkan judul tugas") + const dataDetailFix = dataDetail.map((v: any) => ({ + ...v, + date: moment(v.date).format("YYYY-MM-DD"), + })) + onSet({ dateStart: moment(value[0]).format('YYYY-MM-DD'), dateEnd: moment(value[1]).format('YYYY-MM-DD'), - title: title + title: title, + dataDetail: dataDetailFix }) } @@ -73,8 +83,15 @@ export default function ViewDateEndTask({ onClose, onSet }: { onClose: (val: boo const array = val.split(",") if (array[0] == '' || array[1] == '') { setTouched({ ...touched, date: true }) + setDataDetail([]) } else { setTouched({ ...touched, date: false }) + const datanya = getDatesInRange(value[0]!, value[1]!) + setDataDetail(datanya.map((data: any) => ({ + date: data, + timeStart: null, + timeEnd: null + }))) } } } @@ -145,6 +162,16 @@ export default function ViewDateEndTask({ onClose, onSet }: { onClose: (val: boo ? Tanggal Tidak Boleh Kosong : <> } + + + setOpenModalDetailTask(false)} + data={dataDetail} + onSubmit={(data) => { + setDataDetail(data) + setOpenModalDetailTask(false) + }} + /> ); } diff --git a/src/module/task/ui/create_task.tsx b/src/module/task/ui/create_task.tsx index d83564a..b8cc5f4 100644 --- a/src/module/task/ui/create_task.tsx +++ b/src/module/task/ui/create_task.tsx @@ -223,7 +223,7 @@ export default function CreateTask() { setIndexDelTask(i) setOpenDrawerTask(true) }}> - + ) }) diff --git a/src/module/task/ui/detail_list_tugas_task.tsx b/src/module/task/ui/detail_list_tugas_task.tsx index aff1535..849d194 100644 --- a/src/module/task/ui/detail_list_tugas_task.tsx +++ b/src/module/task/ui/detail_list_tugas_task.tsx @@ -1,8 +1,9 @@ 'use client' import { globalRole, keyWibu, LayoutDrawer, SkeletonDetailListTugasTask, TEMA } from "@/module/_global" import LayoutModal from "@/module/_global/layout/layout_modal" +import { globalIsMemberDivision } from "@/module/division_new" import { useHookstate } from "@hookstate/core" -import { Box, Center, Checkbox, Divider, Flex, Grid, Group, SimpleGrid, Stack, Text, Loader } from "@mantine/core" +import { Box, Center, Checkbox, Divider, Flex, Grid, Group, Loader, SimpleGrid, Stack, Text } from "@mantine/core" import { useShallowEffect } from "@mantine/hooks" import "moment/locale/id" import { useParams, useRouter } from "next/navigation" @@ -10,15 +11,17 @@ import { useState } from "react" import toast from "react-hot-toast" import { AiOutlineFileDone, AiOutlineFileSync } from "react-icons/ai" import { FaCheck, FaPencil, FaTrash } from "react-icons/fa6" +import { IoTimeOutline } from "react-icons/io5" import { useWibuRealtime } from "wibu-realtime" import { funDeleteDetailTask, funGetTaskDivisionById, funUpdateStatusDetailTask } from "../lib/api_task" import { IDataListTaskDivision } from "../lib/type_task" import { globalRefreshTask, valStatusDetailTask } from "../lib/val_task" -import { globalIsMemberDivision } from "@/module/division_new" +import { ModalListDetailTugasTask } from "./modal_list_tugas_task" export default function ListTugasDetailTask() { const roleLogin = useHookstate(globalRole) const memberDivision = useHookstate(globalIsMemberDivision) + const [openModalDetailTask, setOpenModalDetailTask] = useState(false) const [openDrawer, setOpenDrawer] = useState(false) const [openDrawerStatus, setOpenDrawerStatus] = useState(false) const [isOpenModal, setOpenModal] = useState(false) @@ -268,6 +271,15 @@ export default function ListTugasDetailTask() { + { setOpenModalDetailTask(true) }} justify={'center'} align={'center'} direction={'column'} > + + + + + Detail Waktu + + + { setOpenModal(true) }} justify={'center'} align={'center'} direction={'column'} > @@ -281,6 +293,8 @@ export default function ListTugasDetailTask() { + setOpenModalDetailTask(false)} task={idData} /> + setOpenModal(false)} description="Apakah Anda yakin ingin menghapus tugas ini?" onYes={(val) => { diff --git a/src/module/task/ui/edit_detail_task.tsx b/src/module/task/ui/edit_detail_task.tsx index 13b34a0..d5a355e 100644 --- a/src/module/task/ui/edit_detail_task.tsx +++ b/src/module/task/ui/edit_detail_task.tsx @@ -1,4 +1,5 @@ "use client"; +import { getDatesInRange } from "@/lib/getDatesInRange"; import { LayoutNavbarNew, TEMA } from "@/module/_global"; import LayoutModal from "@/module/_global/layout/layout_modal"; import { useHookstate } from "@hookstate/core"; @@ -10,11 +11,14 @@ import { useParams, useRouter } from "next/navigation"; import { useState } from "react"; import toast from "react-hot-toast"; import { funEditDetailTask, funGetDetailTask } from "../lib/api_task"; +import { ModalAddDetailTugasTask } from "./modal_add_detail_tugas_task"; export default function EditDetailTask() { const [value, setValue] = useState<[Date | null, Date | null]>([null, null]); const router = useRouter() + const [openModalDetailTask, setOpenModalDetailTask] = useState(false) + const [dataDetail, setDataDetail] = useState([]) const [title, setTitle] = useState("") const param = useParams<{ id: string, detail: string }>() const [openModal, setOpenModal] = useState(false) @@ -36,10 +40,15 @@ export default function EditDetailTask() { try { setLoadingModal(true) + const dataDetailFix = dataDetail.map((v: any) => ({ + ...v, + date: moment(v.date).format("YYYY-MM-DD"), + })) const res = await funEditDetailTask(param.detail, { title: title, dateStart: moment(value[0]).format('YYYY-MM-DD'), dateEnd: moment(value[1]).format('YYYY-MM-DD'), + dataDetail: dataDetailFix }) if (res.success) { @@ -69,6 +78,18 @@ export default function EditDetailTask() { new Date(moment(res.data.dateStart).format('YYYY-MM-DD')), new Date(moment(res.data.dateEnd).format('YYYY-MM-DD')), ]) + + const res2 = await funGetDetailTask(param.detail, 'detailTask'); + if (res2.data.length == 0) { + const datanya = getDatesInRange(new Date(moment(res.data.dateStart).format('YYYY-MM-DD')), new Date(moment(res.data.dateEnd).format('YYYY-MM-DD'))) + setDataDetail(datanya.map((data: any) => ({ + date: data, + timeStart: null, + timeEnd: null + }))) + } else { + setDataDetail(res2.data) + } } else { toast.error(res.message); } @@ -104,8 +125,15 @@ export default function EditDetailTask() { const array = val.split(",") if (array[0] == '' || array[1] == '') { setTouched({ ...touched, date: true }) + setDataDetail([]) } else { setTouched({ ...touched, date: false }) + const datanya = getDatesInRange(value[0]!, value[1]!) + setDataDetail(datanya.map((data: any) => ({ + date: data, + timeStart: null, + timeEnd: null + }))) } } } @@ -180,7 +208,16 @@ export default function EditDetailTask() { ? Tanggal Tidak Boleh Kosong : <> } - + {loading ? @@ -229,6 +266,16 @@ export default function EditDetailTask() { } + setOpenModalDetailTask(false)} + data={dataDetail} + onSubmit={(data) => { + setDataDetail(data) + setOpenModalDetailTask(false) + }} + /> + setOpenModal(false)} description="Apakah Anda yakin ingin mengubah data?" onYes={(val) => { diff --git a/src/module/task/ui/modal_add_detail_tugas_task.tsx b/src/module/task/ui/modal_add_detail_tugas_task.tsx new file mode 100644 index 0000000..eab0659 --- /dev/null +++ b/src/module/task/ui/modal_add_detail_tugas_task.tsx @@ -0,0 +1,100 @@ +import { TEMA } from "@/module/_global"; +import { Box, Button, Grid, Modal, SimpleGrid, Text } from "@mantine/core"; +import { TimeInput } from "@mantine/dates"; +import moment from "moment"; +import { useEffect, useState } from "react"; + +export function ModalAddDetailTugasTask({ open, onClose, data, onSubmit }: { open: boolean, onClose: () => void, data: any[], onSubmit: (data: any) => void }) { + const [dataDetail, setDataDetail] = useState(data) + const [touched, setTouched] = useState([]) + + useEffect(() => { + setDataDetail(data) + }, [data]) + + function onInputTime(date: any, value: any, cat: 'timeStart' | 'timeEnd') { + if (cat == "timeEnd") { + if (value == "" || dataDetail.find((data: any) => data.date == date)?.timeStart > value) { + setTouched((touched: any) => [...touched, { date: date, timeEnd: true }]) + } else { + setTouched((touched: any) => touched.filter((item: any) => item.date != date)) + } + } else { + if (value == "" || dataDetail.find((data: any) => data.date == date)?.timeEnd < value) { + setTouched((touched: any) => [...touched, { date: date, timeEnd: true }]) + } else { + setTouched((touched: any) => touched.filter((item: any) => item.date != date)) + } + } + + setDataDetail(dataDetail.map((data: any) => { + if (data.date == date) { + return { + ...data, + [cat]: value + } + } + return data + })) + } + + return ( + onClose()} centered withCloseButton={false} title={"Detail Tanggal dan Waktu Tugas"}> + + + { + dataDetail.map((data: any, index: any) => ( + + {moment(data.date).format('DD-MM-YYYY')} + + onInputTime(data.date, event.target.value, 'timeStart')} + /> + onInputTime(data.date, event.target.value, 'timeEnd')} + error={touched.find((item: any) => item.date == data.date)?.timeEnd ? "Waktu akhir harus lebih dari waktu awal" : ""} + /> + + + )) + } + + + + + + + + + + + + + ) +} \ No newline at end of file diff --git a/src/module/task/ui/modal_list_tugas_task.tsx b/src/module/task/ui/modal_list_tugas_task.tsx new file mode 100644 index 0000000..9c23549 --- /dev/null +++ b/src/module/task/ui/modal_list_tugas_task.tsx @@ -0,0 +1,99 @@ +import { Box, Modal, SimpleGrid, Skeleton, Text } from "@mantine/core"; +import { TimeInput } from "@mantine/dates"; +import { useShallowEffect } from "@mantine/hooks"; +import moment from "moment"; +import { useState } from "react"; +import toast from "react-hot-toast"; +import { funGetDetailTask } from "../lib/api_task"; + +export function ModalListDetailTugasTask({ open, onClose, task, }: { open: boolean, onClose: () => void, task: string }) { + const [dataDetail, setDataDetail] = useState([]) + const [loading, setLoading] = useState(false) + + async function getData() { + try { + setLoading(true) + const response = await funGetDetailTask(task, 'detailTask') + if (response.success) { + setDataDetail(response.data) + } else { + toast.error(response.message) + } + } catch (error) { + console.error(error); + toast.error("Gagal mendapatkan detail tugas Kegiatan, coba lagi nanti"); + } finally { + setLoading(false) + } + } + + useShallowEffect(() => { + if(task!=""){ + getData() + } + }, [task]) + + return ( + onClose()} centered withCloseButton={false} title={"Detail Tanggal dan Waktu Tugas"}> + + + { + loading ? + Array(5) + .fill(null) + .map((_, i) => ( + + + + + + )) + : + dataDetail.length > 0 ? + dataDetail.map((data: any, index: any) => ( + + {moment(data.date).format('DD-MM-YYYY')} + + + + + + )) + : + Tidak ada detail tugas + } + + + + ) +} \ No newline at end of file