feat:update communication internal

This commit is contained in:
Anang Yusman 2025-01-20 14:45:54 +08:00
parent a44b275f73
commit ade8b1b296
5 changed files with 67 additions and 14 deletions

View File

@ -116,13 +116,10 @@ const columns: ColumnDef<any>[] = [
"menunggu review": "bg-orange-100 text-orange-600", "menunggu review": "bg-orange-100 text-orange-600",
}; };
// Mengambil `statusName` dari data API
const status = row.getValue("statusName") as string; const status = row.getValue("statusName") as string;
const statusName = status?.toLocaleLowerCase(); // Ubah ke huruf kecil const statusName = status?.toLocaleLowerCase();
// Gunakan `statusName` untuk pencocokan
const statusStyles = const statusStyles =
statusColors[statusName] || "bg-gray-100 text-gray-600"; statusColors[statusName] || "bg-red-200 text-red-600";
return ( return (
<Badge <Badge

View File

@ -25,6 +25,8 @@ import {
saveTicketInternalReply, saveTicketInternalReply,
} from "@/service/communication/communication"; } from "@/service/communication/communication";
import { Icon } from "@iconify/react/dist/iconify.js"; import { Icon } from "@iconify/react/dist/iconify.js";
import { list } from "postcss";
import { htmlToString } from "@/utils/globals";
const taskSchema = z.object({ const taskSchema = z.object({
title: z.string().min(1, { message: "Judul diperlukan" }), title: z.string().min(1, { message: "Judul diperlukan" }),
@ -72,6 +74,19 @@ export type replyDetail = {
fullname: string; fullname: string;
}; };
}; };
export type internalDetail = {
id: number;
message: string;
createdAt: string;
createdBy: {
id: number;
fullname: string;
};
sendTo: {
id: number;
fullname: string;
};
};
export default function FormDetailInternal() { export default function FormDetailInternal() {
const MySwal = withReactContent(Swal); const MySwal = withReactContent(Swal);
@ -79,6 +94,9 @@ export default function FormDetailInternal() {
const [detail, setDetail] = useState<taskDetail>(); const [detail, setDetail] = useState<taskDetail>();
const [ticketReply, setTicketReply] = useState<replyDetail[]>([]); const [ticketReply, setTicketReply] = useState<replyDetail[]>([]);
const [ticketInternal, setTicketInternal] = useState<internalDetail | null>(
null
);
const [replyVisible, setReplyVisible] = useState(false); const [replyVisible, setReplyVisible] = useState(false);
const [replyMessage, setReplyMessage] = useState(""); const [replyMessage, setReplyMessage] = useState("");
const [selectedPriority, setSelectedPriority] = useState(""); const [selectedPriority, setSelectedPriority] = useState("");
@ -96,6 +114,7 @@ export default function FormDetailInternal() {
async function initState() { async function initState() {
if (id) { if (id) {
const response = await getTicketingInternalDetail(id); const response = await getTicketingInternalDetail(id);
setTicketInternal(response?.data?.data || null);
setDetail(response?.data?.data); setDetail(response?.data?.data);
} }
} }
@ -203,6 +222,7 @@ export default function FormDetailInternal() {
<p className="p-4 bg-slate-300 rounded-t-xl text-lg font-semibold"> <p className="p-4 bg-slate-300 rounded-t-xl text-lg font-semibold">
Ticket #{detail?.referenceNumber} Ticket #{detail?.referenceNumber}
</p> </p>
{ticketReply?.map((list) => ( {ticketReply?.map((list) => (
<div key={list.id} className="flex flex-col"> <div key={list.id} className="flex flex-col">
<div className="flex flex-row gap-3 bg-sky-100 p-4 items-center"> <div className="flex flex-row gap-3 bg-sky-100 p-4 items-center">
@ -229,6 +249,38 @@ export default function FormDetailInternal() {
<p className="p-4 bg-white text-sm">{list.message}</p> <p className="p-4 bg-white text-sm">{list.message}</p>
</div> </div>
))} ))}
{ticketInternal && (
<div key={ticketInternal.id} className="flex flex-col">
<div className="flex flex-row gap-3 bg-sky-100 p-4 items-center">
<Icon icon="qlementine-icons:user-16" width={36} />
<div>
<p>
<span className="font-bold text-sm">
{ticketInternal?.createdBy?.fullname}
</span>{" "}
mengirimkan pesan untuk{" "}
<span className="font-bold text-sm">
{ticketInternal?.sendTo?.fullname}
</span>
</p>
<p className="text-xs">
{`${new Date(ticketInternal?.createdAt).getDate()}-${
new Date(ticketInternal?.createdAt).getMonth() + 1
}-${new Date(
ticketInternal?.createdAt
).getFullYear()} ${new Date(
ticketInternal?.createdAt
).getHours()}:${new Date(
ticketInternal?.createdAt
).getMinutes()}`}
</p>
</div>
</div>
<p className="p-4 bg-white text-sm">
{htmlToString(ticketInternal.message)}
</p>
</div>
)}
</div> </div>
</div> </div>
{detail !== undefined && ( {detail !== undefined && (

View File

@ -9,7 +9,7 @@ import { zodResolver } from "@hookform/resolvers/zod";
import * as z from "zod"; import * as z from "zod";
import Swal from "sweetalert2"; import Swal from "sweetalert2";
import withReactContent from "sweetalert2-react-content"; import withReactContent from "sweetalert2-react-content";
import { useParams, useRouter } from "next/navigation"; import { useParams } from "next/navigation";
import { import {
Select, Select,
SelectContent, SelectContent,
@ -55,6 +55,7 @@ import { getCookiesDecrypt } from "@/lib/utils";
import { Icon } from "@iconify/react/dist/iconify.js"; import { Icon } from "@iconify/react/dist/iconify.js";
import { error } from "@/lib/swal"; import { error } from "@/lib/swal";
import dynamic from "next/dynamic"; import dynamic from "next/dynamic";
import { useRouter } from "@/i18n/routing";
const imageSchema = z.object({ const imageSchema = z.object({
title: z.string().min(1, { message: "Judul diperlukan" }), title: z.string().min(1, { message: "Judul diperlukan" }),

View File

@ -167,10 +167,10 @@ export default function FormPressConference() {
)} )}
</div> </div>
<div className="flex flex-row items-center"> <div className="flex flex-row items-center">
<div className="mt-5"> <div className="mt-4 mb-3">
<Label>Live Streaming</Label> <Label>Live Streaming</Label>
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<p>Aktifkan fitur live streaming</p> <Label>Aktifkan fitur live streaming</Label>
<Switch <Switch
defaultChecked={isLiveStreamingEnabled} defaultChecked={isLiveStreamingEnabled}
color="primary" color="primary"
@ -184,7 +184,7 @@ export default function FormPressConference() {
</div> </div>
{isLiveStreamingEnabled && ( {isLiveStreamingEnabled && (
<div className="mt-1"> <div className="mb-2 mt-1">
<Controller <Controller
control={control} control={control}
name="title" name="title"
@ -206,16 +206,17 @@ export default function FormPressConference() {
</div> </div>
)} )}
<div className="flex flex-col lg:flex-row mt-3 items-start lg:items-center justify-between"> <div className="flex flex-col lg:flex-row mb-4 mt-2 items-start lg:items-center justify-between">
<div className="flex flex-col "> <div className="flex flex-col ">
<Label className="mr-3 mb-1">Tanggal</Label> <Label className="mr-3 mb-1">Tanggal</Label>
<Popover> <Popover>
<PopoverTrigger asChild> <PopoverTrigger asChild>
<Button <Button
size="md"
id="date" id="date"
variant={"outline"} variant={"outline"}
className={cn( className={cn(
"w-[280px] lg:w-[300px] justify-start text-left font-normal", "w-[280px] lg:w-[250px] justify-start text-left font-normal border border-slate-300",
!date && "text-muted-foreground" !date && "text-muted-foreground"
)} )}
> >
@ -292,7 +293,7 @@ export default function FormPressConference() {
{errors.location?.message} {errors.location?.message}
</div> </div>
</div> </div>
<p className="text-sm my-2 font-semibold">DI SAMPAIKAN OLEH</p> <p className="text-sm mt-4 font-semibold">DI SAMPAIKAN OLEH</p>
<div className="flex flex-col "> <div className="flex flex-col ">
<div className="mt-1"> <div className="mt-1">
<Label>Nama Pangkat</Label> <Label>Nama Pangkat</Label>

View File

@ -1119,6 +1119,7 @@ export default function FormTaskDetail() {
</div> </div>
<Button <Button
type="button"
size="icon" size="icon"
color="destructive" color="destructive"
variant="outline" variant="outline"
@ -1249,7 +1250,7 @@ export default function FormTaskDetail() {
))} ))}
</div> </div>
{audioUploadedFiles?.length > 0 && ( {/* {audioUploadedFiles?.length > 0 && (
<AudioRecorder <AudioRecorder
onRecordingComplete={addAudioElement} onRecordingComplete={addAudioElement}
audioTrackConstraints={{ audioTrackConstraints={{
@ -1259,7 +1260,7 @@ export default function FormTaskDetail() {
downloadOnSavePress={true} downloadOnSavePress={true}
downloadFileExtension="webm" downloadFileExtension="webm"
/> />
)} )} */}
</div> </div>
{audioFile && ( {audioFile && (
<div className="flex flex-row justify-between items-center"> <div className="flex flex-row justify-between items-center">
@ -1277,6 +1278,7 @@ export default function FormTaskDetail() {
{isRecording && <p>Recording... {timer} seconds remaining</p>}{" "} {isRecording && <p>Recording... {timer} seconds remaining</p>}{" "}
{/* Display remaining time */} {/* Display remaining time */}
<div className="mt-4"> <div className="mt-4">
<Label>Link Url</Label>
{urlInputs.map((url: any, index: any) => ( {urlInputs.map((url: any, index: any) => (
<div <div
key={url.id} key={url.id}