// app/components/WordToPdf.jsx
"use client";
import { useState, useEffect, useCallback, useRef } from "react";
import { FiUpload, FiDownload, FiTrash2, FiCopy, FiFile, FiList, FiFileText, FiCloud, FiCheckCircle, FiStar, FiAlertCircle, FiInfo, FiX } from "react-icons/fi";
import "./styles/WordToPdf.css";
export default function FileUploadDownload() {
const [file, setFile] = useState(null);
const [uploadLoading, setUploadLoading] = useState(false);
const [downloadId, setDownloadId] = useState("");
const [downloadLoading, setDownloadLoading] = useState(false);
const [fileId, setFileId] = useState("");
const [persistentFileId, setPersistentFileId] = useState("");
const [persistentFileName, setPersistentFileName] = useState("");
const [allFiles, setAllFiles] = useState([]);
const [showAll, setShowAll] = useState(false);
const [isDragging, setIsDragging] = useState(false);
const [dragCounter, setDragCounter] = useState(0);
// Toast notification state
const [toast, setToast] = useState(null);
const toastTimeoutRef = useRef(null);
useEffect(() => {
const storedFileId = localStorage.getItem('uploadedFileId');
const storedFileName = localStorage.getItem('uploadedFileName');
if (storedFileId && storedFileName) {
setPersistentFileId(storedFileId);
setPersistentFileName(storedFileName);
}
const userFiles = JSON.parse(localStorage.getItem('userUploadedFiles') || '[]');
setAllFiles(userFiles);
}, []);
// Cleanup toast timeout on unmount
useEffect(() => {
return () => {
if (toastTimeoutRef.current) {
clearTimeout(toastTimeoutRef.current);
}
};
}, []);
// Show toast notification
const showToast = useCallback((message, type = "info") => {
if (toastTimeoutRef.current) {
clearTimeout(toastTimeoutRef.current);
}
setToast({ message, type });
toastTimeoutRef.current = setTimeout(() => {
setToast(null);
}, 4000);
}, []);
// Dismiss toast manually
const dismissToast = useCallback(() => {
if (toastTimeoutRef.current) {
clearTimeout(toastTimeoutRef.current);
}
setToast(null);
}, []);
// Get toast icon based on type
const getToastIcon = (type) => {
switch (type) {
case 'success':
return ;
case 'error':
return ;
default:
return ;
}
};
// Drag and drop handlers
const handleDragEnter = useCallback((e) => {
e.preventDefault();
e.stopPropagation();
setDragCounter(prev => prev + 1);
if (e.dataTransfer.items && e.dataTransfer.items.length > 0) {
setIsDragging(true);
}
}, []);
const handleDragLeave = useCallback((e) => {
e.preventDefault();
e.stopPropagation();
setDragCounter(prev => {
const newCount = prev - 1;
if (newCount === 0) {
setIsDragging(false);
}
return newCount;
});
}, []);
const handleDragOver = useCallback((e) => {
e.preventDefault();
e.stopPropagation();
}, []);
const handleDrop = useCallback((e) => {
e.preventDefault();
e.stopPropagation();
setIsDragging(false);
setDragCounter(0);
if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {
const droppedFile = e.dataTransfer.files[0];
setFile(droppedFile);
showToast(`File "${droppedFile.name}" ready to upload!`, "success");
setFileId("");
e.dataTransfer.clearData();
}
}, [showToast]);
function onFileChange(e) {
const f = e.target.files?.[0];
if (f) {
setFile(f);
setFileId("");
}
}
async function handleUpload() {
if (!file) {
showToast("Please choose a file.", "error");
return;
}
setUploadLoading(true);
showToast("Uploading...", "info");
try {
const fd = new FormData();
fd.append("file", file, file.name);
const res = await fetch("/api/file/upload", {
method: "POST",
body: fd,
});
const data = await res.json();
if (!res.ok) {
showToast(data.error || "Upload failed", "error");
return;
}
setFileId(data.fileId);
setPersistentFileId(data.fileId);
setPersistentFileName(file.name);
localStorage.setItem('uploadedFileId', data.fileId);
localStorage.setItem('uploadedFileName', file.name);
const userFiles = JSON.parse(localStorage.getItem('userUploadedFiles') || '[]');
const newFile = { fileid: data.fileId, originalName: file.name };
const updatedFiles = [newFile, ...userFiles];
localStorage.setItem('userUploadedFiles', JSON.stringify(updatedFiles));
setAllFiles(updatedFiles);
showToast(`Upload complete! File ID: ${data.fileId}`, "success");
} catch (err) {
console.error("Upload error:", err);
showToast("Network error or server unavailable. Please try again.", "error");
} finally {
setUploadLoading(false);
}
}
async function downloadFile(id) {
setDownloadLoading(true);
showToast("Fetching download link...", "info");
try {
const response = await fetch(`/api/file/download/${id}`);
const data = await response.json();
if (!response.ok) {
showToast(data.error || "Failed to fetch download link", "error");
return;
}
const link = document.createElement('a');
link.href = data.downloadUrl;
link.download = data.fileName;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
showToast("Download initiated successfully!", "success");
} catch (err) {
console.error("Download error:", err);
showToast("Failed to initiate download. Please try again.", "error");
} finally {
setDownloadLoading(false);
}
}
async function handleDownload() {
if (!downloadId.trim()) {
showToast("Please enter a file ID.", "error");
return;
}
downloadFile(downloadId.trim());
setDownloadId("");
}
function clearUpload() {
setFile(null);
setFileId("");
}
function clearDownload() {
setDownloadId("");
}
function removeFile(id) {
const updatedFiles = allFiles.filter(file => file.fileid !== id);
setAllFiles(updatedFiles);
localStorage.setItem('userUploadedFiles', JSON.stringify(updatedFiles));
}
function copyToClipboard(text) {
navigator.clipboard.writeText(text);
showToast("ID copied to clipboard!", "success");
}
return (
{/* Toast Notification */}
{toast && (
{getToastIcon(toast.type)}
{toast.message}
)}
{/* Drag overlay */}
{isDragging && (
{/* Decorative floating icons */}
{/* Main drop zone */}
Drop your file here
Release to upload instantly
.DOC
.DOCX
)}
{/* Intro Card */}
1.
File Upload & Download
Free to use • Up to 100MB per file • Files expire after 24 hours
{/* Upload Section */}
Upload File
{fileId && (
File ID:
{fileId}
)}
{/* Last Uploaded / All Files Section */}
{(persistentFileId || allFiles.length > 0) && (
Your Uploaded Files
{persistentFileId && (
{persistentFileName}
Last uploaded
)}
{showAll && (
{allFiles.length === 0 ? (
No files uploaded yet.
) : (
allFiles.map(f => (
{f.originalName}
))
)}
)}
)}
{/* Download Section */}
);
}