import { useState, type ReactNode } from "react"; import { BarChart3, ChevronDown, Pencil, Play, Plus, Search, Trash2, X } from "lucide-react"; import type { ChartWorkspaceResponse } from "../api/chartWorkspaceApi"; const RADIUS = "rounded-[6px]"; export function LayoutButton({ theme, active, icon, title, onClick, }: { theme: "dark" | "light"; active: boolean; icon: ReactNode; title: string; onClick: () => void; }) { const isDark = theme === "dark"; return ( {icon} ); } export function ModeButton({ theme, active, icon, label, onClick, }: { theme: "dark" | "light"; active: boolean; icon?: ReactNode; label: string; onClick: () => void; }) { return ( {icon} {label} ); } export function EmptyWorkspace({ theme, canAddMoreCharts, title = "Nenhum gráfico aberto", description = "Abra um gráfico guardado ou crie um novo gráfico para continuar.", addLabel = "Novo Gráfico", savedLabel = "Abrir Guardado", minHeightClass = "min-h-0 flex-1", onAddChart, onOpenSaved, }: { theme: "dark" | "light"; canAddMoreCharts: boolean; title?: string; description?: string; addLabel?: string; savedLabel?: string; minHeightClass?: string; onAddChart: () => void; onOpenSaved: () => void; }) { const isDark = theme === "dark"; return ( {title} {description} {addLabel} {savedLabel} ); } export function WorkspaceSelector({ theme, workspaces, activeWorkspaceId, detachedWorkspaceIds, loading, creating, canCreateWorkspace, onSelectWorkspace, onCreateWorkspace, onRenameWorkspace, onDeleteWorkspace, }: { theme: "dark" | "light"; workspaces: ChartWorkspaceResponse[]; activeWorkspaceId: number | null; detachedWorkspaceIds: Set; loading: boolean; creating: boolean; canCreateWorkspace: boolean; onSelectWorkspace: (workspaceId: number) => void; onCreateWorkspace: (name: string) => void; onRenameWorkspace: (workspaceId: number, name: string) => void | Promise; onDeleteWorkspace: (workspaceId: number) => void | Promise; }) { const isDark = theme === "dark"; const [open, setOpen] = useState(false); const [createOpen, setCreateOpen] = useState(false); const [renameWorkspace, setRenameWorkspace] = useState(null); const [search, setSearch] = useState(""); const activeWorkspace = workspaces.find((workspace) => workspace.id === activeWorkspaceId) ?? null; const filteredWorkspaces = workspaces.filter((workspace) => workspace.name.toLowerCase().includes(search.toLowerCase()), ); const createWorkspace = (name: string) => { onCreateWorkspace(name); setCreateOpen(false); setOpen(false); }; const renameSelectedWorkspace = (name: string) => { if (!renameWorkspace) return; void onRenameWorkspace(renameWorkspace.id, name); setRenameWorkspace(null); }; return ( setOpen((value) => !value)} className={ isDark ? `flex h-10 min-w-[260px] items-center justify-between gap-3 ${RADIUS} border border-[#263247] bg-[#111A2B] px-4 text-sm font-black text-white transition hover:border-[#36506D] disabled:cursor-not-allowed disabled:text-[#7F8CA3]` : `flex h-10 min-w-[260px] items-center justify-between gap-3 ${RADIUS} border border-[#D7DEE8] bg-[#F8FAFC] px-4 text-sm font-black text-[#0F172A] transition hover:bg-white disabled:cursor-not-allowed disabled:text-slate-400` } > {loading ? "A carregar workspaces..." : activeWorkspace?.name ?? "Workspaces"} {open && ( Workspaces {workspaces.length}/10 workspaces neste modulo. setCreateOpen(true)} className={ canCreateWorkspace && !creating ? `inline-flex h-9 items-center gap-2 ${RADIUS} bg-[#18B8A6] px-3 text-xs font-black text-white transition hover:bg-[#21C7B5]` : `inline-flex h-9 cursor-not-allowed items-center gap-2 ${RADIUS} bg-[#18B8A6]/40 px-3 text-xs font-black text-white` } > Novo setOpen(false)}> setSearch(event.target.value)} placeholder="Pesquisar workspaces..." className="w-full bg-transparent outline-none placeholder:text-inherit" /> {filteredWorkspaces.map((workspace) => { const active = workspace.id === activeWorkspaceId; const detached = detachedWorkspaceIds.has(workspace.id); const chartCount = getWorkspaceChartCount(workspace); return ( {workspace.name} {chartCount}/10 graficos {detached ? " · detached" : workspace.defaultWorkspace ? " · ultimo aberto" : ""} {active ? ( Aberto ) : detached ? ( Detached ) : ( { onSelectWorkspace(workspace.id); setOpen(false); }} title="Abrir workspace" className="text-[#7F8CA3] transition hover:text-[#4FD1C5]" > )} setRenameWorkspace(workspace)} title="Renomear workspace" className="text-[#7F8CA3] transition hover:text-[#4FD1C5]" > void onDeleteWorkspace(workspace.id)} title="Eliminar workspace" className="text-[#7F8CA3] transition hover:text-red-400" > ); })} {filteredWorkspaces.length === 0 && ( Nenhum workspace encontrado. )} )} {createOpen && ( setCreateOpen(false)} onCreate={createWorkspace} /> )} {renameWorkspace && ( setRenameWorkspace(null)} onSubmit={renameSelectedWorkspace} /> )} ); } function getWorkspaceChartCount(workspace: ChartWorkspaceResponse) { try { const charts = JSON.parse(workspace.chartsJson) as unknown[]; return Array.isArray(charts) ? charts.length : 0; } catch { return 0; } } function WorkspaceNameModal({ theme, title, actionLabel, initialName = "", creating, onClose, onSubmit, }: { theme: "dark" | "light"; title: string; actionLabel: string; initialName?: string; creating: boolean; onClose: () => void; onSubmit: (name: string) => void; }) { const isDark = theme === "dark"; const [name, setName] = useState(initialName); const canCreate = name.trim().length > 0 && !creating; return ( {title} Nome setName(event.target.value)} onKeyDown={(event) => { if (event.key === "Enter" && canCreate) { onSubmit(name); } }} placeholder="Ex: Estufa norte" className={ isDark ? `${RADIUS} h-11 w-full border border-[#263247] bg-[#07101B] px-3 text-sm font-bold text-white outline-none focus:border-[#4FD1C5]` : `${RADIUS} h-11 w-full border border-[#D7DEE8] bg-[#F8FAFC] px-3 text-sm font-bold text-[#0F172A] outline-none focus:border-[#0F766E]` } /> ); } function NewWorkspaceModal({ theme, creating, onClose, onCreate, }: { theme: "dark" | "light"; creating: boolean; onClose: () => void; onCreate: (name: string) => void; }) { return ( ); }
{description}
{workspaces.length}/10 workspaces neste modulo.
{workspace.name}
{chartCount}/10 graficos {detached ? " · detached" : workspace.defaultWorkspace ? " · ultimo aberto" : ""}