feat:escalation,video
This commit is contained in:
parent
cfbc6349cc
commit
45a7ec116a
|
|
@ -103,20 +103,6 @@ export default function FormQuestionsDetail() {
|
|||
const [selectedOperatorEscalation, setSelectedOperatorEscalation] = useState<
|
||||
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 {
|
||||
control,
|
||||
|
|
@ -156,12 +142,11 @@ export default function FormQuestionsDetail() {
|
|||
setDetail(detail);
|
||||
setDetailTickets(detail);
|
||||
|
||||
// Ambil escalationTeams seperti ":891:"
|
||||
if (detail?.escalationTeams) {
|
||||
const teamIds = detail.escalationTeams
|
||||
.split(":")
|
||||
.filter((id: string) => id); // hapus string kosong
|
||||
setSelectedOperatorEscalation(teamIds); // set ke state
|
||||
.filter((id: string) => id);
|
||||
setSelectedOperatorEscalation(teamIds);
|
||||
}
|
||||
|
||||
getTicketReply();
|
||||
|
|
@ -409,7 +394,7 @@ export default function FormQuestionsDetail() {
|
|||
|
||||
{/* Tag yang ditampilkan secara kolom */}
|
||||
{selectedOperator.length > 0 && (
|
||||
<div className="flex flex-col gap-2 mb-2">
|
||||
<div className="flex flex-row gap-2 mb-2">
|
||||
{selectedOperator.map((id) => {
|
||||
const label = operatorOpt.find(
|
||||
(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"
|
||||
>
|
||||
<input
|
||||
disabled
|
||||
type="checkbox"
|
||||
checked={selectedOperator.includes(op.value)}
|
||||
onChange={(e) => {
|
||||
|
|
@ -495,7 +481,7 @@ export default function FormQuestionsDetail() {
|
|||
<Label>Eskalasi Untuk</Label>
|
||||
|
||||
{selectedOperatorEscalation.length > 0 && (
|
||||
<div className="flex flex-col gap-2 mb-2">
|
||||
<div className="flex flex-row gap-2 mb-2">
|
||||
{selectedOperatorEscalation.map((id) => {
|
||||
const operator = curatorOpt.find(
|
||||
(op: any) => op.value === id
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ import {
|
|||
import { ChevronDownIcon } from "lucide-react";
|
||||
import { getOperatorUser } from "@/service/management-user/management-user";
|
||||
import makeAnimated from "react-select/animated";
|
||||
import Select from "react-select";
|
||||
import Select, { ActionMeta, MultiValue } from "react-select";
|
||||
|
||||
interface Option {
|
||||
id: string;
|
||||
|
|
@ -109,9 +109,7 @@ export default function FormQuestionsForward() {
|
|||
const [selectedOperator, setSelectedOperator] = useState<string[]>([]);
|
||||
const [options, setOptions] = useState<Option[]>([]);
|
||||
const animatedComponent = makeAnimated();
|
||||
const [selectedOption, setSelectedOption] = useState<Option | undefined>(
|
||||
undefined
|
||||
);
|
||||
const [selectedOption, setSelectedOption] = useState<Option[]>([]);
|
||||
const [replies, setReplies] = useState([
|
||||
{
|
||||
id: 1,
|
||||
|
|
@ -195,7 +193,7 @@ export default function FormQuestionsForward() {
|
|||
parentCommentId: detailTickets?.feedId,
|
||||
operatorTeam: selectedOperator.join(","),
|
||||
isEscalation: true,
|
||||
communicationTeam: selectedOption?.id,
|
||||
communicationTeam: selectedOption.map((item) => item.id).join(","),
|
||||
};
|
||||
|
||||
const response = await saveTicketsQuestion(payload);
|
||||
|
|
@ -206,7 +204,6 @@ export default function FormQuestionsForward() {
|
|||
icon: "success",
|
||||
});
|
||||
|
||||
// Refresh data jika perlu
|
||||
getTicketReply();
|
||||
} catch (error) {
|
||||
console.error("Gagal update:", error);
|
||||
|
|
@ -218,9 +215,11 @@ export default function FormQuestionsForward() {
|
|||
}
|
||||
};
|
||||
|
||||
const handleChange = (e: any) => {
|
||||
const selected = e;
|
||||
setSelectedOption(selected);
|
||||
const handleChange = (
|
||||
selected: MultiValue<Option>,
|
||||
_actionMeta: ActionMeta<Option>
|
||||
) => {
|
||||
setSelectedOption([...selected]);
|
||||
};
|
||||
|
||||
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">
|
||||
<Label>Operator</Label>
|
||||
|
||||
{/* Tag yang ditampilkan secara kolom */}
|
||||
{selectedOperator.length > 0 && (
|
||||
<div className="flex flex-col gap-2 mb-2">
|
||||
<div className="flex flex-row gap-2 mb-2">
|
||||
{selectedOperator.map((id) => {
|
||||
const label = operatorOpt.find(
|
||||
(op: any) => op.value === id
|
||||
|
|
@ -433,7 +431,7 @@ export default function FormQuestionsForward() {
|
|||
components={animatedComponent}
|
||||
onChange={handleChange}
|
||||
formatOptionLabel={formatOptionLabel}
|
||||
isMulti={false}
|
||||
isMulti={true}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -125,7 +125,6 @@ export default function FormConvertSPIT() {
|
|||
const [selectedCategoryId, setSelectedCategoryId] = useState<number | null>(
|
||||
null
|
||||
);
|
||||
const [tags, setTags] = useState<any[]>([]);
|
||||
const [detail, setDetail] = useState<any>();
|
||||
const [refresh, setRefresh] = useState(false);
|
||||
const [selectedPublishers, setSelectedPublishers] = useState<number[]>([]);
|
||||
|
|
@ -159,6 +158,8 @@ export default function FormConvertSPIT() {
|
|||
const [filePlacements, setFilePlacements] = useState<string[][]>([]);
|
||||
const [isUserMabesApprover, setIsUserMabesApprover] = useState(false);
|
||||
const [files, setFiles] = useState<FileType[]>([]);
|
||||
const [tags, setTags] = useState<any[]>([]);
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const [selectedWritingStyle, setSelectedWritingStyle] =
|
||||
useState("Professional");
|
||||
|
||||
|
|
@ -367,6 +368,13 @@ export default function FormConvertSPIT() {
|
|||
setSelectedTarget(matchingCategory.name);
|
||||
}
|
||||
|
||||
if (details?.contentTag) {
|
||||
const initialTags = details.contentTag
|
||||
.split(",")
|
||||
.map((tag: string) => tag.trim());
|
||||
setTags(initialTags);
|
||||
}
|
||||
|
||||
// setSelectedTarget(details.categoryId); // Untuk dropdown
|
||||
}
|
||||
}
|
||||
|
|
@ -477,13 +485,14 @@ export default function FormConvertSPIT() {
|
|||
selectedFileType === "original"
|
||||
? data.contentDescription
|
||||
: data.contentRewriteDescription;
|
||||
const finalTags = tags.join(", ");
|
||||
|
||||
const requestData = {
|
||||
spitId: id,
|
||||
title: data.contentTitle,
|
||||
description,
|
||||
htmlDescription: description,
|
||||
tags: "siap",
|
||||
tags: finalTags,
|
||||
categoryId: selectedCategoryId,
|
||||
publishedFor: publishedFor.join(","),
|
||||
creator: data.contentCreator,
|
||||
|
|
@ -647,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 (
|
||||
<>
|
||||
<Form {...form}>
|
||||
|
|
@ -1054,17 +1076,22 @@ export default function FormConvertSPIT() {
|
|||
<div className="px-3 py-3">
|
||||
<div className="space-y-2">
|
||||
<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">
|
||||
{detail?.contentTag
|
||||
?.split(",")
|
||||
.map((tag: any, index: any) => (
|
||||
<Badge
|
||||
key={index}
|
||||
className="border rounded-md px-2 py-2"
|
||||
>
|
||||
{tag.trim()}
|
||||
</Badge>
|
||||
))}
|
||||
{tags.map((tag, index) => (
|
||||
<Badge
|
||||
key={index}
|
||||
className="border rounded-md px-2 py-2"
|
||||
>
|
||||
{tag}
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -481,7 +481,7 @@ export default function FormVideo() {
|
|||
let id = Cookies.get("idCreate");
|
||||
|
||||
if (scheduleId !== undefined) {
|
||||
requestData.attachFromScheduleId = Number(scheduleId); // ✅ Tambahkan nilai ini
|
||||
requestData.attachFromScheduleId = Number(scheduleId);
|
||||
}
|
||||
|
||||
if (id == undefined) {
|
||||
|
|
@ -495,14 +495,14 @@ export default function FormVideo() {
|
|||
Cookies.set("idCreate", response?.data?.data, { expires: 1 });
|
||||
id = response?.data?.data;
|
||||
|
||||
// Upload Thumbnail
|
||||
const formMedia = new FormData();
|
||||
const thumbnail = files[0];
|
||||
formMedia.append("file", thumbnail);
|
||||
const responseThumbnail = await uploadThumbnail(id, formMedia);
|
||||
if (responseThumbnail?.error == true) {
|
||||
error(responseThumbnail?.message);
|
||||
return false;
|
||||
if (thumbnail) {
|
||||
const formMedia = new FormData();
|
||||
formMedia.append("file", thumbnail);
|
||||
const responseThumbnail = await uploadThumbnail(formMedia, id);
|
||||
if (responseThumbnail?.error) {
|
||||
error(responseThumbnail.message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -526,6 +526,14 @@ export default function FormVideo() {
|
|||
// MySwal.fire("Sukses", "Data berhasil disimpan.", "success");
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (preview) {
|
||||
URL.revokeObjectURL(preview);
|
||||
}
|
||||
};
|
||||
}, [preview]);
|
||||
|
||||
const onSubmit = (data: VideoSchema) => {
|
||||
MySwal.fire({
|
||||
title: "Simpan Data",
|
||||
|
|
@ -633,12 +641,10 @@ export default function FormVideo() {
|
|||
const handleImageChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const file = e.target.files?.[0];
|
||||
if (file) {
|
||||
setThumbnail(file);
|
||||
setThumbnail(file); // Simpan file asli tanpa dimodifikasi
|
||||
setPreview(URL.createObjectURL(file)); // Simpan preview string terpisah
|
||||
console.log("Selected Thumbnail:", file);
|
||||
}
|
||||
if (file) {
|
||||
setPreview(URL.createObjectURL(file));
|
||||
}
|
||||
};
|
||||
|
||||
const renderFilePreview = (file: FileWithPreview) => {
|
||||
|
|
@ -1075,10 +1081,10 @@ export default function FormVideo() {
|
|||
)}
|
||||
</div>
|
||||
</div>
|
||||
{/* <div className="px-3 py-3">
|
||||
<div className="px-3 py-3">
|
||||
<Label htmlFor="fileInput">Gambar Utama</Label>
|
||||
<Input id="fileInput" type="file" onChange={handleImageChange} />
|
||||
</div> */}
|
||||
</div>
|
||||
{preview && (
|
||||
<div className="mt-3 px-3">
|
||||
<img
|
||||
|
|
|
|||
243
lib/menus.ts
243
lib/menus.ts
|
|
@ -38,7 +38,10 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
|||
|
||||
let menusSelected = <any>[];
|
||||
|
||||
if ((Number(roleId) == 3 || Number(roleId) == 14) && Number(levelNumber) == 1) {
|
||||
if (
|
||||
(Number(roleId) == 3 || Number(roleId) == 14) &&
|
||||
Number(levelNumber) == 1
|
||||
) {
|
||||
menusSelected = [
|
||||
{
|
||||
groupLabel: t("apps"),
|
||||
|
|
@ -1531,13 +1534,236 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
|||
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",
|
||||
// label: "nulis ai",
|
||||
// active: pathname.includes("/content/nulisai"),
|
||||
// icon: "heroicons:credit-card",
|
||||
// children: [],
|
||||
// },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
groupLabel: "",
|
||||
id: "agenda-setting",
|
||||
menus: [
|
||||
{
|
||||
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/content/spit",
|
||||
label: "spit",
|
||||
active: pathname.includes("/content/spit"),
|
||||
icon: "heroicons:credit-card",
|
||||
href: "/contributor/planning/mediahub",
|
||||
label: "mediaHub",
|
||||
active: pathname.includes("/planning/mediahub"),
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
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",
|
||||
// label: "nulis ai",
|
||||
|
|
@ -1700,7 +1926,7 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
|||
},
|
||||
];
|
||||
} 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
|
||||
) {
|
||||
if (Number(userLevelId) != 761) {
|
||||
|
|
@ -2158,7 +2384,10 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
|||
];
|
||||
}
|
||||
} 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
|
||||
) {
|
||||
if (Number(userParentLevelId) != 761) {
|
||||
|
|
|
|||
|
|
@ -173,10 +173,10 @@ export async function createMedia(data: any) {
|
|||
|
||||
export async function uploadThumbnail(id: any, data: any) {
|
||||
const url = `media/upload?id=${id}&operation=thumbnail`;
|
||||
const headers = {
|
||||
"Content-Type": "multipart/form-data",
|
||||
};
|
||||
return httpPostInterceptor(url, data, headers);
|
||||
// const headers = {
|
||||
// "Content-Type": "multipart/form-data",
|
||||
// };
|
||||
return httpPostInterceptor(url, data);
|
||||
}
|
||||
|
||||
export async function detailSPIT(id: any) {
|
||||
|
|
@ -234,4 +234,4 @@ export async function postActivityLog(data: any) {
|
|||
"content-type": "application/json",
|
||||
};
|
||||
return httpPost(url, headers, data);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue