AUDIT / src /components /CommandPillar.tsx
Arypulka98's picture
feat(audit): deploy full backend cluster node
aea470f verified
Raw
History Blame Contribute Delete
9.7 kB
/**
* CommandPillar.tsx — 4 Pillar Navigation System
* Sostituisce il menu laterale con 4 bottoni principali (Pillar) che espandono sottocategorie logiche.
*
* Pillar 1: 🔍 RICERCA & ANALISI
* - Web Search, News, Meteo, Analisi Dati
*
* Pillar 2: 💻 SVILUPPO & CODING
* - Code Review, Refactor, Debug, Test
*
* Pillar 3: 🤖 AUTOMAZIONE & TASK
* - Task Automation, Workflow, Scheduling, Integration
*
* Pillar 4: 🎨 CREATIVITÀ & CONTENUTI
* - Generazione Testo, Immagini, Audio, Brainstorming
*/
import React, { useState } from "react";
import { Search, Code2, Zap, Sparkles, ChevronDown, X } from "lucide-react";
export interface PillarCommand {
id: string;
label: string;
description?: string;
icon?: React.ReactNode;
shortcut?: string;
action: () => void;
}
export interface Pillar {
id: string;
name: string;
icon: React.ReactNode;
color: string;
commands: PillarCommand[];
}
interface CommandPillarProps {
onCommandSelect: (cmd: PillarCommand) => void;
isOpen?: boolean;
onClose?: () => void;
}
const PILLARS: Pillar[] = [
{
id: "search",
name: "Ricerca & Analisi",
icon: <Search size={20} />,
color: "#3b82f6",
commands: [
{ id: "web-search", label: "Web Search", description: "Cerca il web in tempo reale", action: () => {} },
{ id: "news", label: "Notizie", description: "Ultime notizie e trend", action: () => {} },
{ id: "weather", label: "Meteo", description: "Previsioni meteo per città", action: () => {} },
{ id: "data-analysis", label: "Analisi Dati", description: "Elabora e visualizza dati", action: () => {} },
],
},
{
id: "coding",
name: "Sviluppo & Coding",
icon: <Code2 size={20} />,
color: "#10b981",
commands: [
{ id: "code-review", label: "Code Review", description: "Analizza e migliora codice", action: () => {} },
{ id: "refactor", label: "Refactor", description: "Rifattorizza il codice", action: () => {} },
{ id: "debug", label: "Debug", description: "Trova e risolvi bug", action: () => {} },
{ id: "test", label: "Test", description: "Genera test e verifica", action: () => {} },
],
},
{
id: "automation",
name: "Automazione & Task",
icon: <Zap size={20} />,
color: "#f59e0b",
commands: [
{ id: "task-auto", label: "Task Automation", description: "Automatizza compiti ripetitivi", action: () => {} },
{ id: "workflow", label: "Workflow", description: "Crea flussi di lavoro", action: () => {} },
{ id: "scheduling", label: "Scheduling", description: "Pianifica esecuzioni", action: () => {} },
{ id: "integration", label: "Integrazione", description: "Connetti servizi esterni", action: () => {} },
],
},
{
id: "creative",
name: "Creatività & Contenuti",
icon: <Sparkles size={20} />,
color: "#a855f7",
commands: [
{ id: "text-gen", label: "Generazione Testo", description: "Crea contenuti scritti", action: () => {} },
{ id: "image-gen", label: "Generazione Immagini", description: "Crea immagini con IA", action: () => {} },
{ id: "audio-gen", label: "Generazione Audio", description: "Crea audio e musica", action: () => {} },
{ id: "brainstorm", label: "Brainstorming", description: "Genera idee creative", action: () => {} },
],
},
];
export const CommandPillar: React.FC<CommandPillarProps> = ({ onCommandSelect, isOpen = false, onClose }) => {
const [expandedPillar, setExpandedPillar] = useState<string | null>(null);
const handlePillarClick = (pillarId: string) => {
setExpandedPillar(expandedPillar === pillarId ? null : pillarId);
};
const handleCommandClick = (cmd: PillarCommand) => {
onCommandSelect(cmd);
setExpandedPillar(null);
onClose?.();
};
if (!isOpen) return null;
return (
<div
style={{
position: "fixed",
inset: 0,
background: "rgba(0,0,0,0.5)",
display: "flex",
alignItems: "flex-end",
zIndex: 1000,
animation: "fadeIn 0.2s ease-out",
}}
onClick={onClose}
>
<div
style={{
background: "var(--bg-secondary)",
borderRadius: "16px 16px 0 0",
width: "100%",
maxWidth: "600px",
maxHeight: "80vh",
overflowY: "auto",
padding: "16px",
boxShadow: "0 -4px 20px rgba(0,0,0,0.3)",
animation: "slideUp 0.3s ease-out",
}}
onClick={(e) => e.stopPropagation()}
>
{/* Header */}
<div
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
marginBottom: "16px",
paddingBottom: "12px",
borderBottom: "1px solid rgba(99,102,241,0.1)",
}}
>
<h2 style={{ margin: 0, fontSize: "1.2rem", fontWeight: 600 }}>Comandi Rapidi</h2>
<button
onClick={onClose}
style={{
background: "none",
border: "none",
cursor: "pointer",
color: "var(--text-dim)",
padding: "4px",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
<X size={20} />
</button>
</div>
{/* Pillars */}
<div style={{ display: "flex", flexDirection: "column", gap: "8px" }}>
{PILLARS.map((pillar) => (
<div key={pillar.id}>
{/* Pillar Button */}
<button
onClick={() => handlePillarClick(pillar.id)}
style={{
width: "100%",
display: "flex",
alignItems: "center",
gap: "12px",
padding: "12px 16px",
background: expandedPillar === pillar.id ? `${pillar.color}20` : "rgba(99,102,241,0.05)",
border: expandedPillar === pillar.id ? `2px solid ${pillar.color}` : "1px solid rgba(99,102,241,0.1)",
borderRadius: "12px",
cursor: "pointer",
transition: "all 0.2s ease",
color: expandedPillar === pillar.id ? pillar.color : "var(--text-primary)",
fontWeight: expandedPillar === pillar.id ? 600 : 500,
fontSize: "1rem",
}}
>
<div style={{ color: pillar.color, display: "flex", alignItems: "center" }}>
{pillar.icon}
</div>
<span style={{ flex: 1, textAlign: "left" }}>{pillar.name}</span>
<ChevronDown
size={18}
style={{
transform: expandedPillar === pillar.id ? "rotate(180deg)" : "rotate(0deg)",
transition: "transform 0.2s ease",
}}
/>
</button>
{/* Expanded Commands */}
{expandedPillar === pillar.id && (
<div
style={{
display: "flex",
flexDirection: "column",
gap: "6px",
padding: "8px 0 0 0",
animation: "slideDown 0.2s ease-out",
}}
>
{pillar.commands.map((cmd) => (
<button
key={cmd.id}
onClick={() => handleCommandClick(cmd)}
style={{
display: "flex",
flexDirection: "column",
gap: "4px",
padding: "10px 16px",
marginLeft: "12px",
background: "rgba(99,102,241,0.08)",
border: "1px solid rgba(99,102,241,0.15)",
borderRadius: "8px",
cursor: "pointer",
transition: "all 0.15s ease",
textAlign: "left",
color: "var(--text-primary)",
}}
onMouseEnter={(e) => {
(e.currentTarget as HTMLButtonElement).style.background = `${pillar.color}25`;
(e.currentTarget as HTMLButtonElement).style.borderColor = pillar.color;
}}
onMouseLeave={(e) => {
(e.currentTarget as HTMLButtonElement).style.background = "rgba(99,102,241,0.08)";
(e.currentTarget as HTMLButtonElement).style.borderColor = "rgba(99,102,241,0.15)";
}}
>
<span style={{ fontWeight: 500, fontSize: "0.95rem" }}>{cmd.label}</span>
{cmd.description && (
<span style={{ fontSize: "0.8rem", color: "var(--text-dim)" }}>
{cmd.description}
</span>
)}
</button>
))}
</div>
)}
</div>
))}
</div>
</div>
<style>{`
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes slideUp {
from { transform: translateY(100%); }
to { transform: translateY(0); }
}
@keyframes slideDown {
from { opacity: 0; max-height: 0; }
to { opacity: 1; max-height: 500px; }
}
`}</style>
</div>
);
};
export default CommandPillar;