diff --git a/src/app/dev/forum/detail/main-detail/[id]/page.tsx b/src/app/dev/forum/detail/main-detail/[id]/page.tsx
index 325f4bb7..0a8c52f1 100644
--- a/src/app/dev/forum/detail/main-detail/[id]/page.tsx
+++ b/src/app/dev/forum/detail/main-detail/[id]/page.tsx
@@ -1,12 +1,13 @@
import { funGetUserIdByToken } from "@/app_modules/_global/fun/get";
import Forum_MainDetail from "@/app_modules/forum/detail/main_detail";
+import Forum_V3_MainDetail from "@/app_modules/forum/detail/v3_main_detail";
export default async function Page() {
const userLoginId = await funGetUserIdByToken();
return (
<>
-
- {/* */}
+ {/* */}
+
>
);
}
diff --git a/src/app/zCoba/text_editor2/page.tsx b/src/app/zCoba/text_editor2/page.tsx
index b868b363..e2bc55b6 100644
--- a/src/app/zCoba/text_editor2/page.tsx
+++ b/src/app/zCoba/text_editor2/page.tsx
@@ -70,12 +70,12 @@ export default function Page() {
const style = document.createElement("style");
style.textContent = `
.ql-editor img {
- max-width: 40px !important;
- max-height: 40px !important;
+ max-width: 100px !important;
+ max-height: 100px !important;
}
.chat-content img {
- max-width: 40px !important;
- max-height: 40px !important;
+ max-width: 70px !important;
+ max-height: 70px !important;
}
`;
document.head.appendChild(style);
diff --git a/src/app_modules/_global/component/new/comp_set_inner_html.tsx b/src/app_modules/_global/component/new/comp_set_inner_html.tsx
index a2c24945..36c43239 100644
--- a/src/app_modules/_global/component/new/comp_set_inner_html.tsx
+++ b/src/app_modules/_global/component/new/comp_set_inner_html.tsx
@@ -1,19 +1,38 @@
import React from "react";
import { MainColor } from "../../color";
+import { useShallowEffect } from "@mantine/hooks";
-export function Component_SetInnerHtml({
+export function Comp_DangerouslySetInnerHTML({
props,
color,
}: {
- props: string
+ props: string;
color?: string;
}) {
+ // useShallowEffect(() => {
+ // // Add custom style for stickers inside Quill editor
+ // const style = document.createElement("style");
+ // style.textContent = `
+ // .chat-content img {
+ // max-width: 100px !important;
+ // max-height: 100px !important;
+ // }
+ // `;
+ // document.head.appendChild(style);
+
+ // return () => {
+ // // Clean up when component unmounts
+ // document.head.removeChild(style);
+ // };
+ // }, []);
+
return (
<>
-
+
diff --git a/src/app_modules/admin/forum/sub_menu/table_posting.tsx b/src/app_modules/admin/forum/sub_menu/table_posting.tsx
index e8712bbf..cac44ce3 100644
--- a/src/app_modules/admin/forum/sub_menu/table_posting.tsx
+++ b/src/app_modules/admin/forum/sub_menu/table_posting.tsx
@@ -27,7 +27,7 @@ import { ComponentAdminGlobal_TitlePage } from "../../_admin_global/_component";
import { Admin_V3_ComponentPaginationBreakpoint } from "../../_components_v3/comp_pagination_breakpoint";
import ComponentAdminForum_ButtonDeletePosting from "../component/button_delete";
import { apiGetAdminForumPublish } from "../lib/api_fetch_admin_forum";
-import { Component_SetInnerHtml } from "@/app_modules/_global/component/new/comp_set_inner_html";
+import { Comp_DangerouslySetInnerHTML } from "@/app_modules/_global/component/new/comp_set_inner_html";
export default function AdminForum_TablePosting() {
return (
@@ -134,7 +134,7 @@ function TablePublish() {
hideLabel="sembunyikan"
showLabel="tampilkan"
>
-
+
diff --git a/src/app_modules/forum/component/detail_component/comp_V3_create.comment.tsx b/src/app_modules/forum/component/detail_component/comp_V3_create.comment.tsx
new file mode 100644
index 00000000..e25a4c71
--- /dev/null
+++ b/src/app_modules/forum/component/detail_component/comp_V3_create.comment.tsx
@@ -0,0 +1,348 @@
+"use client";
+
+import { MainColor } from "@/app_modules/_global/color/color_pallet";
+import ComponentGlobal_InputCountDown from "@/app_modules/_global/component/input_countdown";
+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,
+ Button,
+ Group,
+ Image,
+ Modal,
+ Paper,
+ ScrollArea,
+ SimpleGrid,
+ Stack,
+ Text,
+ Tooltip,
+} from "@mantine/core";
+import { useRouter } from "next/navigation";
+import React, { useState } from "react";
+import { forum_funCreateKomentar } from "../../fun/create/fun_create_komentar";
+import { MODEL_FORUM_POSTING } from "../../model/interface";
+import dynamic from "next/dynamic";
+import { useDisclosure, useShallowEffect } from "@mantine/hooks";
+import { listStiker } from "@/app_modules/_global/lib/stiker";
+import CustomSkeleton from "@/app_modules/components/CustomSkeleton";
+import { maxInputLength } from "@/app_modules/_global/lib/maximal_setting";
+import { funReplaceHtml } from "@/app_modules/_global/fun/fun_replace_html";
+import { IconMoodSmileFilled, IconX } from "@tabler/icons-react";
+
+const ReactQuill = dynamic(
+ async () => {
+ const { default: RQ } = await import("react-quill");
+ // Tidak perlu import CSS dengan import statement
+ return function comp({ forwardedRef, ...props }: any) {
+ return
;
+ };
+ },
+ {
+ ssr: false,
+ loading: () => (
+
+ Ketik pesan di sini atau tambahkan stiker...
+
+ ),
+ }
+);
+
+type ChatItem = {
+ content: string; // HTML content including text and stickers
+};
+export default function Forum_V3_CreateKomentar({
+ postingId,
+ data,
+ userLoginId,
+ onSetNewKomentar,
+}: {
+ postingId: string;
+ data: MODEL_FORUM_POSTING;
+ userLoginId: string;
+ onSetNewKomentar: (val: boolean) => void;
+}) {
+ const [loading, setLoading] = useState(false);
+ const [isComment, setIsComment] = useState(false);
+
+ // New State
+ const [editorContent, setEditorContent] = useState("");
+ const [opened, { open, close }] = useDisclosure(false);
+ const quillRef = React.useRef
(null);
+ const [quillLoaded, setQuillLoaded] = useState(false);
+
+ async function onComment() {
+ if (editorContent.length > 500) {
+ return null;
+ }
+
+ try {
+ setLoading(true);
+ const createComment = await forum_funCreateKomentar(
+ postingId,
+ editorContent
+ );
+ if (createComment.status === 201) {
+ onSetNewKomentar(true);
+ setEditorContent("");
+ ComponentGlobal_NotifikasiBerhasil(createComment.message, 2000);
+
+ if (userLoginId !== data.Author.id) {
+ const dataNotif = {
+ appId: data.id,
+ userId: data.authorId,
+ pesan: editorContent,
+ kategoriApp: "FORUM",
+ title: "Komentar baru",
+ };
+
+ const createNotifikasi = await notifikasiToUser_funCreate({
+ data: dataNotif as any,
+ });
+
+ if (createNotifikasi.status === 201) {
+ mqtt_client.publish(
+ "USER",
+ JSON.stringify({
+ userId: dataNotif.userId,
+ count: 1,
+ })
+ );
+ }
+ }
+ } else {
+ setLoading(false);
+ ComponentGlobal_NotifikasiGagal(createComment.message);
+ }
+ } catch (error) {
+ setLoading(false);
+ clientLogger.error("Error create komentar forum", error);
+ }
+ }
+
+ useShallowEffect(() => {
+ // Add Quill CSS via tag
+ const link = document.createElement("link");
+ link.href = "https://cdn.quilljs.com/1.3.6/quill.snow.css";
+ link.rel = "stylesheet";
+ document.head.appendChild(link);
+
+ // Add custom style for stickers inside Quill editor
+ const style = document.createElement("style");
+ style.textContent = `
+ .ql-editor img {
+ max-width: 70px !important;
+ max-height: 70px !important;
+ }
+ // .chat-content img {
+ // max-width: 70px !important;
+ // max-height: 70px !important;
+ // }
+ `;
+ document.head.appendChild(style);
+
+ setQuillLoaded(true);
+
+ return () => {
+ // Clean up when component unmounts
+ document.head.removeChild(link);
+ document.head.removeChild(style);
+ };
+ }, []);
+
+ // Custom toolbar options for ReactQuill
+ const modules = {
+ toolbar: [
+ [{ header: [1, 2, false] }],
+ ["bold", "italic", "underline", "strike", "blockquote"],
+ [{ list: "ordered" }, { list: "bullet" }],
+ ["link"],
+ ["clean"],
+ ],
+ };
+
+ const formats = [
+ "header",
+ "bold",
+ "italic",
+ "underline",
+ "strike",
+ "blockquote",
+ "list",
+ "bullet",
+ "link",
+ "image",
+ ];
+
+ const insertSticker = (stickerUrl: string) => {
+ if (!quillRef.current) return;
+
+ const quill = quillRef.current.getEditor();
+ const range = quill.getSelection(true);
+
+ // Custom image insertion with size
+ // Use custom blot or HTML string with size attributes
+ const stickerHtml = `
`;
+
+ // Insert HTML at cursor position
+ quill.clipboard.dangerouslyPasteHTML(range.index, stickerHtml);
+
+ // Move cursor after inserted sticker
+ quill.setSelection(range.index + 1, 0);
+
+ // Focus back on editor
+ quill.focus();
+
+ // Close sticker modal
+ close();
+ };
+
+ // // Function to send message
+ // const sendMessage = () => {
+ // if (editorContent.trim() !== "") {
+ // setChat((prev) => [...prev, { content: editorContent }]);
+ // setEditorContent(""); // Clear after sending
+ // }
+ // };
+
+ return (
+ <>
+
+ {isComment ? (
+
+
+
+ setIsComment(false)} variant="transparent">
+
+
+
+
+ {quillLoaded && (
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ) : (
+ setIsComment(true)}
+ py="sm"
+ px={"xl"}
+ withBorder
+ shadow="lg"
+ bg={MainColor.white}
+ >
+
+ Ketik pesan di sini atau tambahkan stiker...
+
+
+ )}
+
+ {/* {JSON.stringify(editorContent, null, 2)} */}
+
+ {/* Sticker Modal */}
+
+
+ {listStiker.map((item) => (
+
+
+ insertSticker(item.url)}
+ />
+
+
+ ))}
+
+
+
+ {/*
+
+
+
+ */}
+
+ >
+ );
+}
diff --git a/src/app_modules/forum/component/detail_component/detail_list_komentar.tsx b/src/app_modules/forum/component/detail_component/detail_list_komentar.tsx
index 1232555b..ed672fe1 100644
--- a/src/app_modules/forum/component/detail_component/detail_list_komentar.tsx
+++ b/src/app_modules/forum/component/detail_component/detail_list_komentar.tsx
@@ -4,6 +4,7 @@ import { Card, Divider, Spoiler, Stack, Text } from "@mantine/core";
import { MODEL_FORUM_KOMENTAR } from "../../model/interface";
import ComponentForum_KomentarAuthorNameOnHeader from "../komentar_component/komentar_author_header_name";
import { ComponentGlobal_CardStyles } from "@/app_modules/_global/component";
+import { useShallowEffect } from "@mantine/hooks";
export default function ComponentForum_KomentarView({
data,
@@ -16,6 +17,30 @@ export default function ComponentForum_KomentarView({
postingId: string;
userLoginId: string;
}) {
+ useShallowEffect(() => {
+
+ // Add custom style for stickers inside Quill editor
+ const style = document.createElement("style");
+ style.textContent = `
+ // .ql-editor img {
+ // max-width: 40px !important;
+ // max-height: 40px !important;
+ // }
+ .chat-content img {
+ max-width: 70px !important;
+ max-height: 70px !important;
+ }
+ `;
+ document.head.appendChild(style);
+
+ // setQuillLoaded(true);
+
+ return () => {
+ // Clean up when component unmounts
+ document.head.removeChild(style);
+ };
+ }, []);
+
return (
<>
@@ -38,7 +63,10 @@ export default function ComponentForum_KomentarView({
maxHeight={100}
showLabel="tampilkan"
>
-
+
) : (
""
diff --git a/src/app_modules/forum/detail/v3_main_detail.tsx b/src/app_modules/forum/detail/v3_main_detail.tsx
new file mode 100644
index 00000000..a8d9a5f8
--- /dev/null
+++ b/src/app_modules/forum/detail/v3_main_detail.tsx
@@ -0,0 +1,193 @@
+"use client";
+
+import ComponentGlobal_IsEmptyData from "@/app_modules/_global/component/is_empty_data";
+import CustomSkeleton from "@/app_modules/components/CustomSkeleton";
+import { clientLogger } from "@/util/clientLogger";
+import mqtt_client from "@/util/mqtt_client";
+import { Box, Center, Loader, Stack } from "@mantine/core";
+import { useShallowEffect } from "@mantine/hooks";
+import _ from "lodash";
+import { ScrollOnly } from "next-scroll-loader";
+import { useParams } from "next/navigation";
+import { useState } from "react";
+import "react-quill/dist/quill.bubble.css";
+import {
+ apiGetKomentarForumById,
+ apiGetOneForumById,
+} from "../component/api_fetch_forum";
+import Forum_V3_CreateKomentar from "../component/detail_component/comp_V3_create.comment";
+import ComponentForum_KomentarView from "../component/detail_component/detail_list_komentar";
+import ComponentForum_DetailForumView from "../component/detail_component/detail_view";
+import {
+ Forum_SkeletonKomentar,
+ Forum_SkeletonListKomentar,
+} from "../component/skeleton_view";
+import { MODEL_FORUM_KOMENTAR, MODEL_FORUM_POSTING } from "../model/interface";
+
+export default function Forum_V3_MainDetail({
+ userLoginId,
+}: {
+ userLoginId: string;
+}) {
+ const param = useParams<{ id: string }>();
+ const [dataPosting, setDataPosting] = useState(
+ null
+ );
+ const [listKomentar, setListKomentar] = useState<
+ MODEL_FORUM_KOMENTAR[] | null
+ >(null);
+ const [activePage, setActivePage] = useState(1);
+ const [newKomentar, setNewKomentar] = useState(false);
+ const [isLoading, setIsLoading] = useState(false);
+
+ useShallowEffect(() => {
+ handleLoadData();
+ }, []);
+
+ const handleLoadData = async () => {
+ try {
+ setIsLoading(true);
+ const response = await apiGetOneForumById({
+ id: param.id,
+ });
+
+ if (response) {
+ setDataPosting(response.data);
+ } else {
+ setDataPosting(null);
+ }
+ } catch (error) {
+ clientLogger.error("Error get data forum", error);
+ setDataPosting(null);
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ useShallowEffect(() => {
+ handleLoadDataKomentar();
+ }, [newKomentar]);
+
+ const handleLoadDataKomentar = async () => {
+ try {
+ const response = await apiGetKomentarForumById({
+ id: param.id,
+ page: `${activePage}`,
+ });
+
+ if (response.success) {
+ setListKomentar(response.data);
+ } else {
+ setListKomentar([]);
+ }
+ } catch (error) {
+ clientLogger.error("Error get data komentar forum", error);
+ setListKomentar([]);
+ }
+ };
+
+ const handleMoreDataKomentar = async () => {
+ try {
+ const nextPage = activePage + 1;
+ const response = await apiGetKomentarForumById({
+ id: param.id,
+ page: `${nextPage}`,
+ });
+
+ if (response.success) {
+ setActivePage(nextPage);
+ return response.data;
+ } else {
+ return null;
+ }
+ } catch (error) {
+ clientLogger.error("Error get data komentar forum", error);
+ return null;
+ }
+ };
+
+ useShallowEffect(() => {
+ mqtt_client.subscribe("Forum_detail_ganti_status");
+
+ mqtt_client.on("message", (topic: any, message: any) => {
+ const newData = JSON.parse(message.toString());
+ if (newData.id === dataPosting?.id) {
+ const cloneData = _.clone(dataPosting);
+
+ // console.log(newData.data);
+ const updateData = {
+ ...cloneData,
+ ForumMaster_StatusPosting: {
+ id: newData.data.id,
+ status: newData.data.status,
+ },
+ };
+
+ setDataPosting(updateData as any);
+ }
+ });
+ }, [dataPosting]);
+
+ return (
+ <>
+
+ {!dataPosting ? (
+
+ ) : (
+ {
+ setDataPosting(val);
+ }}
+ />
+ )}
+
+ {!dataPosting ? (
+
+ ) : (
+ (dataPosting?.ForumMaster_StatusPosting?.id as any) === 1 && (
+ {
+ setNewKomentar(val);
+ }}
+ />
+ )
+ )}
+
+ {!listKomentar ? (
+
+ ) : _.isEmpty(listKomentar) ? (
+
+ ) : (
+
+ (
+
+
+
+ )}
+ data={listKomentar}
+ setData={setListKomentar as any}
+ moreData={handleMoreDataKomentar}
+ >
+ {(item) => (
+
+ )}
+
+
+ )}
+
+ >
+ );
+}