|
import { Button } from "@/components/ui/button"; |
|
import { Badge } from "@/components/ui/badge"; |
|
import { X, Download, Trash2 } from "lucide-react"; |
|
import { type Citation } from "@shared/schema"; |
|
|
|
interface CitationPanelProps { |
|
citations: Citation[]; |
|
isVisible: boolean; |
|
onClose: () => void; |
|
onRemoveCitation: (citationId: number) => void; |
|
} |
|
|
|
export default function CitationPanel({ |
|
citations, |
|
isVisible, |
|
onClose, |
|
onRemoveCitation |
|
}: CitationPanelProps) { |
|
if (!isVisible) return null; |
|
|
|
const handleExportCitations = () => { |
|
const citationText = citations |
|
.map((citation, index) => { |
|
return `[${index + 1}] ${citation.citationText}${citation.section ? ` (${citation.section})` : ''}${citation.pageNumber ? ` - Page ${citation.pageNumber}` : ''}`; |
|
}) |
|
.join('\n\n'); |
|
|
|
const blob = new Blob([citationText], { type: 'text/plain' }); |
|
const url = URL.createObjectURL(blob); |
|
const a = document.createElement('a'); |
|
a.href = url; |
|
a.download = 'citations.txt'; |
|
document.body.appendChild(a); |
|
a.click(); |
|
document.body.removeChild(a); |
|
URL.revokeObjectURL(url); |
|
}; |
|
|
|
return ( |
|
<div className="fixed bottom-6 right-6 z-50"> |
|
<div className="bg-white rounded-xl shadow-lg border border-slate-200 w-80 max-h-96 flex flex-col"> |
|
{/* Header */} |
|
<div className="flex items-center justify-between p-4 border-b border-slate-200"> |
|
<div className="flex items-center gap-2"> |
|
<h4 className="font-medium text-slate-900">Active Citations</h4> |
|
<Badge variant="secondary" className="text-xs"> |
|
{citations.length} |
|
</Badge> |
|
</div> |
|
<Button |
|
variant="ghost" |
|
size="sm" |
|
onClick={onClose} |
|
className="text-slate-400 hover:text-slate-600 p-1" |
|
> |
|
<X className="w-4 h-4" /> |
|
</Button> |
|
</div> |
|
|
|
{/* Citations List */} |
|
<div className="flex-1 overflow-y-auto p-4"> |
|
{citations.length === 0 ? ( |
|
<div className="text-center py-8"> |
|
<div className="text-slate-400 mb-2"> |
|
<svg className="w-8 h-8 mx-auto" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1} d="M9 12h6m-6-4h6m2 5.291A7.962 7.962 0 0112 15c-2.34 0-4.447-.935-6-2.45" /> |
|
</svg> |
|
</div> |
|
<p className="text-sm text-slate-500">No citations added yet</p> |
|
<p className="text-xs text-slate-400 mt-1"> |
|
Click "Add Citation" on search results to build your reference list |
|
</p> |
|
</div> |
|
) : ( |
|
<div className="space-y-3"> |
|
{citations.map((citation, index) => ( |
|
<div |
|
key={citation.id} |
|
className="group flex items-start gap-3 p-3 bg-slate-50 rounded-lg hover:bg-slate-100 transition-colors" |
|
> |
|
<span className="w-6 h-6 bg-blue-600 text-white rounded-full flex items-center justify-center text-xs font-medium flex-shrink-0 mt-0.5"> |
|
{index + 1} |
|
</span> |
|
<div className="flex-1 min-w-0"> |
|
<p className="text-sm text-slate-700 leading-relaxed line-clamp-3"> |
|
{citation.citationText} |
|
</p> |
|
{(citation.section || citation.pageNumber) && ( |
|
<div className="flex items-center gap-2 mt-2"> |
|
{citation.section && ( |
|
<span className="text-xs text-slate-500 bg-white px-2 py-1 rounded"> |
|
{citation.section} |
|
</span> |
|
)} |
|
{citation.pageNumber && ( |
|
<span className="text-xs text-slate-500 bg-white px-2 py-1 rounded"> |
|
Page {citation.pageNumber} |
|
</span> |
|
)} |
|
</div> |
|
)} |
|
</div> |
|
<Button |
|
variant="ghost" |
|
size="sm" |
|
onClick={() => onRemoveCitation(citation.id)} |
|
className="opacity-0 group-hover:opacity-100 transition-opacity text-slate-400 hover:text-red-600 p-1" |
|
> |
|
<Trash2 className="w-3 h-3" /> |
|
</Button> |
|
</div> |
|
))} |
|
</div> |
|
)} |
|
</div> |
|
|
|
{/* Footer */} |
|
{citations.length > 0 && ( |
|
<div className="p-4 border-t border-slate-200"> |
|
<Button |
|
onClick={handleExportCitations} |
|
className="w-full bg-slate-100 text-slate-700 hover:bg-slate-200" |
|
size="sm" |
|
> |
|
<Download className="w-4 h-4 mr-2" /> |
|
Export Citations |
|
</Button> |
|
</div> |
|
)} |
|
</div> |
|
</div> |
|
); |
|
} |
|
|