Files
pieced-portal/src/components/packages/package-list.tsx
admin 7c4e20099d
All checks were successful
Build and Push / build (push) Successful in 1m24s
Role split and owner gating
2026-04-26 22:45:38 +02:00

76 lines
2.2 KiB
TypeScript

"use client";
import { useTranslations } from "next-intl";
import { useRouter } from "next/navigation";
import { PACKAGE_CATALOG } from "@/lib/packages";
import { PackageCard } from "./package-card";
interface Props {
tenantName: string;
enabledPackages: string[];
conditions?: Array<{ type: string; status: string; reason?: string }>;
onRefresh?: () => void;
/** Slice 5: when false, package toggles and edit affordances are hidden. */
canEdit?: boolean;
}
const CATEGORIES = [
{ key: "channel" as const, labelKey: "categories.channels" },
{ key: "skill" as const, labelKey: "categories.skills" },
] as const;
function getPackageStatus(
pkgId: string,
enabled: boolean,
conditions?: Props["conditions"]
): "pending" | "active" | "error" | undefined {
if (!enabled) return undefined;
const cond = conditions?.find((c) => c.type === `Package/${pkgId}`);
if (!cond) return "pending";
if (cond.status === "True") return "active";
if (cond.reason === "SecretReady") return "active";
return "error";
}
export function PackageList({
tenantName,
enabledPackages,
conditions,
onRefresh,
canEdit = true,
}: Props) {
const t = useTranslations("packages");
const router = useRouter();
const handleRefresh = onRefresh || (() => router.refresh());
return (
<div className="space-y-6">
{CATEGORIES.map(({ key, labelKey }) => {
const packages = PACKAGE_CATALOG.filter((p) => p.category === key);
if (packages.length === 0) return null;
return (
<div key={key}>
<h3 className="text-[10px] font-semibold uppercase tracking-wider text-text-muted mb-3">
{t(labelKey)}
</h3>
<div className="grid gap-3 sm:grid-cols-2">
{packages.map((pkg) => (
<PackageCard
key={pkg.id}
pkg={pkg}
enabled={enabledPackages.includes(pkg.id)}
status={getPackageStatus(pkg.id, enabledPackages.includes(pkg.id), conditions)}
tenantName={tenantName}
onToggled={handleRefresh}
canEdit={canEdit}
/>
))}
</div>
</div>
);
})}
</div>
);
}