// "use client"; // import { useState, useEffect } from "react"; // import { useUploadContext } from "../_context/upload-context"; // // Sesuaikan import ini dengan lokasi service API Anda yang sebenarnya // import uploadApi from "@/shared/services/map-upload"; // import { toast } from "sonner"; // // --- 1. Helper Load PDF.js via CDN (Sama seperti di use-upload.ts) --- // const loadPdfJs = async () => { // return new Promise((resolve, reject) => { // // Cek jika global variable sudah ada // if ((window as any).pdfjsLib) { // resolve((window as any).pdfjsLib); // return; // } // const script = document.createElement("script"); // // Gunakan versi yang sama agar konsisten // script.src = "https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js"; // script.async = true; // script.onload = () => { // const pdfjsLib = (window as any).pdfjsLib; // // Set worker // pdfjsLib.GlobalWorkerOptions.workerSrc = // "https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js"; // resolve(pdfjsLib); // }; // script.onerror = (err) => reject(err); // document.body.appendChild(script); // }); // }; // export function usePdfViewer() { // const { state, setState, goToStep } = useUploadContext(); // const [pages, setPages] = useState<{ pageNum: number; imageUrl: string }[]>([]); // const [loading, setLoading] = useState(false); // const [localSelectedPages, setLocalSelectedPages] = useState([]); // // Load PDF saat component mount atau file berubah // useEffect(() => { // if (state.file && state.step === "PDF_VIEWER") { // renderPdfPages(state.file); // } // // eslint-disable-next-line react-hooks/exhaustive-deps // }, [state.file, state.step]); // const renderPdfPages = async (pdfFile: File) => { // setLoading(true); // setPages([]); // Reset halaman lama // try { // // 1. Load Library dari CDN // const pdfjsLib = await loadPdfJs(); // // 2. Baca File // const arrayBuffer = await pdfFile.arrayBuffer(); // const pdf = await pdfjsLib.getDocument({ data: arrayBuffer }).promise; // const totalPages = pdf.numPages; // const pageImages = []; // // 3. Render Setiap Halaman ke Canvas -> Image URL // for (let pageNum = 1; pageNum <= totalPages; pageNum++) { // const page = await pdf.getPage(pageNum); // const viewport = page.getViewport({ scale: 1 }); // Scale 1 cukup untuk thumbnail // const canvas = document.createElement("canvas"); // const ctx = canvas.getContext("2d"); // if (ctx) { // canvas.height = viewport.height; // canvas.width = viewport.width; // await page.render({ // canvasContext: ctx, // viewport: viewport, // }).promise; // pageImages.push({ // pageNum, // imageUrl: canvas.toDataURL("image/jpeg", 0.8), // Gunakan JPEG kompresi agar ringan // }); // } // } // setPages(pageImages); // } catch (err) { // console.error("PDF Error:", err); // toast.error("Gagal memuat halaman PDF. Pastikan file tidak korup."); // } finally { // setLoading(false); // } // }; // const toggleSelectPage = (pageNum: number) => { // setLocalSelectedPages((prev) => { // if (prev.includes(pageNum)) { // return prev.filter((p) => p !== pageNum); // } else { // if (prev.length >= 20) { // toast.warning("Maksimal pilih 20 halaman."); // return prev; // } // return [...prev, pageNum]; // } // }); // }; // const handleProcessPdf = async () => { // if (localSelectedPages.length === 0) { // toast.warning("Pilih minimal 1 halaman."); // return; // } // setLoading(true); // try { // // Panggil API dengan halaman yang DIPILIH SAJA // const res = await uploadApi.uploadFile( // state.file!, // localSelectedPages, // null, // state.fileDesc // ); // setState(prev => ({ ...prev, result: res })); // // Routing Logic setelah upload PDF selesai // if (!res.tables) { // goToStep("VALIDATE"); // } else if (res.tables.length > 1) { // goToStep("TABLE_PICKER"); // toast.success("Beberapa tabel terdeteksi. Silakan pilih tabel."); // } else { // goToStep("TABLE_PICKER"); // Atau langsung validate tergantung kebutuhan // } // } catch (err: any) { // toast.error(err.message || "Gagal memproses halaman PDF"); // } finally { // setLoading(false); // } // }; // // 🔥 PENTING: Wajib me-return object ini agar tidak "undefined" di component // return { // pages, // loading, // localSelectedPages, // toggleSelectPage, // handleProcessPdf, // }; // } "use client"; import { useState, useEffect } from "react"; import { useUploadContext } from "../_context/upload-context"; // Pastikan path ini sesuai dengan lokasi service API upload Anda import uploadApi from "@/shared/services/map-upload"; import { toast } from "sonner"; // --- HELPER: Load PDF.js via CDN (Bypassing Webpack agar tidak Error) --- const loadPdfJs = async () => { return new Promise((resolve, reject) => { // 1. Cek jika library sudah ada di window if ((window as any).pdfjsLib) { resolve((window as any).pdfjsLib); return; } // 2. Inject Script jika belum ada const script = document.createElement("script"); script.src = "https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js"; script.async = true; script.onload = () => { const pdfjsLib = (window as any).pdfjsLib; // Set worker source ke versi yang sama pdfjsLib.GlobalWorkerOptions.workerSrc = "https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js"; resolve(pdfjsLib); }; script.onerror = (err) => reject(err); document.body.appendChild(script); }); }; export function usePdfViewer() { const { state, setState, goToStep } = useUploadContext(); const [pages, setPages] = useState<{ pageNum: number; imageUrl: string }[]>([]); const [loading, setLoading] = useState(false); const [localSelectedPages, setLocalSelectedPages] = useState([]); const MAX_SELECT = 20; // Efek untuk memuat halaman PDF saat komponen dipasang useEffect(() => { if (state.file && state.step === "PDF_VIEWER") { renderPdfPages(state.file); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [state.file, state.step]); // --- FUNGSI RENDER PDF KE GAMBAR --- const renderPdfPages = async (pdfFile: File) => { setLoading(true); setPages([]); try { const pdfjsLib = await loadPdfJs(); const arrayBuffer = await pdfFile.arrayBuffer(); const pdf = await pdfjsLib.getDocument({ data: arrayBuffer }).promise; const totalPages = pdf.numPages; const pageImages = []; for (let pageNum = 1; pageNum <= totalPages; pageNum++) { const page = await pdf.getPage(pageNum); const viewport = page.getViewport({ scale: 1 }); const canvas = document.createElement("canvas"); const ctx = canvas.getContext("2d"); if (ctx) { canvas.height = viewport.height; canvas.width = viewport.width; await page.render({ canvasContext: ctx, viewport }).promise; pageImages.push({ pageNum, imageUrl: canvas.toDataURL("image/jpeg", 0.7), }); } } setPages(pageImages); } catch (err) { console.error("PDF Render Error:", err); toast.error("Gagal memuat visualisasi PDF."); } finally { setLoading(false); } }; // --- FUNGSI PILIH HALAMAN --- const toggleSelectPage = (pageNum: number) => { setLocalSelectedPages((prev) => { if (prev.includes(pageNum)) { return prev.filter((p) => p !== pageNum); } else { if (prev.length >= MAX_SELECT) { toast.warning(`Maksimal ${MAX_SELECT} halaman yang dapat dipilih.`); return prev; } return [...prev, pageNum]; } }); }; // 🔥 SELECT ALL const isAllSelected = pages.length > 0 && localSelectedPages.length === Math.min(pages.length, MAX_SELECT); const handleSelectAll = () => { if (isAllSelected) { // Jika sudah terpilih semua (atau max), batalkan semua setLocalSelectedPages([]); } else { // Pilih semua (tapi batasi sesuai MAX_SELECT) const allPageNums = pages.map(p => p.pageNum).slice(0, MAX_SELECT); setLocalSelectedPages(allPageNums); if (pages.length > MAX_SELECT) { toast.info(`Otomatis memilih ${MAX_SELECT} halaman pertama (Batas Maksimum).`); } } }; // --- LOGIKA PROSES UPLOAD & ROUTING YANG ANDA MINTA --- const handleProcessPdf = async () => { if (localSelectedPages.length === 0) { toast.warning("Harap pilih minimal 1 halaman untuk diproses."); return; } setLoading(true); try { const res = await uploadApi.uploadFile( state.file!, localSelectedPages, null, state.fileDesc ); setState(prev => ({ ...prev, result: res })); if (res.tables && res.tables.length > 0) { goToStep("TABLE_PICKER"); toast.success(`Ditemukan ${res.tables.length} tabel. Silakan pilih tabel.`); } else { goToStep("VALIDATE"); toast.info("Tabel tidak terdeteksi spesifik, lanjut ke validasi."); } } catch (err: any) { console.error(err); toast.error(err.message || "Gagal memproses halaman PDF terpilih."); } finally { setLoading(false); } }; // 🔥 Return wajib agar tidak error destructuring undefined return { pages, loading, localSelectedPages, toggleSelectPage, handleProcessPdf, handleSelectAll, isAllSelected, MAX_SELECT }; }