Plandex / components /NotesPanel.tsx
AUXteam's picture
Fresh deployment: clean and replace all files
b33923b verified
Raw
History Blame
5.9 kB
import React, { useState } from 'react';
import { Plus, Sparkles, MoreVertical, Trash2, Edit2, Check } from 'lucide-react';
import { Note } from '../types';
interface NotesPanelProps {
notes: Note[];
onAddNote: () => void;
onUpdateNote: (note: Note) => void;
onDeleteNote: (id: string) => void;
onUseTemplate: (note: Note) => void;
onGenerateSummary: (note: Note) => void;
}
export const NotesPanel: React.FC<NotesPanelProps> = ({
notes,
onAddNote,
onUpdateNote,
onDeleteNote,
onUseTemplate,
onGenerateSummary
}) => {
const [editingId, setEditingId] = useState<string | null>(null);
return (
<div className="flex flex-col h-full bg-gray-50 border-r border-gray-200">
<div className="p-4 border-b border-gray-200 bg-white flex justify-between items-center sticky top-0 z-10">
<h2 className="font-semibold text-gray-800 text-lg">Message Templates</h2>
<button
onClick={onAddNote}
className="p-2 bg-yellow-400 hover:bg-yellow-500 text-yellow-900 rounded-full shadow-sm transition-all"
title="New Template"
>
<Plus className="w-5 h-5" />
</button>
</div>
<div className="flex-1 overflow-y-auto p-4 space-y-4">
{notes.map((note) => (
<div
key={note.id}
className={`group relative bg-white rounded-xl shadow-sm border border-gray-200 hover:shadow-md transition-all duration-200 ${
editingId === note.id ? 'ring-2 ring-indigo-500 border-transparent' : ''
}`}
>
<div className="p-4">
{editingId === note.id ? (
<div className="space-y-2">
<input
type="text"
value={note.title}
onChange={(e) => onUpdateNote({ ...note, title: e.target.value })}
className="w-full font-bold text-gray-800 bg-transparent outline-none placeholder-gray-400"
placeholder="Title"
autoFocus
/>
<textarea
value={note.content}
onChange={(e) => onUpdateNote({ ...note, content: e.target.value })}
className="w-full text-sm text-gray-600 bg-transparent outline-none resize-none h-24 placeholder-gray-400"
placeholder="Type your message template..."
/>
<div className="flex justify-end gap-2 pt-2">
<button
onClick={() => setEditingId(null)}
className="p-1.5 text-green-600 hover:bg-green-50 rounded-full"
title="Done Editing"
>
<Check className="w-4 h-4" />
</button>
</div>
</div>
) : (
<>
<h3 className="font-bold text-gray-800 mb-2 truncate">{note.title || 'Untitled'}</h3>
<p className="text-sm text-gray-600 line-clamp-3 mb-3 whitespace-pre-wrap">
{note.content || 'Empty note'}
</p>
{/* AI Summary Section */}
{note.summary ? (
<div className="bg-indigo-50 rounded-lg p-2 mb-3">
<div className="flex items-center gap-1.5 text-xs font-semibold text-indigo-700 mb-1">
<Sparkles className="w-3 h-3" />
<span>AI Summary</span>
</div>
<div className="text-xs text-indigo-600 whitespace-pre-wrap leading-relaxed">
{note.summary}
</div>
</div>
) : (
<button
onClick={(e) => {
e.stopPropagation();
onGenerateSummary(note);
}}
className="text-xs flex items-center gap-1 text-gray-400 hover:text-indigo-600 transition-colors mb-3"
>
<Sparkles className="w-3 h-3" />
Generate Summary
</button>
)}
<div className="flex items-center justify-between mt-2 pt-2 border-t border-gray-100 opacity-0 group-hover:opacity-100 transition-opacity">
<div className="flex gap-1">
<button
onClick={(e) => {
e.stopPropagation();
setEditingId(note.id);
}}
className="p-1.5 text-gray-400 hover:text-indigo-600 hover:bg-gray-100 rounded-lg"
title="Edit"
>
<Edit2 className="w-4 h-4" />
</button>
<button
onClick={(e) => {
e.stopPropagation();
onDeleteNote(note.id);
}}
className="p-1.5 text-gray-400 hover:text-red-600 hover:bg-gray-100 rounded-lg"
title="Delete"
>
<Trash2 className="w-4 h-4" />
</button>
</div>
<button
onClick={() => onUseTemplate(note)}
className="text-xs font-medium bg-gray-900 text-white px-3 py-1.5 rounded-lg hover:bg-black transition-colors"
>
Use Template
</button>
</div>
</>
)}
</div>
</div>
))}
</div>
</div>
);
};