// Files screen — folder manager. (() => { const { Card, Badge, Avatar } = window.TechyFuelOSDesignSystem_be0222; const FOLDERS = [ { name: 'Designs', color: 'var(--violet-500)', bg: 'var(--violet-50)', icon: 'palette', mimeKeys: ['figma', 'image'] }, { name: 'Videos', color: 'var(--teal-500)', bg: 'var(--teal-50)', icon: 'film', mimeKeys: ['video'] }, { name: 'Documents', color: 'var(--blue-500)', bg: 'var(--blue-50)', icon: 'file-text', mimeKeys: ['pdf', 'doc', 'sheet', 'excel', 'txt'] }, { name: 'Contracts', color: 'var(--green-500)', bg: 'var(--green-50)', icon: 'file-check', mimeKeys: ['contract'] }, ]; function mimeIcon(mime) { if (!mime) return { icon: 'file', color: 'var(--slate-400)' }; if (mime.startsWith('application/vnd.google-apps.document')) return { icon: 'file-text', color: '#4285F4' }; if (mime.startsWith('application/vnd.google-apps.spreadsheet')) return { icon: 'sheet', color: '#0F9D58' }; if (mime.startsWith('application/vnd.google-apps.presentation')) return { icon: 'presentation', color: '#F4B400' }; if (mime.startsWith('application/vnd.google-apps.folder')) return { icon: 'folder', color: '#0F9D58' }; if (mime.startsWith('application/vnd.google-apps')) return { icon: 'hard-drive', color: '#0F9D58' }; if (mime.includes('pdf')) return { icon: 'file-text', color: 'var(--red-500)' }; if (mime.includes('image')) return { icon: 'image', color: 'var(--violet-500)' }; if (mime.includes('video')) return { icon: 'video', color: 'var(--teal-500)' }; if (mime.includes('zip') || mime.includes('archive')) return { icon: 'folder-archive', color: 'var(--amber-500)' }; if (mime.includes('figma')) return { icon: 'figma', color: 'var(--violet-500)' }; if (mime.includes('pptx') || mime.includes('presentation')) return { icon: 'presentation', color: 'var(--orange-500)' }; if (mime.includes('doc') || mime.includes('word')) return { icon: 'file-text', color: 'var(--blue-500)' }; if (mime.includes('sheet') || mime.includes('excel')) return { icon: 'sheet', color: 'var(--green-500)' }; return { icon: 'file', color: 'var(--slate-400)' }; } function fmtSize(bytes) { if (!bytes) return '—'; if (bytes >= 1073741824) return (bytes / 1073741824).toFixed(1) + ' GB'; if (bytes >= 1048576) return (bytes / 1048576).toFixed(0) + ' MB'; if (bytes >= 1024) return (bytes / 1024).toFixed(0) + ' KB'; return bytes + ' B'; } function fmtWhen(ds) { if (!ds) return '—'; const d = new Date(ds); const now = new Date(); const diff = Math.round((now - d) / 3600000); if (diff < 1) return 'Just now'; if (diff < 24) return diff + 'h ago'; if (diff < 48) return 'Yesterday'; return d.toLocaleDateString('en', { month: 'short', day: 'numeric' }); } function Files() { useLucide(); const [files, setFiles] = React.useState([]); const [loading, setLoading] = React.useState(true); const [uploading, setUploading] = React.useState(false); const [drivePicking, setDrivePicking] = React.useState(false); const fileInputRef = React.useRef(); React.useEffect(() => { if (!window.API) { setLoading(false); return; } window.API.getFiles().then(r => { if (r.data) setFiles(r.data); }).catch(() => {}).finally(() => setLoading(false)); }, []); async function handleFileSelect(e) { const selected = Array.from(e.target.files || []); if (!selected.length) return; setUploading(true); for (const file of selected) { const filePath = `${Date.now()}_${file.name.replace(/\s+/g, '_')}`; let savedToDb = false; // Try Supabase Storage upload if (window.API) { try { await window.API.uploadFile('files', filePath, file); } catch(_) {} } // Save metadata to files table if (window.API) { try { const payload = { name: file.name, file_path: filePath, mime_type: file.type || 'application/octet-stream', file_size: file.size, }; const result = await window.API.createFile(payload); if (result && result.data) { setFiles(prev => [{ ...result.data, team_members: null }, ...prev]); savedToDb = true; } } catch(_) {} } // Always show in list even if DB save failed if (!savedToDb) { setFiles(prev => [{ id: 'local_' + Date.now(), name: file.name, file_path: filePath, mime_type: file.type || 'application/octet-stream', file_size: file.size, created_at: new Date().toISOString(), team_members: null, }, ...prev]); } } setUploading(false); e.target.value = ''; } async function handleConnectDrive() { const gdrive = readIntegrationsCfg().gdrive || {}; if (!gdrive.driveClientId || !gdrive.driveApiKey) { alert('Connect Google Drive first: go to Integrations → Google Drive and add your OAuth Client ID + API Key.'); if (window.TFNavigate) window.TFNavigate('integrations'); return; } setDrivePicking(true); try { const docs = await pickFilesFromGoogleDrive({ clientId: gdrive.driveClientId, apiKey: gdrive.driveApiKey }); for (const doc of docs) { const payload = { name: doc.name, file_path: doc.url || `https://drive.google.com/file/d/${doc.id}/view`, mime_type: doc.mimeType || 'application/vnd.google-apps.file', file_size: doc.sizeBytes ? Number(doc.sizeBytes) : null, }; if (window.API) { try { const result = await window.API.createFile(payload); if (result && result.data) { setFiles(prev => [{ ...result.data, team_members: null }, ...prev]); continue; } } catch (_) {} } setFiles(prev => [{ id: 'drive_' + doc.id, ...payload, created_at: new Date().toISOString(), team_members: null }, ...prev]); } } catch (err) { alert('Could not connect to Google Drive: ' + (err.message || err)); } finally { setDrivePicking(false); } } function folderCount(f) { return files.filter(file => f.mimeKeys.some(k => (file.mime_type || '').toLowerCase().includes(k))).length; } function folderSize(f) { const total = files.filter(file => f.mimeKeys.some(k => (file.mime_type || '').toLowerCase().includes(k))).reduce((s, file) => s + (file.file_size || 0), 0); return fmtSize(total) === '—' ? '0 KB' : fmtSize(total); } return (

Files

{files.length} files · Shared workspace

{FOLDERS.map((f, i) => (
{f.name}
{folderCount(f)} files · {folderSize(f)}
))}

Recent files

Team access · version controlled
{loading && (
Loading…
)} {!loading && files.length === 0 && (
No files yet
Upload your first file using the button above
)} {!loading && files.map((f, i) => { const { icon, color } = mimeIcon(f.mime_type); const uploaderName = f.team_members ? f.team_members.name : '—'; const isDrive = isDriveFile(f); return (
f.url && window.open(f.url, '_blank')} style={{ display: 'flex', alignItems: 'center', gap: 14, padding: '12px 18px', borderTop: '1px solid var(--border-subtle)', cursor: f.url ? 'pointer' : 'default' }}>
{f.name}
{isDrive ? Google Drive : uploaderName} · {fmtWhen(f.created_at)}
{fmtSize(f.file_size)} { e.stopPropagation(); if (f.url) window.open(f.url, '_blank'); }} style={{ color: 'var(--text-muted)', cursor: 'pointer' }} />
); })}
); } Object.assign(window, { Files }); })();