fix: tugas divisi
Deskripsi; - klo lagi loading, total = 0 - pencarian - ga bisa semua di klik saat tampilan list - pencarian saat tambah anggota tambah tugas - loading skeleton saat pencarian anggota - menghapus fitur pilih semua pada pilih anggota - mengganti label error pada edit judul tugas - memberikan loading pada saat upload file No Issues
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
import { keyWibu, LayoutDrawer, LayoutNavbarNew, TEMA } from "@/module/_global";
|
||||
import LayoutModal from "@/module/_global/layout/layout_modal";
|
||||
import { useHookstate } from "@hookstate/core";
|
||||
import { Box, Button, Flex, Group, rem, SimpleGrid, Stack, Text, } from "@mantine/core";
|
||||
import { Box, Button, Flex, Group, Loader, rem, SimpleGrid, Stack, Text, } from "@mantine/core";
|
||||
import { Dropzone } from "@mantine/dropzone";
|
||||
import _ from "lodash";
|
||||
import { useParams, useRouter } from "next/navigation";
|
||||
@@ -27,6 +27,7 @@ export default function AddFileDetailTask() {
|
||||
const [openDrawerFile, setOpenDrawerFile] = useState(false)
|
||||
const tema = useHookstate(TEMA)
|
||||
const openRef = useRef<() => void>(null)
|
||||
const [loadingUpload, setLoadingUpload] = useState(false)
|
||||
const [dataRealTime, setDataRealtime] = useWibuRealtime({
|
||||
WIBU_REALTIME_TOKEN: keyWibu,
|
||||
project: "sdm"
|
||||
@@ -41,6 +42,7 @@ export default function AddFileDetailTask() {
|
||||
|
||||
async function cekFileName(data: any) {
|
||||
try {
|
||||
setLoadingUpload(true)
|
||||
const fd = new FormData();
|
||||
fd.append(`file`, data);
|
||||
const res = await funCekNamFileUploadTask(param.detail, fd)
|
||||
@@ -53,6 +55,8 @@ export default function AddFileDetailTask() {
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
toast.error("Gagal menambahkan file, coba lagi nanti")
|
||||
} finally {
|
||||
setLoadingUpload(false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,6 +150,12 @@ export default function AddFileDetailTask() {
|
||||
</Box>
|
||||
</Box>
|
||||
}
|
||||
{
|
||||
loadingUpload &&
|
||||
<Group justify="center" py={20}>
|
||||
<Loader color="gray" type="dots" />
|
||||
</Group>
|
||||
}
|
||||
</Box>
|
||||
<Box pos={'fixed'} bottom={0} p={rem(20)} w={"100%"} style={{
|
||||
maxWidth: rem(550),
|
||||
|
||||
@@ -4,7 +4,7 @@ import LayoutModal from "@/module/_global/layout/layout_modal";
|
||||
import { funGetSearchMemberDivision, IDataMemberDivision } from "@/module/division_new";
|
||||
import { useHookstate } from "@hookstate/core";
|
||||
import { Carousel } from "@mantine/carousel";
|
||||
import { ActionIcon, Avatar, Box, Button, Center, Divider, Flex, Grid, Group, Indicator, rem, Stack, Text, TextInput } from "@mantine/core";
|
||||
import { ActionIcon, Avatar, Box, Button, Center, Divider, Flex, Grid, Indicator, rem, Stack, Text, TextInput } from "@mantine/core";
|
||||
import { useMediaQuery, useShallowEffect } from "@mantine/hooks";
|
||||
import { useParams, useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
@@ -53,7 +53,6 @@ export default function AddMemberDetailTask() {
|
||||
toast.error(res.message);
|
||||
}
|
||||
|
||||
setLoading(false)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
toast.error("Gagal mendapatkan anggota, coba lagi nanti");
|
||||
@@ -143,6 +142,7 @@ export default function AddMemberDetailTask() {
|
||||
async function fetchGetMember(val: string) {
|
||||
setSearchQuery(val)
|
||||
try {
|
||||
setLoading(true)
|
||||
const res = await funGetSearchMemberDivision('?search=' + val, param.id);
|
||||
if (res.success) {
|
||||
setData(res.data)
|
||||
@@ -151,6 +151,8 @@ export default function AddMemberDetailTask() {
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,12 +245,12 @@ export default function AddMemberDetailTask() {
|
||||
|
||||
|
||||
<Box p={20}>
|
||||
<Group justify="space-between" mt={100} onClick={handleSelectAll}>
|
||||
{/* <Group justify="space-between" mt={100} onClick={handleSelectAll}>
|
||||
<Text c={tema.get().utama} fw={"bold"}>
|
||||
Pilih Semua Anggota
|
||||
</Text>
|
||||
{selectAll ? <FaCheck style={{ marginRight: 10 }} /> : ""}
|
||||
</Group>
|
||||
</Group> */}
|
||||
{loading ? Array(8)
|
||||
.fill(null)
|
||||
.map((_, i) => (
|
||||
@@ -267,7 +269,7 @@ export default function AddMemberDetailTask() {
|
||||
const isSelected = selectedFiles.some((i: any) => i?.idUser == v.idUser);
|
||||
const found = isDataMember.some((i: any) => i.idUser == v.idUser)
|
||||
return (
|
||||
<Box mb={15} key={i} onClick={() => (!found) ? handleFileClick(i) : null}>
|
||||
<Box mb={15} mt={i === 0 ? 100 : 0} key={i} onClick={() => (!found) ? handleFileClick(i) : null}>
|
||||
<Grid align='center'>
|
||||
<Grid.Col span={{
|
||||
base: 1,
|
||||
|
||||
@@ -34,7 +34,6 @@ export default function CreateTask() {
|
||||
const [dataTask, setDataTask] = useState<IFormDateTask[]>([])
|
||||
const openRef = useRef<() => void>(null)
|
||||
const [fileForm, setFileForm] = useState<any[]>([])
|
||||
const [imgForm, setImgForm] = useState<any>()
|
||||
const [listFile, setListFile] = useState<IListFileTask[]>([])
|
||||
const [indexDelFile, setIndexDelFile] = useState<number>(0)
|
||||
const [indexDelTask, setIndexDelTask] = useState<number>(0)
|
||||
|
||||
@@ -1,38 +1,20 @@
|
||||
"use client"
|
||||
import { LayoutNavbarNew, SkeletonList, SkeletonSingle, TEMA } from "@/module/_global";
|
||||
import { funGetDivisionById, funGetSearchMemberDivision, IDataMemberDivision } from "@/module/division_new";
|
||||
import { LayoutNavbarNew, SkeletonList, TEMA } from "@/module/_global";
|
||||
import { funGetSearchMemberDivision, IDataMemberDivision } from "@/module/division_new";
|
||||
import { useHookstate } from "@hookstate/core";
|
||||
import {
|
||||
ActionIcon,
|
||||
Avatar,
|
||||
Box,
|
||||
Button,
|
||||
Center,
|
||||
Divider,
|
||||
Flex,
|
||||
Grid,
|
||||
Group,
|
||||
Indicator,
|
||||
rem,
|
||||
Skeleton,
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
} from "@mantine/core";
|
||||
import { Carousel } from "@mantine/carousel";
|
||||
import { ActionIcon, Avatar, Box, Button, Center, Divider, Flex, Grid, Group, Indicator, rem, Skeleton, Stack, Text, TextInput } from "@mantine/core";
|
||||
import { useMediaQuery, useShallowEffect } from "@mantine/hooks";
|
||||
import { useParams, useRouter } from "next/navigation";
|
||||
import React, { useState } from "react";
|
||||
import { useState } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
import { globalMemberTask } from "../lib/val_task";
|
||||
import { FaCheck } from "react-icons/fa6";
|
||||
import { RiListCheck } from "react-icons/ri";
|
||||
import { BsListCheck } from "react-icons/bs";
|
||||
import { FaCheck } from "react-icons/fa6";
|
||||
import { HiChevronLeft, HiMagnifyingGlass } from "react-icons/hi2";
|
||||
import { IoArrowBackOutline, IoClose } from "react-icons/io5";
|
||||
import { Carousel } from "@mantine/carousel";
|
||||
import { globalMemberTask } from "../lib/val_task";
|
||||
|
||||
export default function CreateUsersProject({ onClose }: { onClose: (val: any) => void }) {
|
||||
const router = useRouter()
|
||||
const param = useParams<{ id: string }>()
|
||||
const [selectedFiles, setSelectedFiles] = useState<any>([])
|
||||
const [isData, setData] = useState<IDataMemberDivision[]>([])
|
||||
@@ -57,7 +39,6 @@ export default function CreateUsersProject({ onClose }: { onClose: (val: any) =>
|
||||
} else {
|
||||
toast.error(response.message)
|
||||
}
|
||||
setLoading(false)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
toast.error("Gagal mendapatkan anggota, coba lagi nanti");
|
||||
@@ -122,6 +103,7 @@ export default function CreateUsersProject({ onClose }: { onClose: (val: any) =>
|
||||
async function fetchGetMember(val: string) {
|
||||
setSearchQuery(val)
|
||||
try {
|
||||
setLoading(true)
|
||||
const res = await funGetSearchMemberDivision('?search=' + val, param.id);
|
||||
if (res.success) {
|
||||
setData(res.data)
|
||||
@@ -130,6 +112,8 @@ export default function CreateUsersProject({ onClose }: { onClose: (val: any) =>
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,7 +212,7 @@ export default function CreateUsersProject({ onClose }: { onClose: (val: any) =>
|
||||
|
||||
|
||||
<Box p={20}>
|
||||
{loading ?
|
||||
{/* {loading ?
|
||||
<Skeleton height={20} width={"100%"} mt={20} />
|
||||
:
|
||||
<Group justify="space-between" mt={100} onClick={handleSelectAll}>
|
||||
@@ -237,7 +221,7 @@ export default function CreateUsersProject({ onClose }: { onClose: (val: any) =>
|
||||
</Text>
|
||||
<BsListCheck size={25} style={{ marginRight: 5 }} color={tema.get().utama} />
|
||||
</Group>
|
||||
}
|
||||
} */}
|
||||
<Box mt={15} mb={100}>
|
||||
{loading ?
|
||||
Array(8)
|
||||
@@ -249,47 +233,47 @@ export default function CreateUsersProject({ onClose }: { onClose: (val: any) =>
|
||||
))
|
||||
:
|
||||
(isData.length === 0) ?
|
||||
<Stack align="stretch" justify="center" w={"100%"} h={"60vh"}>
|
||||
<Text c="dimmed" ta={"center"} fs={"italic"}>Tidak ada anggota</Text>
|
||||
</Stack>
|
||||
:
|
||||
isData.map((v, i) => {
|
||||
const isSelected = selectedFiles.some((i: any) => i?.idUser == v.idUser);
|
||||
return (
|
||||
<Box mb={15} key={i} onClick={() => handleFileClick(i)}>
|
||||
<Grid align='center'>
|
||||
<Grid.Col span={{
|
||||
base: 1,
|
||||
xs: 1,
|
||||
sm: 1,
|
||||
md: 1,
|
||||
lg: 1,
|
||||
xl: 1
|
||||
}}>
|
||||
<Avatar src={`https://wibu-storage.wibudev.com/api/files/${v.img}`} alt="it's me" size="lg" />
|
||||
</Grid.Col>
|
||||
<Grid.Col span={{
|
||||
base: 11,
|
||||
xs: 11,
|
||||
sm: 11,
|
||||
md: 11,
|
||||
lg: 11,
|
||||
xl: 11,
|
||||
}}>
|
||||
<Flex justify='space-between' align={"center"}>
|
||||
<Flex direction={'column'} align="flex-start" justify="flex-start">
|
||||
<Text lineClamp={1} pl={isMobile2 ? 40 : 30}>{v.name}</Text>
|
||||
<Stack align="stretch" justify="center" w={"100%"} h={"60vh"}>
|
||||
<Text c="dimmed" ta={"center"} fs={"italic"}>Tidak ada anggota</Text>
|
||||
</Stack>
|
||||
:
|
||||
isData.map((v, i) => {
|
||||
const isSelected = selectedFiles.some((i: any) => i?.idUser == v.idUser);
|
||||
return (
|
||||
<Box mb={15} key={i} onClick={() => handleFileClick(i)} mt={i===0 ? 100 : 0}>
|
||||
<Grid align='center'>
|
||||
<Grid.Col span={{
|
||||
base: 1,
|
||||
xs: 1,
|
||||
sm: 1,
|
||||
md: 1,
|
||||
lg: 1,
|
||||
xl: 1
|
||||
}}>
|
||||
<Avatar src={`https://wibu-storage.wibudev.com/api/files/${v.img}`} alt="it's me" size="lg" />
|
||||
</Grid.Col>
|
||||
<Grid.Col span={{
|
||||
base: 11,
|
||||
xs: 11,
|
||||
sm: 11,
|
||||
md: 11,
|
||||
lg: 11,
|
||||
xl: 11,
|
||||
}}>
|
||||
<Flex justify='space-between' align={"center"}>
|
||||
<Flex direction={'column'} align="flex-start" justify="flex-start">
|
||||
<Text lineClamp={1} pl={isMobile2 ? 40 : 30}>{v.name}</Text>
|
||||
</Flex>
|
||||
{isSelected ? <FaCheck /> : null}
|
||||
</Flex>
|
||||
{isSelected ? <FaCheck /> : null}
|
||||
</Flex>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
<Box mt={10}>
|
||||
<Divider size={"xs"} />
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
<Box mt={10}>
|
||||
<Divider size={"xs"} />
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
})
|
||||
);
|
||||
})
|
||||
}
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
@@ -114,7 +114,7 @@ export default function EditTask() {
|
||||
onChange={(e) => { onValidation('title', e.target.value) }}
|
||||
error={
|
||||
touched.title && (
|
||||
title == "" ? "Error! harus memasukkan judul tugas" : null
|
||||
title == "" ? "Judul Tugas Tidak Boleh Kosong" : null
|
||||
)
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { currentScroll, globalNotifPage, ReloadButtonTop, SkeletonList, TEMA } from "@/module/_global";
|
||||
import { useHookstate } from "@hookstate/core";
|
||||
import { ActionIcon, Avatar, Box, Card, Center, Divider, Flex, Grid, Group, Progress, Skeleton, Text, TextInput, Title } from "@mantine/core";
|
||||
import { useParams, useRouter, useSearchParams } from "next/navigation";
|
||||
import { useEffect, useState } from "react";
|
||||
import { HiMagnifyingGlass, HiMiniPresentationChartBar, HiOutlineListBullet, HiSquares2X2 } from "react-icons/hi2";
|
||||
import { MdAccountCircle } from "react-icons/md";
|
||||
import { IDataTask } from "../lib/type_task";
|
||||
import { funGetAllTask } from "../lib/api_task";
|
||||
import toast from "react-hot-toast";
|
||||
import { useMediaQuery, useShallowEffect } from "@mantine/hooks";
|
||||
import _ from "lodash";
|
||||
import { useHookstate } from "@hookstate/core";
|
||||
import { useParams, useRouter, useSearchParams } from "next/navigation";
|
||||
import { useEffect, useState } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
import { HiMagnifyingGlass, HiMiniPresentationChartBar, HiOutlineListBullet, HiSquares2X2 } from "react-icons/hi2";
|
||||
import { MdAccountCircle } from "react-icons/md";
|
||||
import { funGetAllTask } from "../lib/api_task";
|
||||
import { IDataTask } from "../lib/type_task";
|
||||
|
||||
export default function ListDivisionTask() {
|
||||
const [isList, setIsList] = useState(false)
|
||||
@@ -46,8 +46,6 @@ export default function ListDivisionTask() {
|
||||
} else {
|
||||
toast.error(response.message);
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
} catch (error) {
|
||||
toast.error("Gagal mendapatkan tugas divisi, coba lagi nanti");
|
||||
console.error(error);
|
||||
@@ -149,7 +147,7 @@ export default function ListDivisionTask() {
|
||||
<Box bg={tema.get().bgTotalKegiatan} p={10} style={{ borderRadius: 10 }}>
|
||||
<Text fw={'bold'} c={tema.get().utama}>Total Tugas</Text>
|
||||
<Flex justify={'center'} align={'center'} h={'100%'}>
|
||||
<Text fz={40} fw={'bold'} c={tema.get().utama}>{totalData}</Text>
|
||||
<Text fz={40} fw={'bold'} c={tema.get().utama}>{loading ? 0 : totalData}</Text>
|
||||
</Flex>
|
||||
</Box>
|
||||
{isList ? (
|
||||
@@ -173,7 +171,7 @@ export default function ListDivisionTask() {
|
||||
isData.map((v, i) => {
|
||||
return (
|
||||
<Box key={i}>
|
||||
<Grid align='center'>
|
||||
<Grid align='center' onClick={() => router.push(`task/${v.id}`)}>
|
||||
<Grid.Col span={{
|
||||
base: 1,
|
||||
xs: 1,
|
||||
@@ -182,7 +180,7 @@ export default function ListDivisionTask() {
|
||||
lg: 1,
|
||||
xl: 1
|
||||
}}>
|
||||
<Group onClick={() => router.push(`task/${v.id}`)}>
|
||||
<Group>
|
||||
<Center>
|
||||
<ActionIcon
|
||||
variant="gradient"
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
'use client'
|
||||
import { Box, Button, Flex, rem, Tabs } from "@mantine/core";
|
||||
import { TEMA } from "@/module/_global";
|
||||
import { useHookstate } from "@hookstate/core";
|
||||
import { Box, Button, Flex, rem } from "@mantine/core";
|
||||
import { useRouter, useSearchParams } from "next/navigation";
|
||||
import { IoIosCheckmarkCircleOutline } from "react-icons/io";
|
||||
import { IoCloseCircleOutline } from "react-icons/io5";
|
||||
import { RiProgress3Line } from "react-icons/ri";
|
||||
import { TbClockPause } from "react-icons/tb";
|
||||
import ListDivisionTask from "./list_division_task";
|
||||
import { useRouter, useSearchParams } from "next/navigation";
|
||||
import { Carousel } from "@mantine/carousel";
|
||||
import { TEMA } from "@/module/_global";
|
||||
import { useHookstate } from "@hookstate/core";
|
||||
|
||||
export default function TabsDivisionTask() {
|
||||
const iconStyle = { width: rem(20), height: rem(20) };
|
||||
@@ -43,40 +42,40 @@ export default function TabsDivisionTask() {
|
||||
return (
|
||||
<Box p={20}>
|
||||
<Box
|
||||
style={{
|
||||
display: "flex",
|
||||
gap: "20px",
|
||||
position: "relative",
|
||||
overflowX: "scroll",
|
||||
scrollbarWidth: "none",
|
||||
maxWidth: "550px"
|
||||
}}
|
||||
>
|
||||
<Flex gap={"md"} justify={"space-between"}>
|
||||
{dataStatus.map((item, index) => (
|
||||
<Button
|
||||
variant="subtle"
|
||||
color={
|
||||
status == item.id
|
||||
? "white"
|
||||
: (status == null && item.id == "0") ? "white" : tema.get().utama
|
||||
}
|
||||
onClick={() => { router.push("?status=" + item.id) }}
|
||||
defaultValue={(status == "1" || status == "2" || status == "3") ? status : "0"}
|
||||
radius={"xl"}
|
||||
key={index}
|
||||
bg={
|
||||
status == item.id
|
||||
? tema.get().bgFiturDivision
|
||||
: (status == null && item.id == "0") ? tema.get().bgFiturDivision : "transparent"
|
||||
}
|
||||
leftSection={item.icon}
|
||||
>
|
||||
{item.title}
|
||||
</Button>
|
||||
))}
|
||||
</Flex>
|
||||
</Box>
|
||||
style={{
|
||||
display: "flex",
|
||||
gap: "20px",
|
||||
position: "relative",
|
||||
overflowX: "scroll",
|
||||
scrollbarWidth: "none",
|
||||
maxWidth: "550px"
|
||||
}}
|
||||
>
|
||||
<Flex gap={"md"} justify={"space-between"}>
|
||||
{dataStatus.map((item, index) => (
|
||||
<Button
|
||||
variant="subtle"
|
||||
color={
|
||||
status == item.id
|
||||
? "white"
|
||||
: (status == null && item.id == "0") ? "white" : tema.get().utama
|
||||
}
|
||||
onClick={() => { router.push("?status=" + item.id) }}
|
||||
defaultValue={(status == "1" || status == "2" || status == "3") ? status : "0"}
|
||||
radius={"xl"}
|
||||
key={index}
|
||||
bg={
|
||||
status == item.id
|
||||
? tema.get().bgFiturDivision
|
||||
: (status == null && item.id == "0") ? tema.get().bgFiturDivision : "transparent"
|
||||
}
|
||||
leftSection={item.icon}
|
||||
>
|
||||
{item.title}
|
||||
</Button>
|
||||
))}
|
||||
</Flex>
|
||||
</Box>
|
||||
<ListDivisionTask />
|
||||
</Box>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user