Admin Collaboration Done

# feat
- Detail Project
- Report Project
## No Issuue
This commit is contained in:
2024-05-10 15:16:09 +08:00
parent c34f9a9b75
commit dc41a5f9af
47 changed files with 2110 additions and 83 deletions

View File

@@ -41,6 +41,8 @@ model User {
ProjectCollaboration_RoomChat ProjectCollaboration_RoomChat[]
ProjectCollaboration_AnggotaRoomChat ProjectCollaboration_AnggotaRoomChat[]
ProjectCollaboration_Message ProjectCollaboration_Message[]
AdminProjectCollaboration_Notifikasi ProjectCollaboration_Notifikasi[] @relation("AdminNotifProjectToUser")
UserProjectCollaboration_Notifikasi ProjectCollaboration_Notifikasi[] @relation("UserNotifProjectToUser")
}
model MasterUserRole {
@@ -732,11 +734,12 @@ model ProjectCollaboration {
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
catatan String?
title String
lokasi String
purpose String @db.Text
benefit String? @db.Text
isReject Boolean? @default(false)
report String?
// jumlah_partisipan Int @default(0)
ProjectCollaborationMaster_Industri ProjectCollaborationMaster_Industri? @relation(fields: [projectCollaborationMaster_IndustriId], references: [id])
@@ -747,6 +750,7 @@ model ProjectCollaboration {
projectCollaborationMaster_StatusId Int? @default(1)
ProjectCollaboration_Partisipasi ProjectCollaboration_Partisipasi[]
ProjectCollaboration_RoomChat ProjectCollaboration_RoomChat[]
ProjectCollaboration_Notifikasi ProjectCollaboration_Notifikasi[]
}
model ProjectCollaborationMaster_Industri {
@@ -820,25 +824,17 @@ model ProjectCollaboration_Message {
projectCollaboration_RoomChatId String?
}
// jumlah yg belom ke read oleh user yang login
// find many ProjectCollaboration_AnggotaRoomChat where iduser login and is active = true,
// select nya relasi ke table chat
// count table message where idroomchat - count read message where idroomchat && iduser login
// TABLE MESSAGE
// id
// idroomchat
// iduser (yg ngesend)
// chat
// isFile def false
// time
// isActive def true
// find many where idroomchat order by time
// if iduser == user yg login >> posisi di kanan
// TABLE READ MESSAGE
// id
// idroomchat
// idmessage
// iduser (yg ngeread)
model ProjectCollaboration_Notifikasi {
id String @id @default(cuid())
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
isRead Boolean @default(false)
note String?
ProjectCollaboration ProjectCollaboration? @relation(fields: [projectCollaborationId], references: [id])
projectCollaborationId String
AdminId User @relation("AdminNotifProjectToUser", fields: [adminId], references: [id], map: "AdminNotifProjectUser")
adminId String
User User @relation("UserNotifProjectToUser", fields: [userId], references: [id], map: "UserNotifProjectUser")
userId String
}

View File

@@ -0,0 +1,9 @@
import ComponentAdminGlobal_LoadingPage from "@/app_modules/admin/component/loading_admin_page";
export default async function Page() {
return (
<>
<ComponentAdminGlobal_LoadingPage />
</>
);
}

View File

@@ -0,0 +1,20 @@
import { AdminColab_Dashboard } from "@/app_modules/admin/colab";
import adminColab_countGroupChat from "@/app_modules/admin/colab/fun/count/count_group_chat";
import adminColab_countIsPublish from "@/app_modules/admin/colab/fun/count/count_publish";
import adminColab_countIsReject from "@/app_modules/admin/colab/fun/count/count_reject";
export default async function Page() {
const countPublish = await adminColab_countIsPublish();
const countRoom = await adminColab_countGroupChat();
const countReject = await adminColab_countIsReject()
return (
<>
<AdminColab_Dashboard
countPublish={countPublish}
countRoom={countRoom}
countReject={countReject}
/>
</>
);
}

View File

@@ -0,0 +1,12 @@
import { AdminColab_TableGroup } from "@/app_modules/admin/colab";
import adminColab_getListAllGroupChat from "@/app_modules/admin/colab/fun/get/get_list_all_group_chat";
export default async function Page() {
const listGroup = await adminColab_getListAllGroupChat({page: 1})
return (
<>
<AdminColab_TableGroup listGroup={listGroup as any} />
</>
);
}

View File

@@ -0,0 +1,9 @@
import ComponentAdminGlobal_LoadingPage from "@/app_modules/admin/component/loading_admin_page";
export default async function Page() {
return (
<>
<ComponentAdminGlobal_LoadingPage />
</>
);
}

View File

@@ -0,0 +1,12 @@
import { AdminColab_TablePublish } from "@/app_modules/admin/colab";
import adminColab_getListAllPublish from "@/app_modules/admin/colab/fun/get/get_list_all_publish";
export default async function Page() {
const listData = await adminColab_getListAllPublish({ page: 1 });
return (
<>
<AdminColab_TablePublish listData={listData} />
</>
);
}

View File

@@ -0,0 +1,12 @@
import { AdminColab_TableRejected } from "@/app_modules/admin/colab";
import adminColab_getListAllRejected from "@/app_modules/admin/colab/fun/get/get_list_all_reject";
export default async function Page() {
const listReject = await adminColab_getListAllRejected({page: 1})
return (
<>
<AdminColab_TableRejected listReject={listReject as any} />
</>
);
}

View File

@@ -0,0 +1,27 @@
import adminColab_getOneRoomChatById from "@/app_modules/admin/colab/fun/get/get_one_room_chat_by_id";
import { Colab_GroupChatView } from "@/app_modules/colab";
import colab_getMessageByRoomId from "@/app_modules/colab/fun/get/room_chat/get_message_by_room_id";
import { user_getOneUserId } from "@/app_modules/fun_global/get_user_token";
import _ from "lodash";
export default async function Page({ params }: { params: { id: string } }) {
const roomId = params.id;
const userLoginId = await user_getOneUserId();
const dataRoom = (await adminColab_getOneRoomChatById({ roomId: roomId }))
.data;
const selectRoom = _.omit(dataRoom, [
"ProjectCollaboration",
"ProjectCollaboration_AnggotaRoomChat",
]);
let listMsg = await colab_getMessageByRoomId({roomId: roomId, page: 1});
return (
<>
<Colab_GroupChatView
userLoginId={userLoginId}
listMsg={listMsg}
selectRoom={selectRoom as any}
/>
</>
);
}

View File

@@ -4,7 +4,7 @@ import colab_getListAnggotaByRoomId from "@/app_modules/colab/fun/get/room_chat/
export default async function Page({ params }: { params: { id: string } }) {
let roomId = params.id;
const dataRoom = await colab_getListAnggotaByRoomId(roomId)
const dataRoom = await colab_getListAnggotaByRoomId(roomId);
return (
<>

View File

@@ -0,0 +1,13 @@
import { Colab_DetailNotifikasi } from "@/app_modules/colab";
import colab_getOneNotifikasiById from "@/app_modules/colab/fun/get/get_one_notifikasi_by_id";
export default async function Page({ params }: { params: { id: string } }) {
let notifId = params.id;
const data = await colab_getOneNotifikasiById({ notifId: notifId });
return (
<>
<Colab_DetailNotifikasi data={data as any} />
</>
);
}

View File

@@ -1,4 +1,5 @@
import { LayoutColab_Main } from "@/app_modules/colab";
import colab_CekNotifikasi from "@/app_modules/colab/fun/get/cek_notifikasi";
import React from "react";
export default async function Layout({
@@ -6,9 +7,11 @@ export default async function Layout({
}: {
children: React.ReactNode;
}) {
const cekNotif = await colab_CekNotifikasi();
return (
<>
<LayoutColab_Main>{children}</LayoutColab_Main>
<LayoutColab_Main cekNotif={cekNotif as any}>{children}</LayoutColab_Main>
</>
);
}

View File

@@ -1,9 +1,13 @@
import { Colab_NotifikasiView } from "@/app_modules/colab";
import colab_getListNotifikasiByUserId from "@/app_modules/colab/fun/get/get_list_notifikasi_by_user_id";
export default async function Page() {
const listNotifikasi = await colab_getListNotifikasiByUserId();
// console.log(listNotifikasi);
return (
<>
<Colab_NotifikasiView />
<Colab_NotifikasiView listNotifikasi={listNotifikasi as any} />
</>
);
}

View File

@@ -0,0 +1,6 @@
export const RouterAdminColab = {
dashboard: "/dev/admin/colab/dashboard",
table_publish: "/dev/admin/colab/sub-menu/publish",
table_group: "/dev/admin/colab/sub-menu/group",
table_reject: "/dev/admin/colab/sub-menu/reject",
};

View File

@@ -22,6 +22,8 @@ export const RouterColab = {
detail_proyek_saya: "/dev/colab/detail/proyek/saya/",
detail_grup: "/dev/colab/detail/grup/",
info_grup: "/dev/colab/detail/info-grup/",
detail_notifikasi: "/dev/colab/detail/notifikasi/",
group_chat: "/dev/colab/detail/group/",
// proyek
};

View File

@@ -5,6 +5,7 @@ import useInfiniteScroll, {
} from "react-easy-infinite-scroll-hook";
import { createItems, loadMore } from "./_util";
import { useShallowEffect } from "@mantine/hooks";
import { Center, Loader } from "@mantine/core";
export default function App() {
const [data, setData] = useState<any[]>([]);
@@ -20,7 +21,7 @@ export default function App() {
setIsLoading(true);
const newData = await loadMore();
const d = direction === "up"? [...newData, ...data]: []
const d = direction === "up" ? [...newData, ...data] : [];
setData(d);
} finally {
setIsLoading(false);
@@ -34,22 +35,25 @@ export default function App() {
});
return (
<div>
<div
ref={ref as any}
className="List"
style={{
height: 500,
overflowY: "auto",
}}
>
{data.map((key: any) => (
<div className="Row" key={key}>
{key}
</div>
))}
<Center>
<div>
<Center>{isLoading && <Loader />}</Center>
<div
ref={ref as any}
className="List"
style={{
height: 500,
overflowY: "auto",
}}
>
{data.map((key: any) => (
<div className="Row" key={key}>
{key}
</div>
))}
</div>
</div>
{isLoading && <div>Loading...</div>}
</div>
</Center>
);
}

View File

@@ -0,0 +1,68 @@
import { MODEL_COLLABORATION } from "@/app_modules/colab/model/interface";
import { Stack, Box, Center, Title, Grid, Text } from "@mantine/core";
export default function ComponentAdminColab_DetailData({
data,
}: {
data: MODEL_COLLABORATION;
}) {
return (
<>
<Stack>
<Box>
<Center px={"md"} mb={"lg"}>
<Title order={4}>{data?.title ? data.title : "Judul Proyek"}</Title>
</Center>
<Stack spacing={"sm"}>
<Grid>
<Grid.Col span={2}>
<Text fw={"bold"} fz={"sm"}>
Industri
</Text>
</Grid.Col>
<Grid.Col span={1}>
<Text fz={"sm"}>:</Text>
</Grid.Col>
<Grid.Col span={"auto"}>
<Text fz={"sm"}>
{data?.ProjectCollaborationMaster_Industri.name
? data.ProjectCollaborationMaster_Industri.name
: "Industri"}
</Text>
</Grid.Col>
</Grid>
<Grid>
<Grid.Col span={2}>
<Text fw={"bold"} fz={"sm"}>
Lokasi
</Text>
</Grid.Col>
<Grid.Col span={1}>
<Text fz={"sm"}>:</Text>
</Grid.Col>
<Grid.Col span={"auto"}>
<Text fz={"sm"} lineClamp={1}>
{data?.lokasi ? data.lokasi : " Lokasi dari proyek"}
</Text>
</Grid.Col>
</Grid>
<Stack spacing={5}>
<Text fw={"bold"} fz={"sm"}>
Tujuan proyek
</Text>
<Text fz={"sm"}>{data?.purpose ? data?.purpose : "-"}</Text>
</Stack>
<Stack spacing={5}>
<Text fw={"bold"} fz={"sm"}>
Keuntungan
</Text>
<Text fz={"sm"}>{data?.benefit ? data?.benefit : "-"}</Text>
</Stack>
</Stack>
</Box>
</Stack>
</>
);
}

View File

@@ -0,0 +1,72 @@
"use client";
import { Stack, SimpleGrid, Paper, Group, Title, Text } from "@mantine/core";
import { useRouter } from "next/navigation";
import ComponentAdminGlobal_HeaderTamplate from "../../component/header_tamplate";
export default function AdminColab_Dashboard({
countPublish,
countRoom,
countReject,
}: {
countPublish: number;
countRoom: number;
countReject: number;
}) {
const router = useRouter();
const listStatus = [
{
id: 1,
name: "Publish",
jumlah: countPublish,
color: "green",
},
{
id: 2,
name: "Group Chat",
jumlah: countRoom,
color: "orange",
},
{
id: 3,
name: "Reject",
jumlah: countReject,
color: "red",
},
];
return (
<>
<Stack>
<ComponentAdminGlobal_HeaderTamplate name="Project Collaboration" />
<SimpleGrid
cols={4}
spacing="lg"
breakpoints={[
{ maxWidth: "62rem", cols: 4, spacing: "lg" },
{ maxWidth: "48rem", cols: 2, spacing: "sm" },
{ maxWidth: "36rem", cols: 1, spacing: "sm" },
]}
>
{listStatus.map((e, i) => (
<Paper
key={i}
bg={"gray.2"}
shadow="md"
radius="md"
p="md"
// sx={{ borderColor: e.color, borderStyle: "solid" }}
>
<Group position="center">
<Stack align="center" spacing={0}>
<Text>{e.name}</Text>
<Title>{e.jumlah ? e.jumlah : 0}</Title>
</Stack>
</Group>
</Paper>
))}
</SimpleGrid>
</Stack>
</>
);
}

View File

@@ -0,0 +1,13 @@
"use server";
import prisma from "@/app/lib/prisma";
export default async function adminColab_countGroupChat() {
const count = await prisma.projectCollaboration_RoomChat.count({
where: {
isActive: true,
},
});
return count;
}

View File

@@ -0,0 +1,13 @@
"use server";
import prisma from "@/app/lib/prisma";
export default async function adminColab_countIsPublish() {
const count = await prisma.projectCollaboration.count({
where: {
isActive: true,
},
});
return count;
}

View File

@@ -0,0 +1,13 @@
"use server";
import prisma from "@/app/lib/prisma";
export default async function adminColab_countIsReject() {
const count = await prisma.projectCollaboration.count({
where: {
isReject: true,
},
});
return count;
}

View File

@@ -0,0 +1,46 @@
"use server";
import prisma from "@/app/lib/prisma";
import { RouterAdminColab } from "@/app/lib/router_admin/router_admin_colab";
import { user_getOneUserId } from "@/app_modules/fun_global/get_user_token";
import { revalidatePath } from "next/cache";
export default async function adminColab_funReportProjectById({
colabId,
report,
}: {
colabId: string;
report: string;
}) {
const authorId = await user_getOneUserId();
const projectUpdate = await prisma.projectCollaboration.update({
where: {
id: colabId,
},
data: {
isActive: false,
isReject: true,
report: report,
},
select: {
userId: true,
},
});
if (!projectUpdate) return { status: 400, message: "Gagal update project" };
const updateReport = await prisma.projectCollaboration_Notifikasi.create({
data: {
projectCollaborationId: colabId,
adminId: authorId,
userId: projectUpdate.userId as any,
note: "Project Anda Telah Direport Admin",
},
});
if (!updateReport) return { status: 400, message: "Gagal update notifikasi" };
revalidatePath(RouterAdminColab.table_publish);
return { status: 200, message: "Berhasil Update" };
}

View File

@@ -0,0 +1,74 @@
"use server";
import prisma from "@/app/lib/prisma";
import { ceil } from "lodash";
export default async function adminColab_getListAllGroupChat({
page,
}: {
page: number;
}) {
const lewat = page * 5 - 5;
const ambil = 5;
const dataAwal = await prisma.projectCollaboration_RoomChat.count({
where: {
isActive: true,
},
});
const getData = await prisma.projectCollaboration_RoomChat.findMany({
orderBy: {
createdAt: "desc",
},
where: {
isActive: true,
},
select: {
id: true,
createdAt: true,
isActive: true,
name: true,
ProjectCollaboration_AnggotaRoomChat: {
select: {
User: {
select: {
id: true,
Profile: true,
},
},
},
},
ProjectCollaboration: {
select: {
id: true,
isActive: true,
title: true,
lokasi: true,
purpose: true,
benefit: true,
createdAt: true,
report: true,
Author: {
select: {
id: true,
Profile: {
select: {
name: true,
},
},
},
},
ProjectCollaborationMaster_Industri: true,
},
},
},
});
const allData = {
data: getData,
nPage: ceil(dataAwal / ambil)
}
return allData;
}

View File

@@ -0,0 +1,76 @@
"use server";
import prisma from "@/app/lib/prisma";
import _, { ceil } from "lodash";
export default async function adminColab_getListAllPublish({
page,
}: {
page: number;
}) {
const lewat = page * 5 - 5;
const ambil = 5;
const awal = await prisma.projectCollaboration.count({
where: {
isActive: true,
isReject: false,
Author: {
active: true,
},
},
});
const getData = await prisma.projectCollaboration.findMany({
skip: lewat,
take: ambil,
orderBy: {
createdAt: "desc",
},
where: {
isActive: true,
isReject: false,
Author: {
active: true,
},
},
select: {
id: true,
createdAt: true,
isActive: true,
title: true,
Author: {
select: {
id: true,
username: true,
Profile: true,
},
},
projectCollaborationMaster_IndustriId: true,
ProjectCollaborationMaster_Industri: true,
ProjectCollaboration_Partisipasi: {
where: {
User: {
active: true,
},
},
// select: {
// User: {
// select: {
// id: true,
// username: true,
// Profile: true,
// },
// },
// },
},
},
});
const allData = {
data: getData,
nPage: ceil(awal / ambil),
};
return allData;
}

View File

@@ -0,0 +1,80 @@
"use server";
import prisma from "@/app/lib/prisma";
import _ from "lodash";
export default async function adminColab_getListAllRejected({
page,
}: {
page: number;
}) {
const lewat = page * 5 - 5;
const ambil = 5;
const dataAwal = await prisma.projectCollaboration.count({
where: {
isActive: false,
isReject: true,
Author: {
active: true,
},
},
});
const getData = await prisma.projectCollaboration.findMany({
skip: lewat,
take: ambil,
orderBy: {
updatedAt: "desc",
},
where: {
isActive: false,
isReject: true,
Author: {
active: true,
},
},
select: {
id: true,
createdAt: true,
isActive: true,
title: true,
report: true,
Author: {
select: {
id: true,
username: true,
Profile: true,
},
},
projectCollaborationMaster_IndustriId: true,
ProjectCollaborationMaster_Industri: true,
ProjectCollaboration_Partisipasi: {
where: {
User: {
active: true,
},
},
select: {
id: true,
User: {
select: {
Profile: {
select: {
name: true,
},
},
},
},
},
},
},
});
const allData = {
data: getData,
nPage: _.ceil(dataAwal / ambil),
};
return allData
}

View File

@@ -0,0 +1,54 @@
"use server";
import prisma from "@/app/lib/prisma";
export default async function adminColab_getOneByColabId({
id,
}: {
id: string;
}) {
const getData = await prisma.projectCollaboration.findFirst({
where: {
id: id,
},
select: {
id: true,
isActive: true,
title: true,
lokasi: true,
purpose: true,
benefit: true,
createdAt: true,
Author: {
select: {
id: true,
Profile: true,
},
},
ProjectCollaborationMaster_Industri: true,
ProjectCollaboration_Partisipasi: {
where: {
User: {
active: true,
},
},
select: {
id: true,
User: {
select: {
id: true,
Profile: {
select: {
name: true,
},
},
},
},
},
},
},
});
if (!getData) return { status: 400, message: "Gagal " };
return { data: getData, status: 200, message: " Berhasil" };
}

View File

@@ -0,0 +1,49 @@
"use server";
import prisma from "@/app/lib/prisma";
export default async function adminColab_getOneRoomChatById({
roomId,
}: {
roomId: string;
}) {
const get = await prisma.projectCollaboration_RoomChat.findFirst({
where: {
id: roomId,
},
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,
},
},
},
},
},
},
},
});
if (!get) return { status: 400, message: "Gagal ambil data" };
return {data: get, status: 200, message: "Berhasil ambil data" };
}

View File

@@ -0,0 +1,11 @@
import AdminColab_Dashboard from "./dashboard";
import AdminColab_TablePublish from "./sub_menu/publish";
import AdminColab_TableGroup from "./sub_menu/group";
import AdminColab_TableRejected from "./sub_menu/reject";
export {
AdminColab_Dashboard,
AdminColab_TablePublish,
AdminColab_TableGroup,
AdminColab_TableRejected,
};

View File

@@ -0,0 +1,249 @@
"use client";
import {
Stack,
Group,
Title,
Paper,
ScrollArea,
Table,
Center,
Text,
Badge,
Spoiler,
Pagination,
Button,
Modal,
SimpleGrid,
Box,
} from "@mantine/core";
import ComponentAdminGlobal_HeaderTamplate from "../../component/header_tamplate";
import {
MODEL_COLLABORATION,
MODEL_COLLABORATION_ROOM_CHAT,
} from "@/app_modules/colab/model/interface";
import { IconBan, IconCircleDot, IconEye } from "@tabler/icons-react";
import { useState } from "react";
import adminColab_getOneByColabId from "../fun/get/get_one_by_colab_id";
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/component_global/notif_global/notifikasi_gagal";
import ComponentAdminColab_DetailData from "../component/detail_data";
import adminColab_getOneRoomChatById from "../fun/get/get_one_room_chat_by_id";
import adminColab_getListAllGroupChat from "../fun/get/get_list_all_group_chat";
export default function AdminColab_TableGroup({
listGroup,
}: {
listGroup: any;
}) {
return (
<>
<Stack>
<ComponentAdminGlobal_HeaderTamplate name="Project Collaboration" />
<TableMenu listGroup={listGroup} />
</Stack>
</>
);
}
function TableMenu({ listGroup }: { listGroup: any }) {
const [data, setData] = useState<MODEL_COLLABORATION_ROOM_CHAT[]>(
listGroup.data
);
const [isNPage, setNPage] = useState(listGroup.nPage);
const [activePage, setActivePage] = useState(1);
const [idProject, setIdProject] = useState("");
const [openDetail, setOpenDetail] = useState(false);
const [loadingDetail, setLoadingDetail] = useState(false);
const [detailData, setDetailData] = useState<MODEL_COLLABORATION_ROOM_CHAT>();
// PAGINATION dan No awal data di tampilkan
let noAwal = activePage * 5 - 4;
async function onLoad(pindahPage: any) {
const load = await adminColab_getListAllGroupChat({ page: pindahPage });
setActivePage(pindahPage);
setData(load.data as any);
setNPage(load.nPage);
}
async function onDetailData(roomId: string) {
setLoadingDetail(true);
await adminColab_getOneRoomChatById({ roomId: roomId }).then((res) => {
if (res.status === 200) {
setIdProject(roomId);
setLoadingDetail(false);
setDetailData(res.data as any);
setOpenDetail(true);
} else {
ComponentGlobal_NotifikasiGagal(res.message);
}
});
}
const tableRow = data.map((e, i) => (
<tr key={i}>
<td>
<Center>{noAwal++}</Center>
</td>
<td>
<Center>
<Text lineClamp={1}>
{e?.ProjectCollaboration?.Author?.Profile?.name}
</Text>
</Center>
</td>
<td>
<Center>
<Text lineClamp={1}>{e?.name}</Text>
</Center>
</td>
<td>
<Center>
<Text>
{e?.ProjectCollaboration?.ProjectCollaborationMaster_Industri?.name}
</Text>
</Center>
</td>
<td>
<Center>
<Text>{e?.ProjectCollaboration_AnggotaRoomChat.length}</Text>
</Center>
</td>
<td>
<Center>
<Stack>
<Button
loading={
idProject === e?.id ? (loadingDetail ? true : false) : false
}
leftIcon={<IconEye />}
loaderPosition="center"
radius={"xl"}
color="green"
onClick={() => {
onDetailData(e?.id);
}}
>
Detail
</Button>
{/* <Button
// loading={
// idProject === e?.id ? (loadingReject ? true : false) : false
// }
leftIcon={<IconBan />}
loaderPosition="center"
radius={"xl"}
color="red"
// onClick={() => {
// onRejected(e.id);
// }}
>
Reject
</Button> */}
</Stack>
</Center>
</td>
</tr>
));
return (
<>
<Stack spacing={"xs"}>
<Group
position="apart"
bg={"blue.4"}
p={"xs"}
style={{ borderRadius: "6px" }}
>
<Title order={4}>Group Chat</Title>
</Group>
<Paper p={"md"} withBorder shadow="lg">
<Stack>
<ScrollArea h={"65vh"}>
<Table
verticalSpacing={"xs"}
horizontalSpacing={"md"}
p={"md"}
striped
highlightOnHover
>
<thead>
<tr>
<th>
<Center>No</Center>
</th>
<th>
<Center>Admin Room</Center>
</th>
<th>
<Center>Nama Group</Center>
</th>
<th>
<Center>Industri</Center>
</th>
<th>
<Center>Jumlah Partisipan</Center>
</th>
<th>
<Center>Aksi</Center>
</th>
</tr>
</thead>
<tbody>{tableRow}</tbody>
</Table>
</ScrollArea>
<Pagination
position="center"
total={isNPage}
value={activePage}
onChange={(val) => {
onLoad(val);
}}
/>
</Stack>
</Paper>
</Stack>
<Modal
opened={openDetail}
onClose={() => setOpenDetail(false)}
centered
size={"xl"}
withCloseButton={false}
>
<SimpleGrid cols={2}>
<Paper bg={"gray.1"} p={"md"} h={500}>
<ScrollArea h={"100%"} w={"100%"}>
<ComponentAdminColab_DetailData
data={detailData?.ProjectCollaboration as any}
/>
</ScrollArea>
</Paper>
<Paper bg={"gray.1"} p={"md"} h={500}>
<ScrollArea h={"100%"}>
<Stack>
<Center>
<Title order={4}>Partisipan</Title>
</Center>
<Stack>
{detailData?.ProjectCollaboration_AnggotaRoomChat?.map(
(e, i) => (
<Box key={i}>
<Text lineClamp={1}>
<IconCircleDot size={10} />{" "}
<Text span inherit>
{e?.User?.Profile?.name}
</Text>
</Text>
</Box>
)
)}
</Stack>
</Stack>
</ScrollArea>
</Paper>
</SimpleGrid>
</Modal>
{/* <pre>{JSON.stringify(detailData, null, 2)}</pre> */}
</>
);
}

View File

@@ -0,0 +1,314 @@
"use client";
import {
Stack,
Group,
Title,
Paper,
ScrollArea,
Table,
Center,
Text,
Badge,
Spoiler,
Pagination,
Button,
Modal,
TextInput,
Textarea,
Box,
} from "@mantine/core";
import ComponentAdminGlobal_HeaderTamplate from "../../component/header_tamplate";
import { MODEL_COLLABORATION } from "@/app_modules/colab/model/interface";
import { useState } from "react";
import { useDisclosure, useShallowEffect } from "@mantine/hooks";
import adminColab_getListAllPublish from "../fun/get/get_list_all_publish";
import ComponentAdminColab_DetailData from "../component/detail_data";
import adminColab_getOneByColabId from "../fun/get/get_one_by_colab_id";
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/component_global/notif_global/notifikasi_peringatan";
import _ from "lodash";
import { IconBan, IconCheck, IconEye } from "@tabler/icons-react";
import adminColab_funReportProjectById from "../fun/edit/fun_report_project_by_id";
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/component_global/notif_global/notifikasi_berhasil";
export default function AdminColab_TablePublish({
listData,
}: {
listData: any;
}) {
return (
<>
<Stack>
<ComponentAdminGlobal_HeaderTamplate name="Project Collaboration" />
<TableMenu listData={listData} />
{/* <pre>{JSON.stringify(listData.nPage, null, 2)}</pre> */}
</Stack>
</>
);
}
function TableMenu({ listData }: { listData: any }) {
const [data, setData] = useState<MODEL_COLLABORATION[]>(listData.data);
const [isNPage, setNPage] = useState(listData.nPage);
const [activePage, setActivePage] = useState(1);
const [idProject, setIdProject] = useState("");
const [openDetail, setOpenDetail] = useState(false);
const [loadingDetail, setLoadingDetail] = useState(false);
const [detailData, setDetailData] = useState<MODEL_COLLABORATION>();
const [openReject, setOpenReject] = useState(false);
const [report, setReport] = useState("");
const [loadingReject, setLoadingReject] = useState(false);
const [loadingReport, setLoadingReport] = useState(false);
// PAGINATION dan No awal data di tampilkan
let noAwal = activePage * 5 - 4;
async function onLoad(pindahPage: any) {
const load = await adminColab_getListAllPublish({ page: pindahPage });
setActivePage(pindahPage);
setData(load.data as any);
setNPage(load.nPage);
}
// Table Body
const tableRow = data.map((e, i) => (
<tr key={i}>
<td>
<Center>{noAwal++}</Center>
</td>
<td>
<Center>
<Text lineClamp={1}>{e?.Author?.Profile?.name}</Text>
</Center>
</td>
<td>
<Center>
<Box>
<Center>
<Text lineClamp={1}>{e?.title}</Text>
</Center>
</Box>
</Center>
</td>
<td>
<Center>
<Text>{e?.ProjectCollaborationMaster_Industri.name}</Text>
</Center>
</td>
<td>
<Center>
<Text>{e?.ProjectCollaboration_Partisipasi.length}</Text>
</Center>
</td>
<td>
<Center>
<Stack>
<Button
loading={
idProject === e?.id ? (loadingDetail ? true : false) : false
}
leftIcon={<IconEye />}
loaderPosition="center"
radius={"xl"}
color="green"
onClick={() => {
getDetailData(e.id);
}}
>
Detail
</Button>
<Button
loading={
idProject === e?.id ? (loadingReject ? true : false) : false
}
leftIcon={<IconBan />}
loaderPosition="center"
radius={"xl"}
color="red"
onClick={() => {
onRejected(e.id);
}}
>
Reject
</Button>
</Stack>
</Center>
</td>
</tr>
));
// Menampilkan Detail Data
async function getDetailData(colabId: any) {
setLoadingDetail(true);
setIdProject(colabId);
await adminColab_getOneByColabId({ id: colabId }).then((res) => {
if (res.status === 200) {
setDetailData(res.data as any);
setOpenDetail(true);
setLoadingDetail(false);
} else {
ComponentGlobal_NotifikasiPeringatan("Gagal Load");
}
});
}
// Menampilkan Data Title yang akan di REJECT
async function onRejected(colabId: string) {
setLoadingReject(true);
setIdProject(colabId);
await adminColab_getOneByColabId({ id: colabId }).then((res) => {
if (res.status === 200) {
const selectedData = _.omit(res.data, [
"Author",
"ProjectCollaborationMaster_Industri",
"ProjectCollaboration_Partisipasi",
"benefit",
"createdAt",
"purpose",
"lokasi",
]);
setDetailData(selectedData as any);
setOpenReject(true);
setLoadingReject(false);
} else {
ComponentGlobal_NotifikasiPeringatan("Gagal Load");
}
});
}
// Update status report pada project
async function onReport() {
if (report === "")
return ComponentGlobal_NotifikasiPeringatan("Lengkapi Alasan Report");
await adminColab_funReportProjectById({
colabId: idProject,
report: report,
}).then(async (res) => {
if (res.status === 200) {
const newData = await adminColab_getListAllPublish({
page: activePage,
});
setActivePage(activePage);
setData(newData.data as any);
setNPage(newData.nPage);
setOpenReject(false);
ComponentGlobal_NotifikasiBerhasil(res.message);
} else {
ComponentGlobal_NotifikasiPeringatan(res.message);
}
});
}
return (
<>
<Stack spacing={"xs"}>
<Group
position="apart"
bg={"green.4"}
p={"xs"}
style={{ borderRadius: "6px" }}
>
<Title order={4}>Publish</Title>
</Group>
<Paper p={"md"} withBorder shadow="lg" >
<Stack>
<ScrollArea h={"65vh"}>
<Table
verticalSpacing={"xs"}
horizontalSpacing={"md"}
p={"md"}
striped
highlightOnHover
>
<thead>
<tr>
<th>
<Center>No</Center>
</th>
<th>
<Center>Username</Center>
</th>
<th>
<Center>Title</Center>
</th>
<th>
<Center>Industri</Center>
</th>
<th>
<Center>Jumlah Partisipan</Center>
</th>
<th>
<Center>Aksi</Center>
</th>
</tr>
</thead>
<tbody>{tableRow}</tbody>
</Table>
</ScrollArea>
<Pagination
position="center"
total={isNPage}
value={activePage}
onChange={(val) => {
onLoad(val);
}}
/>
</Stack>
</Paper>
</Stack>
{/* Detail Data */}
<Modal
opened={openDetail}
onClose={() => setOpenDetail(false)}
centered
withCloseButton={false}
size={"lg"}
>
<Paper p={"md"} bg={"gray.1"}>
<ComponentAdminColab_DetailData data={detailData as any} />
</Paper>
</Modal>
{/* Reject Project */}
<Modal
opened={openReject}
onClose={() => setOpenReject(false)}
centered
withCloseButton={false}
size={"lg"}
>
<Paper p={"md"}>
<Stack>
<Text>
Apakah anda yakin ingin mereport project{" "}
<Text span inherit fw={"bold"}>
{detailData?.title}
</Text>
?
</Text>{" "}
<Textarea
minRows={2}
placeholder="Ketik alasan report.."
onChange={(val) => setReport(val.currentTarget.value)}
/>
<Group position="right">
<Button
leftIcon={<IconCheck />}
radius={"xl"}
onClick={() => onReport()}
>
Simpan
</Button>
</Group>
</Stack>
</Paper>
</Modal>
</>
);
}

View File

@@ -0,0 +1,186 @@
"use client";
import {
Stack,
Group,
Title,
Paper,
ScrollArea,
Table,
Center,
Text,
Badge,
Spoiler,
Box,
Pagination,
} from "@mantine/core";
import ComponentAdminGlobal_HeaderTamplate from "../../component/header_tamplate";
import { useState } from "react";
import { MODEL_COLLABORATION } from "@/app_modules/colab/model/interface";
import adminColab_getListAllRejected from "../fun/get/get_list_all_reject";
export default function AdminColab_TableRejected({
listReject,
}: {
listReject: any;
}) {
return (
<>
<Stack>
<ComponentAdminGlobal_HeaderTamplate name="Project Collaboration" />
<TableMenu listReject={listReject} />
</Stack>
</>
);
}
function TableMenu({ listReject }: { listReject: any }) {
const [data, setData] = useState<MODEL_COLLABORATION[]>(listReject.data);
const [isNPage, setNPage] = useState(listReject.nPage);
const [activePage, setActivePage] = useState(1);
let noAwal = activePage * 5 - 4;
async function onLoad(pindahPage: any) {
const load = await adminColab_getListAllRejected({ page: pindahPage });
setActivePage(pindahPage);
setData(load.data as any);
setNPage(load.nPage);
}
const tableRow = data?.map((e, i) => (
<tr key={i}>
<td>
<Center>{noAwal++}</Center>
</td>
<td>
<Center>
<Text lineClamp={1}>{e?.Author?.Profile?.name}</Text>
</Center>
</td>
<td>
<Center>
<Box>
<Center>
<Text lineClamp={1}>{e?.title}</Text>
</Center>
</Box>
</Center>
</td>
<td>
<Center>
<Text>{e?.ProjectCollaborationMaster_Industri.name}</Text>
</Center>
</td>
<td>
<Center>
<Text>{e?.ProjectCollaboration_Partisipasi.length}</Text>
</Center>
</td>
<td>
<Center>
<Box w={400}>
<Center>
<Spoiler
hideLabel={"sembunyikan"}
maxHeight={50}
showLabel="tampilkan"
>
{e?.report}
</Spoiler>
</Center>
</Box>
</Center>
{/* <Stack>
<Button
loading={
idProject === e?.id ? (loadingDetail ? true : false) : false
}
leftIcon={<IconEye />}
loaderPosition="center"
radius={"xl"}
color="green"
onClick={() => {
getDetailData(e.id);
}}
>
Detail
</Button>
<Button
loading={
idProject === e?.id ? (loadingReject ? true : false) : false
}
leftIcon={<IconBan />}
loaderPosition="center"
radius={"xl"}
color="red"
onClick={() => {
onRejected(e.id);
}}
>
Reject
</Button>
</Stack> */}
</td>
</tr>
));
return (
<>
<Stack spacing={"xs"}>
<Group
position="apart"
bg={"red.4"}
p={"xs"}
style={{ borderRadius: "6px" }}
>
<Title order={4}>Reject</Title>
</Group>
<Paper p={"md"} withBorder shadow="lg">
<Stack>
<ScrollArea h={"65vh"}>
<Table
verticalSpacing={"lg"}
horizontalSpacing={"md"}
p={"md"}
striped
highlightOnHover
>
<thead>
<tr>
<th>
<Center>No</Center>
</th>
<th>
<Center>Username</Center>
</th>
<th>
<Center>Title</Center>
</th>
<th>
<Center>Industri</Center>
</th>
<th>
<Center>Jumlah Partisipan</Center>
</th>
<th>
<Center>Report</Center>
</th>
</tr>
</thead>
<tbody>{tableRow}</tbody>
</Table>
</ScrollArea>
<Pagination
position="center"
total={isNPage}
value={activePage}
onChange={(val) => {
onLoad(val);
}}
/>
</Stack>
</Paper>
</Stack>
</>
);
}

View File

@@ -5,7 +5,7 @@ import { Box, Title, Divider, Stack } from "@mantine/core";
export default function ComponentAdminGlobal_HeaderTamplate({name}: {name: string}) {
return (
<>
<Stack spacing={"xs"}>
<Stack spacing={"xs"} >
<Title>{name ? name : null}</Title>
<Divider/>
</Stack>

View File

@@ -221,18 +221,16 @@ export default function AdminLayout({
navbarOffsetBreakpoint="md"
asideOffsetBreakpoint="sm"
navbar={
<MediaQuery
smallerThan={"md"}
styles={{ display: "none", }}
>
<MediaQuery smallerThan={"md"} styles={{ display: "none" }}>
<Navbar
h={"100vh"}
width={{ lg: 200, md: 200, sm: 200, base: 200 }}
hiddenBreakpoint="md"
hidden={!opened}
p="xs"
bg={"gray.2"}
>
<ScrollArea h={"100vh"} scrollbarSize={2}>
<ScrollArea h={"100vh"} scrollbarSize={2}>
<Navbar.Section>
<Stack>
{userRole === "3" ? navbarItems : notAdminDev}

View File

@@ -1,3 +1,4 @@
import { RouterAdminColab } from "@/app/lib/router_admin/router_admin_colab";
import { RouterAdminDeveloper } from "@/app/lib/router_admin/router_admin_developer";
import { RouterAdminEvent } from "@/app/lib/router_admin/router_admin_event";
import { RouterAdminForum } from "@/app/lib/router_admin/router_admin_forum";
@@ -9,7 +10,13 @@ import {
RouterAdminDonasi,
RouterAdminInvestasi,
} from "@/app/lib/router_hipmi/router_admin";
import { IconBriefcase, IconDashboard, IconMessages, IconUserCog } from "@tabler/icons-react";
import {
IconAffiliate,
IconBriefcase,
IconDashboard,
IconMessages,
IconUserCog,
} from "@tabler/icons-react";
import {
IconHeartHandshake,
IconHome,
@@ -173,6 +180,34 @@ export const listAdminPage = [
// },
],
},
{
id: 8,
name: "Project Collaboration",
path: "",
icon: <IconAffiliate />,
child: [
{
id: 81,
name: "Dashboard",
path: RouterAdminColab.dashboard,
},
{
id: 82,
name: "Table Publish",
path: RouterAdminColab.table_publish,
},
{
id: 83,
name: "Table Group",
path: RouterAdminColab.table_group,
},
{
id: 84,
name: "Table Reject",
path: RouterAdminColab.table_reject,
},
],
},
{
id: 98,
name: "User Access",

View File

@@ -103,8 +103,8 @@ export default function AdminUserAccess_View({
placeholder="Masukan username"
/> */}
</Group>
<Paper p={"md"} withBorder shadow="lg" h={"80vh"}>
<ScrollArea h={"70vh"}>
<Paper p={"md"} withBorder shadow="lg" h={"85vh"}>
<ScrollArea h={"80vh"}>
<Table
verticalSpacing={"xs"}
horizontalSpacing={"md"}

View File

@@ -0,0 +1,315 @@
"use client";
import { RouterColab } from "@/app/lib/router_hipmi/router_colab";
import {
ActionIcon,
Box,
Center,
Grid,
Group,
Header,
Loader,
Paper,
ScrollArea,
Stack,
Text,
Textarea,
Title,
} from "@mantine/core";
import {
IconChevronLeft,
IconCircle,
IconInfoSquareRounded,
IconSend,
} from "@tabler/icons-react";
import { useRouter } from "next/navigation";
import router from "next/router";
import { useRef, useState } from "react";
import { MODEL_COLLABORATION_ROOM_CHAT } from "../../model/interface";
import _ from "lodash";
import ComponentColab_IsEmptyData from "../../component/is_empty_data";
import colab_getMessageByRoomId from "../../fun/get/room_chat/get_message_by_room_id";
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/component_global/notif_global/notifikasi_gagal";
import colab_funCreateMessageByUserId from "../../fun/create/room/fun_create_message_by_user_id";
import { useShallowEffect } from "@mantine/hooks";
import mqtt_client from "@/util/mqtt_client";
import useInfiniteScroll, {
ScrollDirection,
} from "react-easy-infinite-scroll-hook";
export default function Colab_GroupChatView({
userLoginId,
listMsg,
selectRoom,
}: {
userLoginId: string;
listMsg: any;
selectRoom: MODEL_COLLABORATION_ROOM_CHAT;
}) {
const router = useRouter();
const [loadingBack, setLoadingBack] = useState(false);
const [loadingInfo, setLoadingInfo] = useState(false);
const [msg, setMsg] = useState("");
const [data, setData] = useState<any[]>(listMsg);
const [totalPage, setTotalPage] = useState(1);
const [isLoading, setIsLoading] = useState(false);
const [isGet, setIsGet] = useState(true);
const viewport = useRef<HTMLDivElement>(null);
const next = async (direction: ScrollDirection) => {
try {
setIsLoading(true);
await new Promise((a) => setTimeout(a, 500));
const newData = await colab_getMessageByRoomId({
roomId: selectRoom?.id,
page: totalPage + 1,
});
setTotalPage(totalPage + 1);
// console.log(newData, "loading baru");
if (_.isEmpty(newData)) {
setIsGet(false);
} else {
const d =
direction === "down" ? [...data, ...newData] : [...newData, ...data];
setData(d);
}
} finally {
setIsLoading(false);
}
};
const ref = useInfiniteScroll({
next,
rowCount: data.length,
hasMore: { up: isGet },
});
useShallowEffect(() => {
mqtt_client.subscribe(selectRoom.id);
mqtt_client.on("message", () => {
onList(setData);
});
}, [setData]);
async function onList(setData: any) {
await colab_getMessageByRoomId({
roomId: selectRoom?.id,
page: 1,
}).then((val) => {
setData(val);
setTotalPage(totalPage);
});
}
async function onSend() {
await colab_funCreateMessageByUserId(msg, selectRoom.id).then(
async (res) => {
if (res.status === 200) {
mqtt_client.publish(selectRoom.id, msg);
setMsg("");
} else {
ComponentGlobal_NotifikasiGagal(res.message);
}
}
);
}
return (
<>
<Box h={"100vh"}>
{/* Header */}
<Box
style={{
zIndex: 99,
}}
w={"100%"}
pos={"fixed"}
top={0}
h={50}
>
<Stack bg={"gray.2"} h={50} justify="center" px={"sm"}>
<Grid grow gutter={"lg"}>
<Grid.Col span={2}>
<ActionIcon
loading={loadingBack ? true : false}
variant="transparent"
radius={"xl"}
onClick={() => {
setLoadingBack(true);
router.back();
}}
>
<IconChevronLeft />
</ActionIcon>
</Grid.Col>
<Grid.Col span={8}>
<Center>
<Title order={5} lineClamp={1}>
{selectRoom?.name}
</Title>
</Center>
</Grid.Col>
<Grid.Col span={2}>
<Group position="right">
<ActionIcon
loading={loadingInfo ? true : false}
variant="transparent"
radius={"xl"}
onClick={() => {
setLoadingInfo(true);
router.push(RouterColab.info_grup + selectRoom.id);
}}
>
<IconInfoSquareRounded />
</ActionIcon>
</Group>
</Grid.Col>
</Grid>
</Stack>
</Box>
{/* Main View */}
<Box py={"xs"} px={"xs"} pos={"static"}>
{/* Batas atas */}
<Box
style={{
height: 50,
}}
/>
{/* Chat View */}
<Box h={"80vh"}>
<Stack justify="flex-end" h={"100%"}>
<div
ref={ref as any}
style={{
overflowY: "auto",
}}
>
{isLoading && (
<Center>
<Loader size={20} color="gray" />
</Center>
)}
{_.isEmpty(data) ? (
<ComponentColab_IsEmptyData text="Belum ada pesan" />
) : (
data.map((e, i) => (
<Box key={i}>
{userLoginId === e?.User?.id ? (
<Group position="right">
<Paper key={e.id} bg={"blue.2"} p={"sm"} mt={"sm"}>
<Stack spacing={0}>
<Text lineClamp={1} fw={"bold"} fz={"xs"}>
{e.User.Profile.name}
</Text>
<div
dangerouslySetInnerHTML={{ __html: e.message }}
/>
<Group spacing={"xs"}>
<Text fz={7}>
{new Intl.DateTimeFormat("id-ID", {
timeStyle: "medium",
}).format(e.createdAt)}
</Text>
<IconCircle size={3} />
<Text fz={7}>
{new Intl.DateTimeFormat("id-ID", {
dateStyle: "medium",
}).format(e.createdAt)}
</Text>
</Group>
</Stack>
</Paper>
</Group>
) : (
<Group>
<Paper key={e.id} bg={"cyan.2"} p={"sm"} mt={"sm"}>
<Stack spacing={0}>
<Text lineClamp={1} fw={"bold"} fz={"xs"}>
{e.User.Profile.name}
</Text>
<div
dangerouslySetInnerHTML={{ __html: e.message }}
/>
<Group spacing={"xs"}>
<Text fz={7}>
{new Intl.DateTimeFormat("id-ID", {
timeStyle: "medium",
}).format(e.createdAt)}
</Text>
<IconCircle size={3} />
<Text fz={7}>
{new Intl.DateTimeFormat("id-ID", {
dateStyle: "medium",
}).format(e.createdAt)}
</Text>
</Group>
</Stack>
</Paper>
</Group>
)}
</Box>
))
)}
</div>
</Stack>
</Box>
{/* Batas bawah */}
<Box
style={{
height: "10vh",
}}
/>
</Box>
{/* Footer */}
<Box
style={{
zIndex: 98,
}}
w={"100%"}
pos={"fixed"}
bottom={0}
h={"10vh"}
bg={"gray.2"}
>
<Stack justify="center" h={"100%"} px={"sm"}>
<Grid align="center">
<Grid.Col span={"auto"}>
<Textarea
minRows={1}
radius={"md"}
placeholder="Ketik pesan anda..."
value={msg}
onChange={(val) => setMsg(val.currentTarget.value)}
/>
</Grid.Col>
<Grid.Col span={"content"}>
<ActionIcon
disabled={msg === "" ? true : false}
variant="filled"
bg={"cyan"}
radius={"xl"}
size={"xl"}
onClick={() => {
onSend();
}}
>
<IconSend size={20} />
</ActionIcon>
</Grid.Col>
</Grid>
</Stack>
</Box>
</Box>
</>
);
}

View File

@@ -82,17 +82,8 @@ export default function Colab_DetailGrupDiskusi({
hasMore: { up: isGet },
scrollThreshold: 0.1,
initialScroll: { top: 100 },
// initialScroll: { top : -1 },
// onScroll() {
// scrollTo({ y: 100 });
// },
});
// const setRef = useCallback((node: any) => {
// if (node) ref.current = node._outerRef
// }, [ref]);
useShallowEffect(() => {
mqtt_client.subscribe(roomId);
@@ -118,12 +109,12 @@ export default function Colab_DetailGrupDiskusi({
return (
<>
<Box h={"80vh"}>
<Box h={"80vh"} bg={"blue.1"}>
<Stack justify="flex-end" h={"100%"}>
<div
ref={ref as any}
style={{
overflow: "scroll",
// overflow: "scroll",
overflowY: "auto",
// height: "100vh",
// justifyContent: "flex-end",

View File

@@ -0,0 +1,37 @@
"use client";
import AppComponentGlobal_LayoutTamplate from "@/app_modules/component_global/component_layout_tamplate";
import ComponentColab_HeaderTamplate from "../../component/header_tamplate";
import { Center, Stack } from "@mantine/core";
import { MODEL_COLLABORATION_NOTIFIKSI } from "../../model/interface";
import ComponentColab_NotedBox from "../../component/noted_box";
import ComponentColab_DetailData from "../../component/detail/detail_data";
export default function Colab_DetailNotifikasi({
data,
}: {
data: MODEL_COLLABORATION_NOTIFIKSI;
}) {
return (
<>
<AppComponentGlobal_LayoutTamplate
header={<ComponentColab_HeaderTamplate title="Detail Notifikasi" />}
>
<DetailNotif data={data} />
</AppComponentGlobal_LayoutTamplate>
</>
);
}
function DetailNotif({ data }: { data?: MODEL_COLLABORATION_NOTIFIKSI }) {
return (
<>
<Stack px={"sm"}>
<ComponentColab_NotedBox
informasi={data?.ProjectCollaboration.report as any}
/>
<ComponentColab_DetailData data={data?.ProjectCollaboration} />
</Stack>
</>
);
}

View File

@@ -0,0 +1,20 @@
"use server";
import prisma from "@/app/lib/prisma";
import { RouterColab } from "@/app/lib/router_hipmi/router_colab";
import { revalidatePath } from "next/cache";
export default async function colab_funUpdateIsReadByNotifId(notifId: string) {
const updtRead = await prisma.projectCollaboration_Notifikasi.update({
where: {
id: notifId,
},
data: {
isRead: true,
},
});
if (!updtRead) return { status: 400, message: "Gagal Update" };
revalidatePath(RouterColab.notifikasi);
return { status: 200, message: "Berhasil Udpate" };
}

View File

@@ -0,0 +1,24 @@
"use server";
import prisma from "@/app/lib/prisma";
import { user_getOneUserId } from "@/app_modules/fun_global/get_user_token";
export default async function colab_CekNotifikasi() {
const authorId = await user_getOneUserId();
const cekNotif = await prisma.projectCollaboration_Notifikasi.findMany({
where: {
userId: authorId,
isRead: false,
},
select: {
isRead: true,
},
});
if (cekNotif.length > 0) {
return true;
} else {
return false;
}
}

View File

@@ -0,0 +1,31 @@
"use server";
import prisma from "@/app/lib/prisma";
import { user_getOneUserId } from "@/app_modules/fun_global/get_user_token";
export default async function colab_getListNotifikasiByUserId() {
const authorId = await user_getOneUserId();
const get = await prisma.projectCollaboration_Notifikasi.findMany({
orderBy: {
createdAt: "desc",
},
where: {
userId: authorId,
},
select: {
id:true,
createdAt: true,
isRead: true,
note: true,
ProjectCollaboration: {
select: {
id: true,
report: true,
},
},
},
});
return get;
}

View File

@@ -0,0 +1,46 @@
"use server";
import prisma from "@/app/lib/prisma";
export default async function colab_getOneNotifikasiById({
notifId,
}: {
notifId: string;
}) {
const get = await prisma.projectCollaboration_Notifikasi.findFirst({
where: {
id: notifId,
},
select: {
id: true,
createdAt: true,
note: true,
ProjectCollaboration: {
select: {
id: true,
isActive: true,
title: true,
lokasi: true,
purpose: true,
benefit: true,
createdAt: true,
report: true,
Author: {
select: {
id: true,
Profile: true,
},
},
ProjectCollaborationMaster_Industri: true,
ProjectCollaboration_Partisipasi: {
where: {
isActive: true,
},
},
},
},
},
});
return get;
}

View File

@@ -3,13 +3,15 @@
import prisma from "@/app/lib/prisma";
import _ from "lodash";
export default async function colab_getMessageByRoomId(
roomId: string,
page: number
) {
// console.log(page)
const lewat = page * 5 - 5;
const ambil = 5;
export default async function colab_getMessageByRoomId({
roomId,
page,
}: {
roomId: string;
page: number;
}) {
const lewat = page * 6 - 6;
const ambil = 6;
const getList = await prisma.projectCollaboration_Message.findMany({
orderBy: {
createdAt: "desc",
@@ -39,7 +41,5 @@ export default async function colab_getMessageByRoomId(
},
});
const dataRevers = _.reverse(getList);
return getList;
}

View File

@@ -24,6 +24,8 @@ import Colab_NotifikasiView from "./main/pemberitahuan";
import Colab_DetailProyekSaya from "./detail/proyek/saya";
import LayoutColab_DetailProyekSaya from "./detail/proyek/saya/layout";
import Colab_DetailInfoGrup from "./detail/info_grup";
import Colab_DetailNotifikasi from "./detail/notifikasi";
import Colab_GroupChatView from "./detail/group";
export {
Colab_Beranda,
@@ -52,4 +54,6 @@ export {
Colab_DetailProyekSaya,
LayoutColab_DetailProyekSaya,
Colab_DetailInfoGrup,
Colab_DetailNotifikasi,
Colab_GroupChatView,
};

View File

@@ -45,7 +45,7 @@ export default function Colab_GrupDiskus({
p={"md"}
onClick={() => {
router.push(
RouterColab.detail_grup + e?.ProjectCollaboration_RoomChat.id
RouterColab.group_chat + e?.ProjectCollaboration_RoomChat.id
);
setIdRoom(e?.ProjectCollaboration_RoomChat.id);
setLoading(true);
@@ -55,12 +55,12 @@ export default function Colab_GrupDiskus({
<Grid.Col span={"auto"}>
<Stack spacing={0}>
<Text fw={"bold"} lineClamp={1}>
{e.ProjectCollaboration_RoomChat.name}
{e?.ProjectCollaboration_RoomChat?.name}
</Text>
<Text fz={"xs"} c={"gray"}>
{
e.ProjectCollaboration_RoomChat
.ProjectCollaboration_AnggotaRoomChat.length
e?.ProjectCollaboration_RoomChat
?.ProjectCollaboration_AnggotaRoomChat.length
}{" "}
Anggota
</Text>
@@ -68,7 +68,7 @@ export default function Colab_GrupDiskus({
</Grid.Col>
<Grid.Col span={"content"}>
<Center>
{e?.ProjectCollaboration_RoomChat.id === idRoom ? (
{e?.ProjectCollaboration_RoomChat?.id === idRoom ? (
<Loader color="gray" size={20} />
) : (
<IconChevronRight color="gray" />

View File

@@ -7,6 +7,7 @@ import {
Center,
Footer,
Grid,
Indicator,
Loader,
Stack,
Text,
@@ -32,8 +33,10 @@ import { useTimeout } from "@mantine/hooks";
export default function LayoutColab_Main({
children,
cekNotif,
}: {
children: React.ReactNode;
cekNotif: boolean;
}) {
const router = useRouter();
const [hotMenu, setHotMenu] = useAtom(gs_colab_hot_menu);
@@ -70,7 +73,13 @@ export default function LayoutColab_Main({
id: 5,
name: "Notifikasi",
path: RouterColab.notifikasi,
icon: <IconBell />,
icon: cekNotif ? (
<Indicator processing color="orange">
<IconBell />
</Indicator>
) : (
<IconBell />
),
},
];

View File

@@ -1,14 +1,73 @@
"use client";
import { Center, Text, Title } from "@mantine/core";
import {
ActionIcon,
Center,
Group,
Paper,
Stack,
Text,
Title,
} from "@mantine/core";
import ComponentColab_IsEmptyData from "../../component/is_empty_data";
import _ from "lodash";
import { MODEL_COLLABORATION_NOTIFIKSI } from "../../model/interface";
import { IconChevronRight } from "@tabler/icons-react";
import { useState } from "react";
import { useRouter } from "next/navigation";
import { RouterColab } from "@/app/lib/router_hipmi/router_colab";
import colab_funUpdateIsReadByNotifId from "../../fun/edit/fun_is_read_by_id";
export default function Colab_NotifikasiView() {
export default function Colab_NotifikasiView({
listNotifikasi,
}: {
listNotifikasi?: MODEL_COLLABORATION_NOTIFIKSI[];
}) {
const router = useRouter();
const [notifId, setNotifId] = useState("");
if (_.isEmpty(listNotifikasi))
return <ComponentColab_IsEmptyData text="Tidak ada data" />;
async function onRead(notifId: string) {
await colab_funUpdateIsReadByNotifId(notifId).then((res) => {
if (res.status === 200) {
setNotifId(notifId);
router.push(RouterColab.detail_notifikasi + notifId);
} else {
console.log(``);
}
});
}
return (
<>
<Center>
<ComponentColab_IsEmptyData text="Cooming Soon" />
</Center>
<Stack>
{listNotifikasi?.map((e, i) => (
<Paper
key={i}
bg={e?.isRead ? "gray.1" : "gray.4"}
p={"md"}
onClick={() => {
onRead(e?.id);
}}
>
<Group position="apart">
<Stack spacing={0} w={"80%"}>
<Text fw={"bold"} fz={"xs"} lineClamp={1}>
{e.note}
</Text>
<Text lineClamp={1}>{e.ProjectCollaboration.report}</Text>
</Stack>
<ActionIcon
variant="transparent"
loading={e?.id === notifId ? true : false}
>
<IconChevronRight />
</ActionIcon>
</Group>
</Paper>
))}
</Stack>
</>
);
}

View File

@@ -18,6 +18,7 @@ export interface MODEL_COLLABORATION {
lokasi: string;
purpose: string;
benefit: string;
report: string;
jumlah_partisipan: number;
ProjectCollaborationMaster_Industri: MODEL_COLLABORATION_MASTER;
projectCollaborationMaster_IndustriId: number;
@@ -59,3 +60,13 @@ export interface MODEL_COLLABORATION_ANGGOTA_ROOM_CHAT {
ProjectCollaboration_RoomChat: MODEL_COLLABORATION_ROOM_CHAT;
projectCollaboration_RoomChatId: string;
}
export interface MODEL_COLLABORATION_NOTIFIKSI {
id: string;
isRead: boolean;
isActive: boolean;
createdAt: Date;
updatedAt: Date;
note: string;
ProjectCollaboration: MODEL_COLLABORATION;
}