fazeel007's picture
initial commit
7c012de
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>
);
}