upd: fitur baru task divisi
Deskripsi: - api tambah detail detail task divisi - api tambah task detail - api edit task detail - tampilan list detail task - tampilan form tambah data task - tampilan form tambah tugas detail task divisi - tampilan form edit tugas detail task divisi No Issues
This commit is contained in:
@@ -259,8 +259,8 @@ model ProjectTaskDetail {
|
|||||||
ProjectTask ProjectTask @relation(fields: [idTask], references: [id])
|
ProjectTask ProjectTask @relation(fields: [idTask], references: [id])
|
||||||
idTask String
|
idTask String
|
||||||
date DateTime @db.Date
|
date DateTime @db.Date
|
||||||
timeStart DateTime? @db.Time()
|
timeStart DateTime? @db.Time()
|
||||||
timeEnd DateTime? @db.Time()
|
timeEnd DateTime? @db.Time()
|
||||||
isActive Boolean @default(true)
|
isActive Boolean @default(true)
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
@@ -352,6 +352,19 @@ model DivisionProjectTask {
|
|||||||
isActive Boolean @default(true)
|
isActive Boolean @default(true)
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
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 {
|
model DivisionProjectMember {
|
||||||
|
|||||||
@@ -261,25 +261,25 @@ export async function POST(request: Request, context: { params: { id: string } }
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const dataDetailDelete = await prisma.projectTaskDetail.deleteMany({
|
const dataDetailDelete = await prisma.projectTaskDetail.deleteMany({
|
||||||
where: {
|
where: {
|
||||||
idTask: id
|
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
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
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
|
// create log user
|
||||||
const log = await createLogUser({ act: 'UPDATE', desc: 'User mengupdate tahapan kegiatan', table: 'projectTask', data: String(id) })
|
const log = await createLogUser({ act: 'UPDATE', desc: 'User mengupdate tahapan kegiatan', table: 'projectTask', data: String(id) })
|
||||||
|
|||||||
@@ -183,7 +183,8 @@ export async function POST(request: Request, context: { params: { id: string } }
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { id } = context.params;
|
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({
|
const data = await prisma.divisionProject.count({
|
||||||
where: {
|
where: {
|
||||||
id: id,
|
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 cek progress
|
||||||
const dataTask = await prisma.divisionProjectTask.findMany({
|
const dataTask = await prisma.divisionProjectTask.findMany({
|
||||||
where: {
|
where: {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { prisma } from "@/module/_global";
|
|||||||
import { funGetUserByCookies } from "@/module/auth";
|
import { funGetUserByCookies } from "@/module/auth";
|
||||||
import { createLogUser } from "@/module/user";
|
import { createLogUser } from "@/module/user";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
|
import moment from "moment";
|
||||||
import { NextResponse } from "next/server";
|
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 } }) {
|
export async function GET(request: Request, context: { params: { id: string } }) {
|
||||||
try {
|
try {
|
||||||
const { id } = context.params;
|
const { id } = context.params;
|
||||||
|
const { searchParams } = new URL(request.url);
|
||||||
|
const kategori = searchParams.get("cat");
|
||||||
const user = await funGetUserByCookies()
|
const user = await funGetUserByCookies()
|
||||||
|
|
||||||
if (user.id == undefined) {
|
if (user.id == undefined) {
|
||||||
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
|
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let dataFix
|
||||||
const data = await prisma.divisionProjectTask.findUnique({
|
const data = await prisma.divisionProjectTask.findUnique({
|
||||||
where: {
|
where: {
|
||||||
id: String(id),
|
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: 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) {
|
catch (error) {
|
||||||
@@ -192,7 +217,7 @@ export async function POST(request: Request, context: { params: { id: string } }
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { id } = context.params;
|
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({
|
const data = await prisma.divisionProjectTask.count({
|
||||||
where: {
|
where: {
|
||||||
id: id,
|
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
|
// create log user
|
||||||
const log = await createLogUser({ act: 'UPDATE', desc: 'User mengupdate data detail task divisi', table: 'divisionProjectTask', data: id })
|
const log = await createLogUser({ act: 'UPDATE', desc: 'User mengupdate data detail task divisi', table: 'divisionProjectTask', data: id })
|
||||||
|
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ export async function POST(request: Request) {
|
|||||||
|
|
||||||
if (task.length > 0) {
|
if (task.length > 0) {
|
||||||
const dataTask = task.map((v: any) => ({
|
const dataTask = task.map((v: any) => ({
|
||||||
..._.omit(v, ["dateStart", "dateEnd", "title"]),
|
..._.omit(v, ["dateStart", "dateEnd", "title", "dataDetail"]),
|
||||||
idDivision: idDivision,
|
idDivision: idDivision,
|
||||||
idProject: data.id,
|
idProject: data.id,
|
||||||
title: v.title,
|
title: v.title,
|
||||||
@@ -148,8 +148,26 @@ export async function POST(request: Request) {
|
|||||||
dateEnd: new Date(v.dateEnd),
|
dateEnd: new Date(v.dateEnd),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const insertTask = await prisma.divisionProjectTask.createMany({
|
let dataDetailFix = []
|
||||||
data: dataTask
|
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
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { TEMA } from "@/module/_global";
|
import { TEMA } from "@/module/_global";
|
||||||
import { Box, Button, Grid, Modal, SimpleGrid, Text } from "@mantine/core";
|
import { Box, Button, Grid, Modal, SimpleGrid, Text } from "@mantine/core";
|
||||||
import { TimeInput } from "@mantine/dates";
|
import { TimeInput } from "@mantine/dates";
|
||||||
import { timeEnd } from "console";
|
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
@@ -17,13 +16,13 @@ export function ModalAddDetailTaskProject({ open, onClose, data, onSubmit }: { o
|
|||||||
if (cat == "timeEnd") {
|
if (cat == "timeEnd") {
|
||||||
if (value == "" || dataDetail.find((data: any) => data.date == date)?.timeStart > value) {
|
if (value == "" || dataDetail.find((data: any) => data.date == date)?.timeStart > value) {
|
||||||
setTouched((touched: any) => [...touched, { date: date, timeEnd: true }])
|
setTouched((touched: any) => [...touched, { date: date, timeEnd: true }])
|
||||||
}else{
|
} else {
|
||||||
setTouched((touched: any) => touched.filter((item: any) => item.date != date))
|
setTouched((touched: any) => touched.filter((item: any) => item.date != date))
|
||||||
}
|
}
|
||||||
}else{
|
} else {
|
||||||
if (value == "" || dataDetail.find((data: any) => data.date == date)?.timeEnd < value) {
|
if (value == "" || dataDetail.find((data: any) => data.date == date)?.timeEnd < value) {
|
||||||
setTouched((touched: any) => [...touched, { date: date, timeEnd: true }])
|
setTouched((touched: any) => [...touched, { date: date, timeEnd: true }])
|
||||||
}else{
|
} else {
|
||||||
setTouched((touched: any) => touched.filter((item: any) => item.date != date))
|
setTouched((touched: any) => touched.filter((item: any) => item.date != date))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,8 +44,8 @@ export const funUpdateStatusDetailTask = async (path: string, data: { status: nu
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export const funGetDetailTask = async (path: string) => {
|
export const funGetDetailTask = async (path: string, kat?:string) => {
|
||||||
const response = await fetch(`/api/task/detail/${path}`);
|
const response = await fetch(`/api/task/detail/${path}${(kat) ? `?cat=${kat}` : ''}`);
|
||||||
return await response.json().catch(() => null);
|
return await response.json().catch(() => null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,14 +16,16 @@ export interface IFormMemberTask {
|
|||||||
export interface IFormDateTask {
|
export interface IFormDateTask {
|
||||||
dateStart: string,
|
dateStart: string,
|
||||||
dateEnd: string,
|
dateEnd: string,
|
||||||
title: string
|
title: string,
|
||||||
|
dataDetail: any[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IFormAddDetailTask {
|
export interface IFormAddDetailTask {
|
||||||
dateStart: string,
|
dateStart: string,
|
||||||
dateEnd: string,
|
dateEnd: string,
|
||||||
title: string
|
title: string
|
||||||
idDivision: string
|
idDivision: string,
|
||||||
|
dataDetail: any[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
import { getDatesInRange } from "@/lib/getDatesInRange";
|
||||||
import { keyWibu, LayoutNavbarNew, TEMA } from "@/module/_global";
|
import { keyWibu, LayoutNavbarNew, TEMA } from "@/module/_global";
|
||||||
import LayoutModal from "@/module/_global/layout/layout_modal";
|
import LayoutModal from "@/module/_global/layout/layout_modal";
|
||||||
import { useHookstate } from "@hookstate/core";
|
import { useHookstate } from "@hookstate/core";
|
||||||
@@ -11,6 +12,7 @@ import { useState } from "react";
|
|||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
import { useWibuRealtime } from "wibu-realtime";
|
import { useWibuRealtime } from "wibu-realtime";
|
||||||
import { funCreateDetailTask } from "../lib/api_task";
|
import { funCreateDetailTask } from "../lib/api_task";
|
||||||
|
import { ModalAddDetailTugasTask } from "./modal_add_detail_tugas_task";
|
||||||
|
|
||||||
export default function AddDetailTask() {
|
export default function AddDetailTask() {
|
||||||
const [value, setValue] = useState<[Date | null, Date | null]>([null, null]);
|
const [value, setValue] = useState<[Date | null, Date | null]>([null, null]);
|
||||||
@@ -18,6 +20,8 @@ export default function AddDetailTask() {
|
|||||||
const [title, setTitle] = useState("")
|
const [title, setTitle] = useState("")
|
||||||
const [openModal, setOpenModal] = useState(false)
|
const [openModal, setOpenModal] = useState(false)
|
||||||
const [loadingModal, setLoadingModal] = useState(false)
|
const [loadingModal, setLoadingModal] = useState(false)
|
||||||
|
const [openModalDetailTask, setOpenModalDetailTask] = useState(false)
|
||||||
|
const [dataDetail, setDataDetail] = useState<any>([])
|
||||||
const param = useParams<{ id: string, detail: string }>()
|
const param = useParams<{ id: string, detail: string }>()
|
||||||
const tema = useHookstate(TEMA)
|
const tema = useHookstate(TEMA)
|
||||||
const [acuan, setAcuan] = useState(false)
|
const [acuan, setAcuan] = useState(false)
|
||||||
@@ -57,11 +61,17 @@ export default function AddDetailTask() {
|
|||||||
async function onSubmit() {
|
async function onSubmit() {
|
||||||
try {
|
try {
|
||||||
setLoadingModal(true)
|
setLoadingModal(true)
|
||||||
|
const dataDetailFix = dataDetail.map((v: any) => ({
|
||||||
|
...v,
|
||||||
|
date: moment(v.date).format("YYYY-MM-DD"),
|
||||||
|
}))
|
||||||
|
|
||||||
const res = await funCreateDetailTask(param.detail, {
|
const res = await funCreateDetailTask(param.detail, {
|
||||||
title,
|
title,
|
||||||
dateStart: (value[0] != null) ? moment(value[0]).format('YYYY-MM-DD') : moment(new Date).format('YYYY-MM-DD'),
|
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'),
|
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) {
|
if (res.success) {
|
||||||
@@ -96,8 +106,15 @@ export default function AddDetailTask() {
|
|||||||
const array = val.split(",")
|
const array = val.split(",")
|
||||||
if (array[0] == '' || array[1] == '') {
|
if (array[0] == '' || array[1] == '') {
|
||||||
setTouched({ ...touched, date: true })
|
setTouched({ ...touched, date: true })
|
||||||
|
setDataDetail([])
|
||||||
} else {
|
} else {
|
||||||
setTouched({ ...touched, date: false })
|
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() {
|
|||||||
? <Text size="sm" c={"red"}>Tanggal Tidak Boleh Kosong</Text>
|
? <Text size="sm" c={"red"}>Tanggal Tidak Boleh Kosong</Text>
|
||||||
: <></>
|
: <></>
|
||||||
}
|
}
|
||||||
|
<Button
|
||||||
|
variant="light"
|
||||||
|
size="compact-md"
|
||||||
|
radius={5}
|
||||||
|
onClick={() => { setOpenModalDetailTask(true) }}
|
||||||
|
mt={5}
|
||||||
|
disabled={value[0] == null || value[1] == null || touched.date}
|
||||||
|
>
|
||||||
|
Detail
|
||||||
|
</Button>
|
||||||
<Stack pt={15} pb={100}>
|
<Stack pt={15} pb={100}>
|
||||||
<TextInput
|
<TextInput
|
||||||
styles={{
|
styles={{
|
||||||
@@ -202,6 +229,15 @@ export default function AddDetailTask() {
|
|||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
<ModalAddDetailTugasTask
|
||||||
|
open={openModalDetailTask}
|
||||||
|
onClose={() => setOpenModalDetailTask(false)}
|
||||||
|
data={dataDetail}
|
||||||
|
onSubmit={(data) => {
|
||||||
|
setDataDetail(data)
|
||||||
|
setOpenModalDetailTask(false)
|
||||||
|
}} />
|
||||||
|
|
||||||
<LayoutModal loading={loadingModal} opened={openModal} onClose={() => setOpenModal(false)}
|
<LayoutModal loading={loadingModal} opened={openModal} onClose={() => setOpenModal(false)}
|
||||||
description="Apakah Anda yakin ingin menambahkan tugas?"
|
description="Apakah Anda yakin ingin menambahkan tugas?"
|
||||||
onYes={(val) => {
|
onYes={(val) => {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
import { getDatesInRange } from "@/lib/getDatesInRange";
|
||||||
import { LayoutNavbarNew, TEMA } from "@/module/_global";
|
import { LayoutNavbarNew, TEMA } from "@/module/_global";
|
||||||
import { useHookstate } from "@hookstate/core";
|
import { useHookstate } from "@hookstate/core";
|
||||||
import { ActionIcon, Box, Button, Flex, Group, rem, SimpleGrid, Stack, Text, TextInput } from "@mantine/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 toast from "react-hot-toast";
|
||||||
import { HiChevronLeft } from "react-icons/hi2";
|
import { HiChevronLeft } from "react-icons/hi2";
|
||||||
import { IFormDateTask } from "../lib/type_task";
|
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 }) {
|
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 [value, setValue] = useState<[Date | null, Date | null]>([null, null]);
|
||||||
const [title, setTitle] = useState("")
|
const [title, setTitle] = useState("")
|
||||||
const [acuan, setAcuan] = useState(false)
|
const [acuan, setAcuan] = useState(false)
|
||||||
|
const [dataDetail, setDataDetail] = useState<any[]>([])
|
||||||
const tema = useHookstate(TEMA)
|
const tema = useHookstate(TEMA)
|
||||||
|
const [openModalDetailTask, setOpenModalDetailTask] = useState(false)
|
||||||
const [touched, setTouched] = useState({
|
const [touched, setTouched] = useState({
|
||||||
title: false,
|
title: false,
|
||||||
date: false
|
date: false
|
||||||
@@ -28,10 +32,16 @@ export default function ViewDateEndTask({ onClose, onSet }: { onClose: (val: boo
|
|||||||
if (title == "")
|
if (title == "")
|
||||||
return toast.error("Error! harus memasukkan judul tugas")
|
return toast.error("Error! harus memasukkan judul tugas")
|
||||||
|
|
||||||
|
const dataDetailFix = dataDetail.map((v: any) => ({
|
||||||
|
...v,
|
||||||
|
date: moment(v.date).format("YYYY-MM-DD"),
|
||||||
|
}))
|
||||||
|
|
||||||
onSet({
|
onSet({
|
||||||
dateStart: moment(value[0]).format('YYYY-MM-DD'),
|
dateStart: moment(value[0]).format('YYYY-MM-DD'),
|
||||||
dateEnd: moment(value[1]).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(",")
|
const array = val.split(",")
|
||||||
if (array[0] == '' || array[1] == '') {
|
if (array[0] == '' || array[1] == '') {
|
||||||
setTouched({ ...touched, date: true })
|
setTouched({ ...touched, date: true })
|
||||||
|
setDataDetail([])
|
||||||
} else {
|
} else {
|
||||||
setTouched({ ...touched, date: false })
|
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
|
|||||||
? <Text size="sm" c={"red"}>Tanggal Tidak Boleh Kosong</Text>
|
? <Text size="sm" c={"red"}>Tanggal Tidak Boleh Kosong</Text>
|
||||||
: <></>
|
: <></>
|
||||||
}
|
}
|
||||||
|
<Button
|
||||||
|
variant="light"
|
||||||
|
size="compact-md"
|
||||||
|
radius={5}
|
||||||
|
onClick={() => { setOpenModalDetailTask(true) }}
|
||||||
|
mt={5}
|
||||||
|
disabled={value[0] == null || value[1] == null || touched.date}
|
||||||
|
>
|
||||||
|
Detail
|
||||||
|
</Button>
|
||||||
<Stack pt={15} mb={100}>
|
<Stack pt={15} mb={100}>
|
||||||
<TextInput
|
<TextInput
|
||||||
styles={{
|
styles={{
|
||||||
@@ -181,6 +208,16 @@ export default function ViewDateEndTask({ onClose, onSet }: { onClose: (val: boo
|
|||||||
Simpan
|
Simpan
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
<ModalAddDetailTugasTask
|
||||||
|
open={openModalDetailTask}
|
||||||
|
onClose={() => setOpenModalDetailTask(false)}
|
||||||
|
data={dataDetail}
|
||||||
|
onSubmit={(data) => {
|
||||||
|
setDataDetail(data)
|
||||||
|
setOpenModalDetailTask(false)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -223,7 +223,7 @@ export default function CreateTask() {
|
|||||||
setIndexDelTask(i)
|
setIndexDelTask(i)
|
||||||
setOpenDrawerTask(true)
|
setOpenDrawerTask(true)
|
||||||
}}>
|
}}>
|
||||||
<ResultsDateAndTask dateStart={v.dateStart} dateEnd={v.dateEnd} title={v.title} />
|
<ResultsDateAndTask dateStart={v.dateStart} dateEnd={v.dateEnd} title={v.title} dataDetail={v.dataDetail} />
|
||||||
</Box>
|
</Box>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import { globalRole, keyWibu, LayoutDrawer, SkeletonDetailListTugasTask, TEMA } from "@/module/_global"
|
import { globalRole, keyWibu, LayoutDrawer, SkeletonDetailListTugasTask, TEMA } from "@/module/_global"
|
||||||
import LayoutModal from "@/module/_global/layout/layout_modal"
|
import LayoutModal from "@/module/_global/layout/layout_modal"
|
||||||
|
import { globalIsMemberDivision } from "@/module/division_new"
|
||||||
import { useHookstate } from "@hookstate/core"
|
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 { useShallowEffect } from "@mantine/hooks"
|
||||||
import "moment/locale/id"
|
import "moment/locale/id"
|
||||||
import { useParams, useRouter } from "next/navigation"
|
import { useParams, useRouter } from "next/navigation"
|
||||||
@@ -10,15 +11,17 @@ import { useState } from "react"
|
|||||||
import toast from "react-hot-toast"
|
import toast from "react-hot-toast"
|
||||||
import { AiOutlineFileDone, AiOutlineFileSync } from "react-icons/ai"
|
import { AiOutlineFileDone, AiOutlineFileSync } from "react-icons/ai"
|
||||||
import { FaCheck, FaPencil, FaTrash } from "react-icons/fa6"
|
import { FaCheck, FaPencil, FaTrash } from "react-icons/fa6"
|
||||||
|
import { IoTimeOutline } from "react-icons/io5"
|
||||||
import { useWibuRealtime } from "wibu-realtime"
|
import { useWibuRealtime } from "wibu-realtime"
|
||||||
import { funDeleteDetailTask, funGetTaskDivisionById, funUpdateStatusDetailTask } from "../lib/api_task"
|
import { funDeleteDetailTask, funGetTaskDivisionById, funUpdateStatusDetailTask } from "../lib/api_task"
|
||||||
import { IDataListTaskDivision } from "../lib/type_task"
|
import { IDataListTaskDivision } from "../lib/type_task"
|
||||||
import { globalRefreshTask, valStatusDetailTask } from "../lib/val_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() {
|
export default function ListTugasDetailTask() {
|
||||||
const roleLogin = useHookstate(globalRole)
|
const roleLogin = useHookstate(globalRole)
|
||||||
const memberDivision = useHookstate(globalIsMemberDivision)
|
const memberDivision = useHookstate(globalIsMemberDivision)
|
||||||
|
const [openModalDetailTask, setOpenModalDetailTask] = useState(false)
|
||||||
const [openDrawer, setOpenDrawer] = useState(false)
|
const [openDrawer, setOpenDrawer] = useState(false)
|
||||||
const [openDrawerStatus, setOpenDrawerStatus] = useState(false)
|
const [openDrawerStatus, setOpenDrawerStatus] = useState(false)
|
||||||
const [isOpenModal, setOpenModal] = useState(false)
|
const [isOpenModal, setOpenModal] = useState(false)
|
||||||
@@ -268,6 +271,15 @@ export default function ListTugasDetailTask() {
|
|||||||
</Box>
|
</Box>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
|
<Flex onClick={() => { setOpenModalDetailTask(true) }} justify={'center'} align={'center'} direction={'column'} >
|
||||||
|
<Box>
|
||||||
|
<IoTimeOutline size={30} color={tema.get().utama} />
|
||||||
|
</Box>
|
||||||
|
<Box>
|
||||||
|
<Text c={tema.get().utama}>Detail Waktu</Text>
|
||||||
|
</Box>
|
||||||
|
</Flex>
|
||||||
|
|
||||||
<Flex onClick={() => { setOpenModal(true) }} justify={'center'} align={'center'} direction={'column'} >
|
<Flex onClick={() => { setOpenModal(true) }} justify={'center'} align={'center'} direction={'column'} >
|
||||||
<Box>
|
<Box>
|
||||||
<FaTrash size={30} color={tema.get().utama} />
|
<FaTrash size={30} color={tema.get().utama} />
|
||||||
@@ -281,6 +293,8 @@ export default function ListTugasDetailTask() {
|
|||||||
</Box>
|
</Box>
|
||||||
</LayoutDrawer>
|
</LayoutDrawer>
|
||||||
|
|
||||||
|
<ModalListDetailTugasTask open={openModalDetailTask} onClose={() => setOpenModalDetailTask(false)} task={idData} />
|
||||||
|
|
||||||
<LayoutModal loading={loadingHapus} opened={isOpenModal} onClose={() => setOpenModal(false)}
|
<LayoutModal loading={loadingHapus} opened={isOpenModal} onClose={() => setOpenModal(false)}
|
||||||
description="Apakah Anda yakin ingin menghapus tugas ini?"
|
description="Apakah Anda yakin ingin menghapus tugas ini?"
|
||||||
onYes={(val) => {
|
onYes={(val) => {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
import { getDatesInRange } from "@/lib/getDatesInRange";
|
||||||
import { LayoutNavbarNew, TEMA } from "@/module/_global";
|
import { LayoutNavbarNew, TEMA } from "@/module/_global";
|
||||||
import LayoutModal from "@/module/_global/layout/layout_modal";
|
import LayoutModal from "@/module/_global/layout/layout_modal";
|
||||||
import { useHookstate } from "@hookstate/core";
|
import { useHookstate } from "@hookstate/core";
|
||||||
@@ -10,11 +11,14 @@ import { useParams, useRouter } from "next/navigation";
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
import { funEditDetailTask, funGetDetailTask } from "../lib/api_task";
|
import { funEditDetailTask, funGetDetailTask } from "../lib/api_task";
|
||||||
|
import { ModalAddDetailTugasTask } from "./modal_add_detail_tugas_task";
|
||||||
|
|
||||||
|
|
||||||
export default function EditDetailTask() {
|
export default function EditDetailTask() {
|
||||||
const [value, setValue] = useState<[Date | null, Date | null]>([null, null]);
|
const [value, setValue] = useState<[Date | null, Date | null]>([null, null]);
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const [openModalDetailTask, setOpenModalDetailTask] = useState(false)
|
||||||
|
const [dataDetail, setDataDetail] = useState<any>([])
|
||||||
const [title, setTitle] = useState("")
|
const [title, setTitle] = useState("")
|
||||||
const param = useParams<{ id: string, detail: string }>()
|
const param = useParams<{ id: string, detail: string }>()
|
||||||
const [openModal, setOpenModal] = useState(false)
|
const [openModal, setOpenModal] = useState(false)
|
||||||
@@ -36,10 +40,15 @@ export default function EditDetailTask() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
setLoadingModal(true)
|
setLoadingModal(true)
|
||||||
|
const dataDetailFix = dataDetail.map((v: any) => ({
|
||||||
|
...v,
|
||||||
|
date: moment(v.date).format("YYYY-MM-DD"),
|
||||||
|
}))
|
||||||
const res = await funEditDetailTask(param.detail, {
|
const res = await funEditDetailTask(param.detail, {
|
||||||
title: title,
|
title: title,
|
||||||
dateStart: moment(value[0]).format('YYYY-MM-DD'),
|
dateStart: moment(value[0]).format('YYYY-MM-DD'),
|
||||||
dateEnd: moment(value[1]).format('YYYY-MM-DD'),
|
dateEnd: moment(value[1]).format('YYYY-MM-DD'),
|
||||||
|
dataDetail: dataDetailFix
|
||||||
})
|
})
|
||||||
|
|
||||||
if (res.success) {
|
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.dateStart).format('YYYY-MM-DD')),
|
||||||
new Date(moment(res.data.dateEnd).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 {
|
} else {
|
||||||
toast.error(res.message);
|
toast.error(res.message);
|
||||||
}
|
}
|
||||||
@@ -104,8 +125,15 @@ export default function EditDetailTask() {
|
|||||||
const array = val.split(",")
|
const array = val.split(",")
|
||||||
if (array[0] == '' || array[1] == '') {
|
if (array[0] == '' || array[1] == '') {
|
||||||
setTouched({ ...touched, date: true })
|
setTouched({ ...touched, date: true })
|
||||||
|
setDataDetail([])
|
||||||
} else {
|
} else {
|
||||||
setTouched({ ...touched, date: false })
|
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() {
|
|||||||
? <Text size="sm" c={"red"}>Tanggal Tidak Boleh Kosong</Text>
|
? <Text size="sm" c={"red"}>Tanggal Tidak Boleh Kosong</Text>
|
||||||
: <></>
|
: <></>
|
||||||
}
|
}
|
||||||
|
<Button
|
||||||
|
variant="light"
|
||||||
|
size="compact-md"
|
||||||
|
radius={5}
|
||||||
|
onClick={() => { setOpenModalDetailTask(true) }}
|
||||||
|
mt={5}
|
||||||
|
disabled={value[0] == null || value[1] == null || touched.date}
|
||||||
|
>
|
||||||
|
Detail
|
||||||
|
</Button>
|
||||||
<Stack pt={15} pb={100}>
|
<Stack pt={15} pb={100}>
|
||||||
{loading ?
|
{loading ?
|
||||||
<Skeleton height={40} mt={20} radius={10} />
|
<Skeleton height={40} mt={20} radius={10} />
|
||||||
@@ -229,6 +266,16 @@ export default function EditDetailTask() {
|
|||||||
}
|
}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
<ModalAddDetailTugasTask
|
||||||
|
open={openModalDetailTask}
|
||||||
|
onClose={() => setOpenModalDetailTask(false)}
|
||||||
|
data={dataDetail}
|
||||||
|
onSubmit={(data) => {
|
||||||
|
setDataDetail(data)
|
||||||
|
setOpenModalDetailTask(false)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
<LayoutModal loading={loadingModal} opened={openModal} onClose={() => setOpenModal(false)}
|
<LayoutModal loading={loadingModal} opened={openModal} onClose={() => setOpenModal(false)}
|
||||||
description="Apakah Anda yakin ingin mengubah data?"
|
description="Apakah Anda yakin ingin mengubah data?"
|
||||||
onYes={(val) => {
|
onYes={(val) => {
|
||||||
|
|||||||
100
src/module/task/ui/modal_add_detail_tugas_task.tsx
Normal file
100
src/module/task/ui/modal_add_detail_tugas_task.tsx
Normal file
@@ -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<any>([])
|
||||||
|
|
||||||
|
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 (
|
||||||
|
<Modal styles={{
|
||||||
|
body: {
|
||||||
|
borderRadius: 20
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
borderRadius: 20,
|
||||||
|
border: `2px solid ${"#828AFC"}`
|
||||||
|
}
|
||||||
|
}} opened={open} onClose={() => onClose()} centered withCloseButton={false} title={"Detail Tanggal dan Waktu Tugas"}>
|
||||||
|
<Box p={10}>
|
||||||
|
<Box>
|
||||||
|
{
|
||||||
|
dataDetail.map((data: any, index: any) => (
|
||||||
|
<Box key={index} py={10} style={{ borderBottom: `1px solid ${"#D6D8F6"}` }}>
|
||||||
|
<Text fw={"bold"}>{moment(data.date).format('DD-MM-YYYY')}</Text>
|
||||||
|
<SimpleGrid cols={{ base: 2, sm: 2, lg: 2 }}>
|
||||||
|
<TimeInput
|
||||||
|
styles={{
|
||||||
|
input: {
|
||||||
|
border: `1px solid ${"#D6D8F6"}`,
|
||||||
|
borderRadius: 10,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
size="md"
|
||||||
|
label="Waktu Awal"
|
||||||
|
value={data.timeStart}
|
||||||
|
onChange={(event) => onInputTime(data.date, event.target.value, 'timeStart')}
|
||||||
|
/>
|
||||||
|
<TimeInput
|
||||||
|
styles={{
|
||||||
|
input: {
|
||||||
|
border: `1px solid ${"#D6D8F6"}`,
|
||||||
|
borderRadius: 10,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
size="md"
|
||||||
|
label="Waktu Akhir"
|
||||||
|
value={data.timeEnd}
|
||||||
|
onChange={(event) => onInputTime(data.date, event.target.value, 'timeEnd')}
|
||||||
|
error={touched.find((item: any) => item.date == data.date)?.timeEnd ? "Waktu akhir harus lebih dari waktu awal" : ""}
|
||||||
|
/>
|
||||||
|
</SimpleGrid>
|
||||||
|
</Box>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</Box>
|
||||||
|
<Grid mt={10}>
|
||||||
|
<Grid.Col span={6}>
|
||||||
|
<Button variant="light" fullWidth color='#969494' onClick={() => onClose()}>Batalkan</Button>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={6}>
|
||||||
|
<Button variant="light" disabled={touched.length > 0} fullWidth color={TEMA.get().utama} onClick={() => { onSubmit(dataDetail) }}>Simpan</Button>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
</Box>
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}
|
||||||
99
src/module/task/ui/modal_list_tugas_task.tsx
Normal file
99
src/module/task/ui/modal_list_tugas_task.tsx
Normal file
@@ -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 (
|
||||||
|
<Modal styles={{
|
||||||
|
body: {
|
||||||
|
borderRadius: 20
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
borderRadius: 20,
|
||||||
|
border: `2px solid ${"#828AFC"}`
|
||||||
|
}
|
||||||
|
}} opened={open} onClose={() => onClose()} centered withCloseButton={false} title={"Detail Tanggal dan Waktu Tugas"}>
|
||||||
|
<Box p={10}>
|
||||||
|
<Box>
|
||||||
|
{
|
||||||
|
loading ?
|
||||||
|
Array(5)
|
||||||
|
.fill(null)
|
||||||
|
.map((_, i) => (
|
||||||
|
<Box key={i}>
|
||||||
|
<Box>
|
||||||
|
<Skeleton width={"100%"} mb={15} height={30} radius={"md"} />
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
))
|
||||||
|
:
|
||||||
|
dataDetail.length > 0 ?
|
||||||
|
dataDetail.map((data: any, index: any) => (
|
||||||
|
<Box key={index} py={10} style={{ borderBottom: `1px solid ${"#D6D8F6"}` }}>
|
||||||
|
<Text fw={"bold"}>{moment(data.date).format('DD-MM-YYYY')}</Text>
|
||||||
|
<SimpleGrid cols={{ base: 2, sm: 2, lg: 2 }}>
|
||||||
|
<TimeInput
|
||||||
|
styles={{
|
||||||
|
input: {
|
||||||
|
border: `1px solid ${"#D6D8F6"}`,
|
||||||
|
borderRadius: 10,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
size="md"
|
||||||
|
label="Waktu Awal"
|
||||||
|
value={data.timeStart}
|
||||||
|
readOnly
|
||||||
|
/>
|
||||||
|
<TimeInput
|
||||||
|
styles={{
|
||||||
|
input: {
|
||||||
|
border: `1px solid ${"#D6D8F6"}`,
|
||||||
|
borderRadius: 10,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
size="md"
|
||||||
|
label="Waktu Akhir"
|
||||||
|
value={data.timeEnd}
|
||||||
|
readOnly
|
||||||
|
/>
|
||||||
|
</SimpleGrid>
|
||||||
|
</Box>
|
||||||
|
))
|
||||||
|
:
|
||||||
|
<Text ta="center" c={"gray"}>Tidak ada detail tugas</Text>
|
||||||
|
}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user