+ {/* Header */}
Conversations
+
+
+ +
+
+
+ {loading ? '...' : '\u21BB'}
+
+
+
+
+ {/* View mode toggle */}
+
setViewMode('active')}
+ style={{
+ flex: 1, padding: '5px 0', fontSize: 11, fontWeight: 600, border: 'none', cursor: 'pointer',
+ background: viewMode === 'active' ? 'var(--primary-color, #1976d2)' : 'transparent',
+ color: viewMode === 'active' ? '#fff' : '#888',
+ transition: 'background 0.15s, color 0.15s',
+ }}
>
- {loading ? '...' : '\u21BB'}
+ Aktiv {_activeCount > 0 && ({_activeCount}) }
+
+ setViewMode('archived')}
+ style={{
+ flex: 1, padding: '5px 0', fontSize: 11, fontWeight: 600, border: 'none', cursor: 'pointer',
+ borderLeft: '1px solid #ddd',
+ background: viewMode === 'archived' ? '#ff9800' : 'transparent',
+ color: viewMode === 'archived' ? '#fff' : '#888',
+ transition: 'background 0.15s, color 0.15s',
+ }}
+ >
+ Archiv {_archivedCount > 0 && ({_archivedCount}) }
- {conversations.length > 0 && (
+ {/* Filter */}
+ {filtered.length > 3 && (
= ({
/>
)}
- {conversations.length === 0 && !loading && (
+ {/* Empty state */}
+ {filtered.length === 0 && !loading && (
- No conversations yet. Send a message to start.
+ {viewMode === 'archived'
+ ? 'Keine archivierten Chats.'
+ : 'Noch keine Chats. Sende eine Nachricht oder klicke "+".'}
)}
- {_filtered(conversations, filterQuery).map(conv => {
+ {/* List */}
+ {paginated.map(conv => {
const isActive = conv.id === activeWorkflowId;
const isEditing = editingId === conv.id;
return (
@@ -171,12 +265,18 @@ export const ConversationList: React.FC
= ({
background: isActive ? 'var(--primary-light, #e3f2fd)' : 'transparent',
border: isActive ? '1px solid var(--primary-color, #1976d2)20' : '1px solid transparent',
transition: 'background 0.15s',
+ position: 'relative',
}}
onMouseEnter={e => {
if (!isActive) e.currentTarget.style.background = '#f5f5f5';
+ const actions = e.currentTarget.querySelector('[data-actions]') as HTMLElement;
+ if (actions) actions.style.opacity = '1';
}}
onMouseLeave={e => {
if (!isActive) e.currentTarget.style.background = 'transparent';
+ const actions = e.currentTarget.querySelector('[data-actions]') as HTMLElement;
+ if (actions) actions.style.opacity = '0';
+ if (confirmDeleteId === conv.id) setConfirmDeleteId(null);
}}
>
{/* Name row */}
@@ -208,23 +308,72 @@ export const ConversationList: React.FC = ({
minWidth: 0,
}}
onDoubleClick={(e) => { e.stopPropagation(); _startEditing(conv); }}
- title="Double-click to rename"
+ title={conv.name}
>
{conv.name}
)}
+
+ {/* Action buttons (visible on hover) */}
{!isEditing && (
- { e.stopPropagation(); _startEditing(conv); }}
- style={{
- background: 'none', border: 'none', cursor: 'pointer',
- fontSize: 10, color: '#999', padding: '0 2px', flexShrink: 0,
- opacity: 0.6,
- }}
- title="Rename"
+
- ✎
-
+ { e.stopPropagation(); _startEditing(conv); }}
+ style={_actionBtnStyle}
+ title="Umbenennen"
+ >
+ ✎
+
+ {conv.status === 'archived' ? (
+ { e.stopPropagation(); _handleReactivate(conv.id); }}
+ style={{ ..._actionBtnStyle, color: '#4caf50' }}
+ title="Reaktivieren"
+ >
+ ↩
+
+ ) : (
+ { e.stopPropagation(); _handleArchive(conv.id); }}
+ style={_actionBtnStyle}
+ title="Archivieren"
+ >
+ 📦
+
+ )}
+ {confirmDeleteId === conv.id ? (
+
+ { e.stopPropagation(); setConfirmDeleteId(null); _handleDelete(conv.id); }}
+ style={{ ..._actionBtnStyle, color: '#fff', fontSize: 13 }}
+ title="Ja, loeschen"
+ >
+ ✓
+
+ { e.stopPropagation(); setConfirmDeleteId(null); }}
+ style={{ ..._actionBtnStyle, color: '#fff', fontSize: 13 }}
+ title="Abbrechen"
+ >
+ ✗
+
+
+ ) : (
+ { e.stopPropagation(); setConfirmDeleteId(conv.id); }}
+ style={{ ..._actionBtnStyle, color: '#d32f2f' }}
+ title="Loeschen"
+ >
+ 🗑
+
+ )}
+
)}
@@ -232,12 +381,15 @@ export const ConversationList: React.FC = ({
{conv.status === 'active' && (
- {'\u25CF'} active
+ {'\u25CF'} aktiv
)}
{conv.status === 'completed' && (
- {'\u25CF'} completed
+ {'\u25CF'} abgeschlossen
)}
- {conv.status !== 'active' && conv.status !== 'completed' && (
+ {conv.status === 'archived' && (
+ {'\u25CF'} archiviert
+ )}
+ {!['active', 'completed', 'archived'].includes(conv.status) && (
{conv.status}
)}
@@ -251,6 +403,45 @@ export const ConversationList: React.FC = ({
);
})}
+
+ {/* Pagination */}
+ {totalPages > 1 && (
+
+ setPage(p => Math.max(0, p - 1))}
+ disabled={page === 0}
+ style={{ ..._pageBtnStyle, opacity: page === 0 ? 0.3 : 1 }}
+ >
+ <
+
+ {page + 1} / {totalPages}
+ setPage(p => Math.min(totalPages - 1, p + 1))}
+ disabled={page >= totalPages - 1}
+ style={{ ..._pageBtnStyle, opacity: page >= totalPages - 1 ? 0.3 : 1 }}
+ >
+ >
+
+
+ )}