Merge pull request #210 from bipproduction/amalia/06-september-24

upd: calender
This commit is contained in:
Amalia
2024-09-06 17:42:42 +08:00
committed by GitHub
5 changed files with 179 additions and 129 deletions

View File

@@ -0,0 +1,57 @@
import { prisma } from "@/module/_global";
import { funGetUserByCookies } from "@/module/auth";
import { createLogUser } from "@/module/user";
import _ from "lodash";
import { NextResponse } from "next/server";
// TAMBAH MEMBER KALENDER
export async function POST(request: Request, context: { params: { id: string } }) {
try {
const user = await funGetUserByCookies()
if (user.id == undefined) {
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
}
const { id } = context.params
const member = await request.json()
const cek = await prisma.divisionCalendar.count({
where: {
id: id
}
})
if (cek == 0) {
return NextResponse.json(
{
success: false,
message: "Gagal menambahkan anggota, data tidak ditemukan",
},
{ status: 404 }
);
}
if (member.length > 0) {
const dataMember = member.map((v: any) => ({
..._.omit(v, ["idUser", "name", "img"]),
idCalendar: id,
idUser: v.idUser,
}))
const insertMember = await prisma.divisionCalendarMember.createMany({
data: dataMember
})
}
// create log user
const log = await createLogUser({ act: 'CREATE', desc: 'User menambah anggota kalender', table: 'divisionCalendar', data: String(id) })
return NextResponse.json({ success: true, message: "Berhasil menambahkan anggota", }, { status: 200 });
} catch (error) {
console.error(error);
return NextResponse.json({ success: false, message: "Gagal menambah anggota, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
}
}

View File

@@ -1,4 +1,4 @@
import { IEditCalender, IFormCreateCalender } from "./type_calender";
import { IEditCalender, IFormCreateCalender, IFormMemberCalenderNew } from "./type_calender";
export const funGetAllCalender = async (path?: string) => {
const response = await fetch(`/api/calender${(path) ? path : ''}`, { next: { tags: ['calender'] } });
@@ -47,4 +47,15 @@ export const funEditCalenderById = async (path: string, data: IEditCalender) =>
export const funGetIndicatorCalender = async (path?: string) => {
const response = await fetch(`/api/calender/indicator${(path) ? path : ''}`, { next: { tags: ['hostory'] } });
return await response.json().catch(() => null);
}
}
export const funAddMemberCalender = async (path: string, data: IFormMemberCalenderNew) => {
const response = await fetch(`/api/calender/${path}/member`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
});
return await response.json().catch(() => null);
};

View File

@@ -93,4 +93,9 @@ export interface IDetailByIdCalender {
createdAt?: string
linkMeet?: string
repeatEventTyper?: string
}
export interface IFormMemberCalenderNew {
idUser: string
name: string
}

View File

@@ -1,9 +1,7 @@
"use client"
import React, { useState } from 'react';
import { globalCalender } from '../lib/val_calender';
import { useParams, useRouter } from 'next/navigation';
import { funGetDivisionById, funGetSearchMemberDivision, IDataMemberDivision } from '@/module/division_new';
import { useHookstate } from '@hookstate/core';
import { funGetSearchMemberDivision, IDataMemberDivision } from '@/module/division_new';
import toast from 'react-hot-toast';
import { useShallowEffect } from '@mantine/hooks';
import { LayoutNavbarNew, SkeletonSingle, WARNA } from '@/module/_global';
@@ -12,13 +10,15 @@ import { FaCheck } from 'react-icons/fa6';
import { HiMagnifyingGlass } from 'react-icons/hi2';
import { IoArrowBackOutline, IoClose } from 'react-icons/io5';
import { Carousel } from '@mantine/carousel';
import { funAddMemberCalender, funGetOneCalender } from '../lib/api_calender';
import { IDataDetailByIdMember } from '../lib/type_calender';
export default function CreateUserDetailCalender() {
const router = useRouter()
const param = useParams<{ id: string }>()
const param = useParams<{ id: string, detail: string }>()
const [selectedFiles, setSelectedFiles] = useState<any>([])
const [isData, setData] = useState<IDataMemberDivision[]>([])
const member = useHookstate(globalCalender)
const [isDataAnggota, setDataAnggota] = useState<IDataDetailByIdMember[]>([])
const [selectAll, setSelectAll] = useState(false)
const [loading, setLoading] = useState(true)
const [onClickSearch, setOnClickSearch] = useState(false)
@@ -28,11 +28,10 @@ export default function CreateUserDetailCalender() {
try {
setLoading(true)
const response = await funGetSearchMemberDivision("?search=", param.id)
const res = await funGetOneCalender(param.detail)
if (response.success) {
setDataAnggota(res.data.member)
setData(response.data)
if (member.length > 0) {
setSelectedFiles(JSON.parse(JSON.stringify(member.get())))
}
setLoading(false)
} else {
toast.error(response.message)
@@ -79,12 +78,23 @@ export default function CreateUserDetailCalender() {
};
function onSubmit() {
if (selectedFiles.length == 0) {
return toast.error("Error! silahkan pilih anggota")
async function onSubmit() {
try {
if (selectedFiles.length == 0) {
return toast.error("Error! silahkan pilih anggota")
}
const res = await funAddMemberCalender(param.detail, selectedFiles)
if (res.success) {
toast.success(res.message)
router.push('./')
} else {
toast.error(res.message)
}
} catch (error) {
console.error(error);
toast.error("Gagal menambahkan anggota, coba lagi nanti");
}
member.set(selectedFiles)
// onClose(true)
}
const handleSearchClick = () => {
@@ -161,8 +171,8 @@ export default function CreateUserDetailCalender() {
)
: null
}
{/* Close User */}
<Box pos={'fixed'} top={80} pl={rem(20)} pr={rem(20)} pt={rem(20)} pb={rem(5)} w={"100%"} style={{
{/* Close User */}
<Box pos={'fixed'} top={80} pl={rem(20)} pr={rem(20)} pt={rem(20)} pb={rem(5)} w={"100%"} style={{
maxWidth: rem(550),
zIndex: 100,
backgroundColor: `${WARNA.bgWhite}`,
@@ -220,8 +230,9 @@ export default function CreateUserDetailCalender() {
<Box mt={20} mb={100}>
{isData.map((v, i) => {
const isSelected = selectedFiles.some((i: any) => i?.idUser == v.idUser);
const found = isDataAnggota.some((i: any) => i.idUser == v.idUser)
return (
<Box mb={15} key={i} onClick={() => handleFileClick(i)}>
<Box mb={15} key={i} onClick={() => (!found) ? handleFileClick(i) : null}>
<Grid align='center' gutter={{
base: 60,
xl: "xs"
@@ -233,6 +244,7 @@ export default function CreateUserDetailCalender() {
<Flex justify='space-between' align={"center"}>
<Flex direction={'column'} align="flex-start" justify="flex-start">
<Text lineClamp={1}>{v.name}</Text>
<Text c={"dimmed"} lineClamp={1}>{(found) ? "sudah menjadi anggota" : ""}</Text>
</Flex>
{isSelected ? <FaCheck /> : null}
</Flex>

View File

@@ -193,131 +193,96 @@ export default function DetailEventDivision() {
</Stack>
</Box>
}
{/* {loading ?
<Box pt={20}>
<Box
style={{
border: `1px solid ${"#C7D6E8"}`,
borderRadius: 10,
}}
px={20}
pb={20}
>
{Array(4)
.fill(null)
.map((_, i) => (
<Box
key={i}
>
<SkeletonSingle />
</Box>
))}
</Box>
</Box>
:
<Box pt={20}>
<Group justify='space-between'>
<Text fw={"bold"}>Total Anggota</Text>
<Text>{isLengthMember} Anggota</Text>
</Group>
<Box mb={20}>
{
loading ?
<Box pt={20}>
<Box
style={{
border: `1px solid ${"#C7D6E8"}`,
borderRadius: 10,
}}
px={20}
pt={20}
pb={20}
>
{isLengthMember == 0 ? (
<Box style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '30vh' }}>
<Text c="dimmed" ta={"center"} fs={"italic"}>Tidak ada anggota</Text>
</Box>
) :
<Box>
{isDataAnggota.map((v, i) => {
return (
<Box my={10} key={i}>
<Grid align='center' gutter={"lg"}>
<Grid.Col span={{
base: 3,
xl: 2
}}>
<Avatar src={`/api/file/img?jenis=image&cat=user&file=${v.img}`} alt="it's me" size="lg" />
</Grid.Col>
<Grid.Col span={{
base: 9,
xl: 10
}}>
<Flex justify='space-between' align={"center"}>
<Flex direction={'column'} align="flex-start" justify="flex-start">
<Text lineClamp={1}>{v.name}</Text>
<Text c={"#5A687D"} fz={14} lineClamp={1}>
{v.email}
</Text>
</Flex>
</Flex>
</Grid.Col>
</Grid>
<Box mt={10}>
<Divider size={"xs"} />
</Box>
</Box>
);
})}
</Box>
}
{Array(4)
.fill(null)
.map((_, i) => (
<Box
key={i}
>
<SkeletonSingle />
</Box>
))}
</Box>
</Box>
</Box>
} */}
:
<Box pt={20}>
<Group justify='space-between'>
<Text fw={"bold"}>Total Anggota</Text>
<Text>{isLengthMember} Anggota</Text>
</Group>
<Box mb={20}>
<Box
style={{
border: `1px solid ${"#C7D6E8"}`,
borderRadius: 10,
}}
px={20}
pt={20}
>
<Box onClick={() => setOpenDrawerUser(true)}>
<Box my={10}>
<Grid align='center' gutter={"lg"}>
<Grid.Col span={{
base: 3,
xl: 2
}}>
<Avatar src={''} alt="it's me" size="lg" />
</Grid.Col>
<Grid.Col span={{
base: 9,
xl: 10
}}>
<Flex justify='space-between' align={"center"}>
<Flex direction={'column'} align="flex-start" justify="flex-start">
<Text lineClamp={1}>Nama</Text>
<Text c={"#5A687D"} fz={14} lineClamp={1}>
email.com
</Text>
</Flex>
</Flex>
</Grid.Col>
</Grid>
<Box mt={10}>
<Divider size={"xs"} />
</Box>
<Box pt={20}>
<Group justify='space-between'>
<Text fw={"bold"}>Total Anggota</Text>
<Text>{isLengthMember} Anggota</Text>
</Group>
<Box mb={20}>
<Box
style={{
border: `1px solid ${"#C7D6E8"}`,
borderRadius: 10,
}}
px={20}
pt={20}
>
{
isLengthMember == 0 ? (
<Box style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '30vh' }}>
<Text c="dimmed" ta={"center"} fs={"italic"}>Tidak ada anggota</Text>
</Box>
) :
<Box>
{
isDataAnggota.map((v, i) => {
return (
<Box onClick={() => setOpenDrawerUser(true)} key={i}>
<Box my={10}>
<Grid align='center' gutter={"lg"}>
<Grid.Col span={{
base: 3,
xl: 2
}}>
<Avatar src={`/api/file/img?jenis=image&cat=user&file=${v.img}`} alt="it's me" size="lg" />
</Grid.Col>
<Grid.Col span={{
base: 9,
xl: 10
}}>
<Flex justify='space-between' align={"center"}>
<Flex direction={'column'} align="flex-start" justify="flex-start">
<Text lineClamp={1}>{v.name}</Text>
<Text c={"#5A687D"} fz={14} lineClamp={1}>
{v.email}
</Text>
</Flex>
</Flex>
</Grid.Col>
</Grid>
<Box mt={10}>
<Divider size={"xs"} />
</Box>
</Box>
</Box>
)
})
}
</Box>
}
</Box>
</Box>
</Box>
</Box>
</Box>
}
</Box>
<LayoutDrawer opened={openDrawerUser} title={<Text lineClamp={1}>Menu</Text>} onClose={() => setOpenDrawerUser(false)}>
<Box>
<Stack pt={10}>