feat: window management system with minimize, fullscreen, and AI chat split

- Window manager store (Zustand) for managing open/minimized/fullscreen windows
- Window component with header controls: KI-Chat toggle, fullscreen, minimize, close
- AI chat panel with streaming chat via existing /ai/sessions API
- WindowContainer renders all non-minimized windows
- TopBar shows minimized windows as clickable pills
- ContactEditForm extracted from ContactEditModal for window rendering
- ContactsList and ContactDetailPage use openWindow() instead of modal state
- Draggable windows with z-index management
This commit is contained in:
Agent Zero
2026-07-24 23:42:53 +02:00
parent c1d49e4dfe
commit 35e87b5d51
9 changed files with 936 additions and 39 deletions
+13 -16
View File
@@ -6,7 +6,8 @@ import React from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { ContactDetail } from '@/components/contacts/ContactDetail';
import { ContactEditModal } from '@/components/contacts/ContactEditModal';
import { ContactEditForm } from '@/components/contacts/ContactEditForm';
import { useWindowStore } from '@/store/windowStore';
import { useUnifiedContact, type UnifiedContact } from '@/api/hooks';
import { Button } from '@/components/ui/Button';
import { ChevronLeft } from 'lucide-react';
@@ -16,13 +17,20 @@ export function ContactDetailPage() {
const { id } = useParams<{ id: string }>();
const navigate = useNavigate();
const { data: contact, isLoading } = useUnifiedContact(id);
const [editModalOpen, setEditModalOpen] = React.useState(false);
const [editingContact, setEditingContact] = React.useState<UnifiedContact | null>(null);
const openWindow = useWindowStore((s) => s.openWindow);
const handleEdit = () => {
if (contact) {
setEditingContact(contact);
setEditModalOpen(true);
openWindow({
title: t('contacts.edit'),
type: 'contact-edit',
component: ContactEditForm,
componentProps: {
contact,
onClose: () => {},
onSaved: () => {},
},
});
}
};
@@ -30,11 +38,6 @@ export function ContactDetailPage() {
navigate('/contacts');
};
const handleSaved = () => {
setEditModalOpen(false);
setEditingContact(null);
};
return (
<div className="flex flex-col h-full" data-testid="contact-detail-page">
<div className="flex items-center gap-2 px-4 py-2 border-b border-secondary-200 bg-white">
@@ -55,12 +58,6 @@ export function ContactDetailPage() {
onDeleted={handleDeleted}
/>
</div>
<ContactEditModal
open={editModalOpen}
onClose={() => setEditModalOpen(false)}
contact={editingContact}
onSaved={handleSaved}
/>
</div>
);
}