This commit is contained in:
hanif salafi 2025-06-13 16:23:40 +07:00
commit d5be139635
23 changed files with 873 additions and 460 deletions

View File

@ -1,13 +1,12 @@
import SiteBreadcrumb from "@/components/site-breadcrumb"; import SiteBreadcrumb from "@/components/site-breadcrumb";
import FormBlogDetail from "@/components/form/blog/blog--detail-form"; import FormBlogDetail from "@/components/form/blog/blog--detail-form";
import FormSurveyDetailPage from "@/components/form/survey/survey-detail";
const BlogDetailPage = async () => { const BlogDetailPage = async () => {
return ( return (
<div> <div>
<SiteBreadcrumb /> <SiteBreadcrumb />
<div className="space-y-4"> <div className="space-y-4">
<FormSurveyDetailPage /> <FormBlogDetail />
</div> </div>
</div> </div>
); );

View File

@ -0,0 +1,15 @@
import FormAudioTaDetail from "@/components/form/content/task-ta/audio-detail-form";
import SiteBreadcrumb from "@/components/site-breadcrumb";
const AudioDetailPage = async () => {
return (
<div>
<SiteBreadcrumb />
<div className="space-y-4">
<FormAudioTaDetail />
</div>
</div>
);
};
export default AudioDetailPage;

View File

@ -1,3 +1,4 @@
import FormImageTaDetail from "@/components/form/content/task-ta/image-detail-form";
import FormImageDetail from "@/components/form/content/task-ta/image-detail-form"; import FormImageDetail from "@/components/form/content/task-ta/image-detail-form";
import SiteBreadcrumb from "@/components/site-breadcrumb"; import SiteBreadcrumb from "@/components/site-breadcrumb";
@ -6,7 +7,7 @@ const ImageDetailPage = async () => {
<div> <div>
<SiteBreadcrumb /> <SiteBreadcrumb />
<div className="space-y-4"> <div className="space-y-4">
<FormImageDetail /> <FormImageTaDetail />
</div> </div>
</div> </div>
); );

View File

@ -0,0 +1,16 @@
import FormTeksTaDetail from "@/components/form/content/task-ta/teks-detail-form";
import FormTeksDetail from "@/components/form/content/task-ta/teks-detail-form";
import SiteBreadcrumb from "@/components/site-breadcrumb";
const TeksDetailPage = async () => {
return (
<div>
<SiteBreadcrumb />
<div className="space-y-4">
<FormTeksTaDetail />
</div>
</div>
);
};
export default TeksDetailPage;

View File

@ -0,0 +1,16 @@
import FormVideoTaDetail from "@/components/form/content/task-ta/video-detail-form";
import FormVideoDetail from "@/components/form/content/task-ta/video-detail-form";
import SiteBreadcrumb from "@/components/site-breadcrumb";
const VideoDetailPage = async () => {
return (
<div>
<SiteBreadcrumb />
<div className="space-y-4">
<FormVideoTaDetail />
</div>
</div>
);
};
export default VideoDetailPage;

View File

@ -303,7 +303,7 @@ export default function FormBlogDetail() {
</div> </div>
</Card> </Card>
<div className="w-full lg:w-4/12"> <div className="w-full lg:w-4/12">
<Card className=" h-[650px]"> <Card className=" h-[650px] px-3 py-3">
<div className="px-3 py-3"> <div className="px-3 py-3">
<Label htmlFor="fileInput">Gambar Utama</Label> <Label htmlFor="fileInput">Gambar Utama</Label>
<Input <Input

View File

@ -1,6 +1,6 @@
"use client"; "use client";
import React, { ChangeEvent, useEffect, useRef, useState } from "react"; import React, { ChangeEvent, useEffect, useRef, useState } from "react";
import { useForm, Controller } from "react-hook-form"; import { useForm, Controller, useWatch } from "react-hook-form";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
@ -133,6 +133,19 @@ export default function FormBlogUpdate() {
setSelectedFiles((prevImages) => prevImages.filter((_, i) => i !== index)); setSelectedFiles((prevImages) => prevImages.filter((_, i) => i !== index));
}; };
const titleValue = useWatch({ control, name: "title" });
useEffect(() => {
if (titleValue) {
const slugified = titleValue
.toLowerCase()
.trim()
.replace(/\s+/g, "-")
.replace(/[^\w-]+/g, ""); // optional: hapus karakter non-alfanumerik
setValue("slug", slugified);
}
}, [titleValue, setValue]);
useEffect(() => { useEffect(() => {
async function initState() { async function initState() {
if (id) { if (id) {
@ -323,7 +336,7 @@ export default function FormBlogUpdate() {
<Input <Input
size="md" size="md"
type="text" type="text"
defaultValue={detail?.slug} defaultValue={detail?.slug || field?.value}
onChange={field.onChange} onChange={field.onChange}
placeholder="Enter Slug" placeholder="Enter Slug"
/> />
@ -363,7 +376,7 @@ export default function FormBlogUpdate() {
</div> </div>
</Card> </Card>
<div className="w-full lg:w-4/12"> <div className="w-full lg:w-4/12">
<Card className="h-[600px] sm:h-[850px] lg:h-[700px]"> <Card className="h-[600px] sm:h-[850px] lg:h-[700px] px-3 py-3">
<div className="px-3 py-3"> <div className="px-3 py-3">
<Label htmlFor="fileInput">Gambar Utama</Label> <Label htmlFor="fileInput">Gambar Utama</Label>
<input <input

View File

@ -1,6 +1,6 @@
"use client"; "use client";
import React, { ChangeEvent, useEffect, useRef, useState } from "react"; import React, { ChangeEvent, useEffect, useRef, useState } from "react";
import { useForm, Controller } from "react-hook-form"; import { useForm, Controller, useWatch } from "react-hook-form";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
@ -130,6 +130,19 @@ export default function FormBlog() {
setSelectedFiles((prevImages) => prevImages.filter((_, i) => i !== index)); setSelectedFiles((prevImages) => prevImages.filter((_, i) => i !== index));
}; };
const titleValue = useWatch({ control, name: "title" });
useEffect(() => {
if (titleValue) {
const slugified = titleValue
.toLowerCase()
.trim()
.replace(/\s+/g, "-")
.replace(/[^\w-]+/g, ""); // optional: hapus karakter non-alfanumerik
setValue("slug", slugified);
}
}, [titleValue, setValue]);
// useEffect(() => { // useEffect(() => {
// async function initState() { // async function initState() {
// getCategories(); // getCategories();
@ -359,8 +372,8 @@ export default function FormBlog() {
</div> </div>
</Card> </Card>
<div className="w-full lg:w-4/12"> <div className="w-full lg:w-4/12">
<Card className=" h-[600px]"> <Card className=" h-[600px] px-3 py-3">
<div className="px-3 py-3"> <div className="px-3 py-3 flex flex-col">
<label htmlFor="fileInput">Gambar Utama</label> <label htmlFor="fileInput">Gambar Utama</label>
<input id="fileInput" type="file" onChange={handleImageChange} /> <input id="fileInput" type="file" onChange={handleImageChange} />
</div> </div>

View File

@ -20,10 +20,12 @@ import {
} from "@/components/ui/select"; } from "@/components/ui/select";
import { Avatar, AvatarImage } from "@/components/ui/avatar"; import { Avatar, AvatarImage } from "@/components/ui/avatar";
import { import {
deleteEscalationDiscussion,
getEscalationDiscussion, getEscalationDiscussion,
getTicketingDetail, getTicketingDetail,
getTicketingInternalDetail, getTicketingInternalDetail,
getTicketingInternalDiscussion, getTicketingInternalDiscussion,
saveEscalationDiscussion,
saveTicketInternalReply, saveTicketInternalReply,
} from "@/service/communication/communication"; } from "@/service/communication/communication";
import { Textarea } from "@/components/ui/textarea"; import { Textarea } from "@/components/ui/textarea";
@ -33,6 +35,7 @@ import { loading } from "@/lib/swal";
import { id } from "date-fns/locale"; import { id } from "date-fns/locale";
import { htmlToString } from "@/utils/globals"; import { htmlToString } from "@/utils/globals";
import InfoLainnyaModal from "../ticketing/info-lainnya"; import InfoLainnyaModal from "../ticketing/info-lainnya";
import { PlusIcon } from "lucide-react";
const taskSchema = z.object({ const taskSchema = z.object({
title: z.string().min(1, { message: "Judul diperlukan" }), title: z.string().min(1, { message: "Judul diperlukan" }),
@ -62,25 +65,12 @@ export default function FormDetailEscalation() {
const [detail, setDetail] = useState<any>(); const [detail, setDetail] = useState<any>();
const [ticketReply, setTicketReply] = useState<replyDetail[]>([]); const [ticketReply, setTicketReply] = useState<replyDetail[]>([]);
const [replyVisible, setReplyVisible] = useState(false); const [replyVisible, setReplyVisible] = useState(false);
const [listDiscussion, setListDiscussion] = useState(); const [activeReplyId, setActiveReplyId] = useState<number | null>(null);
const [message, setMessage] = useState("");
const [selectedPriority, setSelectedPriority] = useState(""); const [selectedPriority, setSelectedPriority] = useState("");
const [openEmergencyModal, setOpenEmergencyModal] = useState(false); const [openEmergencyModal, setOpenEmergencyModal] = useState(false);
const [replyMessage, setReplyMessage] = useState(""); const [replyMessage, setReplyMessage] = useState("");
const [replies, setReplies] = useState([ const [listDiscussion, setListDiscussion] = useState([]);
{ const [message, setMessage] = useState("");
id: 1,
name: "Mabes Polri - Approver",
message: "test",
timestamp: "2024-12-20 00:56:10",
},
{
id: 2,
name: "Mabes Polri - Approver",
message: "balas",
timestamp: "2025-01-18 17:42:48",
},
]);
const { const {
control, control,
@ -109,40 +99,75 @@ export default function FormDetailEscalation() {
} }
const handleReply = () => { const handleReply = () => {
setReplyVisible((prev) => !prev); // Toggle visibility setReplyVisible((prev) => !prev);
}; };
// useEffect(() => {
// async function initState() {
// if (id != undefined) {
// loading();
// const responseGet = await getEscalationDiscussion(id);
// close();
// console.log("escal data", responseGet?.data); useEffect(() => {
// setListDiscussion(responseGet?.data?.data); const fetchDiscussion = async () => {
// } const response = await getEscalationDiscussion(id);
// } setListDiscussion(response?.data?.data || []);
// initState(); };
// }, [id]);
const handleSendReply = () => { fetchDiscussion();
if (replyMessage.trim() === "") return; }, []);
const newReply = { const postData = async () => {
id: replies.length + 1, if (!message.trim()) return;
name: "Mabes Polri - Approver", // Sesuaikan dengan data dinamis jika ada
const payload = {
ticketId: id,
message,
parentId: null,
};
try {
await saveEscalationDiscussion(payload);
setMessage("");
const response = await getEscalationDiscussion(id);
setListDiscussion(response?.data?.data || []);
} catch (error) {
console.error("Gagal mengirim tanggapan:", error);
}
};
const postDataChild = async (parentId: any) => {
const textarea = document.getElementById(
`input-comment-${parentId}`
) as HTMLTextAreaElement | null;
const replyMessage = textarea?.value;
if (!replyMessage?.trim()) return;
const payload = {
ticketId: Number(id),
parentMessageId: parentId,
message: replyMessage, message: replyMessage,
timestamp: new Date().toISOString().slice(0, 19).replace("T", " "),
}; };
setReplies([...replies, newReply]); try {
setReplyMessage(""); await saveEscalationDiscussion(payload);
if (textarea) textarea.value = "";
const response = await getEscalationDiscussion(id);
setListDiscussion(response?.data?.data || []);
} catch (error) {
console.error("Gagal mengirim balasan:", error);
}
}; };
const openEmergencyIssueDetail = () => { const openEmergencyIssueDetail = () => {
setOpenEmergencyModal(true); setOpenEmergencyModal(true);
}; };
async function deleteDataSuggestion(dataId: any) {
const response = await deleteEscalationDiscussion(dataId);
console.log(response);
const responseGet = await getEscalationDiscussion(id);
setListDiscussion(responseGet?.data?.data);
}
return ( return (
<div> <div>
<div className="flex"> <div className="flex">
@ -273,40 +298,116 @@ export default function FormDetailEscalation() {
</div> </div>
<div className="mx-3 my-3"> <div className="mx-3 my-3">
<h3 className="text-gray-700 font-medium">Tanggapan</h3> <h3 className="text-gray-700 font-medium">Tanggapan</h3>
<div className="space-y-4"> <div className="space-y-4 ml-5 mt-5">
{replies.map((reply) => ( {listDiscussion.map((parent: any) => (
<div key={reply.id} className="border-b pb-2"> <div key={parent.id} className="border-b pb-4">
<p className="font-semibold text-gray-800">{reply.name}</p> <div className="flex justify-between items-start">
<p className="text-gray-600">{reply.message}</p> <div>
<p className="text-sm text-gray-400">{reply.timestamp}</p> <p className="font-semibold text-gray-800">
{parent.messageFrom?.fullname}
</p>
<p className="text-gray-600">{parent.message}</p>
<p className="text-sm text-gray-400">
{parent.createdAt}
</p>
</div>
<button
onClick={() => deleteDataSuggestion(parent.id)}
className="text-red-500 text-sm hover:underline ml-2"
>
Hapus
</button>
</div>
{activeReplyId !== parent.id && (
<button
onClick={() => setActiveReplyId(parent.id)}
className="text-blue-500 text-sm mt-2 hover:underline"
>
Balas
</button>
)}
{activeReplyId === parent.id && (
<div className="mt-2">
<textarea
id={`input-comment-${parent.id}`}
className="w-full h-20 border border-gray-300 rounded-md p-2"
placeholder="Tulis balasan di sini..."
/>
<div className="flex justify-end gap-2 mt-2">
<button
onClick={() => setActiveReplyId(null)}
className="px-4 py-1 text-sm bg-gray-200 text-gray-800 rounded-md"
>
Batal
</button>
<button
onClick={() => {
postDataChild(parent.id);
setActiveReplyId(null);
}}
className="px-4 py-1 text-sm bg-blue-600 text-white rounded-md"
>
Kirim
</button>
</div>
</div>
)}
{parent.children?.length > 0 && (
<div className="ml-4 mt-3 space-y-3 border-l-2 pl-4 border-gray-200">
{parent.children.map((child: any) => (
<div
key={child.id}
className="flex justify-between items-start"
>
<div>
<p className="font-semibold text-gray-800">
{child.messageFrom?.fullname}
</p>
<p className="text-gray-600">{child.message}</p>
<p className="text-sm text-gray-400">
{child.createdAt}
</p>
</div>
<button
onClick={() => deleteDataSuggestion(child.id)}
className="text-red-500 text-sm hover:underline ml-2"
>
Hapus
</button>
</div> </div>
))} ))}
</div> </div>
)}
</div>
))}
</div> </div>
<div className="mx-3"> <div className="mt-6">
<label <label className="block text-gray-700 font-medium mb-2">
htmlFor="replyMessage"
className="block text-gray-700 font-medium mb-2"
>
Tulis Tanggapan Anda Tulis Tanggapan Anda
</label> </label>
<textarea <textarea
id="replyMessage" value={message}
onChange={(e) => setMessage(e.target.value)}
className="w-full h-24 border border-gray-300 rounded-md p-2" className="w-full h-24 border border-gray-300 rounded-md p-2"
value={replyMessage}
onChange={(e) => setReplyMessage(e.target.value)}
placeholder="Tulis tanggapan anda di sini..." placeholder="Tulis tanggapan anda di sini..."
/> />
<Button size="sm" variant={"outline"} color="primary">
<PlusIcon />
Lampiran
</Button>
<div className="flex justify-end gap-3 mt-2 mb-3"> <div className="flex justify-end gap-3 mt-2 mb-3">
<button <button
onClick={() => setReplyMessage("")} onClick={() => setMessage("")}
className="px-4 py-2 bg-gray-200 text-gray-800 rounded-md" className="px-4 py-2 bg-gray-200 text-gray-800 rounded-md"
> >
Batal Batal
</button> </button>
<button <button
onClick={handleSendReply} onClick={postData}
className="px-4 py-2 bg-blue-600 text-white rounded-md" className="px-4 py-2 bg-blue-600 text-white rounded-md"
> >
Kirim Pesan Kirim Pesan
@ -314,6 +415,7 @@ export default function FormDetailEscalation() {
</div> </div>
</div> </div>
</div> </div>
</div>
)} )}
</div> </div>
); );

View File

@ -103,20 +103,6 @@ export default function FormQuestionsDetail() {
const [selectedOperatorEscalation, setSelectedOperatorEscalation] = useState< const [selectedOperatorEscalation, setSelectedOperatorEscalation] = useState<
string[] string[]
>([]); >([]);
// const [replies, setReplies] = useState([
// // {
// // id: 1,
// // name: "Mabes Polri - Approver",
// // message: "test",
// // timestamp: "2024-12-20 00:56:10",
// // },
// // {
// // id: 2,
// // name: "Mabes Polri - Approver",
// // message: "balas",
// // timestamp: "2025-01-18 17:42:48",
// // },
// ]);
const { const {
control, control,
@ -156,12 +142,11 @@ export default function FormQuestionsDetail() {
setDetail(detail); setDetail(detail);
setDetailTickets(detail); setDetailTickets(detail);
// Ambil escalationTeams seperti ":891:"
if (detail?.escalationTeams) { if (detail?.escalationTeams) {
const teamIds = detail.escalationTeams const teamIds = detail.escalationTeams
.split(":") .split(":")
.filter((id: string) => id); // hapus string kosong .filter((id: string) => id);
setSelectedOperatorEscalation(teamIds); // set ke state setSelectedOperatorEscalation(teamIds);
} }
getTicketReply(); getTicketReply();
@ -409,7 +394,7 @@ export default function FormQuestionsDetail() {
{/* Tag yang ditampilkan secara kolom */} {/* Tag yang ditampilkan secara kolom */}
{selectedOperator.length > 0 && ( {selectedOperator.length > 0 && (
<div className="flex flex-col gap-2 mb-2"> <div className="flex flex-row gap-2 mb-2">
{selectedOperator.map((id) => { {selectedOperator.map((id) => {
const label = operatorOpt.find( const label = operatorOpt.find(
(op: any) => op.value === id (op: any) => op.value === id
@ -453,6 +438,7 @@ export default function FormQuestionsDetail() {
className="flex items-center space-x-2 cursor-pointer px-2 py-1 hover:bg-gray-100 rounded" className="flex items-center space-x-2 cursor-pointer px-2 py-1 hover:bg-gray-100 rounded"
> >
<input <input
disabled
type="checkbox" type="checkbox"
checked={selectedOperator.includes(op.value)} checked={selectedOperator.includes(op.value)}
onChange={(e) => { onChange={(e) => {
@ -495,7 +481,7 @@ export default function FormQuestionsDetail() {
<Label>Eskalasi Untuk</Label> <Label>Eskalasi Untuk</Label>
{selectedOperatorEscalation.length > 0 && ( {selectedOperatorEscalation.length > 0 && (
<div className="flex flex-col gap-2 mb-2"> <div className="flex flex-row gap-2 mb-2">
{selectedOperatorEscalation.map((id) => { {selectedOperatorEscalation.map((id) => {
const operator = curatorOpt.find( const operator = curatorOpt.find(
(op: any) => op.value === id (op: any) => op.value === id

View File

@ -43,7 +43,7 @@ import {
import { ChevronDownIcon } from "lucide-react"; import { ChevronDownIcon } from "lucide-react";
import { getOperatorUser } from "@/service/management-user/management-user"; import { getOperatorUser } from "@/service/management-user/management-user";
import makeAnimated from "react-select/animated"; import makeAnimated from "react-select/animated";
import Select from "react-select"; import Select, { ActionMeta, MultiValue } from "react-select";
interface Option { interface Option {
id: string; id: string;
@ -109,9 +109,7 @@ export default function FormQuestionsForward() {
const [selectedOperator, setSelectedOperator] = useState<string[]>([]); const [selectedOperator, setSelectedOperator] = useState<string[]>([]);
const [options, setOptions] = useState<Option[]>([]); const [options, setOptions] = useState<Option[]>([]);
const animatedComponent = makeAnimated(); const animatedComponent = makeAnimated();
const [selectedOption, setSelectedOption] = useState<Option | undefined>( const [selectedOption, setSelectedOption] = useState<Option[]>([]);
undefined
);
const [replies, setReplies] = useState([ const [replies, setReplies] = useState([
{ {
id: 1, id: 1,
@ -195,7 +193,7 @@ export default function FormQuestionsForward() {
parentCommentId: detailTickets?.feedId, parentCommentId: detailTickets?.feedId,
operatorTeam: selectedOperator.join(","), operatorTeam: selectedOperator.join(","),
isEscalation: true, isEscalation: true,
communicationTeam: selectedOption?.id, communicationTeam: selectedOption.map((item) => item.id).join(","),
}; };
const response = await saveTicketsQuestion(payload); const response = await saveTicketsQuestion(payload);
@ -206,7 +204,6 @@ export default function FormQuestionsForward() {
icon: "success", icon: "success",
}); });
// Refresh data jika perlu
getTicketReply(); getTicketReply();
} catch (error) { } catch (error) {
console.error("Gagal update:", error); console.error("Gagal update:", error);
@ -218,9 +215,11 @@ export default function FormQuestionsForward() {
} }
}; };
const handleChange = (e: any) => { const handleChange = (
const selected = e; selected: MultiValue<Option>,
setSelectedOption(selected); _actionMeta: ActionMeta<Option>
) => {
setSelectedOption([...selected]);
}; };
const formatOptionLabel = (option: Option) => ( const formatOptionLabel = (option: Option) => (
@ -353,9 +352,8 @@ export default function FormQuestionsForward() {
<div className="mt-5 px-3 mb-3 flex flex-col gap-y-3"> <div className="mt-5 px-3 mb-3 flex flex-col gap-y-3">
<Label>Operator</Label> <Label>Operator</Label>
{/* Tag yang ditampilkan secara kolom */}
{selectedOperator.length > 0 && ( {selectedOperator.length > 0 && (
<div className="flex flex-col gap-2 mb-2"> <div className="flex flex-row gap-2 mb-2">
{selectedOperator.map((id) => { {selectedOperator.map((id) => {
const label = operatorOpt.find( const label = operatorOpt.find(
(op: any) => op.value === id (op: any) => op.value === id
@ -433,7 +431,7 @@ export default function FormQuestionsForward() {
components={animatedComponent} components={animatedComponent}
onChange={handleChange} onChange={handleChange}
formatOptionLabel={formatOptionLabel} formatOptionLabel={formatOptionLabel}
isMulti={false} isMulti={true}
/> />
</div> </div>
</div> </div>

View File

@ -130,7 +130,7 @@ export default function FormDetailInternal() {
} }
const handleReply = () => { const handleReply = () => {
setReplyVisible((prev) => !prev); // Toggle visibility setReplyVisible((prev) => !prev);
}; };
const handleSendReply = async () => { const handleSendReply = async () => {
@ -149,18 +149,9 @@ export default function FormDetailInternal() {
}; };
try { try {
const response = await saveTicketInternalReply(data); await saveTicketInternalReply(data);
// Tambahkan balasan baru ke daftar balasan await getTicketReply();
const newReply: replyDetail = {
id: response?.data?.id,
message: replyMessage,
createdAt: response?.data?.createdAt,
messageFrom: response?.data?.messageFrom,
messageTo: response?.data?.messageTo,
};
setTicketReply((prevReplies) => [newReply, ...prevReplies]);
MySwal.fire({ MySwal.fire({
title: "Sukses", title: "Sukses",
@ -168,7 +159,6 @@ export default function FormDetailInternal() {
icon: "success", icon: "success",
}); });
// Reset input dan sembunyikan form balasan
setReplyMessage(""); setReplyMessage("");
setReplyVisible(false); setReplyVisible(false);
} catch (error) { } catch (error) {

View File

@ -30,7 +30,7 @@ import dynamic from "next/dynamic";
const taskSchema = z.object({ const taskSchema = z.object({
title: z.string().min(1, { message: "Judul diperlukan" }), title: z.string().min(1, { message: "Judul diperlukan" }),
naration: z.string().min(2, { message: z.string().min(2, {
message: "Narasi Penugasan harus lebih dari 2 karakter.", message: "Narasi Penugasan harus lebih dari 2 karakter.",
}), }),
}); });
@ -77,13 +77,12 @@ export default function FormInternal() {
); );
const animatedComponent = makeAnimated(); const animatedComponent = makeAnimated();
const [platformTypeVisible, setPlatformTypeVisible] = useState(false); const [platformTypeVisible, setPlatformTypeVisible] = useState(false);
const [selectedTarget, setSelectedTarget] = useState(""); const [selectedTarget, setSelectedTarget] = useState<number | null>(null);
// Opsi untuk dropdown
const priority = [ const priority = [
{ value: "low", label: "Low" }, { value: 1, label: "Low" },
{ value: "medium", label: "Medium" }, { value: 2, label: "Medium" },
{ value: "high", label: "High" }, { value: 3, label: "High" },
]; ];
const { const {
@ -142,7 +141,6 @@ export default function FormInternal() {
const rawUser = res?.data?.data?.content; const rawUser = res?.data?.data?.content;
console.log("raw user", rawUser); console.log("raw user", rawUser);
// Tentukan tipe array sebagai Option[]
const optionArr: Option[] = rawUser.map((option: any) => ({ const optionArr: Option[] = rawUser.map((option: any) => ({
id: option?.id, id: option?.id,
label: option?.username + option?.fullname + option?.userLevel?.name, label: option?.username + option?.fullname + option?.userLevel?.name,
@ -159,9 +157,9 @@ export default function FormInternal() {
const save = async (data: TaskSchema) => { const save = async (data: TaskSchema) => {
const requestData = { const requestData = {
title: data.title, title: data.title,
narration: data.naration, message: data.message,
target: selectedTarget, target: selectedTarget,
sendToId: selectedOption?.id, // This should work now without the error sendToId: selectedOption?.id,
}; };
const response = await saveTicketingInternal(requestData); const response = await saveTicketingInternal(requestData);
@ -176,7 +174,7 @@ export default function FormInternal() {
confirmButtonColor: "#3085d6", confirmButtonColor: "#3085d6",
confirmButtonText: "OK", confirmButtonText: "OK",
}).then(() => { }).then(() => {
router.push("/en/shared/communication"); router.push("/in/shared/communication");
}); });
}; };
@ -198,13 +196,15 @@ export default function FormInternal() {
return ( return (
<Card> <Card>
<div className="px-6 py-6"> <div className=" px-6 py-6">
<p className="text-lg font-semibold mb-3">Form Penugasan</p> <p className="text-lg font-semibold mb-3"></p>
<form onSubmit={handleSubmit(onSubmit)}> <form onSubmit={handleSubmit(onSubmit)}>
<div className="gap-5 mb-5"> <div className="flex flex-col justify-center items-center gap-5 mb-5">
{/* Input Title */} {/* Input Title */}
<div className="space-y-2"> <div className="w-6/12 space-y-2">
<Label>Judul</Label> <Label>
Judul<span className="text-red-500">*</span>
</Label>
<Controller <Controller
control={control} control={control}
name="title" name="title"
@ -222,26 +222,28 @@ export default function FormInternal() {
<p className="text-red-400 text-sm">{errors.title.message}</p> <p className="text-red-400 text-sm">{errors.title.message}</p>
)} )}
</div> </div>
<div className="w-full"> <div className="w-6/12">
<div className="mt-5"> <div className="mt-5">
<Label>Priority</Label> <Label>
Priority <span className="text-red-500">*</span>
</Label>
<Select <Select
id="target-select" id="target-select"
options={priority} options={priority}
onChange={(selectedOption) => onChange={(selectedOption) =>
setSelectedTarget(selectedOption?.value || "") setSelectedTarget(selectedOption?.value ?? null)
} }
placeholder="Pilih" placeholder="Pilih"
styles={{ styles={{
control: (base) => ({ control: (base) => ({
...base, ...base,
minHeight: "40px", // Ukuran sesuai dengan size="md" minHeight: "40px",
}), }),
}} }}
/> />
</div> </div>
</div> </div>
<div className="w-full"> <div className="w-6/12">
<div className="mt-5"> <div className="mt-5">
<Label>Ditunjukan Untuk</Label> <Label>Ditunjukan Untuk</Label>
<Select <Select
@ -255,29 +257,28 @@ export default function FormInternal() {
/> />
</div> </div>
</div> </div>
<div className="mt-5"> <div className="w-6/12 mt-5">
<Label>Narasi Penugasan</Label> <Label>Narasi Penugasan</Label>
<Controller <Controller
control={control} control={control}
name="naration" name="message"
render={({ field: { onChange, value } }) => ( render={({ field: { onChange, value } }) => (
<CustomEditor onChange={onChange} initialData={value} /> <CustomEditor onChange={onChange} initialData={value} />
)} )}
/> />
{errors.naration?.message && ( {errors.message?.message && (
<p className="text-red-400 text-sm"> <p className="text-red-400 text-sm">{errors.message.message}</p>
{errors.naration.message}
</p>
)} )}
</div> </div>
</div> <div className="w-6/12 flex justify-end gap-3 mt-5">
<Button type="button" color="primary" variant="outline">
{/* Submit Button */} Batal
<div className="mt-4"> </Button>
<Button type="submit" color="primary"> <Button type="submit" color="primary">
Submit Submit
</Button> </Button>
</div> </div>
</div>
</form> </form>
</div> </div>
</Card> </Card>

View File

@ -125,7 +125,6 @@ export default function FormConvertSPIT() {
const [selectedCategoryId, setSelectedCategoryId] = useState<number | null>( const [selectedCategoryId, setSelectedCategoryId] = useState<number | null>(
null null
); );
const [tags, setTags] = useState<any[]>([]);
const [detail, setDetail] = useState<any>(); const [detail, setDetail] = useState<any>();
const [refresh, setRefresh] = useState(false); const [refresh, setRefresh] = useState(false);
const [selectedPublishers, setSelectedPublishers] = useState<number[]>([]); const [selectedPublishers, setSelectedPublishers] = useState<number[]>([]);
@ -159,30 +158,31 @@ export default function FormConvertSPIT() {
const [filePlacements, setFilePlacements] = useState<string[][]>([]); const [filePlacements, setFilePlacements] = useState<string[][]>([]);
const [isUserMabesApprover, setIsUserMabesApprover] = useState(false); const [isUserMabesApprover, setIsUserMabesApprover] = useState(false);
const [files, setFiles] = useState<FileType[]>([]); const [files, setFiles] = useState<FileType[]>([]);
const [tags, setTags] = useState<any[]>([]);
const inputRef = useRef<HTMLInputElement>(null);
const [selectedWritingStyle, setSelectedWritingStyle] = const [selectedWritingStyle, setSelectedWritingStyle] =
useState("Professional"); useState("Professional");
const imageSchema = z const imageSchema = z.object({
.object({
contentTitle: z.string().min(1, { message: "Judul diperlukan" }), contentTitle: z.string().min(1, { message: "Judul diperlukan" }),
contentDescription: z contentDescription: z
.string() .string()
.min(2, { message: "Narasi Penugasan harus lebih dari 2 karakter." }), .min(2, { message: "Narasi Penugasan harus lebih dari 2 karakter." }),
contentCreator: z.string().min(1, { message: "Creator diperlukan" }), contentCreator: z.string().min(1, { message: "Creator diperlukan" }),
contentRewriteDescription: z.string().optional(), contentRewriteDescription: z.string().optional(),
}) });
.refine( // .refine(
(data) => { // (data) => {
if (isContentRewriteClicked) { // if (isContentRewriteClicked) {
return detail?.contentRewriteDescription?.trim().length > 0; // return detail?.contentRewriteDescription?.trim().length > 0;
} // }
return true; // return true;
}, // },
{ // {
path: ["contentRewriteDescription"], // path: ["contentRewriteDescription"],
message: "File hasil rewrite wajib diisi", // message: "File hasil rewrite wajib diisi",
} // }
); // );
const options: Option[] = [ const options: Option[] = [
{ id: "all", label: "SEMUA" }, { id: "all", label: "SEMUA" },
@ -216,7 +216,7 @@ export default function FormConvertSPIT() {
contentTitle: detail?.contentTitle || "", contentTitle: detail?.contentTitle || "",
contentDescription: detail?.contentDescription || "", contentDescription: detail?.contentDescription || "",
contentCreator: detail?.contentCreator || "", contentCreator: detail?.contentCreator || "",
contentRewriteDescription: detail?.contentRewriteDescription || "",
// dll // dll
}, },
}); });
@ -368,6 +368,13 @@ export default function FormConvertSPIT() {
setSelectedTarget(matchingCategory.name); setSelectedTarget(matchingCategory.name);
} }
if (details?.contentTag) {
const initialTags = details.contentTag
.split(",")
.map((tag: string) => tag.trim());
setTags(initialTags);
}
// setSelectedTarget(details.categoryId); // Untuk dropdown // setSelectedTarget(details.categoryId); // Untuk dropdown
} }
} }
@ -478,13 +485,14 @@ export default function FormConvertSPIT() {
selectedFileType === "original" selectedFileType === "original"
? data.contentDescription ? data.contentDescription
: data.contentRewriteDescription; : data.contentRewriteDescription;
const finalTags = tags.join(", ");
const requestData = { const requestData = {
spitId: id, spitId: id,
title: data.contentTitle, title: data.contentTitle,
description, description,
htmlDescription: description, htmlDescription: description,
tags: "siap", tags: finalTags,
categoryId: selectedCategoryId, categoryId: selectedCategoryId,
publishedFor: publishedFor.join(","), publishedFor: publishedFor.join(","),
creator: data.contentCreator, creator: data.contentCreator,
@ -648,6 +656,19 @@ export default function FormConvertSPIT() {
}); });
} }
const handleAddTag = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === "Enter" && inputRef.current?.value.trim()) {
e.preventDefault();
const newTag = inputRef.current.value.trim();
if (!tags.includes(newTag)) {
setTags((prevTags) => [...prevTags, newTag]);
}
inputRef.current.value = "";
}
};
return ( return (
<> <>
<Form {...form}> <Form {...form}>
@ -809,7 +830,11 @@ export default function FormConvertSPIT() {
) : ( ) : (
<CustomEditor <CustomEditor
onChange={onChange} onChange={onChange}
initialData={articleBody || value} initialData={
articleBody ||
detail?.contentRewriteDescription ||
value
}
/> />
) )
} }
@ -1030,7 +1055,7 @@ export default function FormConvertSPIT() {
<Input <Input
size="md" size="md"
type="text" type="text"
value={detail?.contentCreator} defaultValue={detail?.contentCreator}
onChange={field.onChange} onChange={field.onChange}
placeholder="Enter Title" placeholder="Enter Title"
/> />
@ -1051,15 +1076,20 @@ export default function FormConvertSPIT() {
<div className="px-3 py-3"> <div className="px-3 py-3">
<div className="space-y-2"> <div className="space-y-2">
<Label>{t("tags")}</Label> <Label>{t("tags")}</Label>
<Input
type="text"
id="tags"
placeholder="Add a tag and press Enter"
onKeyDown={handleAddTag}
ref={inputRef}
/>
<div className="flex flex-wrap gap-2"> <div className="flex flex-wrap gap-2">
{detail?.contentTag {tags.map((tag, index) => (
?.split(",")
.map((tag: any, index: any) => (
<Badge <Badge
key={index} key={index}
className="border rounded-md px-2 py-2" className="border rounded-md px-2 py-2"
> >
{tag.trim()} {tag}
</Badge> </Badge>
))} ))}
</div> </div>
@ -1100,7 +1130,7 @@ export default function FormConvertSPIT() {
</div> </div>
<div className="mt-4"> <div className="mt-4">
<Button <Button
type="submit" type="button"
className="bg-red-500 hover:bg-red-700" className="bg-red-500 hover:bg-red-700"
onClick={() => deleteSpitContent()} onClick={() => deleteSpitContent()}
> >

View File

@ -113,7 +113,7 @@ const ViewEditor = dynamic(
{ ssr: false } { ssr: false }
); );
export default function FormAudioDetail() { export default function FormAudioTaDetail() {
const MySwal = withReactContent(Swal); const MySwal = withReactContent(Swal);
const router = useRouter(); const router = useRouter();
const userId = getCookiesDecrypt("uie"); const userId = getCookiesDecrypt("uie");
@ -487,7 +487,7 @@ export default function FormAudioDetail() {
</p> </p>
)} )}
</div> </div>
<div className="flex items-center"> {/* <div className="flex items-center">
<div className="py-3 w-full space-y-2"> <div className="py-3 w-full space-y-2">
<Label>{t("category")}</Label> <Label>{t("category")}</Label>
<Select <Select
@ -509,7 +509,7 @@ export default function FormAudioDetail() {
</SelectContent> </SelectContent>
</Select> </Select>
</div> </div>
</div> </div> */}
<div className="py-3 space-y-2"> <div className="py-3 space-y-2">
<Label>{t("description")}</Label> <Label>{t("description")}</Label>
@ -569,8 +569,7 @@ export default function FormAudioDetail() {
</div> </div>
</Card> </Card>
<div className="w-full lg:w-4/12"> <div className="w-full lg:w-4/12">
<Card className="pb-3"> {/* <div className="px-3 py-3">
<div className="px-3 py-3">
<div className="space-y-2"> <div className="space-y-2">
<Label>{t("creator")}</Label> <Label>{t("creator")}</Label>
<Controller <Controller
@ -663,7 +662,7 @@ export default function FormAudioDetail() {
{formatDateToIndonesian(approval?.approvalDate)} {formatDateToIndonesian(approval?.approvalDate)}
</p> </p>
<ApprovalHistoryModal id={Number(id)} /> <ApprovalHistoryModal id={Number(id)} />
</div> </div> */}
{/* {detail?.isPublish == false ? ( {/* {detail?.isPublish == false ? (
<div className="p-3"> <div className="p-3">
<Button className="bg-blue-600">Publish</Button> <Button className="bg-blue-600">Publish</Button>
@ -699,9 +698,7 @@ export default function FormAudioDetail() {
<div className="flex justify-between text-sm"> <div className="flex justify-between text-sm">
{file.fileName} {file.fileName}
<a <a
onClick={() => onClick={() => handleDeleteFileApproval(file.id)}
handleDeleteFileApproval(file.id)
}
> >
<Icon icon="humbleicons:times" color="red" /> <Icon icon="humbleicons:times" color="red" />
</a> </a>
@ -818,9 +815,7 @@ export default function FormAudioDetail() {
: "default" : "default"
} }
className="cursor-pointer" className="cursor-pointer"
onClick={() => onClick={() => setDescription("Deskripsi kurang lengkap")}
setDescription("Deskripsi kurang lengkap")
}
> >
Deskripsi kurang lengkap Deskripsi kurang lengkap
</Badge> </Badge>
@ -851,9 +846,7 @@ export default function FormAudioDetail() {
</Badge> </Badge>
<Badge <Badge
color={ color={
description === "Konten menarik" description === "Konten menarik" ? "primary" : "default"
? "primary"
: "default"
} }
className="cursor-pointer" className="cursor-pointer"
onClick={() => setDescription("Konten menarik")} onClick={() => setDescription("Konten menarik")}
@ -882,8 +875,8 @@ export default function FormAudioDetail() {
</DialogFooter> </DialogFooter>
</DialogContent> </DialogContent>
</Dialog> </Dialog>
</Card>
{Number(detail?.needApprovalFromLevel) == Number(userLevelId) ? ( {/* {Number(detail?.needApprovalFromLevel) == Number(userLevelId) ? (
Number(detail?.uploadedById) == Number(userId) ? ( Number(detail?.uploadedById) == Number(userId) ? (
"" ""
) : ( ) : (
@ -915,7 +908,7 @@ export default function FormAudioDetail() {
) )
) : ( ) : (
"" ""
)} )} */}
</div> </div>
</div> </div>
) : ( ) : (

View File

@ -116,7 +116,7 @@ const ViewEditor = dynamic(
{ ssr: false } { ssr: false }
); );
export default function FormImageDetail() { export default function FormImageTaDetail() {
const MySwal = withReactContent(Swal); const MySwal = withReactContent(Swal);
const router = useRouter(); const router = useRouter();
const userId = getCookiesDecrypt("uie"); const userId = getCookiesDecrypt("uie");

View File

@ -111,7 +111,7 @@ const ViewEditor = dynamic(
{ ssr: false } { ssr: false }
); );
export default function FormTeksDetail() { export default function FormTeksTaDetail() {
const MySwal = withReactContent(Swal); const MySwal = withReactContent(Swal);
const router = useRouter(); const router = useRouter();
const userId = getCookiesDecrypt("uie"); const userId = getCookiesDecrypt("uie");
@ -459,7 +459,7 @@ export default function FormTeksDetail() {
</p> </p>
)} )}
</div> </div>
<div className="flex items-center"> {/* <div className="flex items-center">
<div className="py-3 w-full space-y-2"> <div className="py-3 w-full space-y-2">
<Label>{t("category")}</Label> <Label>{t("category")}</Label>
<Select <Select
@ -481,7 +481,7 @@ export default function FormTeksDetail() {
</SelectContent> </SelectContent>
</Select> </Select>
</div> </div>
</div> </div> */}
<div className="py-3 space-y-2"> <div className="py-3 space-y-2">
<Label>{t("description")}</Label> <Label>{t("description")}</Label>
@ -584,7 +584,7 @@ export default function FormTeksDetail() {
</Card> </Card>
<div className="w-full lg:w-4/12"> <div className="w-full lg:w-4/12">
<Card className="pb-3"> <Card className="pb-3">
<div className="px-3 py-3"> {/* <div className="px-3 py-3">
<div className="space-y-2"> <div className="space-y-2">
<Label>{t("creator")}</Label> <Label>{t("creator")}</Label>
<Controller <Controller
@ -606,7 +606,7 @@ export default function FormTeksDetail() {
</p> </p>
)} )}
</div> </div>
</div> </div> */}
{/* <div className="mt-3 px-3"> {/* <div className="mt-3 px-3">
<Label>Pratinjau Gambar Utama</Label> <Label>Pratinjau Gambar Utama</Label>
<Card className="mt-2"> <Card className="mt-2">
@ -617,7 +617,7 @@ export default function FormTeksDetail() {
/> />
</Card> </Card>
</div> */} </div> */}
<div className="px-3 py-3"> {/* <div className="px-3 py-3">
<div className="space-y-2"> <div className="space-y-2">
<Label>{t("tags")}</Label> <Label>{t("tags")}</Label>
<div className="flex flex-wrap gap-2"> <div className="flex flex-wrap gap-2">
@ -633,8 +633,8 @@ export default function FormTeksDetail() {
))} ))}
</div> </div>
</div> </div>
</div> </div> */}
<div className="px-3 py-3"> {/* <div className="px-3 py-3">
<div className="flex flex-col gap-6 space-y-2"> <div className="flex flex-col gap-6 space-y-2">
<Label>{t("publish-target")}</Label> <Label>{t("publish-target")}</Label>
<div className="flex gap-2 items-center"> <div className="flex gap-2 items-center">
@ -674,8 +674,8 @@ export default function FormTeksDetail() {
<SuggestionModal <SuggestionModal
id={Number(id)} id={Number(id)}
numberOfSuggestion={detail?.numberOfSuggestion} 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>
<p>Komentar</p> <p>Komentar</p>
@ -686,7 +686,7 @@ export default function FormTeksDetail() {
{formatDateToIndonesian(approval?.approvalDate)} {formatDateToIndonesian(approval?.approvalDate)}
</p> </p>
<ApprovalHistoryModal id={Number(id)} /> <ApprovalHistoryModal id={Number(id)} />
</div> </div> */}
{/* {detail?.isPublish == false ? ( {/* {detail?.isPublish == false ? (
<div className="p-3"> <div className="p-3">
<Button className="bg-blue-600">Publish</Button> <Button className="bg-blue-600">Publish</Button>

View File

@ -113,7 +113,7 @@ const ViewEditor = dynamic(
{ ssr: false } { ssr: false }
); );
export default function FormVideoDetail() { export default function FormVideoTaDetail() {
const MySwal = withReactContent(Swal); const MySwal = withReactContent(Swal);
const router = useRouter(); const router = useRouter();
const userId = getCookiesDecrypt("uie"); const userId = getCookiesDecrypt("uie");
@ -449,7 +449,7 @@ export default function FormVideoDetail() {
</p> </p>
)} )}
</div> </div>
<div className="flex items-center"> {/* <div className="flex items-center">
<div className="py-3 w-full space-y-2"> <div className="py-3 w-full space-y-2">
<Label>{t("category")}</Label> <Label>{t("category")}</Label>
<Select <Select
@ -471,7 +471,7 @@ export default function FormVideoDetail() {
</SelectContent> </SelectContent>
</Select> </Select>
</div> </div>
</div> </div> */}
<div className="py-3 space-y-2"> <div className="py-3 space-y-2">
<Label>{t("description")}</Label> <Label>{t("description")}</Label>
@ -538,7 +538,7 @@ export default function FormVideoDetail() {
</Card> </Card>
<div className="w-full lg:w-4/12"> <div className="w-full lg:w-4/12">
<Card className="pb-3"> <Card className="pb-3">
<div className="px-3 py-3"> {/* <div className="px-3 py-3">
<div className="space-y-2"> <div className="space-y-2">
<Label>{t("creator")}</Label> <Label>{t("creator")}</Label>
<Controller <Controller
@ -640,7 +640,7 @@ export default function FormVideoDetail() {
{formatDateToIndonesian(approval?.approvalDate)} {formatDateToIndonesian(approval?.approvalDate)}
</p> </p>
<ApprovalHistoryModal id={Number(id)} /> <ApprovalHistoryModal id={Number(id)} />
</div> </div> */}
{/* {detail?.isPublish == false ? ( {/* {detail?.isPublish == false ? (
<div className="p-3"> <div className="p-3">
<Button className="bg-blue-600">Publish</Button> <Button className="bg-blue-600">Publish</Button>

View File

@ -481,7 +481,7 @@ export default function FormVideo() {
let id = Cookies.get("idCreate"); let id = Cookies.get("idCreate");
if (scheduleId !== undefined) { if (scheduleId !== undefined) {
requestData.attachFromScheduleId = Number(scheduleId); // ✅ Tambahkan nilai ini requestData.attachFromScheduleId = Number(scheduleId);
} }
if (id == undefined) { if (id == undefined) {
@ -495,16 +495,16 @@ export default function FormVideo() {
Cookies.set("idCreate", response?.data?.data, { expires: 1 }); Cookies.set("idCreate", response?.data?.data, { expires: 1 });
id = response?.data?.data; id = response?.data?.data;
// Upload Thumbnail if (thumbnail) {
const formMedia = new FormData(); const formMedia = new FormData();
const thumbnail = files[0];
formMedia.append("file", thumbnail); formMedia.append("file", thumbnail);
const responseThumbnail = await uploadThumbnail(id, formMedia); const responseThumbnail = await uploadThumbnail(formMedia, id);
if (responseThumbnail?.error == true) { if (responseThumbnail?.error) {
error(responseThumbnail?.message); error(responseThumbnail.message);
return false; return false;
} }
} }
}
// Upload File // Upload File
const progressInfoArr = []; const progressInfoArr = [];
@ -526,6 +526,14 @@ export default function FormVideo() {
// MySwal.fire("Sukses", "Data berhasil disimpan.", "success"); // MySwal.fire("Sukses", "Data berhasil disimpan.", "success");
}; };
useEffect(() => {
return () => {
if (preview) {
URL.revokeObjectURL(preview);
}
};
}, [preview]);
const onSubmit = (data: VideoSchema) => { const onSubmit = (data: VideoSchema) => {
MySwal.fire({ MySwal.fire({
title: "Simpan Data", title: "Simpan Data",
@ -633,12 +641,10 @@ export default function FormVideo() {
const handleImageChange = (e: React.ChangeEvent<HTMLInputElement>) => { const handleImageChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0]; const file = e.target.files?.[0];
if (file) { if (file) {
setThumbnail(file); setThumbnail(file); // Simpan file asli tanpa dimodifikasi
setPreview(URL.createObjectURL(file)); // Simpan preview string terpisah
console.log("Selected Thumbnail:", file); console.log("Selected Thumbnail:", file);
} }
if (file) {
setPreview(URL.createObjectURL(file));
}
}; };
const renderFilePreview = (file: FileWithPreview) => { const renderFilePreview = (file: FileWithPreview) => {
@ -1075,10 +1081,10 @@ export default function FormVideo() {
)} )}
</div> </div>
</div> </div>
{/* <div className="px-3 py-3"> <div className="px-3 py-3">
<Label htmlFor="fileInput">Gambar Utama</Label> <Label htmlFor="fileInput">Gambar Utama</Label>
<Input id="fileInput" type="file" onChange={handleImageChange} /> <Input id="fileInput" type="file" onChange={handleImageChange} />
</div> */} </div>
{preview && ( {preview && (
<div className="mt-3 px-3"> <div className="mt-3 px-3">
<img <img

View File

@ -535,10 +535,10 @@ const LoginForm = () => {
</div> </div>
<Button <Button
type="button" type="submit"
fullWidth fullWidth
onClick={handleEmailValidation} // onClick={handleEmailValidation}
disabled={isPending} // disabled={isPending}
> >
Selanjutnya Selanjutnya
</Button> </Button>

View File

@ -38,7 +38,10 @@ export function getMenuList(pathname: string, t: any): Group[] {
let menusSelected = <any>[]; let menusSelected = <any>[];
if ((Number(roleId) == 3 || Number(roleId) == 14) && Number(levelNumber) == 1) { if (
(Number(roleId) == 3 || Number(roleId) == 14) &&
Number(levelNumber) == 1
) {
menusSelected = [ menusSelected = [
{ {
groupLabel: t("apps"), groupLabel: t("apps"),
@ -1531,13 +1534,236 @@ export function getMenuList(pathname: string, t: any): Group[] {
icon: "heroicons:share", icon: "heroicons:share",
children: [], children: [],
}, },
// {
// href: "/contributor/content/spit",
// label: "spit",
// active: pathname.includes("/content/spit"),
// icon: "heroicons:credit-card",
// children: [],
// },
// {
// href: "/contributor/content/nulis-ai",
// label: "nulis ai",
// active: pathname.includes("/content/nulisai"),
// icon: "heroicons:credit-card",
// children: [],
// },
],
},
],
},
{ {
href: "/contributor/content/spit", groupLabel: "",
label: "spit", id: "agenda-setting",
active: pathname.includes("/content/spit"), menus: [
icon: "heroicons:credit-card", {
id: "agenda-setting",
href: "/contributor/agenda-setting",
label: t("agenda-setting"),
active: pathname.includes("/agenda-setting"),
icon: "iconoir:journal-page",
submenus: [],
},
],
},
{
groupLabel: "",
id: "planning",
menus: [
{
id: "planning",
href: "/contributor/planning",
label: t("planning"),
active: pathname.includes("/planning"),
icon: "pajamas:planning",
submenus: [
{
href: "/contributor/planning/mediahub",
label: "mediaHub",
active: pathname.includes("/planning/mediahub"),
icon: "heroicons:arrow-trending-up",
children: [], children: [],
}, },
{
href: "/contributor/planning/medsos-mediahub",
label: "medsos mediahub",
active: pathname.includes("/planning/medsos-mediahub"),
icon: "heroicons:shopping-cart",
children: [],
},
],
},
],
},
{
groupLabel: "",
id: "task",
menus: [
{
id: "task",
href: "/contributor/task",
label: t("task"),
active: pathname.includes("/task"),
icon: "fluent:clipboard-task-add-24-regular",
submenus: [],
},
],
},
{
groupLabel: "",
id: "schedule",
menus: [
{
id: "schedule",
href: "/contributor/schedule",
label: t("schedule"),
active: pathname.includes("/schedule"),
icon: "uil:schedule",
submenus: [
{
href: "/contributor/schedule/press-conference",
label: t("press-conference"),
active: pathname.includes("/schedule/press-conference"),
icon: "heroicons:arrow-trending-up",
children: [],
},
{
href: "/contributor/schedule/event",
label: t("event"),
active: pathname.includes("/schedule/event"),
icon: "heroicons:shopping-cart",
children: [],
},
{
href: "/contributor/schedule/press-release",
label: t("press-release"),
active: pathname.includes("/schedule/press-release"),
icon: "heroicons:shopping-cart",
children: [],
},
],
},
],
},
{
groupLabel: "",
id: "blog",
menus: [
{
id: "blog",
href: "/contributor/blog",
label: t("blog"),
active: pathname.includes("/blog"),
icon: "fluent:clipboard-text-32-regular",
submenus: [],
},
],
},
{
groupLabel: "",
id: "curatedcontent",
menus: [
{
id: "curatedcontent",
href: "/shared/curated-content",
label: t("curated-content"),
active: pathname.includes("/curated-content"),
icon: "pixelarticons:calendar-text",
submenus: [],
},
],
},
{
groupLabel: "",
id: "communication",
menus: [
{
id: "communication",
href: "/shared/communication",
label: t("communication"),
active: pathname.includes("/communication"),
icon: "token:chat",
submenus: [],
},
],
},
{
groupLabel: "",
id: "contest",
menus: [
{
id: "contest",
href: "/shared/contest",
label: t("contest"),
active: pathname.includes("/contest"),
icon: "ic:outline-emoji-events",
submenus: [],
},
],
},
];
} else if (Number(roleId) == 4 && Number(levelNumber) == 2) {
menusSelected = [
{
groupLabel: t("apps"),
id: "dashboard",
menus: [
{
id: "dashboard",
href: "/dashboard",
label: t("dashboard"),
active: pathname.includes("/dashboard"),
icon: "material-symbols:dashboard",
submenus: [],
},
],
},
{
groupLabel: "",
id: "content",
menus: [
{
id: "content",
href: "/contributor/content/image",
label: t("content"),
active: pathname.includes("/content"),
icon: "line-md:youtube",
submenus: [
{
href: "/contributor/content/image",
label: t("image"),
active: pathname.includes("/content/image"),
icon: "ic:outline-image",
children: [],
},
{
href: "/contributor/content/video",
label: t("video"),
active: pathname.includes("/content/video"),
icon: "line-md:youtube",
children: [],
},
{
href: "/contributor/content/teks",
label: t("text"),
active: pathname.includes("/content/teks"),
icon: "heroicons:document",
children: [],
},
{
href: "/contributor/content/audio",
label: t("audio"),
active: pathname.includes("/content/audio"),
icon: "heroicons:share",
children: [],
},
// {
// href: "/contributor/content/spit",
// label: "spit",
// active: pathname.includes("/content/spit"),
// icon: "heroicons:credit-card",
// children: [],
// },
// { // {
// href: "/contributor/content/nulis-ai", // href: "/contributor/content/nulis-ai",
// label: "nulis ai", // label: "nulis ai",
@ -1700,7 +1926,7 @@ export function getMenuList(pathname: string, t: any): Group[] {
}, },
]; ];
} else if ( } else if (
(Number(roleId) == 3 || Number(roleId) == 4 || Number(roleId) == 14 || Number(roleId) == 15) && (Number(roleId) == 3 || Number(roleId) == 14 || Number(roleId) == 15) &&
Number(levelNumber) == 2 Number(levelNumber) == 2
) { ) {
if (Number(userLevelId) != 761) { if (Number(userLevelId) != 761) {
@ -2158,7 +2384,10 @@ export function getMenuList(pathname: string, t: any): Group[] {
]; ];
} }
} else if ( } else if (
(Number(roleId) == 3 || Number(roleId) == 4 || Number(roleId) == 14 || Number(roleId) == 15) && (Number(roleId) == 3 ||
Number(roleId) == 4 ||
Number(roleId) == 14 ||
Number(roleId) == 15) &&
Number(levelNumber) == 3 Number(levelNumber) == 3
) { ) {
if (Number(userParentLevelId) != 761) { if (Number(userParentLevelId) != 761) {

View File

@ -156,3 +156,8 @@ export async function saveTicketsQuestion(data: any) {
const url = "ticketing/convert-question"; const url = "ticketing/convert-question";
return httpPostInterceptor(url, data); return httpPostInterceptor(url, data);
} }
export async function deleteEscalationDiscussion(id: any) {
const url = `ticketing/escalation/discussion?id=${id}`;
return httpDeleteInterceptor(url);
}

View File

@ -173,10 +173,10 @@ export async function createMedia(data: any) {
export async function uploadThumbnail(id: any, data: any) { export async function uploadThumbnail(id: any, data: any) {
const url = `media/upload?id=${id}&operation=thumbnail`; const url = `media/upload?id=${id}&operation=thumbnail`;
const headers = { // const headers = {
"Content-Type": "multipart/form-data", // "Content-Type": "multipart/form-data",
}; // };
return httpPostInterceptor(url, data, headers); return httpPostInterceptor(url, data);
} }
export async function detailSPIT(id: any) { export async function detailSPIT(id: any) {