Some checks failed
Profile Linker Docker Build / Build and push Docker image (push) Failing after 3s
- Integrated Cloudflare R2 for template storage and converted file management - Added Google Gemini AI for resume parsing and HTML generation - Created backend API endpoints for templates, conversion, and history - Refactored frontend to use real API instead of mock data - Fixed Docker networking issues (IPv6/IPv4) for R2 connectivity - Added resumeService.ts for frontend API integration - Updated Vite configuration for proper asset serving in Docker - Successfully tested with 13 templates from R2 bucket
60 lines
2.3 KiB
TypeScript
60 lines
2.3 KiB
TypeScript
import React from 'react';
|
|
import { FileText, FileCode, Download, Eye } from 'lucide-react';
|
|
import { FileData } from '../types';
|
|
import { formatBytes, formatDate } from '../utils/formatters';
|
|
|
|
interface FileItemProps {
|
|
file: FileData;
|
|
onPreview: (url: string) => void;
|
|
}
|
|
|
|
const FileItem: React.FC<FileItemProps> = ({ file, onPreview }) => {
|
|
const getFileIcon = () => {
|
|
switch (file.type) {
|
|
case 'pdf':
|
|
return <FileText className="w-5 h-5 text-red-500" />;
|
|
case 'html':
|
|
return <FileCode className="w-5 h-5 text-blue-500" />;
|
|
default:
|
|
return <FileText className="w-5 h-5 text-slate-500" />;
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="group grid grid-cols-1 md:grid-cols-[2fr,1fr,1.5fr,1.5fr] gap-4 items-center p-3 border-b border-slate-200 dark:border-slate-700 last:border-b-0 hover:bg-slate-50 dark:hover:bg-slate-800/50 transition-colors">
|
|
<div className="flex items-center gap-3 truncate">
|
|
{getFileIcon()}
|
|
<span className="font-medium text-slate-700 dark:text-slate-300 truncate group-hover:text-primary transition-colors" title={file.name}>{file.name}</span>
|
|
</div>
|
|
<div className="text-sm text-slate-500 dark:text-slate-400">
|
|
{formatBytes(file.size)}
|
|
</div>
|
|
<div className="text-sm text-slate-500 dark:text-slate-400 hidden md:block">
|
|
{formatDate(file.lastModified)}
|
|
</div>
|
|
<div className="flex items-center justify-start md:justify-end gap-2">
|
|
{file.type === 'html' && (
|
|
<button
|
|
onClick={() => onPreview(file.url)}
|
|
className="flex items-center gap-1.5 text-sm bg-slate-200 dark:bg-slate-700 text-slate-700 dark:text-slate-300 hover:bg-slate-300 dark:hover:bg-slate-600 px-3 py-1.5 rounded-md transition-colors font-semibold"
|
|
>
|
|
<Eye className="w-4 h-4" />
|
|
Preview
|
|
</button>
|
|
)}
|
|
<a
|
|
href={file.url}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
download={file.name}
|
|
className="flex items-center gap-1.5 text-sm bg-primary hover:bg-blue-600 text-white px-3 py-1.5 rounded-md transition-colors font-semibold"
|
|
>
|
|
<Download className="w-4 h-4" />
|
|
Download
|
|
</a>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default FileItem; |