| import React, { useState } from 'react';
|
| import {
|
| Headphones, Video, Network, FileText, Component,
|
| HelpCircle, Package, Columns, Projector, Activity,
|
| Loader2, X, BookOpen
|
| } from 'lucide-react';
|
| import { generateSourceContent } from '../api';
|
|
|
|
|
| const TOOLS = [
|
| { id: 'audio', label: 'Audio Overview', icon: Headphones, color: 'text-purple-600', bg: 'bg-purple-50' },
|
| { id: 'video', label: 'Video Overview', icon: Video, color: 'text-red-600', bg: 'bg-red-50' },
|
| { id: 'mind_map', label: 'Mind Map', icon: Network, color: 'text-blue-600', bg: 'bg-blue-50' },
|
| { id: 'reports', label: 'Reports', icon: FileText, color: 'text-emerald-600', bg: 'bg-emerald-50' },
|
| { id: 'flashcards', label: 'Flashcards', icon: Component, color: 'text-amber-600', bg: 'bg-amber-50' },
|
| { id: 'quiz', label: 'Quiz', icon: HelpCircle, color: 'text-cyan-600', bg: 'bg-cyan-50' },
|
| { id: 'artifact', label: 'Create Artifact', icon: Package, color: 'text-indigo-600', bg: 'bg-indigo-50' },
|
| { id: 'infographic', label: 'Infographic', icon: Columns, color: 'text-pink-600', bg: 'bg-pink-50' },
|
| { id: 'slides', label: 'Slide Deck', icon: Projector, color: 'text-orange-600', bg: 'bg-orange-50' },
|
| { id: 'data_table', label: 'Data Table', icon: Activity, color: 'text-teal-600', bg: 'bg-teal-50' },
|
| ];
|
|
|
| const SourceGuide = ({ onGenerate, activeCitation, onCloseCitation, notebookId }) => {
|
| const [generating, setGenerating] = useState(null);
|
|
|
| const handleToolClick = async (toolId) => {
|
| if (generating) return;
|
| setGenerating(toolId);
|
| try {
|
| const result = await generateSourceContent(toolId, notebookId);
|
|
|
| onGenerate(toolId, result.answer);
|
| } catch (error) {
|
| console.error(error);
|
| alert("Failed to generate content: " + (error.response?.data?.detail || error.message));
|
| } finally {
|
| setGenerating(null);
|
| }
|
| };
|
|
|
|
|
| if (activeCitation) {
|
| return (
|
| <div className="h-full border-l border-slate-200 bg-white flex flex-col">
|
| <div className="p-4 border-b border-slate-100 flex items-center justify-between">
|
| <h3 className="font-semibold text-slate-700 flex items-center gap-2">
|
| <BookOpen size={16} /> Source Guide
|
| </h3>
|
| <button onClick={onCloseCitation} className="p-1 hover:bg-slate-100 rounded-full text-slate-400">
|
| <X size={16} />
|
| </button>
|
| </div>
|
| <div className="p-4 flex-1 overflow-y-auto">
|
| <div className="bg-blue-50 border border-blue-100 p-4 rounded-xl mb-4">
|
| <span className="text-xs font-bold text-blue-600 uppercase">Selected Source</span>
|
| <h4 className="font-medium text-slate-900 mt-1">{activeCitation.paper_id}</h4>
|
| </div>
|
| <p className="p-4 bg-slate-50 rounded-lg text-slate-700 italic border-l-4 border-slate-300">
|
| "{activeCitation.text_snippet}"
|
| </p>
|
| <div className="mt-4 text-center">
|
| <button onClick={onCloseCitation} className="text-sm text-blue-600 hover:underline">
|
| Back to Tools
|
| </button>
|
| </div>
|
| </div>
|
| </div>
|
| );
|
| }
|
|
|
| return (
|
| <div className="h-full border-l border-slate-200 bg-white flex flex-col">
|
| <div className="p-6 border-b border-slate-100">
|
| <h2 className="text-lg font-bold text-slate-800">Source Guide</h2>
|
| <p className="text-sm text-slate-500 mt-1">Transform your sources into...</p>
|
| </div>
|
|
|
| <div className="flex-1 overflow-y-auto p-4">
|
| <div className="grid grid-cols-2 gap-3">
|
| {TOOLS.map((tool) => {
|
| const Icon = tool.icon;
|
| const isProcessing = generating === tool.id;
|
| return (
|
| <button
|
| key={tool.id}
|
| onClick={() => handleToolClick(tool.id)}
|
| disabled={!!generating}
|
| className={`flex flex-col items-center justify-center gap-3 p-4 rounded-xl border border-slate-100 hover:border-slate-300 hover:shadow-md transition-all text-center bg-white group disabled:opacity-50 h-32 ${isProcessing ? 'bg-slate-50' : ''}`}
|
| >
|
| <div className={`w-12 h-12 rounded-full flex items-center justify-center ${tool.bg} ${tool.color} group-hover:scale-110 transition-transform`}>
|
| {isProcessing ? <Loader2 size={24} className="animate-spin" /> : <Icon size={24} />}
|
| </div>
|
| <div>
|
| <h3 className="font-semibold text-slate-700 text-sm">{tool.label}</h3>
|
| {isProcessing && <p className="text-[10px] text-slate-400 mt-0.5">Generating...</p>}
|
| </div>
|
| </button>
|
| );
|
| })}
|
| </div>
|
| </div>
|
| </div>
|
| );
|
| };
|
|
|
| export default SourceGuide;
|
|
|