'use client'; import React, { useState } from 'react'; import { Upload, Video, Image as ImageIcon, X, Loader2, CheckCircle2 } from 'lucide-react'; import { toast } from 'sonner'; import { adminService } from '@/services/api/adminService'; interface MediaProofModalProps { open: boolean; onClose: () => void; jobId: string; targetStatus: 'INSPECTION_COMPLETED' | 'READY_FOR_DELIVERY'; onSuccess: () => void; } export function MediaProofModal({ open, onClose, jobId, targetStatus, onSuccess, }: MediaProofModalProps) { const [files, setFiles] = useState([]); const [uploading, setUploading] = useState(false); const [uploadProgress, setUploadProgress] = useState(''); if (!open) return null; const isInspection = targetStatus === 'INSPECTION_COMPLETED'; const title = isInspection ? 'Inspection Done Proof Required' : 'Ready for Delivery Proof Required'; const category = isInspection ? 'INSPECTION_DONE' : 'READY_FOR_DELIVERY'; const subtitle = isInspection ? 'Upload 1 short video (max 30 seconds) OR up to 4 photos of the inspected product condition before proceeding.' : 'Upload video or photo proof of the completed repair showing the device fully functional and ready for delivery.'; const handleFileChange = (e: React.ChangeEvent) => { if (!e.target.files || e.target.files.length === 0) return; const selectedList = Array.from(e.target.files); const hasVideo = selectedList.some((f) => f.type.startsWith('video/')); const images = selectedList.filter((f) => f.type.startsWith('image/')); if (hasVideo && selectedList.length > 1) { toast.error('Please upload either 1 video OR photos (not combined).'); return; } if (hasVideo) { const videoFile = selectedList.find((f) => f.type.startsWith('video/'))!; const videoEl = document.createElement('video'); videoEl.preload = 'metadata'; videoEl.onloadedmetadata = () => { window.URL.revokeObjectURL(videoEl.src); if (videoEl.duration > 30.5) { toast.error(`Video length is ${Math.round(videoEl.duration)}s. Maximum allowed video length is 30 seconds.`); } else { setFiles([videoFile]); toast.success(`Video verified (${Math.round(videoEl.duration)}s). Ready to upload.`); } }; videoEl.onerror = () => { toast.error('Failed to parse video file duration.'); }; videoEl.src = URL.createObjectURL(videoFile); return; } if (images.length > 4) { toast.error('Maximum 4 photos allowed.'); setFiles(images.slice(0, 4)); } else { setFiles(images); } }; const removeFile = (index: number) => { setFiles((prev) => prev.filter((_, i) => i !== index)); }; const handleSubmit = async () => { if (files.length === 0) { toast.warning('Please select at least 1 video or photo proof to continue.'); return; } setUploading(true); setUploadProgress('Starting upload...'); try { const fileIds: string[] = []; for (let i = 0; i < files.length; i++) { const file = files[i]; const fileSizeMb = (file.size / (1024 * 1024)).toFixed(1); setUploadProgress(`Uploading file ${i + 1} of ${files.length} (${fileSizeMb} MB)...`); const res = await adminService.uploadMediaFile(file); if (res.file_id) { fileIds.push(res.file_id); } } if (fileIds.length === 0) { throw new Error('Media file upload failed.'); } setUploadProgress('Saving job status & linking proof...'); await adminService.attachJobMedia(jobId, category, fileIds); await adminService.updateServiceJobStatus(jobId, targetStatus); toast.success(`${isInspection ? 'Inspection proof' : 'Ready for delivery proof'} uploaded successfully.`); onSuccess(); onClose(); } catch (err: any) { toast.error(err.message || 'Failed to attach media proof.'); } finally { setUploading(false); setUploadProgress(''); } }; return (
{isInspection ?

{title}

{subtitle}

{files.length > 0 && (
Selected Proof Files ({files.length})
{files.map((file, idx) => (
{file.type.startsWith('video/') ? (
{!uploading && ( )}
))}
)}
); }