From 5ff7e6dd1eea2541e3aac820d42470dc710a79f2 Mon Sep 17 00:00:00 2001 From: Leo dev Date: Fri, 2 Jan 2026 23:40:48 +0100 Subject: [PATCH] Deployments patch --- src/app/deployments/page.tsx | 186 +++++++++++++++++++++-------------- 1 file changed, 112 insertions(+), 74 deletions(-) diff --git a/src/app/deployments/page.tsx b/src/app/deployments/page.tsx index 382185e..e269250 100644 --- a/src/app/deployments/page.tsx +++ b/src/app/deployments/page.tsx @@ -1,120 +1,158 @@ "use client"; +import { useEffect, useMemo, useState } from "react"; import { DashboardLayout } from "@/components/dashboard/DashboardLayout"; import { Card, CardContent } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; -import { - Rocket, - RotateCcw, - Eye, - MoreVertical, - Plus, - GitBranch, -} from "lucide-react"; -import { useEffect, useState } from "react"; +import { Rocket, RotateCcw, Eye, MoreVertical, Plus } from "lucide-react"; import { Application, Deployment } from "@/lib/types"; import { getDeployments } from "@/lib/dockship/deploy"; import { getApplications } from "@/lib/dockship/application"; import { cn } from "@/lib/utils"; import DeployAppDialog from "@/components/dialogs/DeployApp"; +const statusDot = { + running: "bg-chart-2", + pending: "bg-chart-1", + stopped: "bg-slate-400 dark:bg-slate-600", +} as const; + export default function DeploymentsPage() { const [applications, setApplications] = useState([]); const [deployments, setDeployments] = useState([]); + const [loading, setLoading] = useState(true); useEffect(() => { - const fetch = async () => { - setApplications(await getApplications()); - setDeployments((await getDeployments()).filter((d) => d !== null)); + let mounted = true; + + async function fetchData() { + try { + const [apps, deps] = await Promise.all([ + getApplications(), + getDeployments(), + ]); + + if (!mounted) return; + + setApplications(apps); + setDeployments(deps.filter((d) => d !== null)); + } catch (err) { + console.error("Failed to load deployments:", err); + } finally { + if (mounted) setLoading(false); + } + } + + fetchData(); + return () => { + mounted = false; }; - fetch(); }, []); + const appNameByContainer = useMemo(() => { + const map = new Map(); + for (const app of applications) { + for (const container of app.deployments) { + map.set(container, app.name); + } + } + return map; + }, [applications]); + return ( {/* Header */} -
- {deployments.length} deployments +
+ + {loading ? "Loading…" : `${deployments.length} deployments`} + -
-
- {deployments.map((dep) => ( -
-
- -
-
- { - applications.find((app) => - app.deployments.includes(dep.image) - )?.name - } -
-
- {/* {dep.version} */} + {/* Desktop */} +
+ {deployments.map((dep) => { + const appName = appNameByContainer.get(dep.container) ?? "Unknown app"; + + return ( +
+
+ +
+
{appName}
+
+ {dep.image} +
+ +
+ + + +
-
- {/* {dep.time} */} -
-
- ))} + ); + })}
- {/* Mobile cards */} + {/* Mobile */}
- {deployments.map((dep) => ( -
-
-
- - {dep.image} + {deployments.map((dep) => { + const appName = + appNameByContainer.get(dep.container) ?? "Unknown app"; + + return ( +
+
+
+ + {appName} +
+ + {dep.status} +
- {dep.status} -
- {/*
-
- By -
{dep.deployedBy}
-
-
*/} - -
- - - +
+ + + +
-
- ))} + ); + })}
);