Files
Atomizer/atomizer-dashboard/frontend/src/pages/CanvasView.tsx
Anto01 5bd142780f feat(canvas): Add Phase 3+4 - Bidirectional sync, templates, and visual polish
Phase 3 - Bidirectional Sync:
- Add loadFromIntent and loadFromConfig to canvas store
- Create useIntentParser hook for parsing Claude messages
- Create ConfigImporter component (file upload, paste JSON, load study)
- Add import/clear buttons to CanvasView header

Phase 4 - Templates & Polish:
- Create template library with 5 presets:
  - Mass Minimization (single-objective)
  - Multi-Objective Pareto (NSGA-II)
  - Turbo Mode (with MLP surrogate)
  - Mirror Zernike (optical optimization)
  - Frequency Optimization (modal)
- Create TemplateSelector component with category filters
- Enhanced BaseNode with animations, glow effects, status indicators
- Add colorBg to all node types for visual distinction
- Add notification toast system
- Update all exports

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 20:30:28 -05:00

114 lines
3.6 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useState } from 'react';
import { AtomizerCanvas } from '../components/canvas/AtomizerCanvas';
import { TemplateSelector } from '../components/canvas/panels/TemplateSelector';
import { ConfigImporter } from '../components/canvas/panels/ConfigImporter';
import { useCanvasStore } from '../hooks/useCanvasStore';
import { CanvasTemplate } from '../lib/canvas/templates';
export function CanvasView() {
const [showTemplates, setShowTemplates] = useState(false);
const [showImporter, setShowImporter] = useState(false);
const [notification, setNotification] = useState<string | null>(null);
const { nodes, clear } = useCanvasStore();
const handleTemplateSelect = (template: CanvasTemplate) => {
showNotification(`Loaded template: ${template.name}`);
};
const handleImport = (source: string) => {
showNotification(`Imported from ${source}`);
};
const handleClear = () => {
if (nodes.length === 0 || window.confirm('Clear all nodes from the canvas?')) {
clear();
showNotification('Canvas cleared');
}
};
const showNotification = (message: string) => {
setNotification(message);
setTimeout(() => setNotification(null), 3000);
};
return (
<div className="h-screen flex flex-col">
{/* Header with actions */}
<header className="bg-white border-b border-gray-200 px-6 py-3 flex items-center justify-between">
<div>
<h1 className="text-xl font-bold text-gray-800">
Optimization Canvas
</h1>
<p className="text-sm text-gray-500">
Drag components from the palette to build your optimization workflow
</p>
</div>
{/* Action Buttons */}
<div className="flex items-center gap-2">
<button
onClick={() => setShowTemplates(true)}
className="px-4 py-2 bg-gradient-to-r from-blue-500 to-purple-500 text-white rounded-lg hover:from-blue-600 hover:to-purple-600 transition-all shadow-sm flex items-center gap-2"
>
<span>📋</span>
Templates
</button>
<button
onClick={() => setShowImporter(true)}
className="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg hover:bg-gray-200 transition-colors flex items-center gap-2"
>
<span>📥</span>
Import
</button>
<button
onClick={handleClear}
className="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg hover:bg-gray-200 transition-colors flex items-center gap-2"
>
<span>🗑</span>
Clear
</button>
</div>
</header>
{/* Main Canvas */}
<main className="flex-1 overflow-hidden">
<AtomizerCanvas />
</main>
{/* Template Selector Modal */}
<TemplateSelector
isOpen={showTemplates}
onClose={() => setShowTemplates(false)}
onSelect={handleTemplateSelect}
/>
{/* Config Importer Modal */}
<ConfigImporter
isOpen={showImporter}
onClose={() => setShowImporter(false)}
onImport={handleImport}
/>
{/* Notification Toast */}
{notification && (
<div
className="fixed bottom-4 left-1/2 transform -translate-x-1/2 px-4 py-2 bg-gray-800 text-white rounded-lg shadow-lg z-50"
style={{ animation: 'slideUp 0.3s ease-out' }}
>
{notification}
</div>
)}
<style>{`
@keyframes slideUp {
from { opacity: 0; transform: translate(-50%, 20px); }
to { opacity: 1; transform: translate(-50%, 0); }
}
`}</style>
</div>
);
}
export default CanvasView;