'use client'
import { useEffect, useState, useRef, useCallback } from 'react'
import { FileText, Download, Upload, Eye, LogOut, Pencil, Globe } from 'lucide-react'
interface Doc {
id: string
filename: string
display_name: string | null
description_de: string | null
description_en: string | null
mime_type: string
file_size: number
released_at: string
}
interface MyUpload {
id: string
filename: string
display_name: string | null
description_de: string | null
description_en: string | null
mime_type: string
file_size: number
created_at: string
}
function fmt(bytes: number) {
if (bytes < 1024) return `${bytes} B`
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`
}
function isPDF(mime: string) { return mime === 'application/pdf' }
function LangToggle({ lang, onChange }: { lang: 'de' | 'en'; onChange: (l: 'de' | 'en') => void }) {
return (
{(['de', 'en'] as const).map(l => (
))}
)
}
export default function DataroomPage() {
const [docs, setDocs] = useState([])
const [uploads, setUploads] = useState([])
const [dragging, setDragging] = useState(false)
const [uploading, setUploading] = useState(false)
const [toast, setToast] = useState(null)
const [description, setDescription] = useState('')
const [descLang, setDescLang] = useState<'de' | 'en'>('en')
const [editingUpload, setEditingUpload] = useState<{ id: string; text: string; lang: 'de' | 'en' } | null>(null)
const fileRef = useRef(null)
function flash(msg: string) { setToast(msg); setTimeout(() => setToast(null), 3500) }
async function loadAll() {
const [dr, ur] = await Promise.all([fetch('/api/dataroom/documents'), fetch('/api/dataroom/uploads')])
if (dr.ok) setDocs((await dr.json()).documents)
if (ur.ok) setUploads((await ur.json()).uploads)
}
useEffect(() => { loadAll() }, [])
async function uploadFiles(files: FileList | File[]) {
const list = Array.from(files).filter(f => f.size > 0)
if (!list.length) return
setUploading(true)
const fd = new FormData()
list.forEach(f => fd.append('file', f))
if (description.trim()) { fd.append('description', description.trim()); fd.append('description_lang', descLang) }
const r = await fetch('/api/dataroom/uploads', { method: 'POST', body: fd })
setUploading(false)
if (r.ok) {
flash(`${list.length} file${list.length > 1 ? 's' : ''} uploaded`)
setDescription(''); loadAll()
} else {
const d = await r.json().catch(() => ({}))
flash(d.error || 'Upload failed')
}
}
const handleDrop = useCallback((e: React.DragEvent) => {
e.preventDefault(); setDragging(false)
if (e.dataTransfer.files.length) uploadFiles(e.dataTransfer.files)
}, [description, descLang])
async function saveEditDescription() {
if (!editingUpload) return
const r = await fetch(`/api/dataroom/uploads/${editingUpload.id}`, {
method: 'PATCH', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ description: editingUpload.text || null, description_lang: editingUpload.lang }),
})
if (r.ok) {
const updated = (await r.json()).upload as MyUpload
setUploads(prev => prev.map(u => u.id === updated.id ? updated : u))
setEditingUpload(null); flash('Description saved & translated')
} else flash('Save failed')
}
return (
Data Room
BreakPilot ComplAI · Investor Portal
{/* Released documents */}
Documents
{docs.length === 0 ? (
No documents have been shared with you yet.
) : (
{docs.map(doc => (
{doc.display_name || doc.filename}
{fmt(doc.file_size)} · Released {new Date(doc.released_at).toLocaleDateString()}
{(doc.description_en || doc.description_de) && (
{doc.description_en &&
{doc.description_en}
}
{doc.description_de && !doc.description_en &&
{doc.description_de}
}
{doc.description_de && doc.description_en &&
{doc.description_de}
}
)}
))}
)}
{/* Upload section */}
Your Documents
Upload documents you want to share with us — NDAs, term sheets, financial statements, or any other relevant files.
{/* Description field */}
{/* Drop zone */}
{ e.preventDefault(); setDragging(true) }}
onDragLeave={() => setDragging(false)}
onDrop={handleDrop}
onClick={() => fileRef.current?.click()}
className={`border-2 border-dashed rounded-2xl p-10 text-center cursor-pointer transition-all select-none ${dragging ? 'border-indigo-400/60 bg-indigo-500/10' : 'border-white/[0.08] bg-white/[0.02] hover:border-white/20 hover:bg-white/[0.03]'}`}
>
{uploading
?
Uploading…
: <>
Drop files here
or click to browse · multiple files supported
>}
{ if (e.target.files) uploadFiles(e.target.files); e.target.value = '' }} />
{/* Uploaded files list */}
{uploads.length > 0 && (
{uploads.map(u => {
const isEditing = editingUpload?.id === u.id
return (
{u.display_name || u.filename}
{fmt(u.file_size)} · {new Date(u.created_at).toLocaleString()}
Received
{(u.description_en || u.description_de) && !isEditing && (
{u.description_en &&
{u.description_en}
}
{u.description_de && !u.description_en &&
{u.description_de}
}
)}
{isEditing && editingUpload && (
)}
)
})}
)}
{toast && (
{toast}
)}
)
}