fix sticker on user UI
This commit is contained in:
@@ -1,40 +1,80 @@
|
|||||||
|
import { APIs } from "@/lib";
|
||||||
import {
|
import {
|
||||||
ActionIcon,
|
ActionIcon,
|
||||||
Box,
|
Box,
|
||||||
|
Button,
|
||||||
|
CloseButton,
|
||||||
Image,
|
Image,
|
||||||
|
Loader,
|
||||||
ScrollArea,
|
ScrollArea,
|
||||||
SimpleGrid,
|
SimpleGrid,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
Loader,
|
|
||||||
Group,
|
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import { IconMoodSmileFilled } from "@tabler/icons-react";
|
import { IconMoodSmileFilled } from "@tabler/icons-react";
|
||||||
|
import { useRef, useState } from "react";
|
||||||
import { MainColor } from "../../color";
|
import { MainColor } from "../../color";
|
||||||
import { UIGlobal_Modal } from "../../ui";
|
import { UIGlobal_Modal } from "../../ui";
|
||||||
import { insertStickerReactQuill } from "./react_quill_format_for_stiker";
|
import { insertStickerReactQuill } from "./react_quill_format_for_stiker";
|
||||||
import { APIs } from "@/lib";
|
import { ISticker } from "../interface/stiker";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
open: () => void;
|
open: () => void;
|
||||||
close: () => void;
|
close: () => void;
|
||||||
opened: boolean;
|
opened: boolean;
|
||||||
quillRef: any;
|
quillRef: any;
|
||||||
dataSticker: any;
|
dataSticker: ISticker[] | null;
|
||||||
listEmotions: any
|
// listEmotions: any[];
|
||||||
|
// onEmotionSelect?: (val: string | null) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Comp_ButtonSticker = ({
|
export const Comp_ButtonSticker = ({
|
||||||
open,
|
open,
|
||||||
close,
|
close,
|
||||||
opened,
|
opened,
|
||||||
quillRef,
|
quillRef,
|
||||||
dataSticker,
|
dataSticker,
|
||||||
listEmotions,
|
// listEmotions,
|
||||||
|
// onEmotionSelect,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
|
|
||||||
|
const scrollRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
// Menyimpan id emosi yang dipilih
|
||||||
|
const [selectedEmotions, setSelectedEmotions] = useState<string[]>([]);
|
||||||
|
|
||||||
|
// Menyimpan urutan awal
|
||||||
|
// const [originalOrder] = useState(listEmotions);
|
||||||
|
|
||||||
|
// const handleEmotionClick = (value: string) => {
|
||||||
|
// setSelectedEmotions(
|
||||||
|
// (prev) =>
|
||||||
|
// prev.includes(value)
|
||||||
|
// ? prev.filter((v) => v !== value) // batal pilih
|
||||||
|
// : [...prev, value] // tambah pilih
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
|
// Urutkan emosi: yang dipilih muncul di depan
|
||||||
|
// const orderedEmotions = [
|
||||||
|
// ...selectedEmotions.map((val) => listEmotions.find((e: any) => e.value === val)),
|
||||||
|
// ...originalOrder.filter((e: any) => !selectedEmotions.includes(e.value)),
|
||||||
|
// ];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ActionIcon onClick={open} variant="transparent" disabled={dataSticker.length === 0}>
|
<ActionIcon
|
||||||
<IconMoodSmileFilled color={dataSticker.length === 0 ? "gray" : MainColor.white} size={30} />
|
onClick={open}
|
||||||
|
variant="transparent"
|
||||||
|
disabled={!dataSticker}
|
||||||
|
>
|
||||||
|
<IconMoodSmileFilled
|
||||||
|
color={
|
||||||
|
!dataSticker
|
||||||
|
? "gray"
|
||||||
|
: MainColor.yellow
|
||||||
|
}
|
||||||
|
size={30}
|
||||||
|
/>
|
||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
|
|
||||||
<UIGlobal_Modal
|
<UIGlobal_Modal
|
||||||
@@ -43,19 +83,59 @@ export const Comp_ButtonSticker = ({
|
|||||||
title="Pilih Stiker"
|
title="Pilih Stiker"
|
||||||
closeButton
|
closeButton
|
||||||
closeOnClickOutside={false}
|
closeOnClickOutside={false}
|
||||||
|
|
||||||
>
|
>
|
||||||
<Box mah={`${500}dvh`}>
|
<Box mah={`${500}dvh`}>
|
||||||
{/* <Group position="center">
|
{/* <ScrollArea type="never" viewportRef={scrollRef}>
|
||||||
{listEmotions.map((item: any) => (
|
<Box
|
||||||
<ActionIcon key={item.id} onClick={() => open()}>
|
p="sm"
|
||||||
<IconMoodSmileFilled color={item.value} size={30} />
|
style={{
|
||||||
</ActionIcon>
|
display: "flex",
|
||||||
))}
|
flexDirection: "row",
|
||||||
</Group> */}
|
gap: "0.5rem",
|
||||||
<ScrollArea h={380}>
|
overflowX: "auto",
|
||||||
|
overflowY: "hidden",
|
||||||
|
whiteSpace: "nowrap",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{orderedEmotions.map((item: any) => {
|
||||||
|
const isSelected = selectedEmotions.includes(item.value);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
key={item.id}
|
||||||
|
variant={isSelected ? "filled" : "light"}
|
||||||
|
color={isSelected ? "blue" : "gray"}
|
||||||
|
radius="xl"
|
||||||
|
style={{ flexShrink: 0, position: "relative" }}
|
||||||
|
onClick={() => handleEmotionClick(item.value)}
|
||||||
|
>
|
||||||
|
{item.label}
|
||||||
|
{isSelected && (
|
||||||
|
<CloseButton
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation(); // agar tidak trigger lagi handleEmotionClick
|
||||||
|
handleEmotionClick(item.value);
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
top: -6,
|
||||||
|
right: -6,
|
||||||
|
backgroundColor: "white",
|
||||||
|
borderRadius: "50%",
|
||||||
|
boxShadow: "0 0 2px rgba(0,0,0,0.3)",
|
||||||
|
}}
|
||||||
|
size="sm"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Box>
|
||||||
|
</ScrollArea> */}
|
||||||
|
|
||||||
|
<ScrollArea h={480}>
|
||||||
<SimpleGrid cols={3} spacing="md">
|
<SimpleGrid cols={3} spacing="md">
|
||||||
{dataSticker.map((item: any) => (
|
{dataSticker?.map((item: any) => (
|
||||||
<Box key={item.id}>
|
<Box key={item.id}>
|
||||||
<Tooltip label={item.name}>
|
<Tooltip label={item.name}>
|
||||||
<Image
|
<Image
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import {
|
|||||||
MODEL_FORUM_KOMENTAR,
|
MODEL_FORUM_KOMENTAR,
|
||||||
MODEL_FORUM_POSTING,
|
MODEL_FORUM_POSTING,
|
||||||
} from "../../model/interface";
|
} from "../../model/interface";
|
||||||
|
import { ISticker } from "@/app_modules/_global/lib/interface/stiker";
|
||||||
|
|
||||||
const ReactQuill = dynamic(
|
const ReactQuill = dynamic(
|
||||||
async () => {
|
async () => {
|
||||||
@@ -52,11 +53,13 @@ export default function Forum_V3_CreateKomentar({
|
|||||||
data,
|
data,
|
||||||
userLoginId,
|
userLoginId,
|
||||||
onSetLoadData,
|
onSetLoadData,
|
||||||
|
dataSticker,
|
||||||
}: {
|
}: {
|
||||||
postingId: string;
|
postingId: string;
|
||||||
data: MODEL_FORUM_POSTING;
|
data: MODEL_FORUM_POSTING;
|
||||||
userLoginId: string;
|
userLoginId: string;
|
||||||
onSetLoadData: (val: string) => void;
|
onSetLoadData: (val: string) => void;
|
||||||
|
dataSticker: ISticker[] | null;
|
||||||
}) {
|
}) {
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [isComment, setIsComment] = useState(false);
|
const [isComment, setIsComment] = useState(false);
|
||||||
@@ -196,6 +199,7 @@ export default function Forum_V3_CreateKomentar({
|
|||||||
close={close}
|
close={close}
|
||||||
opened={opened}
|
opened={opened}
|
||||||
quillRef={quillRef}
|
quillRef={quillRef}
|
||||||
|
dataSticker={dataSticker}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ import React, { useState } from "react";
|
|||||||
import Forum_ButtonCreatePosting from "../component/button/button_create_posting";
|
import Forum_ButtonCreatePosting from "../component/button/button_create_posting";
|
||||||
import { apiGetStickerForUser } from "@/app_modules/_global/lib/stiker/api_fecth_stiker_for_user";
|
import { apiGetStickerForUser } from "@/app_modules/_global/lib/stiker/api_fecth_stiker_for_user";
|
||||||
import { apiGetMasterEmotions } from "@/app_modules/_global/lib/api_fetch_master";
|
import { apiGetMasterEmotions } from "@/app_modules/_global/lib/api_fetch_master";
|
||||||
|
import pLimit from "p-limit";
|
||||||
|
import global_limit from "@/lib/limit";
|
||||||
|
import { ISticker } from "@/app_modules/_global/lib/interface/stiker";
|
||||||
|
|
||||||
export function Forum_V3_Create() {
|
export function Forum_V3_Create() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -21,18 +24,32 @@ export function Forum_V3_Create() {
|
|||||||
const quillRef = React.useRef<any>(null);
|
const quillRef = React.useRef<any>(null);
|
||||||
const [quillLoaded, setQuillLoaded] = useState<boolean>(false);
|
const [quillLoaded, setQuillLoaded] = useState<boolean>(false);
|
||||||
const [isReady, setIsReady] = useState<boolean>(false);
|
const [isReady, setIsReady] = useState<boolean>(false);
|
||||||
const [sticker, setSticker] = useState<any>([]);
|
const [sticker, setSticker] = useState<ISticker[] | null>(null);
|
||||||
const [emotion, setEmotion] = useState<any>([]);
|
const [emotion, setEmotion] = useState<any>([]);
|
||||||
|
|
||||||
|
// useShallowEffect(() => {
|
||||||
|
// handleLoadData();
|
||||||
|
// }, []);
|
||||||
|
|
||||||
|
// async function handleLoadData() {
|
||||||
|
// const listLoadData = [
|
||||||
|
// global_limit(onLoadEmotion),
|
||||||
|
// global_limit(onLoadSticker),
|
||||||
|
// ];
|
||||||
|
// await Promise.all(listLoadData);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// useShallowEffect(() => {
|
||||||
|
// onLoadEmotion();
|
||||||
|
// }, []);
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
onLoadSticker();
|
onLoadSticker();
|
||||||
onLoadEmotion();
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
async function onLoadSticker() {
|
async function onLoadSticker() {
|
||||||
try {
|
try {
|
||||||
const response = await apiGetStickerForUser({ emotion });
|
const response = await apiGetStickerForUser({ emotion });
|
||||||
console.log("response >>", response);
|
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
setSticker(response.res.data);
|
setSticker(response.res.data);
|
||||||
} else {
|
} else {
|
||||||
@@ -48,7 +65,6 @@ export function Forum_V3_Create() {
|
|||||||
async function onLoadEmotion() {
|
async function onLoadEmotion() {
|
||||||
try {
|
try {
|
||||||
const response = await apiGetMasterEmotions();
|
const response = await apiGetMasterEmotions();
|
||||||
console.log("response >>", response);
|
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
setEmotion(response.data);
|
setEmotion(response.data);
|
||||||
} else {
|
} else {
|
||||||
@@ -124,7 +140,12 @@ export function Forum_V3_Create() {
|
|||||||
opened={opened}
|
opened={opened}
|
||||||
quillRef={quillRef}
|
quillRef={quillRef}
|
||||||
dataSticker={sticker}
|
dataSticker={sticker}
|
||||||
listEmotions={emotion}
|
// listEmotions={emotion}
|
||||||
|
// onEmotionSelect={(val) => {
|
||||||
|
// console.log("val >>", val);
|
||||||
|
// // setEmotion(val ? [val] : []);
|
||||||
|
// // onLoadSticker(val ? [val] : []);
|
||||||
|
// }}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Forum_ButtonCreatePosting value={editorContent} />
|
<Forum_ButtonCreatePosting value={editorContent} />
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ import {
|
|||||||
Forum_SkeletonListKomentar,
|
Forum_SkeletonListKomentar,
|
||||||
} from "../component/skeleton_view";
|
} from "../component/skeleton_view";
|
||||||
import { MODEL_FORUM_KOMENTAR, MODEL_FORUM_POSTING } from "../model/interface";
|
import { MODEL_FORUM_KOMENTAR, MODEL_FORUM_POSTING } from "../model/interface";
|
||||||
|
import { ISticker } from "@/app_modules/_global/lib/interface/stiker";
|
||||||
|
import { apiGetStickerForUser } from "@/app_modules/_global/lib/stiker/api_fecth_stiker_for_user";
|
||||||
|
|
||||||
export default function Forum_V3_MainDetail({
|
export default function Forum_V3_MainDetail({
|
||||||
userLoginId,
|
userLoginId,
|
||||||
@@ -40,6 +42,28 @@ export default function Forum_V3_MainDetail({
|
|||||||
const [activePage, setActivePage] = useState(1);
|
const [activePage, setActivePage] = useState(1);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
|
const [sticker, setSticker] = useState<ISticker[] | null>(null);
|
||||||
|
const [emotion, setEmotion] = useState<any>([]);
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
onLoadSticker();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
async function onLoadSticker() {
|
||||||
|
try {
|
||||||
|
const response = await apiGetStickerForUser({ emotion: "" });
|
||||||
|
if (response.success) {
|
||||||
|
setSticker(response.res.data);
|
||||||
|
} else {
|
||||||
|
console.error("Failed to get sticker", response.message);
|
||||||
|
setSticker([]);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error get sticker", error);
|
||||||
|
setSticker([]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
handleLoadData();
|
handleLoadData();
|
||||||
}, []);
|
}, []);
|
||||||
@@ -180,6 +204,7 @@ export default function Forum_V3_MainDetail({
|
|||||||
onSetLoadData={(val) => {
|
onSetLoadData={(val) => {
|
||||||
setListKomentar((prev: any) => [val, ...prev]);
|
setListKomentar((prev: any) => [val, ...prev]);
|
||||||
}}
|
}}
|
||||||
|
dataSticker={sticker}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import React, { useState } from "react";
|
|||||||
import { apiGetOneForumById } from "../../component/api_fetch_forum";
|
import { apiGetOneForumById } from "../../component/api_fetch_forum";
|
||||||
import Forum_ButtonUpdatePosting from "../../component/button/button_update_posting";
|
import Forum_ButtonUpdatePosting from "../../component/button/button_update_posting";
|
||||||
import { MODEL_FORUM_POSTING } from "../../model/interface";
|
import { MODEL_FORUM_POSTING } from "../../model/interface";
|
||||||
|
import { ISticker } from "@/app_modules/_global/lib/interface/stiker";
|
||||||
|
import { apiGetStickerForUser } from "@/app_modules/_global/lib/stiker/api_fecth_stiker_for_user";
|
||||||
|
|
||||||
export default function Forum_V3_EditPosting() {
|
export default function Forum_V3_EditPosting() {
|
||||||
const param = useParams<{ id: string }>();
|
const param = useParams<{ id: string }>();
|
||||||
@@ -24,6 +26,28 @@ export default function Forum_V3_EditPosting() {
|
|||||||
const quillRef = React.useRef<any>(null);
|
const quillRef = React.useRef<any>(null);
|
||||||
const [quillLoaded, setQuillLoaded] = useState<boolean>(false);
|
const [quillLoaded, setQuillLoaded] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const [sticker, setSticker] = useState<ISticker[] | null>(null);
|
||||||
|
const [emotion, setEmotion] = useState<any>([]);
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
onLoadSticker();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
async function onLoadSticker() {
|
||||||
|
try {
|
||||||
|
const response = await apiGetStickerForUser({ emotion: "" });
|
||||||
|
if (response.success) {
|
||||||
|
setSticker(response.res.data);
|
||||||
|
} else {
|
||||||
|
console.error("Failed to get sticker", response.message);
|
||||||
|
setSticker([]);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error get sticker", error);
|
||||||
|
setSticker([]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
handleLoadData();
|
handleLoadData();
|
||||||
}, []);
|
}, []);
|
||||||
@@ -102,6 +126,7 @@ export default function Forum_V3_EditPosting() {
|
|||||||
close={close}
|
close={close}
|
||||||
opened={opened}
|
opened={opened}
|
||||||
quillRef={quillRef}
|
quillRef={quillRef}
|
||||||
|
dataSticker={sticker}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Forum_ButtonUpdatePosting
|
<Forum_ButtonUpdatePosting
|
||||||
|
|||||||
Reference in New Issue
Block a user