"use client"; import React, { useEffect, useRef, useState } from "react"; import Image from "next/image"; import Swal from "sweetalert2"; import { apiUpdateApplicationStatus } from "@/service/adminService"; import { URL_MEDIA } from "../../../api"; 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 { IsolatedContent } from "@/components/ui/IsolatedContent"; import { apiDeleteHistorianCV } from "@/service/historianService"; import { statusConfig } from "@/service/handler"; interface Props { isOpen: boolean; onClose: () => void; application: any; onRefresh: () => void; } export default function ApplicationDetailModal({ isOpen, onClose, application, onRefresh, }: Props) { const [reviewNote, setReviewNote] = useState(""); const [isSubmitting, setIsSubmitting] = useState(false); const textareaRef = useRef(null); const [index, setIndex] = useState(-1); useEffect(() => { if (isOpen && application) { setReviewNote(application.review_note || ""); } else { setReviewNote(""); } }, [isOpen, application]); const isImageFile = (file: any) => { const isImageMime = file.mime_type?.startsWith("image/"); const isImageExt = /\.(jpg|jpeg|png|webp|gif)$/i.test(file.storage_key); return isImageMime || isImageExt; }; const mediaList = application?.media || []; const imageMediaOnly = mediaList.filter(isImageFile); const imageSlides = imageMediaOnly.map((item: any) => ({ src: `${URL_MEDIA}${item.storage_key}`, title: item.original_name, description: `Dung lượng: ${(item.size / 1024).toFixed(2)} KB`, })); const handleMediaClick = (item: any) => { const fileUrl = `${URL_MEDIA}${item.storage_key}`; if (isImageFile(item)) { const photoIndex = imageMediaOnly.findIndex( (img: any) => img.id === item.id, ); setIndex(photoIndex); } else { const googleDocsUrl = `https://docs.google.com/viewer?url=${encodeURIComponent(fileUrl)}&embedded=true`; window.open(googleDocsUrl, "_blank"); } }; const handleUpdateStatus = async (status: "APPROVED" | "REJECTED") => { if (!application) return; if (!reviewNote.trim()) { textareaRef.current?.focus(); return; } try { setIsSubmitting(true); await apiUpdateApplicationStatus(application.id, { status, review_note: reviewNote, }); Swal.fire("Thành công!", "Trạng thái hồ sơ đã được cập nhật.", "success"); onRefresh(); onClose(); } catch (error) { Swal.fire("Lỗi", "Không thể cập nhật trạng thái.", "error"); } finally { setIsSubmitting(false); } }; const handleDeleteApplication = async () => { await apiDeleteHistorianCV(application.id); Swal.fire("Thành công!", "Hồ sơ đã được xóa.", "success"); onRefresh(); onClose(); }; if (!isOpen || !application) return null; const userData = application.user || {}; const currentStatus = statusConfig[application.status] || { container: "bg-gray-50 border-gray-200 text-gray-600 shadow-sm", }; return (

Chi tiết yêu cầu nâng cấp

Thông tin ứng viên

avatar

{userData.display_name || "N/A"}

{userData.email || "Không có email"}

{application.verify_type} {application.status}

Nội dung ứng tuyển

Tệp đính kèm ({mediaList.length})

{mediaList.length > 0 ? (
{mediaList.map((media: any, idx: number) => { const isImg = isImageFile(media); return (
handleMediaClick(media)} className="relative overflow-hidden border border-gray-200 group aspect-square rounded-xl dark:border-gray-700 bg-gray-50 dark:bg-gray-800 cursor-pointer" > {isImg ? ( media ) : (
📄
{media.original_name}
)}
{isImg ? "Xem ảnh" : "Xem file"}
); })}
) : (

Không có tệp đính kèm.

)}

Ghi chú duyệt hồ sơ