import React, { useState, useRef, useMemo } from "react"; import { LayoutDashboard, FolderOpen, Folder, FileText, Search, Upload, CheckCircle2, XCircle, Clock, PenTool, Users, Settings, Plus, ChevronRight, ChevronDown, History, Share2, Trash2, Shield, MoreVertical, X, Download, AlertCircle, UserCircle2, LayoutGrid } from "lucide-react"; // ---------- mock data ---------- let uid = 1000; const nid = () => `id_${uid++}`; const ROLES = ["admin", "editor", "viewer"]; const STATUS_META = { draft: { label: "Draft", color: "#8A8F98", bg: "#8A8F98" }, pending: { label: "Pending approval", color: "#B98900", bg: "#B98900" }, approved: { label: "Approved", color: "#1A8754", bg: "#1A8754" }, rejected: { label: "Rejected", color: "#C93A3A", bg: "#C93A3A" }, signed: { label: "Signed", color: "#2F5FCC", bg: "#2F5FCC" }, }; const initialFolders = [ { id: "f_hr", name: "HR" }, { id: "f_fin", name: "Finance" }, { id: "f_legal", name: "Legal" }, { id: "f_ops", name: "Operations" }, ]; const initialDocs = [ { id: nid(), name: "Employee Handbook 2026.pdf", folderId: "f_hr", version: 3, status: "approved", owner: "Riya Sharma", modified: "2026-07-08", size: "1.2 MB", history: [{ v: 1, date: "2026-05-01", user: "Riya Sharma", note: "Initial draft" }, { v: 2, date: "2026-06-10", user: "Riya Sharma", note: "Added leave policy" }, { v: 3, date: "2026-07-08", user: "Riya Sharma", note: "Legal review changes" }], approvals: [{ by: "Admin", status: "approved", date: "2026-07-08", comment: "Looks good." }], signers: [] }, { id: nid(), name: "Q2 Budget Report.xlsx", folderId: "f_fin", version: 1, status: "pending", owner: "Karan Mehta", modified: "2026-07-10", size: "480 KB", history: [{ v: 1, date: "2026-07-10", user: "Karan Mehta", note: "Initial submission" }], approvals: [], signers: [] }, { id: nid(), name: "Vendor NDA - Acme Corp.pdf", folderId: "f_legal", version: 2, status: "signed", owner: "Legal Team", modified: "2026-07-05", size: "220 KB", history: [{ v: 1, date: "2026-06-20", user: "Legal Team", note: "Draft" }, { v: 2, date: "2026-07-05", user: "Legal Team", note: "Signed copy" }], approvals: [{ by: "Admin", status: "approved", date: "2026-07-04", comment: "" }], signers: [{ name: "Amit Verma", date: "2026-07-05" }] }, { id: nid(), name: "Warehouse SOP Draft.docx", folderId: "f_ops", version: 1, status: "draft", owner: "Sana Iqbal", modified: "2026-07-11", size: "310 KB", history: [{ v: 1, date: "2026-07-11", user: "Sana Iqbal", note: "First draft" }], approvals: [], signers: [] }, { id: nid(), name: "Reimbursement Policy.pdf", folderId: "f_fin", version: 4, status: "rejected", owner: "Karan Mehta", modified: "2026-07-09", size: "150 KB", history: [{ v: 4, date: "2026-07-09", user: "Karan Mehta", note: "Revised limits" }], approvals: [{ by: "Admin", status: "rejected", date: "2026-07-09", comment: "Limits need finance sign-off first." }], signers: [] }, ]; const initialUsers = [ { id: nid(), name: "You", email: "you@company.com", role: "admin" }, { id: nid(), name: "Riya Sharma", email: "riya@company.com", role: "editor" }, { id: nid(), name: "Karan Mehta", email: "karan@company.com", role: "editor" }, { id: nid(), name: "Sana Iqbal", email: "sana@company.com", role: "viewer" }, ]; const NAV = [ { id: "dashboard", label: "Dashboard", icon: LayoutDashboard }, { id: "documents", label: "Documents", icon: FolderOpen }, { id: "approvals", label: "Approvals", icon: CheckCircle2 }, { id: "signatures", label: "Shared & e-sign", icon: PenTool }, { id: "users", label: "Users & roles", icon: Users }, ]; export default function EDMS() { const [role, setRole] = useState("admin"); const [folders, setFolders] = useState(initialFolders); const [docs, setDocs] = useState(initialDocs); const [users, setUsers] = useState(initialUsers); const [activeNav, setActiveNav] = useState("documents"); const [activeFolder, setActiveFolder] = useState("all"); const [search, setSearch] = useState(""); const [selectedDoc, setSelectedDoc] = useState(null); const [showAddFolder, setShowAddFolder] = useState(false); const [newFolderName, setNewFolderName] = useState(""); const [dragOver, setDragOver] = useState(false); const [signName, setSignName] = useState(""); const [rejectComment, setRejectComment] = useState(""); const canEdit = role === "admin" || role === "editor"; const canApprove = role === "admin"; const filteredDocs = useMemo(() => { return docs.filter(d => { const inFolder = activeFolder === "all" || d.folderId === activeFolder; const matches = d.name.toLowerCase().includes(search.toLowerCase()) || d.owner.toLowerCase().includes(search.toLowerCase()); return inFolder && matches; }); }, [docs, activeFolder, search]); const pendingApprovals = docs.filter(d => d.status === "pending"); const sharedForSign = docs.filter(d => d.status === "signed" || d.status === "approved"); const addFolder = () => { const name = newFolderName.trim() || "Untitled folder"; setFolders(f => [...f, { id: `f_${nid()}`, name }]); setNewFolderName(""); setShowAddFolder(false); }; const handleDrop = (e) => { e.preventDefault(); setDragOver(false); if (!canEdit) return; const files = Array.from(e.dataTransfer.files || []); const targetFolder = activeFolder === "all" ? (folders[0]?.id || "f_hr") : activeFolder; const newDocs = files.length ? files.map(f => makeDoc(f.name, targetFolder)) : [makeDoc(`New Document ${docs.length + 1}.pdf`, targetFolder)]; setDocs(d => [...newDocs, ...d]); }; const makeDoc = (name, folderId) => ({ id: nid(), name, folderId, version: 1, status: "draft", owner: "You", modified: new Date().toISOString().slice(0, 10), size: "—", history: [{ v: 1, date: new Date().toISOString().slice(0, 10), user: "You", note: "Uploaded" }], approvals: [], signers: [], }); const updateDoc = (id, patch) => setDocs(prev => prev.map(d => (d.id === id ? { ...d, ...patch } : d))); const submitForApproval = (doc) => updateDoc(doc.id, { status: "pending" }); const decide = (doc, decision, comment) => { updateDoc(doc.id, { status: decision, approvals: [...doc.approvals, { by: "Admin", status: decision, date: new Date().toISOString().slice(0, 10), comment }], }); setRejectComment(""); setSelectedDoc(prev => prev ? { ...prev, status: decision } : prev); }; const newVersion = (doc) => { const v = doc.version + 1; updateDoc(doc.id, { version: v, status: "draft", history: [...doc.history, { v, date: new Date().toISOString().slice(0, 10), user: "You", note: "New version uploaded" }], modified: new Date().toISOString().slice(0, 10), }); }; const signDoc = (doc) => { if (!signName.trim()) return; updateDoc(doc.id, { status: "signed", signers: [...doc.signers, { name: signName.trim(), date: new Date().toISOString().slice(0, 10) }], }); setSignName(""); setSelectedDoc(prev => prev ? { ...prev, status: "signed" } : prev); }; const changeUserRole = (id, newRole) => setUsers(prev => prev.map(u => (u.id === id ? { ...u, role: newRole } : u))); return (
{/* SIDEBAR */} {/* MAIN */}
{activeNav === "dashboard" && } {activeNav === "documents" && ( )} {activeNav === "approvals" && ( )} {activeNav === "signatures" && ( )} {activeNav === "users" && ( )}
{/* DOCUMENT DETAIL DRAWER */} {selectedDoc && ( d.id === selectedDoc.id) || selectedDoc} folders={folders} canEdit={canEdit} canApprove={canApprove} onClose={() => setSelectedDoc(null)} submitForApproval={submitForApproval} decide={decide} newVersion={newVersion} signDoc={signDoc} signName={signName} setSignName={setSignName} rejectComment={rejectComment} setRejectComment={setRejectComment} /> )} {/* ADD FOLDER MODAL */} {showAddFolder && (
setShowAddFolder(false)}>
e.stopPropagation()}>

New folder

setNewFolderName(e.target.value)} onKeyDown={e => e.key === "Enter" && addFolder()} placeholder="Folder name" className="w-full border border-[#D8DAE0] rounded-lg px-3 py-2 text-[12.5px] outline-none focus:border-[#1E3A8A] mb-4" />
)}
); } // ---------- status pill ---------- function StatusPill({ status }) { const m = STATUS_META[status]; return ( {m.label} ); } // ---------- dashboard ---------- function Dashboard({ docs, folders, pendingApprovals }) { const stats = [ { label: "Total documents", value: docs.length, icon: FileText }, { label: "Pending approvals", value: pendingApprovals.length, icon: Clock }, { label: "Signed", value: docs.filter(d => d.status === "signed").length, icon: PenTool }, { label: "Folders", value: folders.length, icon: Folder }, ]; return (

Dashboard

{stats.map(s => { const Icon = s.icon; return (
{s.value}
{s.label}
); })}

Recent activity

{docs.slice(0, 5).map(d => (
{d.name}
{d.modified}
))}
); } // ---------- documents view ---------- function DocumentsView({ docs, folders, activeFolder, search, setSearch, dragOver, setDragOver, handleDrop, canEdit, onSelect }) { const folderName = activeFolder === "all" ? "All documents" : folders.find(f => f.id === activeFolder)?.name; return ( <>

{folderName}

{docs.length} documents

setSearch(e.target.value)} placeholder="Search documents..." className="bg-transparent outline-none text-[12px] flex-1" />
{canEdit && (
{ e.preventDefault(); setDragOver(true); }} onDragLeave={() => setDragOver(false)} onDrop={handleDrop} className={`mb-5 border-2 border-dashed rounded-xl py-6 flex flex-col items-center justify-center gap-1.5 transition-colors ${ dragOver ? "border-[#1E3A8A] bg-[#1E3A8A]/5" : "border-[#D8DAE0] bg-white" }`} > Drag & drop files here, or drop anywhere to add a sample document
)}
Name
Owner
Version
Modified
Status
{docs.length === 0 && (
No documents match here yet.
)} {docs.map(d => ( ))}
); } // ---------- approvals view ---------- function ApprovalsView({ pending, canApprove, onSelect, decide }) { return ( <>

Approvals

{pending.length} documents waiting for a decision

{pending.length === 0 && (
Nothing pending approval right now.
)} {pending.map(d => (
{canApprove ? (
) : ( Needs admin )}
))}
); } // ---------- signatures view ---------- function SignaturesView({ docs, onSelect }) { return ( <>

Shared & e-sign

Approved documents ready to share or sign

{docs.map(d => ( ))}
); } // ---------- users view ---------- function UsersView({ users, role, changeUserRole }) { return ( <>

Users & roles

{users.length} people have access

Name
Email
Role
{users.map(u => (
{u.name}
{u.email}
{role === "admin" ? ( ) : ( {u.role} )}
))}
); } // ---------- document drawer ---------- function DocDrawer({ doc, folders, canEdit, canApprove, onClose, submitForApproval, decide, newVersion, signDoc, signName, setSignName, rejectComment, setRejectComment }) { const folder = folders.find(f => f.id === doc.folderId); return (
Document details

{doc.name}

v{doc.version} · {folder?.name}
Owner
{doc.owner}
Modified
{doc.modified}
Size
{doc.size}
Folder
{folder?.name}
{/* actions */}
{canEdit && doc.status === "draft" && ( )} {canEdit && ( )}
{/* approval action */} {canApprove && doc.status === "pending" && (
Approval decision
setRejectComment(e.target.value)} placeholder="Optional comment" className="w-full border border-[#D8DAE0] rounded-lg px-2.5 py-1.5 text-[11.5px] outline-none" />
)} {/* e-sign */} {(doc.status === "approved" || doc.status === "signed") && (
E-signature
{doc.signers.length > 0 && (
{doc.signers.map((s, i) => (
✓ Signed by {s.name} on {s.date}
))}
)}
setSignName(e.target.value)} placeholder="Type full name to sign" className="flex-1 border border-[#D8DAE0] rounded-lg px-2.5 py-1.5 text-[11.5px] outline-none" />
)} {/* version history */}
Version history
{[...doc.history].reverse().map((h, i) => (
v{h.v}
{h.note}
{h.user} · {h.date}
))}
{/* approval history */} {doc.approvals.length > 0 && (
Approval log
{doc.approvals.map((a, i) => (
{a.status === "approved" ? : } {a.by} {a.date}
{a.comment &&
"{a.comment}"
}
))}
)}
); }