2024-11-28 17:23:53 +00:00
|
|
|
"use client";
|
2025-04-14 06:06:56 +00:00
|
|
|
import React, { useEffect, useState } from "react";
|
2024-11-28 17:23:53 +00:00
|
|
|
import DateRangePicker from "@/components/date-range-picker";
|
|
|
|
|
import { usePathname } from "@/components/navigation";
|
2024-12-12 18:38:15 +00:00
|
|
|
import { cn, getCookiesDecrypt } from "@/lib/utils";
|
2025-03-05 16:37:57 +00:00
|
|
|
import {
|
|
|
|
|
Dialog,
|
|
|
|
|
DialogContent,
|
|
|
|
|
DialogFooter,
|
|
|
|
|
DialogHeader,
|
|
|
|
|
DialogTitle,
|
|
|
|
|
DialogTrigger,
|
|
|
|
|
} from "./ui/dialog";
|
|
|
|
|
import { Button } from "./ui/button";
|
|
|
|
|
import { Label } from "./ui/label";
|
|
|
|
|
import { Input } from "./ui/input";
|
2025-04-14 06:06:56 +00:00
|
|
|
import pdfGenerator from "@/utils/pdf-generator";
|
2025-05-19 01:24:48 +00:00
|
|
|
import {
|
|
|
|
|
tableauSignin,
|
|
|
|
|
tableauViewImage,
|
|
|
|
|
} from "@/service/tableau/tableau-service";
|
2024-11-26 03:09:48 +00:00
|
|
|
|
2024-11-28 17:23:53 +00:00
|
|
|
const PageTitle = ({
|
|
|
|
|
title,
|
|
|
|
|
className,
|
|
|
|
|
}: {
|
|
|
|
|
title?: string;
|
|
|
|
|
className?: string;
|
|
|
|
|
}) => {
|
2025-04-14 06:06:56 +00:00
|
|
|
const [reportDate, setReportDate] = useState<any>();
|
2024-11-28 17:23:53 +00:00
|
|
|
const pathname = usePathname();
|
|
|
|
|
const name = pathname?.split("/").slice(1).join(" ");
|
2024-12-12 18:38:15 +00:00
|
|
|
const roleId = getCookiesDecrypt("urie");
|
2024-11-26 03:09:48 +00:00
|
|
|
|
2024-12-12 18:38:15 +00:00
|
|
|
useEffect(() => {
|
2025-08-12 06:31:20 +00:00
|
|
|
// console.log("role", roleId);
|
2024-12-12 18:38:15 +00:00
|
|
|
}, [roleId]);
|
2025-04-14 06:06:56 +00:00
|
|
|
|
|
|
|
|
const downloadReport = async () => {
|
2025-08-12 06:31:20 +00:00
|
|
|
// console.log(reportDate);
|
2025-04-14 06:06:56 +00:00
|
|
|
const formattedDate = `${reportDate.year}-${String(
|
|
|
|
|
reportDate.month
|
|
|
|
|
).padStart(2, "0")}-${String(reportDate.day).padStart(2, "0")}`;
|
|
|
|
|
|
|
|
|
|
const resLogin = await tableauSignin();
|
|
|
|
|
const token = resLogin?.data?.data?.credentials?.token;
|
|
|
|
|
|
|
|
|
|
const resFrontCover = await tableauViewImage(
|
|
|
|
|
token,
|
|
|
|
|
"5b35ec9c-add5-45e7-b71a-31a28db9954d",
|
|
|
|
|
reportDate
|
|
|
|
|
);
|
|
|
|
|
const resAssignmentDetail = await tableauViewImage(
|
|
|
|
|
token,
|
|
|
|
|
"b2e7e184-8311-49e1-8314-a6b2d8a8c6f8",
|
|
|
|
|
reportDate
|
|
|
|
|
);
|
|
|
|
|
// const resMonitoringContent = await tableauViewImage(
|
|
|
|
|
// token,
|
|
|
|
|
// "34683f52-1029-49e4-950d-2c94159ebd8f",
|
|
|
|
|
// reportDate
|
|
|
|
|
// );
|
|
|
|
|
// const resMonitoringArticle = await tableauViewImage(
|
|
|
|
|
// token,
|
|
|
|
|
// "34683f52-1029-49e4-950d-2c94159ebd8f",
|
|
|
|
|
// reportDate
|
|
|
|
|
// );
|
|
|
|
|
const resInteractionContent = await tableauViewImage(
|
|
|
|
|
token,
|
|
|
|
|
"8f038669-4135-4693-96e5-e6a957a1cc4f",
|
|
|
|
|
reportDate
|
|
|
|
|
);
|
|
|
|
|
const resTotalInteractionContent = await tableauViewImage(
|
|
|
|
|
token,
|
|
|
|
|
"e019e7f7-8d3b-4303-aa20-3fdbb318df1e",
|
|
|
|
|
reportDate
|
|
|
|
|
);
|
|
|
|
|
const resInteractionContentCategory1 = await tableauViewImage(
|
|
|
|
|
token,
|
|
|
|
|
"c1dcc6c8-17dc-4e30-85db-7938e30b4418",
|
|
|
|
|
reportDate
|
|
|
|
|
);
|
|
|
|
|
const resInteractionContentCategory2 = await tableauViewImage(
|
|
|
|
|
token,
|
|
|
|
|
"68b95c1d-aee1-4073-afb7-05188eccee67",
|
|
|
|
|
reportDate
|
|
|
|
|
);
|
|
|
|
|
const resInteractionContentCategory3 = await tableauViewImage(
|
|
|
|
|
token,
|
|
|
|
|
"7de1f07f-9a09-45a8-8ff6-96484106492d",
|
|
|
|
|
reportDate
|
|
|
|
|
);
|
|
|
|
|
const resInteractionDistribution = await tableauViewImage(
|
|
|
|
|
token,
|
|
|
|
|
"0781d7e6-e133-416c-bf41-e5b2fa5996dd",
|
|
|
|
|
reportDate
|
|
|
|
|
);
|
|
|
|
|
const resAssignments = await tableauViewImage(
|
|
|
|
|
token,
|
|
|
|
|
"b2e7e184-8311-49e1-8314-a6b2d8a8c6f8",
|
|
|
|
|
reportDate
|
|
|
|
|
);
|
|
|
|
|
const resUserCount = await tableauViewImage(
|
|
|
|
|
token,
|
|
|
|
|
"36ff675d-790c-4420-b0c7-0a6441f59cb1",
|
|
|
|
|
reportDate
|
|
|
|
|
);
|
|
|
|
|
const resUserCountDistribution = await tableauViewImage(
|
|
|
|
|
token,
|
|
|
|
|
"86370e20-b13d-4cb0-a54a-c25dc13bb427",
|
|
|
|
|
reportDate
|
|
|
|
|
);
|
|
|
|
|
const resBackCover = await tableauViewImage(
|
|
|
|
|
token,
|
|
|
|
|
"516c8790-ccd5-44dc-bb66-b0e146d7168b",
|
|
|
|
|
reportDate
|
|
|
|
|
);
|
2025-05-19 01:24:48 +00:00
|
|
|
const blobFrontCover = new Blob([resFrontCover.data], {
|
|
|
|
|
type: "image/png",
|
|
|
|
|
});
|
|
|
|
|
const blobAssignmentDetail = new Blob([resAssignmentDetail.data], {
|
|
|
|
|
type: "image/png",
|
|
|
|
|
});
|
2025-04-14 06:06:56 +00:00
|
|
|
// const blobMonitoringContent = new Blob([resMonitoringContent.data], { type: "image/png" });
|
|
|
|
|
// const blobMonitoringArticle = new Blob([resMonitoringArticle.data], { type: "image/png" });
|
2025-05-19 01:24:48 +00:00
|
|
|
const blobInteractionContent = new Blob([resInteractionContent.data], {
|
|
|
|
|
type: "image/png",
|
|
|
|
|
});
|
|
|
|
|
const blobTotalInteractionContent = new Blob(
|
|
|
|
|
[resTotalInteractionContent.data],
|
|
|
|
|
{ type: "image/png" }
|
|
|
|
|
);
|
|
|
|
|
const blobInteractionContentCategory1 = new Blob(
|
|
|
|
|
[resInteractionContentCategory1.data],
|
|
|
|
|
{ type: "image/png" }
|
|
|
|
|
);
|
|
|
|
|
const blobInteractionContentCategory2 = new Blob(
|
|
|
|
|
[resInteractionContentCategory2.data],
|
|
|
|
|
{ type: "image/png" }
|
|
|
|
|
);
|
|
|
|
|
const blobInteractionContentCategory3 = new Blob(
|
|
|
|
|
[resInteractionContentCategory3.data],
|
|
|
|
|
{ type: "image/png" }
|
|
|
|
|
);
|
|
|
|
|
const blobInteractionDistribution = new Blob(
|
|
|
|
|
[resInteractionDistribution.data],
|
|
|
|
|
{ type: "image/png" }
|
|
|
|
|
);
|
|
|
|
|
const blobAssignments = new Blob([resAssignments.data], {
|
|
|
|
|
type: "image/png",
|
|
|
|
|
});
|
2025-04-14 06:06:56 +00:00
|
|
|
const blobUserCount = new Blob([resUserCount.data], { type: "image/png" });
|
2025-05-19 01:24:48 +00:00
|
|
|
const blobUserCountDistribution = new Blob(
|
|
|
|
|
[resUserCountDistribution.data],
|
|
|
|
|
{ type: "image/png" }
|
|
|
|
|
);
|
2025-04-14 06:06:56 +00:00
|
|
|
const blobBackCover = new Blob([resBackCover.data], { type: "image/png" });
|
|
|
|
|
|
2025-08-12 06:31:20 +00:00
|
|
|
// console.log(blobFrontCover);
|
2025-04-14 06:06:56 +00:00
|
|
|
|
|
|
|
|
await pdfGenerator([
|
|
|
|
|
blobFrontCover,
|
|
|
|
|
blobAssignmentDetail,
|
|
|
|
|
// blobMonitoringContent,
|
|
|
|
|
// blobMonitoringArticle,
|
|
|
|
|
blobInteractionContent,
|
|
|
|
|
blobTotalInteractionContent,
|
|
|
|
|
blobInteractionContentCategory1,
|
|
|
|
|
blobInteractionContentCategory2,
|
|
|
|
|
blobInteractionContentCategory3,
|
|
|
|
|
blobInteractionDistribution,
|
|
|
|
|
blobAssignments,
|
|
|
|
|
blobUserCount,
|
|
|
|
|
blobUserCountDistribution,
|
2025-05-19 01:24:48 +00:00
|
|
|
blobBackCover,
|
2025-04-14 06:06:56 +00:00
|
|
|
]);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
async function mergeImagesToCanvas(blobs: Blob[]) {
|
|
|
|
|
try {
|
|
|
|
|
const images = await Promise.all(
|
2025-05-19 01:24:48 +00:00
|
|
|
blobs.map((blob) => {
|
2025-04-14 06:06:56 +00:00
|
|
|
return new Promise<HTMLImageElement>((resolve) => {
|
|
|
|
|
const url = URL.createObjectURL(blob);
|
|
|
|
|
const img = new Image();
|
|
|
|
|
img.onload = () => {
|
|
|
|
|
resolve(img);
|
|
|
|
|
URL.revokeObjectURL(url);
|
|
|
|
|
};
|
|
|
|
|
img.src = url;
|
|
|
|
|
});
|
|
|
|
|
})
|
|
|
|
|
);
|
2025-05-19 01:24:48 +00:00
|
|
|
|
2025-04-14 06:06:56 +00:00
|
|
|
// Hitung total tinggi dari semua gambar (stacked vertically)
|
2025-05-19 01:24:48 +00:00
|
|
|
const width = Math.max(...images.map((img) => img.width));
|
2025-04-14 06:06:56 +00:00
|
|
|
const height = images.reduce((sum, img) => sum + img.height, 0);
|
2025-05-19 01:24:48 +00:00
|
|
|
|
|
|
|
|
const canvas = document.getElementById("pdf-canvas") as HTMLCanvasElement;
|
|
|
|
|
const ctx = canvas.getContext("2d")!;
|
2025-04-14 06:06:56 +00:00
|
|
|
canvas.width = width;
|
|
|
|
|
canvas.height = height;
|
2025-05-19 01:24:48 +00:00
|
|
|
|
2025-04-14 06:06:56 +00:00
|
|
|
let y = 0;
|
|
|
|
|
for (const img of images) {
|
|
|
|
|
ctx.drawImage(img, 0, y, img.width, img.height);
|
|
|
|
|
y += img.height;
|
|
|
|
|
}
|
2025-05-19 01:24:48 +00:00
|
|
|
|
2025-04-14 06:06:56 +00:00
|
|
|
// Simpan hasil sebagai gambar (PNG) atau bisa print
|
2025-05-19 01:24:48 +00:00
|
|
|
const dataURL = canvas.toDataURL("image/png");
|
|
|
|
|
|
2025-04-14 06:06:56 +00:00
|
|
|
// Simpan atau cetak (print sebagai PDF)
|
2025-05-19 01:24:48 +00:00
|
|
|
const link = document.createElement("a");
|
2025-04-14 06:06:56 +00:00
|
|
|
link.href = dataURL;
|
2025-05-19 01:24:48 +00:00
|
|
|
link.download = "merged-image.png";
|
2025-04-14 06:06:56 +00:00
|
|
|
link.click();
|
2025-05-19 01:24:48 +00:00
|
|
|
|
2025-04-14 06:06:56 +00:00
|
|
|
// Atau tampilkan dan user bisa "Print to PDF"
|
2025-05-19 01:24:48 +00:00
|
|
|
window.open(dataURL, "_blank");
|
2025-04-14 06:06:56 +00:00
|
|
|
} catch (error) {
|
2025-08-12 06:31:20 +00:00
|
|
|
// console.log("Error :::", error);
|
2025-04-14 06:06:56 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-12 18:38:15 +00:00
|
|
|
return Number(roleId) == 2 || Number(roleId) == 11 || Number(roleId) == 12 ? (
|
|
|
|
|
""
|
|
|
|
|
) : (
|
2024-11-28 17:23:53 +00:00
|
|
|
<div
|
|
|
|
|
className={cn(
|
|
|
|
|
"flex flex-wrap gap-4 items-center justify-between",
|
|
|
|
|
className
|
|
|
|
|
)}
|
|
|
|
|
>
|
|
|
|
|
<div className="text-2xl font-medium text-default-800 capitalize">
|
|
|
|
|
Dashboard
|
|
|
|
|
</div>
|
2025-05-19 01:24:48 +00:00
|
|
|
{/* <Dialog>
|
2025-03-05 16:37:57 +00:00
|
|
|
<DialogTrigger asChild>
|
|
|
|
|
<Button variant="outline">Download Report</Button>
|
|
|
|
|
</DialogTrigger>
|
|
|
|
|
<DialogContent className="sm:max-w-[425px]">
|
|
|
|
|
<DialogHeader>
|
|
|
|
|
<DialogTitle>Download Report</DialogTitle>
|
|
|
|
|
</DialogHeader>
|
|
|
|
|
<div className="grid gap-4 py-4">
|
|
|
|
|
<div className="w-full">
|
2025-04-14 06:06:56 +00:00
|
|
|
<canvas id="pdf-canvas"></canvas>
|
2025-03-05 16:37:57 +00:00
|
|
|
<Label>Date</Label>
|
|
|
|
|
<Input
|
|
|
|
|
type="date"
|
2025-04-14 06:06:56 +00:00
|
|
|
value={reportDate}
|
|
|
|
|
onChange={(e) => setReportDate(e.target.value)}
|
2025-03-05 16:37:57 +00:00
|
|
|
className="w-full"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<DialogFooter>
|
2025-05-19 01:24:48 +00:00
|
|
|
<Button type="submit" onClick={downloadReport}>
|
2025-03-05 16:37:57 +00:00
|
|
|
Download
|
|
|
|
|
</Button>
|
|
|
|
|
</DialogFooter>
|
|
|
|
|
</DialogContent>
|
2025-05-19 01:24:48 +00:00
|
|
|
</Dialog> */}
|
2024-11-28 17:23:53 +00:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|
2024-11-26 03:09:48 +00:00
|
|
|
|
2024-11-28 17:23:53 +00:00
|
|
|
export default PageTitle;
|