feat:escalation,video

This commit is contained in:
Anang Yusman 2025-06-13 16:21:08 +08:00
parent cfbc6349cc
commit 45a7ec116a
6 changed files with 316 additions and 70 deletions

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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) {

View File

@ -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);
}
}