"use client"; import PageBreadcrumb from "@/components/common/PageBreadCrumb"; import RichTextEditor from "@/components/form/role-upgrade/Editor"; import { confirmUpload, getPresignedUrl, uploadFileToS3, } from "@/service/mediaService"; import React, { useState } from "react"; import Image from "next/image"; import Lightbox from "yet-another-react-lightbox"; import Zoom from "yet-another-react-lightbox/plugins/zoom"; import Captions from "yet-another-react-lightbox/plugins/captions"; import "yet-another-react-lightbox/styles.css"; import "yet-another-react-lightbox/plugins/captions.css"; import { createHistorianCV } from "@/service/historianService"; import { toast } from "sonner"; import Swal from "sweetalert2"; type PendingFile = { id: string; file: File; previewUrl: string; name: string; size: number; type: "image" | "document"; extension: string; presigned?: any; }; export default function RoleUpgrade() { const [content, setContent] = useState(""); const [isSubmitting, setIsSubmitting] = useState(false); const [verifyType, setVerifyType] = useState("OTHER"); const [pendingFiles, setPendingFiles] = useState([]); const [lightboxIndex, setLightboxIndex] = useState(-1); const [isPreparingFiles, setIsPreparingFiles] = useState(false); const [showPreview, setShowPreview] = useState(false); const cleanHTMLContent = (rawHtml: string) => { if (!rawHtml) return ""; const doc = new DOMParser().parseFromString(rawHtml, "text/html"); let decoded = doc.documentElement.textContent || rawHtml; decoded = decoded.replace(/]*>/g, "").replace(/<\/pre>/g, ""); return decoded; }; const handleContentChange = (value: string) => { setContent(value); }; const handleFileChange = async ( event: React.ChangeEvent, ) => { const files = event.target.files; if (!files || files.length === 0) return; setIsPreparingFiles(true); try { const newFilesPromises = Array.from(files).map(async (file) => { const isImage = file.type.startsWith("image/"); const extension = file.name.split(".").pop()?.toLowerCase() || ""; const presigned = await getPresignedUrl(file); return { id: Math.random().toString(36).substring(7), file: file, previewUrl: isImage ? URL.createObjectURL(file) : "", name: file.name, size: file.size, type: isImage ? "image" : "document", extension: extension, presigned: presigned, } as PendingFile; }); const newPendingFiles = await Promise.all(newFilesPromises); setPendingFiles((prev) => [...prev, ...newPendingFiles]); } catch (error) { console.error("Lỗi khi chuẩn bị file:", error); toast.error("Lỗi khi chuẩn bị kết nối upload."); } finally { setIsPreparingFiles(false); if (event.target) event.target.value = ""; } }; const removePendingFile = (idToRemove: string, e: React.MouseEvent) => { e.stopPropagation(); setPendingFiles((prev) => prev.filter((item) => item.id !== idToRemove)); }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!content.trim()) { toast.warning("Vui lòng nhập nội dung hồ sơ!"); return; } try { setIsSubmitting(true); const uploadPromises = pendingFiles.map(async (item) => { await uploadFileToS3(item.file, item.presigned); const confirmRes = await confirmUpload(item.presigned.token_id); return confirmRes?.data?.id || confirmRes?.id; }); const uploadedMediaIds = await Promise.all(uploadPromises); const cleanPayloadContent = cleanHTMLContent(content); const payload = { content: cleanPayloadContent, media_ids: uploadedMediaIds, verify_type: verifyType, }; await createHistorianCV(payload); Swal.fire({ title: "Gửi yêu cầu thành công!", text: "Hồ sơ của bạn đã được ghi nhận và đang chờ duyệt.", icon: "success", }); setContent(""); setPendingFiles([]); setVerifyType("OTHER"); } catch (error) { console.error("Lỗi submit:", error); toast.error("Có lỗi xảy ra khi gửi yêu cầu."); } finally { setIsSubmitting(false); } }; const imageFiles = pendingFiles.filter((f) => f.type === "image"); const slides = imageFiles.map((item) => ({ src: item.previewUrl, title: item.name, description: `Size: ${(item.size / 1024).toFixed(2)} KB`, })); const handleItemClick = (item: PendingFile) => { if (item.type === "image") { const index = imageFiles.findIndex((img) => img.id === item.id); setLightboxIndex(index); } else { const fileUrl = URL.createObjectURL(item.file); window.open(fileUrl, "_blank"); } }; const getDocumentStyle = (ext: string) => { if (["pdf"].includes(ext)) return { color: "text-red-500", bg: "bg-red-50" }; if (["doc", "docx"].includes(ext)) return { color: "text-blue-500", bg: "bg-blue-50" }; if (["xls", "xlsx"].includes(ext)) return { color: "text-emerald-500", bg: "bg-emerald-50" }; return { color: "text-gray-500", bg: "bg-gray-100" }; }; return (
{showPreview ? "Preview Mode" : "Edit Mode"}
{!showPreview ? ( ) : (
{content ? (
) : (

Chưa có nội dung để xem trước

)}
)}
{/* Upload Files */}

Tài liệu đính kèm

{pendingFiles.length > 0 && (
{pendingFiles.map((item) => { const docStyle = getDocumentStyle(item.extension); return (
{item.type === "image" ? ( preview ) : (
{item.extension.toUpperCase()} {item.name}
)}
); })}
)}
= 0} close={() => setLightboxIndex(-1)} slides={slides} plugins={[Zoom, Captions]} />
); }