feat:kotak saran
This commit is contained in:
parent
9231546780
commit
2e6a2beb5c
|
|
@ -49,6 +49,7 @@ import {
|
|||
Dialog,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { close, loading, successCallback } from "@/config/swal";
|
||||
|
|
@ -59,6 +60,7 @@ import dynamic from "next/dynamic";
|
|||
import { useRouter } from "@/i18n/routing";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { UnitMapping } from "@/app/[locale]/(protected)/contributor/agenda-setting/unit-mapping";
|
||||
import SuggestionModal from "@/components/modal/suggestions-modal";
|
||||
|
||||
const imageSchema = z.object({
|
||||
title: z.string().min(1, { message: "Judul diperlukan" }),
|
||||
|
|
@ -628,10 +630,11 @@ export default function FormImageDetail() {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="px-3 py-3 flex flex-row items-center text-blue-500 gap-2 text-sm">
|
||||
<MailIcon />
|
||||
<p className="">{t("suggestion-box")} (0)</p>
|
||||
</div>
|
||||
|
||||
<SuggestionModal
|
||||
id={Number(id)}
|
||||
numberOfSuggestion={detail?.numberOfSuggestion}
|
||||
/>
|
||||
<div className="px-3 py-3 border mx-3">
|
||||
<p>{t("information")}:</p>
|
||||
<p className="text-sm text-slate-400">{detail?.statusName}</p>
|
||||
|
|
|
|||
|
|
@ -87,7 +87,6 @@ export default function FormDetailLiveReport() {
|
|||
const roleId = getCookiesDecrypt("urie");
|
||||
const userLevelNumber = getCookiesDecrypt("ulne");
|
||||
|
||||
console.log("cookie", userId, userLevelId, roleId, userLevelNumber);
|
||||
const [startTime, setStartTime] = useState("08:00");
|
||||
const [endTime, setEndTime] = useState("09:00");
|
||||
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}`;
|
||||
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