Files
pdf/frontend/src/components/Sidebar.tsx
T

152 lines
5.4 KiB
TypeScript
Raw Normal View History

2026-05-20 15:39:50 +05:30
import React from 'react';
import type { DocumentInfo } from '../lib/gatewayService';
import type { Annotation } from '../viewer/AnnotationLayer';
interface SidebarProps {
documents: DocumentInfo[];
selectedDocumentId: string;
onSelectDocument: (id: string) => void;
annotations: Annotation[];
totalPages: number;
activeTab: 'documents' | 'annotations' | 'outline';
setActiveTab: (tab: 'documents' | 'annotations' | 'outline') => void;
}
export const Sidebar: React.FC<SidebarProps> = ({
documents,
selectedDocumentId,
onSelectDocument,
annotations,
totalPages,
activeTab,
setActiveTab,
}) => {
const formatBytes = (bytes: number) => {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
};
return (
<div className="sidebar">
{/* Sidebar Tabs */}
<div className="sidebar-tabs">
<button
onClick={() => setActiveTab('documents')}
className={`tab-btn ${activeTab === 'documents' ? 'active' : ''}`}
>
Files
</button>
<button
onClick={() => setActiveTab('outline')}
className={`tab-btn ${activeTab === 'outline' ? 'active' : ''}`}
>
Thumbnails
</button>
<button
onClick={() => setActiveTab('annotations')}
className={`tab-btn ${activeTab === 'annotations' ? 'active' : ''} relative-tab`}
>
Notes
{annotations.length > 0 && (
<span className="badge-notification">
{annotations.length}
</span>
)}
</button>
</div>
{/* Tab Contents */}
<div className="sidebar-content">
{/* DOCUMENTS TAB */}
{activeTab === 'documents' && (
<div className="doc-list-container">
<span className="tab-section-header">
Active Documents
</span>
{documents.map((doc) => {
const isSelected = doc.id === selectedDocumentId;
return (
<div
key={doc.id}
onClick={() => onSelectDocument(doc.id)}
className={`doc-card ${isSelected ? 'active' : ''}`}
>
<div className="doc-card-body">
<div className={`doc-icon-container ${isSelected ? 'active' : ''}`}>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
<path strokeLinecap="round" strokeLinejoin="round" d="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" />
</svg>
</div>
<div className="doc-details">
<p className="doc-filename">
{doc.filename}
</p>
<div className="doc-metadata">
<span>{formatBytes(doc.sizeBytes)}</span>
<span></span>
<span>{doc.totalPages} Pages</span>
</div>
</div>
</div>
</div>
);
})}
</div>
)}
{/* THUMBNAILS TAB */}
{activeTab === 'outline' && (
<div className="thumbnails-grid">
{Array.from({ length: totalPages }).map((_, idx) => (
<div key={idx} className="thumbnail-card">
<div className="thumbnail-preview">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" className="thumbnail-svg-icon" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
<path strokeLinecap="round" strokeLinejoin="round" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" />
</svg>
<span className="thumbnail-label">Page {idx + 1}</span>
</div>
</div>
))}
</div>
)}
{/* ANNOTATIONS TAB */}
{activeTab === 'annotations' && (
<div className="annotations-list">
<span className="tab-section-header">
Active Highlights
</span>
{annotations.length === 0 ? (
<div className="empty-state">
No active highlights yet. Select 'Highlight' tool and drag/select text on pages.
</div>
) : (
annotations.map((anno) => (
<div key={anno.id} className="annotation-card">
<div className="annotation-header">
<span className="annotation-type-badge">
{anno.type}
</span>
<span className="annotation-author">
{anno.author}
</span>
</div>
<p className="annotation-content">
"{anno.content}"
</p>
</div>
))
)}
</div>
)}
</div>
</div>
);
};