diff --git a/frontend/src/components/Tasks/KanbanBoard.tsx b/frontend/src/components/Tasks/KanbanBoard.tsx index 74cd545..c02db23 100644 --- a/frontend/src/components/Tasks/KanbanBoard.tsx +++ b/frontend/src/components/Tasks/KanbanBoard.tsx @@ -22,19 +22,19 @@ function ProjectRow({ project }: { project: Project }) { if (totalTasks === 0) return null; return ( -
+
{/* Project header */} -
-

+
+

{project.name}

- + {totalTasks} tareas
{/* Progress bar */} -
+
{stages.map(([stageName, tasks], i) => { const pct = (tasks.length / totalTasks) * 100; if (pct < 1) return null; @@ -50,17 +50,17 @@ function ProjectRow({ project }: { project: Project }) {
{/* Stage chips */} -
+
{stages.map(([stageName, tasks], i) => ( - {stageName} - {tasks.length} + {stageName} + {tasks.length} ))}
@@ -82,20 +82,20 @@ export function KanbanBoard({ projects }: KanbanBoardProps) { return (
{/* Summary bar */} -
- +
+ {activeProjects.length} proyectos activos - | - + | + {totalTasks} tareas totales
{/* Projects grid */} -
-
+
+
{activeProjects.map((project) => ( ))} diff --git a/frontend/src/components/Topology/NetworkGraph.tsx b/frontend/src/components/Topology/NetworkGraph.tsx index 9e1a08a..27ecf4e 100644 --- a/frontend/src/components/Topology/NetworkGraph.tsx +++ b/frontend/src/components/Topology/NetworkGraph.tsx @@ -28,7 +28,6 @@ function categorizeNodes(nodes: NetworkNode[]) { } } - // Any remaining nodes const remaining = nodes.filter((n) => !assigned.has(n.ip)); if (remaining.length > 0) { categorized.push({ label: "Otros", nodes: remaining }); @@ -45,37 +44,37 @@ export function NetworkGraph({ nodes }: NetworkGraphProps) { return (
{/* Summary bar */} -
+
- - + + {onlineCount} online
- - + + {total - onlineCount} offline
- | - + | + {total} dispositivos
{/* Scrollable grid */} -
+
{categories.map((cat) => (
-

+

{cat.label} - ({cat.nodes.length}) + ({cat.nodes.length})

{cat.nodes.map((node) => ( diff --git a/frontend/src/components/Topology/NodeCard.tsx b/frontend/src/components/Topology/NodeCard.tsx index f97deea..32c9903 100644 --- a/frontend/src/components/Topology/NodeCard.tsx +++ b/frontend/src/components/Topology/NodeCard.tsx @@ -20,7 +20,7 @@ interface NodeCardProps { } export function NodeCard({ node }: NodeCardProps) { - const [expanded, setExpanded] = useState(false); + const [showPassword, setShowPassword] = useState(false); const isUp = node.status === "up"; const statusBg = isUp ? "bg-success-dim" : "bg-danger-dim"; @@ -29,42 +29,45 @@ export function NodeCard({ node }: NodeCardProps) { return (
setExpanded((prev) => !prev)} + className={`${statusBg} border ${statusBorder} rounded-2xl px-6 py-5 cursor-pointer transition-all duration-200 hover:bg-bg-card-hover`} + onClick={() => setShowPassword((prev) => !prev)} > -
- - {ICON_MAP[node.icon] || "📦"} -
-

+ {/* Row 1: Icon + Name + Status */} +

+ {ICON_MAP[node.icon] || "📦"} +
+

{node.name}

-

{node.ip}

- {node.public_url && ( - - {node.public_url.replace(/^https?:\/\//, "")} - - )} +
- {expanded && (node.username || node.public_url) && ( -
- {node.username && ( -

- User: {node.username} - {node.password && ( - - Pass:{" "} - {node.password} - - )} -

+ {/* Row 2: IP */} +

{node.ip}

+ + {/* Row 3: Credentials */} + {node.username && ( +

+ Usuario:{" "} + {node.username} + {node.password && ( + <> + {" · "} + Clave:{" "} + + {showPassword ? node.password : "••••••"} + + )} - {node.public_url && ( -

{node.public_url}

- )} -
+

+ )} + + {/* Row 4: Public URL */} + {node.public_url && ( +

+ {node.public_url} +

)}
);