perbaikan(kolaborasi): memperbaiki bug modul kolaborasi dan tingkatkan komponen UI

Deskripsi:

- Perbaikan endpoint API dan routing kolaborasi
- Pembaruan tampilan grup kolaborasi dan partisipasi proyek
- Peningkatan komponen skeleton loading
- Perbaikan tampilan komponen avatar dan username
- Refaktor layout pembuatan dan detail kolaborasi
This commit is contained in:
2025-01-02 14:42:49 +08:00
parent ea2e52937c
commit d0def08ff6
26 changed files with 981 additions and 459 deletions

View File

@@ -1,4 +1,5 @@
import { prisma } from "@/app/lib";
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
import backendLogger from "@/util/backendLogger";
import { NextResponse } from "next/server";
@@ -11,36 +12,87 @@ export async function GET(
try {
let fixData;
const { id } = context.params;
const { searchParams } = new URL(request.url);
const kategori = searchParams.get("kategori");
const page = searchParams.get("page");
const takeData = 10;
const dataSkip = Number(page) * takeData - takeData;
// Buatkan api untuk list partisipasi
fixData = await prisma.projectCollaboration.findFirst({
where: {
id: id,
},
select: {
id: true,
isActive: true,
title: true,
lokasi: true,
purpose: true,
benefit: true,
createdAt: true,
// jumlah_partisipan: true,
Author: {
select: {
id: true,
Profile: true,
const userLoginId = await funGetUserIdByToken();
if (userLoginId == null) {
return NextResponse.json(
{
success: false,
message: "Gagal mendapatkan data, user id tidak ada",
},
{ status: 500 }
);
}
if (kategori == "detail") {
fixData = await prisma.projectCollaboration.findFirst({
where: {
id: id,
},
select: {
id: true,
isActive: true,
title: true,
lokasi: true,
purpose: true,
benefit: true,
createdAt: true,
// jumlah_partisipan: true,
Author: {
select: {
id: true,
Profile: true,
},
},
ProjectCollaborationMaster_Industri: true,
ProjectCollaboration_Partisipasi: {
where: {
isActive: true,
},
},
},
ProjectCollaborationMaster_Industri: true,
ProjectCollaboration_Partisipasi: {
where: {
isActive: true,
},
});
} else if (kategori == "list_partisipan") {
fixData = await prisma.projectCollaboration_Partisipasi.findMany({
take: takeData,
skip: dataSkip,
where: {
projectCollaborationId: id,
isActive: true,
},
},
});
select: {
id: true,
User: {
select: {
id: true,
Profile: true,
},
},
deskripsi_diri: true,
},
});
} else if (kategori == "cek_partisipasi") {
const cek = await prisma.projectCollaboration_Partisipasi.findFirst({
where: {
projectCollaborationId: id,
userId: userLoginId,
},
});
if (cek === null) {
fixData = false;
} else {
fixData = true;
}
}
return NextResponse.json(
{ success: true, message: "Berhasil mendapatkan data", data: fixData },

View File

@@ -0,0 +1,82 @@
import { prisma } from "@/app/lib";
import backendLogger from "@/util/backendLogger";
import { NextResponse } from "next/server";
export const dynamic = "force-dynamic";
export async function GET(
request: Request,
context: { params: { id: string } }
) {
try {
let fixData;
const { id } = context.params;
const { searchParams } = new URL(request.url);
const kategori = searchParams.get("kategori");
const page = searchParams.get("page");
const takeData = 10;
const skipData = Number(page) * takeData - takeData;
// data room { id, grup_name}
if (kategori == "detail") {
fixData = await prisma.projectCollaboration_RoomChat.findFirst({
where: {
id: id,
},
select: {
id: true,
name: true,
},
});
} else if (kategori == "info_group") {
fixData = await prisma.projectCollaboration_RoomChat.findFirst({
where: {
id: id,
},
select: {
id: true,
name: true,
ProjectCollaboration: {
select: {
id: true,
isActive: true,
title: true,
lokasi: true,
purpose: true,
benefit: true,
createdAt: true,
ProjectCollaborationMaster_Industri: true,
},
},
ProjectCollaboration_AnggotaRoomChat: {
select: {
User: {
select: {
id: true,
Profile: {
select: {
id: true,
name: true,
imageId: true,
},
},
},
},
},
},
},
});
}
return NextResponse.json(
{ success: true, message: "Berhasil mendapatkan data", data: fixData },
{ status: 200 }
);
} catch (error) {
backendLogger.error("Gagal mendapatkan data", error);
return NextResponse.json(
{ success: false, message: "Gagal mendapatkan data" },
{ status: 500 }
);
}
}

View File

@@ -15,6 +15,8 @@ export default async function Page({ params }: { params: { id: string } }) {
"ProjectCollaboration",
"ProjectCollaboration_AnggotaRoomChat",
]);
let listMsg = await colab_getMessageByRoomId({ roomId: roomId, page: 1 });
const dataUserLogin = await user_getOneByUserId(userLoginId as string);

View File

@@ -1,14 +1,9 @@
import prisma from "@/app/lib/prisma";
import { Colab_DetailInfoGrup } from "@/app_modules/colab";
import colab_getListAnggotaByRoomId from "@/app_modules/colab/fun/get/room_chat/get_list_anggota_by_room_id";
export default async function Page({ params }: { params: { id: string } }) {
let roomId = params.id;
const dataRoom = await colab_getListAnggotaByRoomId(roomId);
export default async function Page() {
return (
<>
<Colab_DetailInfoGrup dataRoom={dataRoom as any} />
<Colab_DetailInfoGrup />
</>
);
}

View File

@@ -1,24 +1,13 @@
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
import { Colab_MainDetail } from "@/app_modules/colab";
import colab_funCekPartisipasiById from "@/app_modules/colab/fun/get/cek_partisipasi_by_user_id";
import colab_getListPartisipanByColabId from "@/app_modules/colab/fun/get/get_list_partisipan_by_id";
import colab_getOneCollaborationById from "@/app_modules/colab/fun/get/get_one_by_id";
export default async function Page({ params }: { params: { id: string } }) {
let colabId = params.id;
export default async function Page() {
const userLoginId = await funGetUserIdByToken();
const dataColab = await colab_getOneCollaborationById(colabId);
const listPartisipan = await colab_getListPartisipanByColabId(colabId);
const cekPartisipan = await colab_funCekPartisipasiById(colabId);
return (
<>
<Colab_MainDetail
dataColab={{} as any}
userLoginId={userLoginId as string}
listPartisipan={listPartisipan as any}
cekPartisipan={cekPartisipan}
/>
</>
);

View File

@@ -3,7 +3,9 @@ import { LayoutColab_DetailPartisipasiProyek } from "@/app_modules/colab";
export default async function Layout({ children }: { children: any }) {
return (
<>
<LayoutColab_DetailPartisipasiProyek>{children}</LayoutColab_DetailPartisipasiProyek>
<LayoutColab_DetailPartisipasiProyek>
{children}
</LayoutColab_DetailPartisipasiProyek>
</>
);
}

View File

@@ -1,18 +1,9 @@
import { Colab_DetailPartisipasiProyek } from "@/app_modules/colab";
import colab_getListPartisipanByColabId from "@/app_modules/colab/fun/get/get_list_partisipan_by_id";
import colab_getOneCollaborationById from "@/app_modules/colab/fun/get/get_one_by_id";
export default async function Page({params}: {params: {id: string}}) {
const colabId = params.id
const dataColab = await colab_getOneCollaborationById(colabId)
const listPartisipan = await colab_getListPartisipanByColabId(colabId)
export default async function Page() {
return (
<>
<Colab_DetailPartisipasiProyek
dataColab={dataColab as any}
listPartisipan={listPartisipan as any}
/>
<Colab_DetailPartisipasiProyek />
</>
);
}

View File

@@ -3,19 +3,12 @@ import React from "react";
export default async function Layout({
children,
params,
}: {
children: React.ReactNode;
params: { id: string };
}) {
let colabId = params.id;
return (
<>
<LayoutColab_DetailProyekSaya colabId={colabId}>
{children}
</LayoutColab_DetailProyekSaya>
<LayoutColab_DetailProyekSaya>{children}</LayoutColab_DetailProyekSaya>
</>
);
}

View File

@@ -1,19 +1,9 @@
import { Colab_DetailProyekSaya } from "@/app_modules/colab";
import colab_getListPartisipanByColabId from "@/app_modules/colab/fun/get/get_list_partisipan_by_id";
import colab_getOneCollaborationById from "@/app_modules/colab/fun/get/get_one_by_id";
export default async function Page({ params }: { params: { id: string } }) {
const colabId = params.id;
const dataColab = await colab_getOneCollaborationById(colabId);
const listPartisipan = await colab_getListPartisipanByColabId(colabId);
export default async function Page() {
return (
<>
{/* <pre>{JSON.stringify(listPartisipan, null,2)}</pre> */}
<Colab_DetailProyekSaya
dataColab={dataColab as any}
listPartisipan={listPartisipan as any}
/>
<Colab_DetailProyekSaya />
</>
);
}

View File

@@ -5,7 +5,7 @@ import {
UIGlobal_LayoutHeaderTamplate,
UIGlobal_LayoutTamplate,
} from "@/app_modules/_global/ui";
import { Center, Grid, Group, Skeleton, Stack } from "@mantine/core";
import { Grid, Skeleton, Stack } from "@mantine/core";
export default function Voting_ComponentSkeletonViewPuh() {
return (
@@ -15,6 +15,23 @@ export default function Voting_ComponentSkeletonViewPuh() {
>
<Stack>
<ComponentGlobal_CardStyles marginBottom={"0"}>
<Stack>
<Skeleton h={20} w={100} />
{Array.from(new Array(2)).map((e, i) => (
<Grid align="center" gutter={"md"} key={i}>
<Grid.Col span={"content"}>
<Skeleton circle height={40} />
</Grid.Col>
<Grid.Col span={3}>
<Skeleton height={20} w={150} />
</Grid.Col>
</Grid>
))}
</Stack>
</ComponentGlobal_CardStyles>
{/* <ComponentGlobal_CardStyles marginBottom={"0"}>
<Stack spacing={"xl"}>
<Grid align="center" gutter={"md"}>
<Grid.Col span={"content"}>
@@ -23,9 +40,6 @@ export default function Voting_ComponentSkeletonViewPuh() {
<Grid.Col span={3}>
<Skeleton height={20} w={150} />
</Grid.Col>
{/* <Grid.Col span={3} offset={3}>
<Skeleton height={20} w={150} />
</Grid.Col> */}
</Grid>
<Center>
<Skeleton height={15} w={200} />
@@ -54,7 +68,7 @@ export default function Voting_ComponentSkeletonViewPuh() {
<Skeleton height={15} w={100} />
<Skeleton height={15} w={"100%"} />
</Stack>
</ComponentGlobal_CardStyles>
</ComponentGlobal_CardStyles> */}
{/* <ComponentGlobal_CardStyles>
<Stack>

View File

@@ -63,7 +63,7 @@ export function ComponentGlobal_AvatarAndUsername({
<Text
c={MainColor.white}
fw={"bold"}
fz={fontSize ? fontSize : "sm"}
fz={fontSize ? fontSize : "md"}
lineClamp={1}
onClick={() => onCheckProfile()}
>

View File

@@ -2,6 +2,20 @@ import { AccentColor, MainColor } from "@/app_modules/_global/color";
import { Card } from "@mantine/core";
import React from "react";
/**
* ComponentGlobal_CardStyles
*
* A React component that renders a customizable card element.
*
* Props:
* - children (React.ReactNode): Content to be displayed inside the card.
* - backgroundColor (string, optional): Background color of the card. Defaults to AccentColor.darkblue.
* - border (string, optional): Border color of the card. Defaults to AccentColor.blue.
* - marginBottom (string | number, optional): Margin below the card. Defaults to "15px".
* - height (string | number, optional): Height of the card. Defaults to "auto".
* - color (string, optional): Text color inside the card. Defaults to MainColor.white.
* - onClickHandler (React.MouseEventHandler<HTMLDivElement>, optional): Function to handle click events on the card.
*/
export function ComponentGlobal_CardStyles({
children,
backgroundColor,

View File

@@ -11,7 +11,33 @@ export const apiGetAllCollaboration = async ({
return await respone.json().catch(() => null);
};
export const apiGetOneCollaborationById = async ({ id }: { id: string }) => {
const respone = await fetch(`/api/collaboration/${id}`);
export const apiGetOneCollaborationById = async ({
id,
kategori,
page,
}: {
id: string;
kategori: "detail" | "list_partisipan" | "cek_partisipasi";
page?: string;
}) => {
const respone = await fetch(
`/api/collaboration/${id}?kategori=${kategori}&page=${page}`
);
return await respone.json().catch(() => null);
};
};
export const apiGetDataGroupById = async ({
id,
kategori,
page,
}: {
id: string;
kategori: "detail" | "info_group"
page?: string;
}) => {
const respone = await fetch(
`/api/collaboration/group/${id}?kategori=${kategori}&page=${page}`
);
return await respone.json().catch(() => null)
}

View File

@@ -19,15 +19,15 @@ export default function ComponentColab_DetailData({
<Stack spacing={"sm"}>
<Grid>
<Grid.Col span={2}>
<Text fw={"bold"} fz={"sm"}>
<Text fw={"bold"} >
Industri
</Text>
</Grid.Col>
<Grid.Col span={1}>
<Text fz={"sm"}>:</Text>
<Text >:</Text>
</Grid.Col>
<Grid.Col span={"auto"}>
<Text fz={"sm"}>
<Text >
{data?.ProjectCollaborationMaster_Industri.name
? data.ProjectCollaborationMaster_Industri.name
: "Industri"}
@@ -37,31 +37,31 @@ export default function ComponentColab_DetailData({
<Grid>
<Grid.Col span={2}>
<Text fw={"bold"} fz={"sm"}>
<Text fw={"bold"} >
Lokasi
</Text>
</Grid.Col>
<Grid.Col span={1}>
<Text fz={"sm"}>:</Text>
<Text >:</Text>
</Grid.Col>
<Grid.Col span={"auto"}>
<Text fz={"sm"} lineClamp={1}>
<Text lineClamp={1}>
{data?.lokasi ? data.lokasi : " Lokasi dari proyek"}
</Text>
</Grid.Col>
</Grid>
<Stack spacing={5}>
<Text fw={"bold"} fz={"sm"}>
<Text fw={"bold"} >
Tujuan proyek
</Text>
<Text fz={"sm"}>{data?.purpose ? data?.purpose : "-"}</Text>
<Text >{data?.purpose ? data?.purpose : "-"}</Text>
</Stack>
<Stack spacing={5}>
<Text fw={"bold"} fz={"sm"}>
<Text fw={"bold"} >
Keuntungan
</Text>
<Text fz={"sm"}>{data?.benefit ? data?.benefit : "-"}</Text>
<Text >{data?.benefit ? data?.benefit : "-"}</Text>
</Stack>
</Stack>
</Box>

View File

@@ -4,9 +4,14 @@ import {
AccentColor,
MainColor,
} from "@/app_modules/_global/color/color_pallet";
import { ComponentGlobal_CardStyles } from "@/app_modules/_global/component";
import ComponentGlobal_InputCountDown from "@/app_modules/_global/component/input_countdown";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil";
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global/notifikasi_gagal";
import notifikasiToUser_funCreate from "@/app_modules/notifikasi/fun/create/create_notif_to_user";
import { clientLogger } from "@/util/clientLogger";
import mqtt_client from "@/util/mqtt_client";
import {
ActionIcon,
Box,
@@ -14,86 +19,219 @@ import {
Center,
Drawer,
Group,
Paper,
ScrollArea,
Loader,
Stack,
Text,
Textarea,
Title,
} from "@mantine/core";
import { useDisclosure } from "@mantine/hooks";
import { useDisclosure, useShallowEffect } from "@mantine/hooks";
import { IconX } from "@tabler/icons-react";
import _ from "lodash";
import { ScrollOnly } from "next-scroll-loader";
import { useParams } from "next/navigation";
import { useState } from "react";
import { apiGetOneCollaborationById } from "../../_lib/api_collaboration";
import colab_funCreatePartisipan from "../../fun/create/fun_create_partisipan_by_user_id";
import colab_getListPartisipanByColabId from "../../fun/get/get_list_partisipan_by_id";
import { MODEL_COLLABORATION_PARTISIPASI } from "../../model/interface";
import { Collaboration_SkeletonListPrtisipanIsUser } from "../skeleton_view";
import ComponentColab_AuthorNameOnListPartisipan from "./header_author_list_partisipan";
import notifikasiToUser_funCreate from "@/app_modules/notifikasi/fun/create/create_notif_to_user";
import mqtt_client from "@/util/mqtt_client";
import { ComponentGlobal_CardStyles } from "@/app_modules/_global/component";
export default function ComponentColab_DetailListPartisipasiUser({
listPartisipan,
userLoginId,
authorId,
colabId,
cekPartisipan,
}: {
listPartisipan?: MODEL_COLLABORATION_PARTISIPASI[];
userLoginId?: string;
authorId?: string;
colabId?: string;
cekPartisipan?: boolean;
}) {
const [apply, setApply] = useState(false);
const [data, setData] = useState(listPartisipan);
const params = useParams<{ id: string }>();
const [data, setData] = useState<MODEL_COLLABORATION_PARTISIPASI[] | null>(
null
);
const [isPartisipan, setCekPartisipan] = useState<boolean | null>(null);
const [activePage, setActivePage] = useState(1);
const [opened, { open, close }] = useDisclosure(false);
const [deskripsi, setDeskripsi] = useState("");
const [isLoading, setIsLoading] = useState(false);
useShallowEffect(() => {
onLoadDataPartisipan();
}, []);
async function onJoin() {
const res = await colab_funCreatePartisipan(
colabId as any,
userLoginId as any,
deskripsi
);
if (res.status === 201) {
const dataNotif = {
appId: res?.data?.ProjectCollaboration?.id,
userId: res?.data?.ProjectCollaboration?.userId,
pesan: res?.data?.ProjectCollaboration?.title,
status: "Partisipan Project",
kategoriApp: "COLLABORATION",
title: "Partisipan baru telah bergabung !",
};
const createNotifikasi = await notifikasiToUser_funCreate({
data: dataNotif as any,
async function onLoadDataPartisipan() {
try {
const respone = await apiGetOneCollaborationById({
id: params.id,
kategori: "list_partisipan",
page: `${activePage}`,
});
if (createNotifikasi.status === 201) {
mqtt_client.publish(
"USER",
JSON.stringify({
userId: dataNotif.userId,
count: 1,
})
);
if (respone) {
setData(respone.data);
}
const resList = await colab_getListPartisipanByColabId(colabId as any);
setApply(true);
close();
setData(resList as any);
ComponentGlobal_NotifikasiBerhasil(res.message);
} else {
ComponentGlobal_NotifikasiGagal(res.message);
} catch (error) {
clientLogger.error("Error get list partisipan", error);
}
}
useShallowEffect(() => {
onCheckPartisipasi();
}, []);
async function onCheckPartisipasi() {
try {
const respone = await apiGetOneCollaborationById({
id: params.id,
kategori: "cek_partisipasi",
});
if (respone) {
setCekPartisipan(respone.data);
}
} catch (error) {
clientLogger.error("Error cek partisipasi", error);
}
}
async function onJoin() {
try {
setIsLoading(true);
const res = await colab_funCreatePartisipan({
id: params.id,
deskripsi: deskripsi,
});
if (res.status === 201) {
// const dataNotif = {
// appId: res?.data?.ProjectCollaboration?.id,
// userId: res?.data?.ProjectCollaboration?.userId,
// pesan: res?.data?.ProjectCollaboration?.title,
// status: "Partisipan Project",
// kategoriApp: "COLLABORATION",
// title: "Partisipan baru telah bergabung !",
// };
// const createNotifikasi = await notifikasiToUser_funCreate({
// data: dataNotif as any,
// });
// if (createNotifikasi.status === 201) {
// mqtt_client.publish(
// "USER",
// JSON.stringify({
// userId: dataNotif.userId,
// count: 1,
// })
// );
// }
const respone = await apiGetOneCollaborationById({
id: params.id,
kategori: "list_partisipan",
page: `${activePage}`,
});
if (respone) {
setData(respone.data);
}
const cekPartisipan = await apiGetOneCollaborationById({
id: params.id,
kategori: "cek_partisipasi",
});
if (cekPartisipan) {
setCekPartisipan(cekPartisipan);
}
close();
ComponentGlobal_NotifikasiBerhasil(res.message);
} else {
ComponentGlobal_NotifikasiGagal(res.message);
}
} catch (error) {
clientLogger.error("Error create partisipan", error);
} finally {
setIsLoading(false);
}
}
if (_.isNull(data) || _.isNull(isPartisipan)) {
return <Collaboration_SkeletonListPrtisipanIsUser />;
}
return (
<>
<Stack>
{userLoginId !== authorId && (
<Center>
<Button
radius={"xl"}
disabled={isPartisipan}
color={isPartisipan ? "green" : "yellow"}
onClick={open}
// bg={MainColor.yellow}
>
{isPartisipan ? "Telah Berpartisipasi" : "Partisipasi"}
</Button>
</Center>
)}
{_.isEmpty(data) ? (
<ComponentGlobal_CardStyles>
<Stack>
<Center>
<Title order={5}>Partispasi User ({data?.length})</Title>
</Center>
<ComponentGlobal_IsEmptyData
height={10}
text=" Tidak ada partisipan"
/>
</Stack>
</ComponentGlobal_CardStyles>
) : (
<ComponentGlobal_CardStyles>
<Stack spacing={"xl"}>
<Center>
<Title order={5}>Partispasi User ({data?.length})</Title>
</Center>{" "}
<Box>
<ScrollOnly
height="50vh"
renderLoading={() => (
<Center mt={"lg"}>
<Loader color={"yellow"} />
</Center>
)}
data={data}
setData={setData as any}
moreData={async () => {
const respone = await apiGetOneCollaborationById({
id: params.id,
kategori: "list_partisipan",
page: `${activePage + 1}`,
});
setActivePage((val) => val + 1);
return respone.data;
}}
>
{(item) => (
<ComponentColab_AuthorNameOnListPartisipan
isPembatas={true}
author={item.User}
deskripsi={item.deskripsi_diri}
/>
)}
</ScrollOnly>
</Box>
</Stack>
</ComponentGlobal_CardStyles>
)}
</Stack>
<Drawer
opened={opened}
onClose={close}
@@ -149,6 +287,8 @@ export default function ComponentColab_DetailListPartisipasiUser({
maxInput={300}
/>
<Button
loaderPosition="center"
loading={isLoading}
disabled={!deskripsi}
radius={"xl"}
color="yellow"
@@ -163,55 +303,6 @@ export default function ComponentColab_DetailListPartisipasiUser({
</Group>
</Stack>
</Drawer>
<Stack>
{userLoginId !== authorId ? (
<Center>
<Button
radius={"xl"}
disabled={cekPartisipan ? true : false}
color={cekPartisipan ? "green" : "yellow"}
onClick={open}
// bg={MainColor.yellow}
>
{cekPartisipan ? "Telah Berpartisipasi" : "Partisipasi"}
</Button>
</Center>
) : (
""
)}
<ComponentGlobal_CardStyles>
<Stack spacing={"xl"}>
<Center>
<Title order={5}>Partispasi User ({data?.length})</Title>
</Center>{" "}
<ScrollArea h={data?.length === 0 ? 30 : 400}>
<Box>
<Stack>
{data?.length === 0 ? (
<Center>
<Text fz={"xs"} fw={"bold"} c={"gray"}>
Tidak ada partisipan
</Text>
</Center>
) : (
data?.map((e, i) => (
<Box key={i}>
<ComponentColab_AuthorNameOnListPartisipan
isPembatas={true}
author={e.User}
deskripsi={e.deskripsi_diri}
/>
</Box>
))
)}
</Stack>
</Box>
</ScrollArea>
</Stack>
</ComponentGlobal_CardStyles>
</Stack>
</>
);
}

View File

@@ -3,6 +3,8 @@
import { ComponentGlobal_AvatarAndUsername } from "@/app_modules/_global/component";
import { Group, Stack, Text } from "@mantine/core";
import { useRouter } from "next/navigation";
import moment from "moment";
import "moment/locale/id";
export default function ComponentColab_AuthorNameOnHeader({
tglPublish,
@@ -19,10 +21,8 @@ export default function ComponentColab_AuthorNameOnHeader({
component={
<Group position="right">
{tglPublish ? (
<Text fz={"xs"}>
{new Intl.DateTimeFormat("id-ID", {
dateStyle: "medium",
}).format(tglPublish)}
<Text lineClamp={1}>
{moment(tglPublish).locale("id").format("ll")}
</Text>
) : (
""
@@ -65,7 +65,7 @@ export default function ComponentColab_AuthorNameOnHeader({
<Grid.Col span={"content"}>
<Stack justify="center" h={"100%"}>
{tglPublish ? (
<Text fz={"xs"}>
<Text >
{new Intl.DateTimeFormat("id-ID", {
dateStyle: "medium"

View File

@@ -1,30 +1,38 @@
import { ComponentGlobal_CardStyles } from "@/app_modules/_global/component";
import { Center, Grid, Skeleton, Stack } from "@mantine/core";
import { Center, Grid, Group, Skeleton, Stack } from "@mantine/core";
export {
Collaboration_SkeletonCreate,
Collaboration_SkeletonBeranda,
Collaboration_SkeletonCreate,
Collaboration_SkeletonDetail,
Collaboration_SkeletonDetailInfoGroup,
Collaboration_SkeletonGrup,
Collaboration_SkeletonListPartisipan,
Collaboration_SkeletonListPrtisipanIsUser,
};
function Collaboration_SkeletonCreate() {
return (
<>
<Stack px={"xl"} spacing={"lg"}>
<Stack px={"xl"} spacing={"md"}>
<Stack spacing={"xs"}>
<Skeleton height={10} width={50} />
<Skeleton height={15} width={50} />
<Skeleton height={40} />
</Stack>
<Stack spacing={"xs"}>
<Skeleton height={10} width={50} />
<Skeleton height={15} width={50} />
<Skeleton height={40} />
</Stack>
<Stack spacing={"xs"}>
<Skeleton height={10} width={50} />
<Skeleton height={15} width={50} />
<Skeleton height={40} />
</Stack>
<Stack spacing={"xs"}>
<Skeleton height={15} width={50} />
<Skeleton height={130} />
</Stack>
<Stack spacing={"xs"}>
<Skeleton height={10} width={50} />
<Skeleton height={15} width={50} />
<Skeleton height={130} />
</Stack>
@@ -94,9 +102,176 @@ function Collaboration_SkeletonGrup() {
<>
{Array.from(new Array(2)).map((e, i) => (
<ComponentGlobal_CardStyles marginBottom={"15px"} key={i}>
<Skeleton h={40} />
<Group position="apart">
<Stack>
<Skeleton h={15} w={100} />
<Skeleton h={15} w={50} />
</Stack>
<Skeleton circle height={20} />
</Group>
</ComponentGlobal_CardStyles>
))}
</>
);
}
function Collaboration_SkeletonDetail() {
return (
<>
<ComponentGlobal_CardStyles marginBottom={"0"}>
<Stack spacing={"xl"}>
<Grid align="center" gutter={"md"}>
<Grid.Col span={"content"}>
<Skeleton circle height={40} />
</Grid.Col>
<Grid.Col span={3}>
<Skeleton height={20} w={150} />
</Grid.Col>
</Grid>
<Center>
<Skeleton height={20} w={200} />
</Center>
<Grid align="center" gutter={"md"}>
<Grid.Col span={"content"}>
<Skeleton h={20} w={70} />
</Grid.Col>
<Grid.Col span={3}>
<Skeleton height={20} w={200} />
</Grid.Col>
</Grid>
<Grid align="center" gutter={"md"}>
<Grid.Col span={"content"}>
<Skeleton h={20} w={70} />
</Grid.Col>
<Grid.Col span={3}>
<Skeleton height={20} w={200} />
</Grid.Col>
</Grid>
<Skeleton height={20} w={100} />
<Skeleton height={20} w={"100%"} />
<Skeleton height={20} w={100} />
<Skeleton height={20} w={"100%"} />
</Stack>
</ComponentGlobal_CardStyles>
</>
);
}
function Collaboration_SkeletonListPrtisipanIsUser() {
return (
<>
<Stack>
<ComponentGlobal_CardStyles marginBottom={"0"}>
<Stack>
<Center>
<Skeleton h={20} w={100} />
</Center>
{Array.from(new Array(2)).map((e, i) => (
<Grid align="center" gutter={"md"} key={i}>
<Grid.Col span={"content"}>
<Skeleton circle height={40} />
</Grid.Col>
<Grid.Col span={3}>
<Skeleton height={20} w={150} />
</Grid.Col>
</Grid>
))}
</Stack>
</ComponentGlobal_CardStyles>
</Stack>
</>
);
}
function Collaboration_SkeletonListPartisipan() {
return (
<>
<Stack>
<Center>
<Skeleton h={40} w={150} radius={"xl"} />
</Center>
<ComponentGlobal_CardStyles marginBottom={"0"}>
<Stack>
<Center>
<Skeleton h={20} w={100} />
</Center>
{Array.from(new Array(2)).map((e, i) => (
<Grid align="center" gutter={"md"} key={i}>
<Grid.Col span={"content"}>
<Skeleton circle height={40} />
</Grid.Col>
<Grid.Col span={3}>
<Skeleton height={20} w={150} />
</Grid.Col>
</Grid>
))}
</Stack>
</ComponentGlobal_CardStyles>
</Stack>
</>
);
}
function Collaboration_SkeletonDetailInfoGroup() {
return (
<>
<Stack>
<ComponentGlobal_CardStyles marginBottom={"0"}>
<Stack spacing={"xl"}>
<Center>
<Skeleton height={20} w={200} />
</Center>
<Grid align="center" gutter={"md"}>
<Grid.Col span={"content"}>
<Skeleton h={20} w={70} />
</Grid.Col>
<Grid.Col span={3}>
<Skeleton height={20} w={200} />
</Grid.Col>
</Grid>
<Grid align="center" gutter={"md"}>
<Grid.Col span={"content"}>
<Skeleton h={20} w={70} />
</Grid.Col>
<Grid.Col span={3}>
<Skeleton height={20} w={200} />
</Grid.Col>
</Grid>
<Skeleton height={20} w={100} />
<Skeleton height={20} w={"100%"} />
<Skeleton height={20} w={"100%"} />
<Skeleton height={20} w={100} />
<Skeleton height={20} w={"100%"} />
<Skeleton height={20} w={"100%"} />
</Stack>
</ComponentGlobal_CardStyles>
<ComponentGlobal_CardStyles marginBottom={"0"}>
<Stack>
<Skeleton h={20} w={100} />
{Array.from(new Array(2)).map((e, i) => (
<Grid align="center" gutter={"md"} key={i}>
<Grid.Col span={"content"}>
<Skeleton circle height={40} />
</Grid.Col>
<Grid.Col span={3}>
<Skeleton height={20} w={150} />
</Grid.Col>
</Grid>
))}
</Stack>
</ComponentGlobal_CardStyles>
</Stack>
</>
);
}

View File

@@ -5,26 +5,22 @@ import ComponentGlobal_InputCountDown from "@/app_modules/_global/component/inpu
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil";
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global/notifikasi_gagal";
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global/notifikasi_peringatan";
import { clientLogger } from "@/util/clientLogger";
import mqtt_client from "@/util/mqtt_client";
import {
Button,
Center,
Select,
Stack,
TextInput,
Textarea,
Loader,
Textarea
} from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { Collaboration_SkeletonCreate } from "../component";
import { apiGetMasterCollaboration } from "../component/lib/api_collaboration";
import colab_funCreateProyek from "../fun/create/fun_create_proyek";
import { MODEL_COLLABORATION_MASTER } from "../model/interface";
import mqtt_client from "@/util/mqtt_client";
import { useHookstate } from "@hookstate/core";
import { useGsCollabCreate } from "../global_state/state";
import { useShallowEffect } from "@mantine/hooks";
import { apiGetMasterCollaboration } from "../component/lib/api_collaboration";
import { clientLogger } from "@/util/clientLogger";
import { Collaboration_SkeletonCreate } from "../component";
export default function Colab_Create() {
const [value, setValue] = useState({
@@ -103,7 +99,7 @@ export default function Colab_Create() {
}}
/>
{/* <Select
<Select
styles={{
label: {
color: "white",
@@ -122,25 +118,7 @@ export default function Colab_Create() {
projectCollaborationMaster_IndustriId: val as any,
});
}}
/> */}
{/* <TextInput
description={
<Text fz={10}>
minimal partisipan yang akan di pilih untuk mendiskusikan proyek
</Text>
}
type="number"
withAsterisk
label="Jumlah Partisipan"
placeholder={"2"}
onChange={(val) => {
setValue({
...value,
jumlah_partisipan: val.currentTarget.value as any,
});
}}
/> */}
/>
<Stack spacing={5}>
<Textarea
@@ -207,7 +185,6 @@ function ButtonAction({ value }: { value: any }) {
JSON.stringify({ isNewPost: true, count: 1 })
);
console.log(value.jumlah_partisipan);
if (value.title === "")
return ComponentGlobal_NotifikasiPeringatan("Lengkapi Data");
if (value.lokasi === "")
@@ -227,7 +204,6 @@ function ButtonAction({ value }: { value: any }) {
}
}
// console.log(value);
return (
<>

View File

@@ -26,7 +26,7 @@ import {
IconSend,
} from "@tabler/icons-react";
import _ from "lodash";
import { useRouter } from "next/navigation";
import { useParams, useRouter } from "next/navigation";
import { useState } from "react";
import useInfiniteScroll, {
ScrollDirection,
@@ -43,6 +43,8 @@ import {
MainColor,
} from "@/app_modules/_global/color/color_pallet";
import ComponentGlobal_Loader from "@/app_modules/_global/component/loader";
import { apiGetDataGroupById } from "../../_lib/api_collaboration";
import { clientLogger } from "@/util/clientLogger";
export default function Colab_GroupChatView({
userLoginId,
@@ -55,6 +57,7 @@ export default function Colab_GroupChatView({
selectRoom: MODEL_COLLABORATION_ROOM_CHAT;
dataUserLogin: MODEL_USER;
}) {
const params = useParams<{ id: string }>();
const router = useRouter();
const [loadingBack, setLoadingBack] = useState(false);
const [loadingInfo, setLoadingInfo] = useState(false);
@@ -66,6 +69,30 @@ export default function Colab_GroupChatView({
const [isGet, setIsGet] = useState(true);
const [newMessageId, setIdMessage] = useState("");
// NEW
const [dataGroup, setDataGroup] =
useState<MODEL_COLLABORATION_ROOM_CHAT | null>(null);
useShallowEffect(() => {
onLoadDataGroup();
}, []);
async function onLoadDataGroup() {
try {
const respone = await apiGetDataGroupById({
id: params.id,
kategori: "detail",
});
if (respone) {
setDataGroup(respone.data);
}
} catch (error) {
clientLogger.error("Error get data group", error);
}
}
const next = async (direction: ScrollDirection) => {
try {
setIsLoading(true);
@@ -220,7 +247,9 @@ export default function Colab_GroupChatView({
radius={"xl"}
onClick={() => {
setLoadingInfo(true);
router.push(RouterColab.info_grup + selectRoom.id, {scroll: false});
router.push(RouterColab.info_grup + selectRoom.id, {
scroll: false,
});
}}
>
{loadingInfo ? (

View File

@@ -1,56 +1,90 @@
"use client";
import { AccentColor } from "@/app_modules/_global/color/color_pallet";
import { ComponentGlobal_AvatarAndUsername, ComponentGlobal_CardStyles } from "@/app_modules/_global/component";
import {
ComponentGlobal_AvatarAndUsername,
ComponentGlobal_CardStyles,
} from "@/app_modules/_global/component";
import UIGlobal_LayoutHeaderTamplate from "@/app_modules/_global/ui/ui_header_tamplate";
import UIGlobal_LayoutTamplate from "@/app_modules/_global/ui/ui_layout_tamplate";
import { Box, Paper, Stack, Title } from "@mantine/core";
import { clientLogger } from "@/util/clientLogger";
import { Box, Stack, Title } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import _ from "lodash";
import { useParams } from "next/navigation";
import { useState } from "react";
import {
apiGetDataGroupById
} from "../../_lib/api_collaboration";
import ComponentColab_DetailData from "../../component/detail/detail_data";
import { MODEL_COLLABORATION_ROOM_CHAT } from "../../model/interface";
import {
Collaboration_SkeletonDetailInfoGroup
} from "../../component/skeleton_view";
import {
MODEL_COLLABORATION_ROOM_CHAT
} from "../../model/interface";
export default function Colab_DetailInfoGrup({
dataRoom,
}: {
dataRoom: MODEL_COLLABORATION_ROOM_CHAT;
}) {
export default function Colab_DetailInfoGrup() {
return (
<>
<UIGlobal_LayoutTamplate
header={<UIGlobal_LayoutHeaderTamplate title="Info Grup" />}
>
<InfoGroup dataRoom={dataRoom} />
<InfoGroup />
</UIGlobal_LayoutTamplate>
</>
);
}
function InfoGroup({ dataRoom }: { dataRoom: MODEL_COLLABORATION_ROOM_CHAT }) {
function InfoGroup() {
const params = useParams<{ id: string }>();
const [data, setData] = useState<MODEL_COLLABORATION_ROOM_CHAT | null>(null);
useShallowEffect(() => {
onLoadData();
}, []);
async function onLoadData() {
try {
const respone = await apiGetDataGroupById({
id: params.id,
kategori: "info_group",
});
if (respone) {
setData(respone.data);
}
} catch (error) {
clientLogger.error("Error get data info group", error);
}
}
if (_.isNull(data)) {
return (
<>
<Collaboration_SkeletonDetailInfoGroup />
</>
);
}
return (
<>
<ComponentGlobal_CardStyles>
<Stack>
<ComponentColab_DetailData data={dataRoom.ProjectCollaboration} />
<Paper
style={{
border: `2px solid ${AccentColor.softblue}`,
backgroundColor: AccentColor.blue,
color: "white",
borderRadius: "10px",
padding: "15px",
}}
>
<Stack>
<Title order={6}>Anggota Grup</Title>
{dataRoom.ProjectCollaboration_AnggotaRoomChat.map((e, i) => (
<Box key={i}>
<ComponentGlobal_AvatarAndUsername profile={e.User.Profile as any}/>
</Box>
))}
</Stack>
</Paper>
</Stack>
</ComponentGlobal_CardStyles>
<Stack>
<ComponentGlobal_CardStyles marginBottom={"0px"}>
<ComponentColab_DetailData data={data?.ProjectCollaboration} />
</ComponentGlobal_CardStyles>
<ComponentGlobal_CardStyles>
<Stack>
<Title order={6}>Anggota Grup</Title>
{data?.ProjectCollaboration_AnggotaRoomChat.map((e, i) => (
<Box mb={"sm"} key={i}>
<ComponentGlobal_AvatarAndUsername
profile={e.User.Profile as any}
/>
</Box>
))}
</Stack>
</ComponentGlobal_CardStyles>
</Stack>
</>
);
}

View File

@@ -1,38 +1,26 @@
"use client";
import { AccentColor } from "@/app_modules/_global/color/color_pallet";
import { Center, Stack, Loader } from "@mantine/core";
import { ComponentGlobal_CardStyles } from "@/app_modules/_global/component";
import { clientLogger } from "@/util/clientLogger";
import { Stack } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import _ from "lodash";
import { useParams } from "next/navigation";
import { useState } from "react";
import { apiGetOneCollaborationById } from "../../_lib/api_collaboration";
import ComponentColab_DetailData from "../../component/detail/detail_data";
import ComponentColab_DetailListPartisipasiUser from "../../component/detail/list_partisipasi_user";
import ComponentColab_AuthorNameOnHeader from "../../component/header_author_name";
import { Collaboration_SkeletonDetail } from "../../component/skeleton_view";
import { MODEL_COLLABORATION } from "../../model/interface";
import { ComponentGlobal_CardStyles } from "@/app_modules/_global/component";
import { clientLogger } from "@/util/clientLogger";
import { useShallowEffect } from "@mantine/hooks";
import { useState } from "react";
import {
apiGetAllCollaboration,
apiGetOneCollaborationById,
} from "../../_lib/api_collaboration";
import { useParams } from "next/navigation";
import _ from "lodash";
export default function Colab_MainDetail({
dataColab,
userLoginId,
listPartisipan,
cekPartisipan,
}: {
dataColab?: MODEL_COLLABORATION;
userLoginId?: string;
listPartisipan?: any[];
cekPartisipan: boolean;
}) {
const params = useParams<{ id: string }>();
const [data, setData] = useState<MODEL_COLLABORATION | null>(null);
const [activePage, setActivePage] = useState(1);
const [isNewPost, setIsNewPost] = useState(false);
useShallowEffect(() => {
onLoadData();
@@ -42,6 +30,7 @@ export default function Colab_MainDetail({
try {
const respone = await apiGetOneCollaborationById({
id: params.id,
kategori: "detail",
});
if (respone) {
@@ -52,38 +41,27 @@ export default function Colab_MainDetail({
}
}
if (_.isNull(data)) {
return (
<>
<Center>
<Loader />
</Center>
</>
);
}
return (
<>
<Stack>
<ComponentGlobal_CardStyles>
<Stack>
<ComponentColab_AuthorNameOnHeader
tglPublish={new Date()}
profile={data?.Author?.Profile as any}
/>
<ComponentColab_DetailData data={data as any} />
</Stack>
</ComponentGlobal_CardStyles>
{_.isNull(data) ? (
<Collaboration_SkeletonDetail />
) : (
<ComponentGlobal_CardStyles>
<Stack>
<ComponentColab_AuthorNameOnHeader
tglPublish={data.createdAt}
profile={data?.Author?.Profile as any}
/>
<ComponentColab_DetailData data={data as any} />
</Stack>
</ComponentGlobal_CardStyles>
)}
<ComponentColab_DetailListPartisipasiUser
listPartisipan={listPartisipan}
userLoginId={userLoginId}
authorId={data?.Author.id}
colabId={data?.id}
cekPartisipan={cekPartisipan}
/>
{/* <ComponentGlobal_CardStyles>
</ComponentGlobal_CardStyles> */}
<ComponentColab_DetailListPartisipasiUser
userLoginId={userLoginId}
authorId={data?.Author.id}
/>
</Stack>
</>
);

View File

@@ -1,36 +1,60 @@
"use client";
import { AccentColor } from "@/app_modules/_global/color/color_pallet";
import { ComponentGlobal_CardStyles } from "@/app_modules/_global/component";
import { apiGetOneCollaborationById } from "@/app_modules/colab/_lib/api_collaboration";
import ComponentColab_DetailData from "@/app_modules/colab/component/detail/detail_data";
import ComponentColab_DetailListPartisipasiUser from "@/app_modules/colab/component/detail/list_partisipasi_user";
import ComponentColab_AuthorNameOnHeader from "@/app_modules/colab/component/header_author_name";
import {
MODEL_COLLABORATION,
MODEL_COLLABORATION_PARTISIPASI,
} from "@/app_modules/colab/model/interface";
import { Stack, Text } from "@mantine/core";
import { Collaboration_SkeletonDetail } from "@/app_modules/colab/component/skeleton_view";
import { MODEL_COLLABORATION } from "@/app_modules/colab/model/interface";
import { clientLogger } from "@/util/clientLogger";
import { Stack } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import _ from "lodash";
import { useParams } from "next/navigation";
import { useState } from "react";
export default function Colab_DetailPartisipasiProyek() {
const params = useParams<{ id: string }>();
const [data, setData] = useState<MODEL_COLLABORATION | null>(null);
useShallowEffect(() => {
onLoadData();
}, []);
async function onLoadData() {
try {
const respone = await apiGetOneCollaborationById({
id: params.id,
kategori: "detail",
});
if (respone) {
setData(respone.data);
}
} catch (error) {
clientLogger.error("Error get all collaboration", error);
}
}
export default function Colab_DetailPartisipasiProyek({
dataColab,
listPartisipan,
}: {
dataColab: MODEL_COLLABORATION;
listPartisipan: MODEL_COLLABORATION_PARTISIPASI[];
}) {
return (
<>
<ComponentGlobal_CardStyles>
{_.isNull(data) ? (
<Collaboration_SkeletonDetail />
) : (
<Stack>
<ComponentColab_AuthorNameOnHeader
profile={dataColab.Author.Profile}
/>
<ComponentColab_DetailData data={dataColab} />
<ComponentColab_DetailListPartisipasiUser
listPartisipan={listPartisipan}
/>
<ComponentGlobal_CardStyles>
<Stack>
<ComponentColab_AuthorNameOnHeader
profile={data.Author.Profile}
/>
<ComponentColab_DetailData data={data} />
</Stack>
</ComponentGlobal_CardStyles>
<ComponentColab_DetailListPartisipasiUser />
</Stack>
</ComponentGlobal_CardStyles>
)}
</>
);
}

View File

@@ -9,83 +9,120 @@ import { ComponentGlobal_CardStyles } from "@/app_modules/_global/component";
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil";
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global/notifikasi_gagal";
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/_global/notif_global/notifikasi_peringatan";
import { apiGetOneCollaborationById } from "@/app_modules/colab/_lib/api_collaboration";
import ComponentColab_DetailData from "@/app_modules/colab/component/detail/detail_data";
import ComponentColab_AuthorNameOnListPartisipan from "@/app_modules/colab/component/detail/header_author_list_partisipan";
import ComponentColab_IsEmptyData from "@/app_modules/colab/component/is_empty_data";
import {
Collaboration_SkeletonDetail,
Collaboration_SkeletonListPrtisipanIsUser,
} from "@/app_modules/colab/component/skeleton_view";
import colab_funCreateRoomChat from "@/app_modules/colab/fun/create/fun_create_room_chat";
import { gs_colab_hot_menu } from "@/app_modules/colab/global_state";
import {
MODEL_COLLABORATION,
MODEL_COLLABORATION_PARTISIPASI,
} from "@/app_modules/colab/model/interface";
import mqtt_client from "@/util/mqtt_client";
import { clientLogger } from "@/util/clientLogger";
import {
ActionIcon,
Box,
Button,
Center,
Checkbox,
Drawer,
Grid,
Group,
Paper,
ScrollArea,
Loader,
Stack,
Text,
TextInput,
Title,
} from "@mantine/core";
import { useDisclosure } from "@mantine/hooks";
import { useDisclosure, useShallowEffect } from "@mantine/hooks";
import { IconX } from "@tabler/icons-react";
import { useAtom } from "jotai";
import _ from "lodash";
import { useRouter } from "next/navigation";
import { ScrollOnly } from "next-scroll-loader";
import { useParams, useRouter } from "next/navigation";
import { useState } from "react";
export default function Colab_DetailProyekSaya({
dataColab,
listPartisipan,
}: {
dataColab: MODEL_COLLABORATION;
listPartisipan: MODEL_COLLABORATION_PARTISIPASI[];
}) {
return (
<>
<ComponentGlobal_CardStyles marginBottom={"15px"}>
<Stack>
<ComponentColab_DetailData data={dataColab} />
<CheckBoxPartisipan
listPartisipan={listPartisipan}
colabId={dataColab.id}
/>
</Stack>
</ComponentGlobal_CardStyles>
</>
);
}
export default function Colab_DetailProyekSaya() {
const params = useParams<{ id: string }>();
const [data, setData] = useState<MODEL_COLLABORATION | null>(null);
function CheckBoxPartisipan({
listPartisipan,
colabId,
}: {
listPartisipan: MODEL_COLLABORATION_PARTISIPASI[];
colabId: string;
}) {
const [value, setValue] = useState<string[]>([]);
useShallowEffect(() => {
onLoadData();
}, []);
async function onLoadData() {
try {
const respone = await apiGetOneCollaborationById({
id: params.id,
kategori: "detail",
});
if (respone) {
setData(respone.data);
}
} catch (error) {
clientLogger.error("Error get all collaboration", error);
}
}
return (
<>
<Stack>
{/* <pre>{JSON.stringify(listPartisipan,null,2)}</pre> */}
<Paper
style={{
border: `2px solid ${AccentColor.softblue}`,
backgroundColor: AccentColor.blue,
color: "white",
borderRadius: "10px",
marginBottom: "20px",
padding: "15px",
}}
>
{/* {JSON.stringify(value, null, 2)} */}
{_.isNull(data) ? (
<Collaboration_SkeletonDetail />
) : (
<ComponentGlobal_CardStyles marginBottom={"15px"}>
<ComponentColab_DetailData data={data} />
</ComponentGlobal_CardStyles>
)}
<CheckBoxPartisipan />
</Stack>
</>
);
}
function CheckBoxPartisipan() {
const params = useParams<{ id: string }>();
const [value, setValue] = useState<string[]>([]);
const [data, setData] = useState<MODEL_COLLABORATION_PARTISIPASI[] | null>(
null
);
const [activePage, setActivePage] = useState(1);
useShallowEffect(() => {
onLoadDataPartisipan();
}, []);
async function onLoadDataPartisipan() {
try {
const respone = await apiGetOneCollaborationById({
id: params.id,
kategori: "list_partisipan",
page: `${activePage}`,
});
if (respone) {
setData(respone.data);
}
} catch (error) {
clientLogger.error("Error get list partisipan", error);
}
}
if (_.isNull(data)) {
return <Collaboration_SkeletonListPrtisipanIsUser />;
}
return (
<>
<Stack mb={"lg"}>
<ComponentGlobal_CardStyles>
<Stack>
<Stack spacing={5}>
<Text c={"red"} fz={10}>
@@ -94,52 +131,63 @@ function CheckBoxPartisipan({
Pilih user yang akan menjadi tim proyek anda
</Text>
</Text>
{/* <Text c={"red"} fz={10}>
*
<Text px={"xs"} span inherit c={"white"}>
Room chat dapat dibentuk jika ada 2 user yang dipilih
</Text>
</Text> */}
</Stack>
<ScrollArea h={400} offsetScrollbars>
<Checkbox.Group value={value} onChange={setValue}>
<Stack mt="xs">
{_.isEmpty(listPartisipan) ? (
<ComponentColab_IsEmptyData text="Tidak Ada Pertisipan" />
) : (
listPartisipan.map((e, i) => (
<Grid key={i} align="center">
{_.isEmpty(data) ? (
<ComponentColab_IsEmptyData text="Tidak Ada Pertisipan" />
) : (
<Box>
<ScrollOnly
height="50vh"
renderLoading={() => (
<Center mt={"lg"}>
<Loader color={"yellow"} />
</Center>
)}
data={data}
setData={setData as any}
moreData={async () => {
const respone = await apiGetOneCollaborationById({
id: params.id,
kategori: "list_partisipan",
page: `${activePage + 1}`,
});
setActivePage((val) => val + 1);
return respone.data;
}}
>
{(item) => (
<Checkbox.Group value={value} onChange={setValue}>
<Grid key={item} align="center">
<Grid.Col span={2}>
<Checkbox color={"yellow"} value={e?.User?.id} />
<Checkbox color={"yellow"} value={item.User?.id} />
</Grid.Col>
<Grid.Col span={"auto"}>
<ComponentColab_AuthorNameOnListPartisipan
isPembatas={true}
author={e?.User}
deskripsi={e?.deskripsi_diri}
author={item.User}
deskripsi={item.deskripsi_diri}
/>
</Grid.Col>
</Grid>
))
</Checkbox.Group>
)}
</Stack>
</Checkbox.Group>
</ScrollArea>
</ScrollOnly>
</Box>
)}
</Stack>
</Paper>
<ButtonAction value={value} colabId={colabId} />
</ComponentGlobal_CardStyles>
<ButtonAction value={value} />
</Stack>
</>
);
}
function ButtonAction({
value,
colabId,
}: {
value: string[];
colabId: string;
}) {
function ButtonAction({ value }: { value: string[] }) {
const params = useParams<{ id: string }>();
const router = useRouter();
const [opened, { open, close }] = useDisclosure(false);
const [hotMenu, setHotMenu] = useAtom(gs_colab_hot_menu);
@@ -147,29 +195,35 @@ function ButtonAction({
const [loading, setLoading] = useState(false);
async function onSave() {
if (nameRoom === "")
return ComponentGlobal_NotifikasiPeringatan("Lengkapi Nama Grup");
try {
setLoading(true);
if (nameRoom === "")
return ComponentGlobal_NotifikasiPeringatan("Lengkapi Nama Grup");
// await notifikasiToUser_CreateGroupCollaboration({ colabId: colabId });
// await notifikasiToUser_CreateGroupCollaboration({ colabId: colabId });
const res = await colab_funCreateRoomChat(nameRoom, value, colabId);
if (res.status === 201) {
for (let a of value) {
mqtt_client.publish(
"USER",
JSON.stringify({
userId: a,
count: 1,
})
);
const res = await colab_funCreateRoomChat(nameRoom, value, params.id);
if (res.status === 201) {
// for (let a of value) {
// mqtt_client.publish(
// "USER",
// JSON.stringify({
// userId: a,
// count: 1,
// })
// );
// }
ComponentGlobal_NotifikasiBerhasil("Berhasil Membuat Grup");
setHotMenu(4);
router.replace(RouterColab.grup_diskusi);
} else {
ComponentGlobal_NotifikasiGagal("Gagal Membuat Grup");
}
setLoading(true);
ComponentGlobal_NotifikasiBerhasil("Berhasil Membuat Grup");
setHotMenu(4);
router.push(RouterColab.grup_diskusi);
} else {
ComponentGlobal_NotifikasiGagal("Gagal Membuat Grup");
} catch (error) {
clientLogger.error("Error create room chat", error);
} finally {
setLoading(false);
}
}
@@ -188,7 +242,7 @@ function ButtonAction({
transition: "0.5s",
}}
>
Buat Ruang Diskusi{" "}
Buat Ruang Diskusi
</Button>
<Drawer

View File

@@ -6,22 +6,22 @@ import UIGlobal_LayoutHeaderTamplate from "@/app_modules/_global/ui/ui_header_ta
import UIGlobal_LayoutTamplate from "@/app_modules/_global/ui/ui_layout_tamplate";
import { ActionIcon } from "@mantine/core";
import { IconDotsVertical, IconEdit } from "@tabler/icons-react";
import { useParams } from "next/navigation";
import React, { useState } from "react";
export default function LayoutColab_DetailProyekSaya({
children,
colabId,
}: {
children: React.ReactNode;
colabId: string;
}) {
const params = useParams<{id: string}>()
const [openDrawer, setOpenDrawer] = useState(false);
const listPage = [
{
id: "1",
name: "Edit Proyek",
icon: <IconEdit />,
path: RouterColab.edit + colabId,
path: RouterColab.edit + params.id,
},
];

View File

@@ -2,17 +2,29 @@
import prisma from "@/app/lib/prisma";
import { RouterColab } from "@/app/lib/router_hipmi/router_colab";
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
import { revalidatePath } from "next/cache";
export default async function colab_funCreatePartisipan(
colabId: string,
userId: string,
deskripsi: string
) {
export default async function colab_funCreatePartisipan({
id,
deskripsi,
}: {
id: string;
deskripsi: string;
}) {
const userLoginId = await funGetUserIdByToken();
if (userLoginId == null) {
return {
status: 500,
message: "Gagal mendapatkan data, user id tidak ada",
};
}
const create = await prisma.projectCollaboration_Partisipasi.create({
data: {
projectCollaborationId: colabId,
userId: userId,
projectCollaborationId: id,
userId: userLoginId,
deskripsi_diri: deskripsi,
},
select: {
@@ -27,7 +39,7 @@ export default async function colab_funCreatePartisipan(
});
if (!create) return { status: 400, message: "Gagal menambahkan partisipan" };
revalidatePath(RouterColab.main_detail + colabId);
revalidatePath(RouterColab.main_detail + id);
return {
data: create,
status: 201,

View File

@@ -2,17 +2,16 @@
import { RouterColab } from "@/app/lib/router_hipmi/router_colab";
import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
import { clientLogger } from "@/util/clientLogger";
import { Box, Center, Loader } from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import _ from "lodash";
import { ScrollOnly } from "next-scroll-loader";
import { useState } from "react";
import { ComponentColab_CardSemuaPartisipan } from "../../component/card_view/card_semua_partisipan";
import colab_getListPartisipasiProyekByAuthorId from "../../fun/get/pasrtisipan/get_list_partisipasi_proyek_by_author_id";
import { MODEL_COLLABORATION_PARTISIPASI } from "../../model/interface";
import { useShallowEffect } from "@mantine/hooks";
import { apiGetAllCollaboration } from "../../_lib/api_collaboration";
import { clientLogger } from "@/util/clientLogger";
import { ComponentColab_CardSemuaPartisipan } from "../../component/card_view/card_semua_partisipan";
import { Collaboration_SkeletonBeranda } from "../../component/skeleton_view";
import { MODEL_COLLABORATION_PARTISIPASI } from "../../model/interface";
export default function Colab_PartisipasiProyek() {
const [data, setData] = useState<MODEL_COLLABORATION_PARTISIPASI[] | null>(