diff --git a/app/[locale]/(protected)/supervisor/communications/escalation/detail/[id]/page.tsx b/app/[locale]/(protected)/supervisor/communications/escalation/detail/[id]/page.tsx
new file mode 100644
index 00000000..c62e9bb0
--- /dev/null
+++ b/app/[locale]/(protected)/supervisor/communications/escalation/detail/[id]/page.tsx
@@ -0,0 +1,21 @@
+import { Card, CardContent } from "@/components/ui/card";
+import SiteBreadcrumb from "@/components/site-breadcrumb";
+import FormTask from "@/components/form/task/task-form";
+import FormTaskDetail from "@/components/form/task/task-detail-form";
+import FormDetailInternal from "@/components/form/communication/internal-detail-form";
+import FormDetailEscalation from "@/components/form/communication/escalation-detail-form";
+import FormQuestionsForward from "@/components/form/communication/escalation-forward-form";
+import FormQuestionsDetail from "@/components/form/communication/escalation-detail-new-form";
+
+const EscalationDetailPage = async () => {
+ return (
+
-
-
-
(
-
- )}
- />
- {/* {errors.title?.message && (
-
- {errors.title.message}
-
- )} */}
-
-
-
-
-
-
-
-
(
-
- )}
- />
- {/* {errors.title?.message && (
-
- {errors.title.message}
-
- )} */}
-
-
-
Tanggapan
-
- {replies.map((reply) => (
-
-
{reply.name}
-
{reply.message}
-
{reply.timestamp}
-
- ))}
+ {detailTickets && (
+
)}
);
diff --git a/components/form/communication/questions-reply-form.tsx b/components/form/communication/questions-reply-form.tsx
index 9e31dbb7..cb02c6cb 100644
--- a/components/form/communication/questions-reply-form.tsx
+++ b/components/form/communication/questions-reply-form.tsx
@@ -42,6 +42,13 @@ import { DetailTicket } from "../ticketing/info-lainnya-types";
import InfoLainnyaModal from "../ticketing/info-lainnya";
import { Description } from "@radix-ui/react-toast";
import { Link } from "@/i18n/routing";
+import {
+ Popover,
+ PopoverContent,
+ PopoverTrigger,
+} from "@/components/ui/popover";
+import { ChevronDownIcon } from "lucide-react";
+import { getOperatorUser } from "@/service/management-user/management-user";
const taskSchema = z.object({
title: z.string().min(1, { message: "Judul diperlukan" }),
@@ -125,8 +132,12 @@ export default function FormQuestionsReply() {
const [selectedPriority, setSelectedPriority] = useState("");
const [selectedStatus, setSelectedStatus] = useState("");
const [openEmergencyModal, setOpenEmergencyModal] = useState(false);
- const [replyValue, setReplyValue] = useState
(0); // beri tipe number
- const [replyText, setReplyText] = useState(""); // untuk isi balasan
+ const [replyValue, setReplyValue] = useState(0);
+ const [replyText, setReplyText] = useState("");
+ const [operatorOpt, setOperatorOpt] = useState<
+ { id: string; label: string; value: string }[]
+ >([]);
+ const [selectedOperator, setSelectedOperator] = useState([]);
const {
control,
handleSubmit,
@@ -196,6 +207,23 @@ export default function FormQuestionsReply() {
}
}
+ useEffect(() => {
+ async function getOperator() {
+ const res = await getOperatorUser(detailTickets?.typeId);
+ if (res?.data !== null) {
+ const rawUser = res?.data?.data;
+ const optionArr = rawUser?.map((option: any) => ({
+ id: option.id,
+ label: option.fullName,
+ value: option.id,
+ }));
+ setOperatorOpt(optionArr);
+ }
+ }
+
+ getOperator();
+ }, [detailTickets]);
+
const handleSendReply = async () => {
if (replyMessage.trim() === "") {
MySwal.fire({
@@ -254,6 +282,7 @@ export default function FormQuestionsReply() {
statusId: selectedStatus,
typeId: detailTickets?.typeId,
parentCommentId: detailTickets?.feedId,
+ operatorTeam: selectedOperator.join(","),
};
const response = await saveTicketsQuestion(payload);
@@ -488,6 +517,7 @@ export default function FormQuestionsReply() {
@@ -513,19 +543,78 @@ export default function FormQuestionsReply() {
-
-
+
+
+ {/* Tag yang ditampilkan secara kolom */}
+ {selectedOperator.length > 0 && (
+
+ {selectedOperator.map((id) => {
+ const label = operatorOpt.find(
+ (op: any) => op.value === id
+ )?.label;
+ return (
+
+ {label}
+
+
+ );
+ })}
+
+ )}
+
+ {/* Popover Checkbox Dropdown */}
+
+
+
+
+
+
+ {operatorOpt.map((op: any) => (
+
+ ))}
+
+
+
diff --git a/components/form/ticketing/info-lainnya-types.ts b/components/form/ticketing/info-lainnya-types.ts
index 4c91411c..51ff1472 100644
--- a/components/form/ticketing/info-lainnya-types.ts
+++ b/components/form/ticketing/info-lainnya-types.ts
@@ -1,4 +1,7 @@
export type DetailTicket = {
+ commentFromUserId: string;
+ assignedTeams: string;
+ message: string;
typeId: number;
feedId: any;
commentId: string;
diff --git a/components/form/ticketing/ticketing-detail-form.tsx b/components/form/ticketing/ticketing-detail-form.tsx
index eb5a9dd6..d72a8b02 100644
--- a/components/form/ticketing/ticketing-detail-form.tsx
+++ b/components/form/ticketing/ticketing-detail-form.tsx
@@ -38,7 +38,13 @@ import { useRouter } from "next/navigation";
import InfoLainnyaModal from "./info-lainnya";
import { DetailTicket } from "./info-lainnya-types";
import { useMediaQuery } from "react-responsive";
-import { ArrowLeft } from "lucide-react";
+import { ArrowLeft, ChevronDownIcon } from "lucide-react";
+import {
+ Popover,
+ PopoverContent,
+ PopoverTrigger,
+} from "@/components/ui/popover";
+import { getOperatorUser } from "@/service/management-user/management-user";
const taskSchema = z.object({
title: z.string().min(1, { message: "Judul diperlukan" }),
@@ -120,8 +126,12 @@ export default function FormDetailTicketing() {
const [selectedPriority, setSelectedPriority] = useState("");
const [selectedStatus, setSelectedStatus] = useState("");
const [openEmergencyModal, setOpenEmergencyModal] = useState(false);
- const [replyValue, setReplyValue] = useState(0); // beri tipe number
- const [replyText, setReplyText] = useState(""); // untuk isi balasan
+ const [replyValue, setReplyValue] = useState(0);
+ const [replyText, setReplyText] = useState("");
+ const [operatorOpt, setOperatorOpt] = useState<
+ { id: string; label: string; value: string }[]
+ >([]);
+ const [selectedOperator, setSelectedOperator] = useState([]);
const {
control,
handleSubmit,
@@ -146,6 +156,31 @@ export default function FormDetailTicketing() {
getTicketReply();
}, [id]);
+ useEffect(() => {
+ async function getOperator() {
+ const res = await getOperatorUser(detailTickets?.typeId);
+ if (res?.data !== null) {
+ const rawUser = res?.data?.data;
+ const optionArr = rawUser?.map((option: any) => ({
+ id: option.id,
+ label: option.fullName,
+ value: option.id.toString(), // pastikan string
+ }));
+ setOperatorOpt(optionArr);
+
+ // 👇 Parse `assignedTeams` ke dalam array string
+ if (detailTickets?.assignedTeams) {
+ const assigned = detailTickets.assignedTeams
+ .split(":")
+ .filter((id: string) => id); // hapus string kosong
+ setSelectedOperator(assigned);
+ }
+ }
+ }
+
+ getOperator();
+ }, [detailTickets]);
+
const handleReply = () => {
setReplyValue((prev) => (prev === 1 ? 0 : 1));
};
@@ -505,6 +540,77 @@ export default function FormDetailTicketing() {
+
+
+
+ {/* Tag yang ditampilkan secara kolom */}
+ {selectedOperator.length > 0 && (
+
+ {selectedOperator.map((id) => {
+ const label = operatorOpt.find(
+ (op: any) => op.value === id
+ )?.label;
+ return (
+
+ {label}
+
+
+ );
+ })}
+
+ )}
+
+ {/* Popover Checkbox Dropdown */}
+
+
+
+
+
+
+ {operatorOpt.map((op: any) => (
+
+ ))}
+
+
+
+
(
null
);
+ const [detailTickets, setDetailTickets] = useState(null);
+ const [replyValue, setReplyValue] = useState(0);
+ const [replyText, setReplyText] = useState("");
+ const [operatorOpt, setOperatorOpt] = useState<
+ { id: string; label: string; value: string }[]
+ >([]);
+ const [selectedOperator, setSelectedOperator] = useState([]);
const [replyVisible, setReplyVisible] = useState(false);
const [replyMessage, setReplyMessage] = useState("");
const [selectedPriority, setSelectedPriority] = useState("");
@@ -114,23 +130,67 @@ export default function FormUpdateTicketing() {
const {
control,
handleSubmit,
+ setValue,
formState: { errors },
} = useForm({
resolver: zodResolver(taskSchema),
+ defaultValues: {
+ title: "",
+ description: "",
+ priority: "",
+ status: "",
+ },
});
useEffect(() => {
async function initState() {
- if (id) {
- const response = await getTicketingDetail(id);
- setTicketInternal(response?.data?.data || null);
- setDetail(response?.data?.data);
+ setReplyValue(0);
+ const response = await getTicketingDetail(id);
+ setTicketInternal(response?.data?.data || null);
+ setDetail(response?.data?.data);
+
+ if (response?.data?.data) {
+ const detailData = response.data.data;
+ setValue("title", detailData.title || "");
+ setValue("description", detailData.description || "");
+ setSelectedPriority(detailData.priority?.name || "");
+ setSelectedStatus(detailData.status?.name || "");
+ }
+
+ if (response?.data !== null) {
+ setDetailTickets(response?.data?.data);
}
}
+
initState();
getTicketReply();
}, [id]);
+ useEffect(() => {
+ async function getOperator() {
+ const res = await getOperatorUser(detailTickets?.typeId);
+ if (res?.data !== null) {
+ const rawUser = res?.data?.data;
+ const optionArr = rawUser?.map((option: any) => ({
+ id: option.id,
+ label: option.fullName,
+ value: option.id.toString(), // pastikan string
+ }));
+ setOperatorOpt(optionArr);
+
+ // 👇 Parse `assignedTeams` ke dalam array string
+ if (detailTickets?.assignedTeams) {
+ const assigned = detailTickets.assignedTeams
+ .split(":")
+ .filter((id: string) => id); // hapus string kosong
+ setSelectedOperator(assigned);
+ }
+ }
+ }
+
+ getOperator();
+ }, [detailTickets]);
+
async function getTicketReply() {
const res = await getTicketingReply(id);
if (res?.data !== null) {
@@ -227,6 +287,39 @@ export default function FormUpdateTicketing() {
});
};
+ async function save(data: any) {
+ const reqData: any = {
+ title: data.title,
+ description: data.description,
+ priority: data.priority,
+ status: data.status,
+ operatorTeam: selectedOperator.join(","), // Gunakan selectedOperator yang sudah ada
+ };
+
+ if (id) {
+ reqData.id = id;
+ }
+
+ const response = await saveTicketing(reqData);
+
+ if (response?.error) {
+ MySwal.fire({
+ title: "Error",
+ text: response.message,
+ icon: "error",
+ });
+ return false;
+ }
+
+ MySwal.fire({
+ title: "Sukses",
+ icon: "success",
+ confirmButtonText: "OK",
+ }).then(() => {
+ router.push(`/in/supervisor/ticketing`);
+ });
+ }
+
return (
@@ -331,83 +424,158 @@ export default function FormUpdateTicketing() {
{detail !== undefined && (
-
Properties
-
-
-
(
-
- )}
- />
- {/* {errors.title?.message && (
+
+
+
+
+
)}
diff --git a/service/management-user/management-user.ts b/service/management-user/management-user.ts
index 33d4460c..b2098c4e 100644
--- a/service/management-user/management-user.ts
+++ b/service/management-user/management-user.ts
@@ -70,3 +70,8 @@ export async function deleteUser(userId: number | string) {
const url = `users/delete-user?userId=${userId}`;
return httpDeleteInterceptor(url);
}
+
+export async function getOperatorUser(typeId: any) {
+ const url = `users/search-operator-user?code=opt-id&typeId=${typeId}`;
+ return httpGetInterceptor(url);
+}