From 65c69a96e5e309aa06416ffc3b274de5c45f6100 Mon Sep 17 00:00:00 2001 From: Bagasbanuna02 Date: Thu, 24 Apr 2025 17:36:21 +0800 Subject: [PATCH] fix stiker di forum --- src/app/dev/forum/create/page.tsx | 5 +- src/app/zCoba/text_editor2/page.tsx | 18 +- .../new/comp_V3_set_html_with_stiker.tsx | 18 ++ ...ext_editor.tsx => comp_V3_text_editor.tsx} | 2 +- .../new/comp_V3_text_editor_stiker.tsx | 284 ++++++++++++++++++ src/app_modules/_global/lib/stiker.ts | 82 ++++- src/app_modules/_global/ui/ui_modal.tsx | 27 +- .../comp_V3_create.comment.tsx | 60 +--- .../detail_component/detail_view.tsx | 25 +- .../component/main_component/card_view.tsx | 25 +- src/app_modules/forum/create/V3_create.tsx | 265 ++++++++++++++++ src/app_modules/forum/create/new_create.tsx | 4 +- src/app_modules/forum/edit/posting/index.tsx | 4 +- 13 files changed, 730 insertions(+), 89 deletions(-) create mode 100644 src/app_modules/_global/component/new/comp_V3_set_html_with_stiker.tsx rename src/app_modules/_global/component/new/{new_text_editor.tsx => comp_V3_text_editor.tsx} (97%) create mode 100644 src/app_modules/_global/component/new/comp_V3_text_editor_stiker.tsx create mode 100644 src/app_modules/forum/create/V3_create.tsx diff --git a/src/app/dev/forum/create/page.tsx b/src/app/dev/forum/create/page.tsx index 5d9f38c0..8d2a75aa 100644 --- a/src/app/dev/forum/create/page.tsx +++ b/src/app/dev/forum/create/page.tsx @@ -1,11 +1,14 @@ import { Forum_Create } from "@/app_modules/forum"; import Forum_NewCreate from "@/app_modules/forum/create/new_create"; +import { Forum_V3_Create } from "@/app_modules/forum/create/V3_create"; + export default async function Page() { return ( <> {/* */} - + {/* */} + ); } diff --git a/src/app/zCoba/text_editor2/page.tsx b/src/app/zCoba/text_editor2/page.tsx index e2bc55b6..580423c3 100644 --- a/src/app/zCoba/text_editor2/page.tsx +++ b/src/app/zCoba/text_editor2/page.tsx @@ -16,6 +16,7 @@ import { import { useDisclosure } from "@mantine/hooks"; import dynamic from "next/dynamic"; import { MainColor } from "@/app_modules/_global/color"; +import { listStiker } from "@/app_modules/_global/lib/stiker"; // Dynamic import ReactQuill dengan SSR disabled const ReactQuill = dynamic( @@ -29,23 +30,6 @@ const ReactQuill = dynamic( { ssr: false, loading: () =>

Loading Editor...

} ); -const listStiker = [ - { - id: 1, - name: "stiker2", - url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQN9AKmsBY4yqdn3GueJJEVPJbfmf853gDL4cN8uc9eqsCTiJ1fzhcpywzVP68NCJEA5NQ&usqp=CAU", - }, - { - id: 2, - name: "stiker3", - url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS2lkV3ZiQ8m-OELSui2JGVy80vnh1cyRUV7NrgFNluPVVs2HUAyCHwCMAKGe2s5jk2sn8&usqp=CAU", - }, - { - id: 3, - name: "stiker4", - url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQHy9ZdsPc6dHgVTl5yIGpRJ-KtpTIsXA2_kbfO1Oc-pv_f7CNKGxhO56RjKujE3xCyb9k&usqp=CAU", - }, -]; type ChatItem = { content: string; // HTML content including text and stickers diff --git a/src/app_modules/_global/component/new/comp_V3_set_html_with_stiker.tsx b/src/app_modules/_global/component/new/comp_V3_set_html_with_stiker.tsx new file mode 100644 index 00000000..b7b7f542 --- /dev/null +++ b/src/app_modules/_global/component/new/comp_V3_set_html_with_stiker.tsx @@ -0,0 +1,18 @@ + +export function Comp_V3_SetHtmlWithSticker({ + props, + className, + color, +}: { + props: string; + className: string; + color?: string; +}) { + return ( + <> +
+ + ); +} diff --git a/src/app_modules/_global/component/new/new_text_editor.tsx b/src/app_modules/_global/component/new/comp_V3_text_editor.tsx similarity index 97% rename from src/app_modules/_global/component/new/new_text_editor.tsx rename to src/app_modules/_global/component/new/comp_V3_text_editor.tsx index 94b277bd..daf9f196 100644 --- a/src/app_modules/_global/component/new/new_text_editor.tsx +++ b/src/app_modules/_global/component/new/comp_V3_text_editor.tsx @@ -9,7 +9,7 @@ import { maxInputLength } from "../../lib/maximal_setting"; const ReactQuill = dynamic(() => import("react-quill"), { ssr: false }); -export function ComponentTextEditor({ +export function Component_V3_TextEditor({ data, onSetData, // lengthData, diff --git a/src/app_modules/_global/component/new/comp_V3_text_editor_stiker.tsx b/src/app_modules/_global/component/new/comp_V3_text_editor_stiker.tsx new file mode 100644 index 00000000..e0affdfc --- /dev/null +++ b/src/app_modules/_global/component/new/comp_V3_text_editor_stiker.tsx @@ -0,0 +1,284 @@ +import CustomSkeleton from "@/app_modules/components/CustomSkeleton"; +import { + ActionIcon, + Box, + Button, + Group, + Image, + Paper, + ScrollArea, + SimpleGrid, + Stack, + Text, + Tooltip, +} from "@mantine/core"; +import { useDisclosure, useShallowEffect } from "@mantine/hooks"; +import React, { useState } from "react"; +import dynamic from "next/dynamic"; +import { MainColor } from "../../color"; +import { maxInputLength } from "../../lib/maximal_setting"; +import ComponentGlobal_InputCountDown from "../input_countdown"; +import { funReplaceHtml } from "../../fun/fun_replace_html"; +import { forum_funCreate } from "@/app_modules/forum/fun/create/fun_create"; +import { + ComponentGlobal_NotifikasiBerhasil, + ComponentGlobal_NotifikasiGagal, +} from "../../notif_global"; +import { useRouter } from "next/navigation"; +import { IconMoodSmileFilled } from "@tabler/icons-react"; +import { listStiker } from "../../lib/stiker"; +import { UIGlobal_Modal } from "../../ui"; + +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... + + ), + } +); + +export function Component_V3_TextEditorWithStiker({ + data, + onSetData, + onSetLengthData, +}: { + data: string; + onSetData: (value: string) => void; + onSetLengthData: (value: number) => void; +}) { + const router = useRouter(); + const [editorContent, setEditorContent] = useState(""); + const [opened, { open, close }] = useDisclosure(false); + const quillRef = React.useRef(null); + const [quillLoaded, setQuillLoaded] = useState(false); + const [isReady, setIsReady] = useState(false); + + useShallowEffect(() => { + setIsReady(true); // Set ready on client-side mount + }, []); + + useShallowEffect(() => { + setQuillLoaded(true); // Set ready on client-side mount + }, []); + + const handleChange = (input: string) => { + const text = input.replace(/<[^>]+>/g, "").trim(); // Remove HTML tags and trim + // if (text.length <= maxInputLength) { + // } + onSetData(input); + onSetLengthData(text.length); + // Input diabaikan jika panjang > maxLength + }; + + 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 = `sticker`; + + // 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(); + }; + + return ( + <> + {isReady ? ( + + {quillLoaded && ( + + + + + + )} + + + + + + + + + + + + + + + + {listStiker.map((item) => ( + + + {item.name} insertSticker(item.url)} + /> + + + ))} + + + + ) : ( + + )} + + ); +} + +interface ButtonActionProps { + value: string; + lengthData: number; +} + +function ButtonAction({ value, lengthData }: ButtonActionProps) { + const router = useRouter(); + const [loading, setLoading] = useState(false); + + async function onCreate() { + try { + setLoading(true); + const create = await forum_funCreate(value); + if (create.status === 201) { + ComponentGlobal_NotifikasiBerhasil(create.message); + router.back(); + + mqtt_client.publish( + "Forum_create_new", + JSON.stringify({ isNewPost: true, count: 1 }) + ); + } else { + ComponentGlobal_NotifikasiGagal(create.message); + } + } catch (error) { + console.log(error); + } finally { + setLoading(false); + } + } + + return ( + + ); +} diff --git a/src/app_modules/_global/lib/stiker.ts b/src/app_modules/_global/lib/stiker.ts index 237cf009..7ad745b2 100644 --- a/src/app_modules/_global/lib/stiker.ts +++ b/src/app_modules/_global/lib/stiker.ts @@ -1,17 +1,89 @@ -export const listStiker = [ +const dummyStiker = [ { id: 1, - name: "stiker2", + name: "stiker1", url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQN9AKmsBY4yqdn3GueJJEVPJbfmf853gDL4cN8uc9eqsCTiJ1fzhcpywzVP68NCJEA5NQ&usqp=CAU", }, { id: 2, - name: "stiker3", + name: "stiker2", url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS2lkV3ZiQ8m-OELSui2JGVy80vnh1cyRUV7NrgFNluPVVs2HUAyCHwCMAKGe2s5jk2sn8&usqp=CAU", }, { id: 3, - name: "stiker4", + name: "stiker3", url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQHy9ZdsPc6dHgVTl5yIGpRJ-KtpTIsXA2_kbfO1Oc-pv_f7CNKGxhO56RjKujE3xCyb9k&usqp=CAU", }, -]; \ No newline at end of file + { + id: 4, + name: "stiker4", + url: "https://i.pinimg.com/236x/0a/2e/54/0a2e544c9a908beed6b544d031a444ca.jpg", + }, + { + id: 5, + name: "stiker5", + url: "https://i.pinimg.com/564x/ff/d3/f7/ffd3f7498d09e4fdf48967fb4651b70b.jpg", + }, + { + id: 6, + name: "stiker6", + url: "https://s.cafebazaar.ir/images/icons/com.apikdev.stickerwapentol-4febefdb-b3d4-4436-a241-e5e140ba3e0a_512x512.png?x-img=v1/resize,h_256,w_256,lossless_false/optimize", + }, + { + id: 7, + name: "stiker7", + url: "https://play-lh.googleusercontent.com/MHPScwJ_owQJtf26PpiANC83sGj8d_cPz_83R3XhmFN9nJUuoWHJ0Y-GaEsKhXk4sA", + }, + { + id: 8, + name: "stiker8", + url: "https://i.pinimg.com/236x/34/73/91/3473915a7434885e80ca11728e9b376a.jpg", + }, + { + id: 9, + name: "stiker9", + url: "https://i.pinimg.com/736x/ae/8b/29/ae8b29377f241616e57e5d5745a8984a.jpg", + }, + { + id: 10, + name: "stiker10", + url: "https://i.pinimg.com/564x/cd/da/68/cdda68c895e9e74382d912cbf1161634.jpg", + }, + { + id: 11, + name: "stiker11", + url: "https://i.pinimg.com/564x/7c/af/41/7caf412dd8f5336951a45ca5f8105423.jpg", + }, + { + id: 12, + name: "stiker12", + url: "https://i.pinimg.com/736x/43/55/5a/43555a618afc52331fd9a8effbbb33b1.jpg", + }, + { + id: 13, + name: "stiker13", + url: "https://i.pinimg.com/564x/77/52/b1/7752b14b010db94a40132bf4f7aede8f.jpg", + }, + { + id: 14, + name: "stiker14", + url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSEeCX_gq9XpK9CwQvEtIwWXlciBHFBP5IpB5YPWR6QqD4TFIs8xj2ezCGzJfMgH4vR34Q&usqp=CAU", + }, + { + id: 15, + name: "stiker15", + url: "https://i.pinimg.com/originals/03/a5/2f/03a52faa637fe35f33316e95b9e3f1ee.gif", + }, + { + id: 16, + name: "stiker16", + url: "https://teknogram.id/gallery/stiker-wa/kartun-bergerak/stiker-kartun-bergerak-3.png", + }, + { + id: 17, + name: "stiker17", + url: "https://id-live-01.slatic.net/p/1cbe0e62964c31030d12cfdf9dadb96b.jpg", + }, +]; + +export const listStiker = dummyStiker; \ No newline at end of file diff --git a/src/app_modules/_global/ui/ui_modal.tsx b/src/app_modules/_global/ui/ui_modal.tsx index fdfcac6e..78116b52 100644 --- a/src/app_modules/_global/ui/ui_modal.tsx +++ b/src/app_modules/_global/ui/ui_modal.tsx @@ -1,7 +1,9 @@ "use client"; -import { Modal, Stack, Title, Group, Button, Box } from "@mantine/core"; +import { Modal, Stack, Title, Group, Button, Box, ActionIcon } from "@mantine/core"; import { MainColor, AccentColor } from "../color/color_pallet"; +import React from "react"; +import { IconX } from "@tabler/icons-react"; export default function UIGlobal_Modal({ opened, @@ -9,19 +11,23 @@ export default function UIGlobal_Modal({ title, buttonKiri, buttonKanan, + children, + closeButton }: { opened: any; close: any; title: any; - buttonKiri: any; - buttonKanan: any; + buttonKiri?: any; + buttonKanan?: any; + children?: React.ReactNode; + closeButton?: boolean }) { return ( <> { - close(); + close(); }} centered withCloseButton={false} @@ -32,14 +38,19 @@ export default function UIGlobal_Modal({ }, }} > - - + <Stack spacing={"lg"}> + <Group position="apart"> + <Title order={6} color={MainColor.white} align="center"> {title} - + {closeButton ? + + : null} + + {children ? children : {buttonKiri} {buttonKanan} - + } 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 index 853c08bc..5aa95ab6 100644 --- 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 @@ -2,8 +2,12 @@ import { MainColor } from "@/app_modules/_global/color/color_pallet"; import ComponentGlobal_InputCountDown from "@/app_modules/_global/component/input_countdown"; +import { funReplaceHtml } from "@/app_modules/_global/fun/fun_replace_html"; +import { maxInputLength } from "@/app_modules/_global/lib/maximal_setting"; +import { listStiker } from "@/app_modules/_global/lib/stiker"; import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil"; import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global/notifikasi_gagal"; +import { UIGlobal_Modal } from "@/app_modules/_global/ui"; 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"; @@ -13,7 +17,6 @@ import { Button, Group, Image, - Modal, Paper, ScrollArea, SimpleGrid, @@ -21,20 +24,15 @@ import { Text, Tooltip, } from "@mantine/core"; -import { useRouter } from "next/navigation"; +import { useDisclosure, useShallowEffect } from "@mantine/hooks"; +import { IconMoodSmileFilled, IconX } from "@tabler/icons-react"; +import dynamic from "next/dynamic"; import React, { useState } from "react"; import { forum_funCreateKomentar } from "../../fun/create/fun_create_komentar"; import { MODEL_FORUM_KOMENTAR, 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 () => { @@ -54,9 +52,6 @@ const ReactQuill = dynamic( } ); -type ChatItem = { - content: string; // HTML content including text and stickers -}; export default function Forum_V3_CreateKomentar({ postingId, data, @@ -299,15 +294,11 @@ export default function Forum_V3_CreateKomentar({ )} - {/* {JSON.stringify(editorContent, null, 2)} */} - - {/* Sticker Modal */} - {listStiker.map((item) => ( @@ -325,36 +316,7 @@ export default function Forum_V3_CreateKomentar({ ))} - - - {/* - - - - */} + ); diff --git a/src/app_modules/forum/component/detail_component/detail_view.tsx b/src/app_modules/forum/component/detail_component/detail_view.tsx index 7f36366b..4205a409 100644 --- a/src/app_modules/forum/component/detail_component/detail_view.tsx +++ b/src/app_modules/forum/component/detail_component/detail_view.tsx @@ -5,6 +5,8 @@ import { Box, Group, Stack, Text } from "@mantine/core"; import { IconMessageCircle, IconMessageCircleX } from "@tabler/icons-react"; import { MODEL_FORUM_POSTING } from "../../model/interface"; import ComponentForum_DetailHeader from "./detail_header"; +import { useShallowEffect } from "@mantine/hooks"; +import { Comp_V3_SetHtmlWithSticker } from "@/app_modules/_global/component/new/comp_V3_set_html_with_stiker"; export default function ComponentForum_DetailForumView({ data, @@ -17,6 +19,22 @@ export default function ComponentForum_DetailForumView({ userLoginId: string; onLoadData: (val: any) => void; }) { + useShallowEffect(() => { + // Add custom style for stickers inside Quill editor + const style = document.createElement("style"); + style.textContent = ` + .chat-content img { + max-width: 70px !important; + max-height: 70px !important; + } + `; + document.head.appendChild(style); + return () => { + // Clean up when component unmounts + document.head.removeChild(style); + }; + }, []); + return ( <> @@ -31,10 +49,13 @@ export default function ComponentForum_DetailForumView({ /> {/* CONTENT */} - + {data?.diskusi ? ( -
+ ) : ( "" )} diff --git a/src/app_modules/forum/component/main_component/card_view.tsx b/src/app_modules/forum/component/main_component/card_view.tsx index 1d271af2..df391804 100644 --- a/src/app_modules/forum/component/main_component/card_view.tsx +++ b/src/app_modules/forum/component/main_component/card_view.tsx @@ -11,6 +11,8 @@ import { useRouter } from "next/navigation"; import { useState } from "react"; import { MODEL_FORUM_POSTING } from "../../model/interface"; import ComponentForum_BerandaHeaderCard from "./card_header"; +import { Comp_V3_SetHtmlWithSticker } from "@/app_modules/_global/component/new/comp_V3_set_html_with_stiker"; +import { useShallowEffect } from "@mantine/hooks"; export default function ComponentForum_BerandaCardView({ data, @@ -26,6 +28,22 @@ export default function ComponentForum_BerandaCardView({ const router = useRouter(); const [visible, setVisible] = useState(false); + useShallowEffect(() => { + // Add custom style for stickers inside Quill editor + const style = document.createElement("style"); + style.textContent = ` + .chat-content img { + max-width: 70px !important; + max-height: 70px !important; + } + `; + document.head.appendChild(style); + return () => { + // Clean up when component unmounts + document.head.removeChild(style); + }; + }, []); + return ( <> @@ -45,8 +63,11 @@ export default function ComponentForum_BerandaCardView({ setVisible(true), router.push(RouterForum.main_detail + data?.id); }} > - -
+ + diff --git a/src/app_modules/forum/create/V3_create.tsx b/src/app_modules/forum/create/V3_create.tsx new file mode 100644 index 00000000..6f604d38 --- /dev/null +++ b/src/app_modules/forum/create/V3_create.tsx @@ -0,0 +1,265 @@ +"use client"; + +import CustomSkeleton from "@/app_modules/components/CustomSkeleton"; +import { + ActionIcon, + Box, + Button, + Group, + Image, + Paper, + ScrollArea, + SimpleGrid, + Stack, + Text, + Tooltip, +} from "@mantine/core"; +import { useDisclosure, useShallowEffect } from "@mantine/hooks"; +import React, { useState } from "react"; +import dynamic from "next/dynamic"; +import { useRouter } from "next/navigation"; +import { MainColor } from "@/app_modules/_global/color"; +import { ComponentGlobal_InputCountDown } from "@/app_modules/_global/component"; +import { funReplaceHtml } from "@/app_modules/_global/fun/fun_replace_html"; +import { maxInputLength } from "@/app_modules/_global/lib/maximal_setting"; +import { listStiker } from "@/app_modules/_global/lib/stiker"; +import { + ComponentGlobal_NotifikasiBerhasil, + ComponentGlobal_NotifikasiGagal, +} from "@/app_modules/_global/notif_global"; +import { UIGlobal_Modal } from "@/app_modules/_global/ui"; +import { IconMoodSmileFilled } from "@tabler/icons-react"; +import { forum_funCreate } from "../fun/create/fun_create"; + +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... + + ), + } +); + +export function Forum_V3_Create() { + const router = useRouter(); + const [editorContent, setEditorContent] = useState(""); + const [opened, { open, close }] = useDisclosure(false); + const quillRef = React.useRef(null); + const [quillLoaded, setQuillLoaded] = useState(false); + const [isReady, setIsReady] = useState(false); + + useShallowEffect(() => { + setIsReady(true); // Set ready on client-side mount + }, []); + + useShallowEffect(() => { + setQuillLoaded(true); // Set ready on client-side mount + }, []); + + 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 = `sticker`; + + // 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(); + }; + + return ( + <> + {isReady ? ( + + {quillLoaded && ( + + + + + + )} + + + + + + + + + + + + + + + + {listStiker.map((item) => ( + + + {item.name} insertSticker(item.url)} + /> + + + ))} + + + + ) : ( + + )} + + ); +} + +interface ButtonActionProps { + value: string; +} + +function ButtonAction({ value }: ButtonActionProps) { + const router = useRouter(); + const [loading, setLoading] = useState(false); + + async function onCreate() { + try { + setLoading(true); + const create = await forum_funCreate(value); + if (create.status === 201) { + ComponentGlobal_NotifikasiBerhasil(create.message); + router.back(); + + mqtt_client.publish( + "Forum_create_new", + JSON.stringify({ isNewPost: true, count: 1 }) + ); + } else { + ComponentGlobal_NotifikasiGagal(create.message); + } + } catch (error) { + console.log(error); + } finally { + setLoading(false); + } + } + + return ( + + ); +} diff --git a/src/app_modules/forum/create/new_create.tsx b/src/app_modules/forum/create/new_create.tsx index 61f2b1e0..051ad4c0 100644 --- a/src/app_modules/forum/create/new_create.tsx +++ b/src/app_modules/forum/create/new_create.tsx @@ -2,7 +2,6 @@ import { MainColor } from "@/app_modules/_global/color/color_pallet"; import ComponentGlobal_InputCountDown from "@/app_modules/_global/component/input_countdown"; -import { ComponentTextEditor } from "@/app_modules/_global/component/new/new_text_editor"; import { maxInputLength } from "@/app_modules/_global/lib/maximal_setting"; import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil"; import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/_global/notif_global/notifikasi_gagal"; @@ -12,6 +11,7 @@ import { useRouter } from "next/navigation"; import { useState } from "react"; import "react-quill/dist/quill.snow.css"; import { forum_funCreate } from "../fun/create/fun_create"; +import { Component_V3_TextEditor } from "@/app_modules/_global/component/new/comp_V3_text_editor"; export default function Forum_NewCreate() { const [data, setData] = useState(""); @@ -19,7 +19,7 @@ export default function Forum_NewCreate() { return ( - { setData(val); diff --git a/src/app_modules/forum/edit/posting/index.tsx b/src/app_modules/forum/edit/posting/index.tsx index a431307c..78bab78c 100644 --- a/src/app_modules/forum/edit/posting/index.tsx +++ b/src/app_modules/forum/edit/posting/index.tsx @@ -2,7 +2,7 @@ import { MainColor } from "@/app_modules/_global/color/color_pallet"; import ComponentGlobal_InputCountDown from "@/app_modules/_global/component/input_countdown"; -import { ComponentTextEditor } from "@/app_modules/_global/component/new/new_text_editor"; +import { Component_V3_TextEditor } from "@/app_modules/_global/component/new/comp_V3_text_editor"; import { funReplaceHtml } from "@/app_modules/_global/fun/fun_replace_html"; import { maxInputLength } from "@/app_modules/_global/lib/maximal_setting"; import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/_global/notif_global/notifikasi_berhasil"; @@ -45,7 +45,7 @@ export default function Forum_EditPosting() { return ( <> - { setData({