feat:kotak saran
This commit is contained in:
parent
9231546780
commit
2e6a2beb5c
|
|
@ -49,6 +49,7 @@ import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
} from "@/components/ui/dialog";
|
} from "@/components/ui/dialog";
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
import { close, loading, successCallback } from "@/config/swal";
|
import { close, loading, successCallback } from "@/config/swal";
|
||||||
|
|
@ -59,6 +60,7 @@ import dynamic from "next/dynamic";
|
||||||
import { useRouter } from "@/i18n/routing";
|
import { useRouter } from "@/i18n/routing";
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
import { UnitMapping } from "@/app/[locale]/(protected)/contributor/agenda-setting/unit-mapping";
|
import { UnitMapping } from "@/app/[locale]/(protected)/contributor/agenda-setting/unit-mapping";
|
||||||
|
import SuggestionModal from "@/components/modal/suggestions-modal";
|
||||||
|
|
||||||
const imageSchema = z.object({
|
const imageSchema = z.object({
|
||||||
title: z.string().min(1, { message: "Judul diperlukan" }),
|
title: z.string().min(1, { message: "Judul diperlukan" }),
|
||||||
|
|
@ -628,10 +630,11 @@ export default function FormImageDetail() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="px-3 py-3 flex flex-row items-center text-blue-500 gap-2 text-sm">
|
|
||||||
<MailIcon />
|
<SuggestionModal
|
||||||
<p className="">{t("suggestion-box")} (0)</p>
|
id={Number(id)}
|
||||||
</div>
|
numberOfSuggestion={detail?.numberOfSuggestion}
|
||||||
|
/>
|
||||||
<div className="px-3 py-3 border mx-3">
|
<div className="px-3 py-3 border mx-3">
|
||||||
<p>{t("information")}:</p>
|
<p>{t("information")}:</p>
|
||||||
<p className="text-sm text-slate-400">{detail?.statusName}</p>
|
<p className="text-sm text-slate-400">{detail?.statusName}</p>
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,6 @@ export default function FormDetailLiveReport() {
|
||||||
const roleId = getCookiesDecrypt("urie");
|
const roleId = getCookiesDecrypt("urie");
|
||||||
const userLevelNumber = getCookiesDecrypt("ulne");
|
const userLevelNumber = getCookiesDecrypt("ulne");
|
||||||
|
|
||||||
console.log("cookie", userId, userLevelId, roleId, userLevelNumber);
|
|
||||||
const [startTime, setStartTime] = useState("08:00");
|
const [startTime, setStartTime] = useState("08:00");
|
||||||
const [endTime, setEndTime] = useState("09:00");
|
const [endTime, setEndTime] = useState("09:00");
|
||||||
const [date, setDate] = useState<DateRange | undefined>();
|
const [date, setDate] = useState<DateRange | undefined>();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,269 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { MailIcon, UserIcon } from "lucide-react";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTrigger,
|
||||||
|
} from "../ui/dialog";
|
||||||
|
import { Button } from "../ui/button";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
import { Input } from "../ui/input";
|
||||||
|
import { getCookiesDecrypt } from "@/lib/utils";
|
||||||
|
import { close, error, loading } from "@/config/swal";
|
||||||
|
import {
|
||||||
|
createSuggestion,
|
||||||
|
deleteSuggestion,
|
||||||
|
getSuggestionList,
|
||||||
|
} from "@/service/curated-content/curated-content";
|
||||||
|
import { formatDateToIndonesian } from "@/utils/globals";
|
||||||
|
|
||||||
|
export default function SuggestionModal(props: {
|
||||||
|
id: number;
|
||||||
|
numberOfSuggestion: number;
|
||||||
|
}) {
|
||||||
|
const { id, numberOfSuggestion } = props;
|
||||||
|
const t = useTranslations("Form");
|
||||||
|
|
||||||
|
const [suggestionValue, setSuggestionValue] = useState("");
|
||||||
|
const userId = getCookiesDecrypt("uie");
|
||||||
|
|
||||||
|
const [listData, setListData] = useState([]);
|
||||||
|
const [replyId, setReplyId] = useState(0);
|
||||||
|
const [replyValue, setReplyValue] = useState("");
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
initState();
|
||||||
|
}, [id]);
|
||||||
|
|
||||||
|
async function initState() {
|
||||||
|
loading();
|
||||||
|
const response = await getSuggestionList(id);
|
||||||
|
setListData(response?.data?.data);
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
const saveSuggestion = async (parentId?: number) => {
|
||||||
|
console.log("suggestion vval", suggestionValue);
|
||||||
|
const data = {
|
||||||
|
mediaUploadId: Number(id),
|
||||||
|
message: parentId ? replyValue : suggestionValue,
|
||||||
|
parentId: parentId ? parentId : null,
|
||||||
|
};
|
||||||
|
loading();
|
||||||
|
const response = await createSuggestion(data);
|
||||||
|
if (response?.error) {
|
||||||
|
error(response?.message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
close();
|
||||||
|
setSuggestionValue("");
|
||||||
|
setReplyValue("");
|
||||||
|
initState();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDeleteSuggestion = async (id: number) => {
|
||||||
|
loading();
|
||||||
|
const response = await deleteSuggestion(id);
|
||||||
|
if (response?.error) {
|
||||||
|
error(response?.message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
close();
|
||||||
|
initState();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog>
|
||||||
|
<DialogTrigger>
|
||||||
|
<a className="px-3 py-3 flex flex-row items-center text-blue-500 gap-2 text-sm cursor-pointer">
|
||||||
|
<MailIcon />
|
||||||
|
<p className="">
|
||||||
|
{t("suggestion-box")} ({numberOfSuggestion || 0})
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
</DialogTrigger>
|
||||||
|
<DialogContent size="md" className="px-1 lg:px-4">
|
||||||
|
<DialogHeader>Suggestions</DialogHeader>
|
||||||
|
|
||||||
|
<div className="flex flex-row items-center justify-center">
|
||||||
|
<Input
|
||||||
|
value={suggestionValue}
|
||||||
|
onChange={(e) => setSuggestionValue(e.target.value)}
|
||||||
|
/>
|
||||||
|
<Button size="sm" onClick={() => saveSuggestion()}>
|
||||||
|
{t("submit")}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
{listData?.length > 0 &&
|
||||||
|
listData?.map((data: any) => (
|
||||||
|
<div key={data?.id} className="flex flex-col gap-1 w-full">
|
||||||
|
<div className="flex flex-row gap-2">
|
||||||
|
<div className="mt-2 w-[24px] h-[24px] md:w-[50px] md:h-[50px] border-2 flex items-center justify-center rounded-full bg-stone-200 border-stone-300">
|
||||||
|
<UserIcon size={36} />
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-2 w-full">
|
||||||
|
<div className="flex justify-between bg-stone-200 px-2 lg:px-4 py-2 w-full rounded-lg">
|
||||||
|
<div className="flex flex-col gap-1">
|
||||||
|
<b className="text-sm md:text-base">
|
||||||
|
{data.suggestionFrom?.fullname}
|
||||||
|
</b>
|
||||||
|
<p className="text-xs md:text-sm">{data.message}</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-1">
|
||||||
|
<p className="text-xs md:text-sm text-right">
|
||||||
|
{formatDateToIndonesian(data.createdAt)}
|
||||||
|
</p>
|
||||||
|
<div className="flex flex-col items-end md:flex-row gap-2 text-xs md:text-sm justify-end">
|
||||||
|
<a
|
||||||
|
className="text-primary cursor-pointer"
|
||||||
|
onClick={() => {
|
||||||
|
setReplyId(replyId === data?.id ? 0 : data?.id);
|
||||||
|
setReplyValue("");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Balas
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
onClick={() => handleDeleteSuggestion(data?.id)}
|
||||||
|
className="text-destructive cursor-pointer"
|
||||||
|
>
|
||||||
|
Hapus
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{replyId === data?.id && (
|
||||||
|
<div className="flex flex-row items-center justify-center">
|
||||||
|
<Input
|
||||||
|
value={replyValue}
|
||||||
|
onChange={(e) => setReplyValue(e.target.value)}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
onClick={() => saveSuggestion(data?.id)}
|
||||||
|
>
|
||||||
|
{t("submit")}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{data?.children.length > 0 &&
|
||||||
|
data?.children.map((child: any) => (
|
||||||
|
<div key={child.id} className="flex flex-row gap-2">
|
||||||
|
<div className="w-[50px]"></div>
|
||||||
|
<div className="flex flex-col w-full gap-2">
|
||||||
|
<div className="flex flex-row gap-2 w-full">
|
||||||
|
<div className="mt-2 w-[24px] h-[24px] md:w-[50px] md:h-[50px] border-2 flex items-center justify-center rounded-full bg-stone-200 border-stone-300">
|
||||||
|
<UserIcon size={36} />
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-2 w-full">
|
||||||
|
<div className="flex justify-between bg-stone-100 px-2 lg:px-4 py-2 w-full rounded-lg">
|
||||||
|
<div className="flex flex-col gap-1">
|
||||||
|
<b className="text-xs md:text-base">
|
||||||
|
{child.suggestionFrom?.fullname}
|
||||||
|
</b>
|
||||||
|
<p className="text-xs md:text-sm">
|
||||||
|
{child.message}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-1">
|
||||||
|
<p className="text-xs md:text-sm text-right">
|
||||||
|
{formatDateToIndonesian(child.createdAt)}
|
||||||
|
</p>
|
||||||
|
<div className="flex flex-col items-end md:flex-row gap-2 text-xs md:text-sm justify-end">
|
||||||
|
<a
|
||||||
|
className="text-primary cursor-pointer"
|
||||||
|
onClick={() => {
|
||||||
|
setReplyId(
|
||||||
|
replyId === child?.id ? 0 : child?.id
|
||||||
|
);
|
||||||
|
setReplyValue("");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Balas
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
onClick={() =>
|
||||||
|
handleDeleteSuggestion(child?.id)
|
||||||
|
}
|
||||||
|
className="text-destructive cursor-pointer"
|
||||||
|
>
|
||||||
|
Hapus
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{replyId === child?.id && (
|
||||||
|
<div className="flex flex-row items-center justify-center">
|
||||||
|
<Input
|
||||||
|
value={replyValue}
|
||||||
|
onChange={(e) =>
|
||||||
|
setReplyValue(e.target.value)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
onClick={() => saveSuggestion(child?.id)}
|
||||||
|
>
|
||||||
|
{t("submit")}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{child?.children.length > 0 &&
|
||||||
|
child?.children.map((items: any) => (
|
||||||
|
<div key={items.id} className="flex flex-row gap-2">
|
||||||
|
<div className="w-[50px]"></div>
|
||||||
|
<div className="flex flex-row gap-2 w-full">
|
||||||
|
<div className="mt-2 w-[24px] h-[24px] md:w-[50px] md:h-[50px] border-2 flex items-center justify-center rounded-full bg-stone-200 border-stone-300">
|
||||||
|
<UserIcon size={36} />
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-2 w-full">
|
||||||
|
<div className="flex justify-between bg-stone-50 px-2 lg:px-4 py-2 w-full rounded-lg">
|
||||||
|
<div className="flex flex-col gap-1">
|
||||||
|
<b className="text-xs md:text-base">
|
||||||
|
{items.suggestionFrom?.fullname}
|
||||||
|
</b>
|
||||||
|
<p className="text-xs md:text-sm">
|
||||||
|
{items.message}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-1">
|
||||||
|
<p className="text-xs md:text-sm text-right">
|
||||||
|
{formatDateToIndonesian(
|
||||||
|
items.createdAt
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
<div className="flex flex-col items-end md:flex-row gap-2 text-xs md:text-sm justify-end">
|
||||||
|
<a
|
||||||
|
onClick={() =>
|
||||||
|
handleDeleteSuggestion(items?.id)
|
||||||
|
}
|
||||||
|
className="text-destructive cursor-pointer"
|
||||||
|
>
|
||||||
|
Hapus
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -35,3 +35,18 @@ export async function deleteMediaCurationMessage(id: any) {
|
||||||
const url = `media/curation/message?id=${id}`;
|
const url = `media/curation/message?id=${id}`;
|
||||||
return httpDeleteInterceptor(url);
|
return httpDeleteInterceptor(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getSuggestionList(id: number | string) {
|
||||||
|
const url = `media/suggestion?mediaId=${id}`;
|
||||||
|
return httpGetInterceptor(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function createSuggestion(data: any) {
|
||||||
|
const url = "media/suggestion";
|
||||||
|
return httpPostInterceptor(url, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function deleteSuggestion(id: number | string) {
|
||||||
|
const url = `media/suggestion?id=${id}`;
|
||||||
|
return httpDeleteInterceptor(url);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue