QUDO-374, QUDO-375, QUDO-377, QUDO-380

This commit is contained in:
Sabda Yagra 2025-08-28 20:59:12 +07:00
parent bbed0c29c1
commit e5541c3b35
5 changed files with 228 additions and 70 deletions

View File

@ -108,6 +108,66 @@ const ReportTable = () => {
const [previewData, setPreviewData] = React.useState<any>(null);
const [openDateDialog, setOpenDateDialog] = React.useState(false);
const [reportDate, setReportDate] = React.useState("");
const [startDate, setStartDate] = React.useState("");
const [endDate, setEndDate] = React.useState("");
// handleGenerateReport ubah sedikit
const handleGenerateReport = async () => {
if (!startDate || !endDate) {
MySwal.fire(
"Warning",
"Silakan pilih tanggal awal dan tanggal akhir terlebih dahulu",
"warning"
);
return;
}
if (new Date(startDate) > new Date(endDate)) {
MySwal.fire(
"Warning",
"Tanggal awal tidak boleh lebih besar dari tanggal akhir",
"warning"
);
return;
}
const title = `Report ${format(
new Date(startDate),
"dd-MM-yyyy"
)} - ${format(new Date(endDate), "dd-MM-yyyy")}`;
const requestData = {
title,
startDate,
endDate,
};
try {
const response = await saveReport(requestData);
if (response?.error) {
MySwal.fire(
"Error",
response?.message || "Gagal menyimpan laporan",
"error"
);
return;
}
MySwal.fire({
title: "Sukses",
text: "Laporan berhasil dibuat.",
icon: "success",
confirmButtonColor: "#3085d6",
confirmButtonText: "OK",
}).then(() => {
fetchData();
setStartDate("");
setEndDate("");
});
} catch (error) {
console.error("Generate report error:", error);
MySwal.fire("Error", "Terjadi kesalahan saat membuat laporan", "error");
}
};
const handlePreview = (id: string) => {
const url = `https://new.netidhub.com/api/media/report/view?id=${id}`;
@ -247,49 +307,6 @@ const ReportTable = () => {
// }
// };
const handleGenerateReport = async () => {
if (!reportDate) {
MySwal.fire(
"Warning",
"Silakan pilih tanggal laporan terlebih dahulu",
"warning"
);
return;
}
const title = `Report ${format(new Date(reportDate), "dd-MM-yyyy")}`;
const requestData = {
title,
date: reportDate,
};
try {
const response = await saveReport(requestData);
if (response?.error) {
MySwal.fire(
"Error",
response?.message || "Gagal menyimpan laporan",
"error"
);
return;
}
MySwal.fire({
title: "Sukses",
text: "Laporan berhasil dibuat.",
icon: "success",
confirmButtonColor: "#3085d6",
confirmButtonText: "OK",
}).then(() => {
fetchData();
setReportDate("");
});
} catch (error) {
console.error("Generate report error:", error);
MySwal.fire("Error", "Terjadi kesalahan saat membuat laporan", "error");
}
};
return (
<div>
<Dialog open={openPreview} onOpenChange={setOpenPreview}>
@ -391,13 +408,13 @@ const ReportTable = () => {
</DropdownMenuTrigger>
<DropdownMenuContent
align="end"
className="w-64 h-[200px] overflow-y-auto"
className="w-64 h-fit overflow-y-auto"
>
<div className="flex flex-row justify-between my-1 mx-1">
<p>Filter</p>
</div>
<div className="mx-2 my-1">
<Label>{t("date", { defaultValue: "Date" })}</Label>
<Label>Tanggal Generate</Label>
<Input
type="date"
value={dateFilter}
@ -414,8 +431,8 @@ const ReportTable = () => {
className="max-w-sm"
/>
</div> */}
<Label className="ml-2 mt-2">Status</Label>
<div className="flex items-center px-4 py-1">
{/* <Label className="ml-2 mt-2">Status</Label> */}
{/* <div className="flex items-center px-4 py-1">
<input
type="checkbox"
id="status-1"
@ -426,8 +443,8 @@ const ReportTable = () => {
<label htmlFor="status-1" className="text-sm">
{t("wait-review", { defaultValue: "Wait Review" })}
</label>
</div>
<div className="flex items-center px-4 py-1">
</div> */}
{/* <div className="flex items-center px-4 py-1">
<input
type="checkbox"
id="status-2"
@ -438,7 +455,7 @@ const ReportTable = () => {
<label htmlFor="status-2" className="text-sm">
{t("acc", { defaultValue: "Acc" })}
</label>
</div>
</div> */}
</DropdownMenuContent>
</DropdownMenu>
</div>
@ -528,16 +545,27 @@ const ReportTable = () => {
<Dialog open={openDateDialog} onOpenChange={setOpenDateDialog}>
<DialogContent className="sm:max-w-md">
<DialogHeader>
<DialogTitle>Pilih Tanggal Laporan</DialogTitle>
<DialogTitle>Pilih Rentang Tanggal Laporan</DialogTitle>
</DialogHeader>
<div className="space-y-4">
<Label htmlFor="reportDate">Tanggal</Label>
<Input
id="reportDate"
type="date"
value={reportDate}
onChange={(e) => setReportDate(e.target.value)}
/>
<div>
<Label htmlFor="startDate">Tanggal Awal</Label>
<Input
id="startDate"
type="date"
value={startDate}
onChange={(e) => setStartDate(e.target.value)}
/>
</div>
<div>
<Label htmlFor="endDate">Tanggal Akhir</Label>
<Input
id="endDate"
type="date"
value={endDate}
onChange={(e) => setEndDate(e.target.value)}
/>
</div>
<div className="flex justify-end gap-2">
<Button
variant="outline"

View File

@ -300,7 +300,7 @@ export default function ContentBlast(props: { type: string }) {
Untuk melihat Email Terkirim silahkan cek menu Sent!
</div>
<DialogFooter className="flex justify-center">
<Link
{/* <Link
href={`/admin/broadcast/campaign-list/detail/${
form.getValues("selected")[0]?.id
}`}
@ -308,7 +308,7 @@ export default function ContentBlast(props: { type: string }) {
<Button type="button" color="success">
Menu "Sent"
</Button>
</Link>
</Link> */}
<Button
type="button"

View File

@ -44,6 +44,7 @@ import { ChevronDownIcon } from "lucide-react";
import { getOperatorUser } from "@/service/management-user/management-user";
import makeAnimated from "react-select/animated";
import Select, { ActionMeta, MultiValue } from "react-select";
import { Checkbox } from "@/components/ui/checkbox";
interface Option {
id: string;
@ -114,6 +115,7 @@ export default function FormQuestionsForward() {
const [selectedOperator, setSelectedOperator] = useState<string[]>([]);
const [options, setOptions] = useState<Option[]>([]);
const animatedComponent = makeAnimated();
const [isCollaboration, setIsCollaboration] = useState(false);
const [selectedOption, setSelectedOption] = useState<Option[]>([]);
const [replies, setReplies] = useState([
{
@ -199,6 +201,7 @@ export default function FormQuestionsForward() {
operatorTeam: selectedOperator.join(","),
isEscalation: true,
communicationTeam: selectedOption.map((item) => item.id).join(","),
isCollaboration: isCollaboration,
};
const response = await saveTicketsQuestion(payload);
@ -453,6 +456,14 @@ export default function FormQuestionsForward() {
/>
</div>
<div className="flex flex-row gap-2 px-3 py-3">
<Label className="">Bagikan Untuk Kolaborasi</Label>
<Checkbox
checked={isCollaboration}
onCheckedChange={(e: boolean) => setIsCollaboration(e)}
/>
</div>
<div className="flex justify-end mt-3 mr-3 py-3">
<Button type="submit" color="primary">
Simpan

View File

@ -790,6 +790,117 @@ export default function FormConvertSPIT() {
{/* Content Editor */}
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Edit3 className="h-5 w-5" />
Content Editor
</CardTitle>
</CardHeader>
<CardContent className="space-y-8">
{/* Original Content */}
<div className="space-y-2">
<Label className="text-lg text-black">Original Content</Label>
<Controller
control={control}
name="contentDescription"
render={({ field }) => (
<CustomEditor
onChange={field.onChange}
initialData={field.value}
/>
)}
/>
</div>
{/* Content Rewrite */}
<div className="space-y-4">
<Label className="text-lg text-black">
Rewritten Content
</Label>
<div className="flex items-center justify-between">
<div className="space-y-2">
<Label>Writing Style</Label>
<Select
value={selectedWritingStyle}
onValueChange={setSelectedWritingStyle}
>
<SelectTrigger className="w-48">
<SelectValue placeholder="Select style" />
</SelectTrigger>
<SelectContent>
{WRITING_STYLES.map((style) => (
<SelectItem key={style.value} value={style.value}>
{style.label}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
<Button
type="button"
onClick={handleRewriteClick}
disabled={
isGeneratingRewrite || !detail?.contentDescription
}
className="bg-blue-600 hover:bg-blue-700"
>
{isGeneratingRewrite ? (
<Loader2 className="h-4 w-4 mr-2 animate-spin" />
) : (
<Edit3 className="h-4 w-4 mr-2" />
)}
Generate Rewrite
</Button>
</div>
{showRewriteEditor && (
<div className="space-y-4">
{articleIds.length > 0 && (
<div className="flex gap-2">
{articleIds.map((articleId, index) => (
<Button
key={articleId}
type="button"
variant={
selectedArticleId === articleId
? "default"
: "outline"
}
size="sm"
onClick={() => handleArticleSelect(articleId)}
disabled={isLoadingRewrite}
>
{isLoadingRewrite &&
selectedArticleId === articleId && (
<Loader2 className="h-4 w-4 mr-2 animate-spin" />
)}
Narrative {index + 1}
</Button>
))}
</div>
)}
<div className="space-y-2">
<Label>Rewritten Content</Label>
<Controller
control={control}
name="contentRewriteDescription"
render={({ field }) => (
<CustomEditor
onChange={field.onChange}
initialData={articleBody || field.value}
/>
)}
/>
</div>
</div>
)}
</div>
</CardContent>
</Card>
{/* <Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Edit3 className="h-5 w-5" />
@ -815,7 +926,7 @@ export default function FormConvertSPIT() {
</RadioGroup>
{/* Original Content */}
{selectedFileType === "original" && (
{/* {selectedFileType === "original" && (
<div className="space-y-2">
<Label>Content Description</Label>
<Controller
@ -829,10 +940,10 @@ export default function FormConvertSPIT() {
)}
/>
</div>
)}
)} */}
{/* Content Rewrite */}
{selectedFileType === "rewrite" && (
{/* Content Rewrite */}
{/* {selectedFileType === "rewrite" && (
<div className="space-y-4">
<div className="flex items-center justify-between">
<div className="space-y-2">
@ -915,7 +1026,7 @@ export default function FormConvertSPIT() {
</div>
)}
</CardContent>
</Card>
</Card> */}
{/* Media Files */}
{detailThumb.length > 0 && (
@ -1073,7 +1184,9 @@ export default function FormConvertSPIT() {
<div className="flex-1 space-y-3">
<p className="font-medium text-sm">
{file.fileName || file.contentFileName || `File ${file.contentId}`}
{file.fileName ||
file.contentFileName ||
`File ${file.contentId}`}
</p>
<div className="flex flex-wrap gap-3">
{PLACEMENT_OPTIONS.map((option) => (
@ -1271,7 +1384,6 @@ export default function FormConvertSPIT() {
);
}
// "use client";
// import React, { ChangeEvent, useEffect, useRef, useState } from "react";
// import { useForm, Controller } from "react-hook-form";
@ -2484,5 +2596,3 @@ export default function FormConvertSPIT() {
// </div>
// );
// }

View File

@ -92,10 +92,19 @@ export default function InfoLainnyaModal({
className="max-h-[300px] w-auto object-contain border rounded"
/>
) : (
// <iframe
// src={getIframeUrl(currentFile?.fileUrl || "")}
// title={`Lampiran ${currentIndex + 1}`}
// className="w-full max-w-2xl h-[300px] border rounded"
// onError={(e) => {
// (e.target as HTMLIFrameElement).style.display = "none";
// }}
// />
<iframe
src={getIframeUrl(currentFile?.fileUrl || "")}
title={`Lampiran ${currentIndex + 1}`}
className="w-full max-w-2xl h-[300px] border rounded"
className="w-full max-w-2xl h-[500px] rounded overflow-hidden"
scrolling="no"
onError={(e) => {
(e.target as HTMLIFrameElement).style.display = "none";
}}