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 (
{docs.length} documents
{pending.length} documents waiting for a decision
Approved documents ready to share or sign
{users.length} people have access