forked from baron/baron-sso
129 lines
4.3 KiB
TypeScript
129 lines
4.3 KiB
TypeScript
import { useQuery } from "@tanstack/react-query";
|
|
import { Building2, Plus } from "lucide-react";
|
|
import { Link, useNavigate, useParams } from "react-router-dom";
|
|
import {
|
|
commonStickyTableHeaderClass,
|
|
commonTableShellClass,
|
|
commonTableViewportClass,
|
|
} from "../../../../../common/ui/table";
|
|
import { Badge } from "../../../components/ui/badge";
|
|
import { Button } from "../../../components/ui/button";
|
|
import {
|
|
Card,
|
|
CardContent,
|
|
CardDescription,
|
|
CardHeader,
|
|
CardTitle,
|
|
} from "../../../components/ui/card";
|
|
import {
|
|
Table,
|
|
TableBody,
|
|
TableCell,
|
|
TableHead,
|
|
TableHeader,
|
|
TableRow,
|
|
} from "../../../components/ui/table";
|
|
import { fetchAllTenants } from "../../../lib/adminApi";
|
|
import { t } from "../../../lib/i18n";
|
|
|
|
function TenantSubTenantsPage() {
|
|
const { tenantId } = useParams<{ tenantId: string }>();
|
|
const navigate = useNavigate();
|
|
|
|
const { data } = useQuery({
|
|
queryKey: ["sub-tenants", tenantId],
|
|
queryFn: () => fetchAllTenants({ parentId: tenantId ?? undefined }),
|
|
enabled: !!tenantId,
|
|
});
|
|
|
|
const subTenants = data?.items ?? [];
|
|
|
|
return (
|
|
<Card className="mt-6 bg-[var(--color-panel)] flex-1 flex flex-col min-h-0 overflow-hidden">
|
|
<CardHeader className="flex flex-row items-center justify-between flex-shrink-0">
|
|
<div>
|
|
<CardTitle className="flex items-center gap-2">
|
|
<Building2 size={18} className="text-primary" />
|
|
{t("ui.admin.tenants.sub.title", "Sub-tenants ({{count}})", {
|
|
count: subTenants.length,
|
|
})}
|
|
</CardTitle>
|
|
<CardDescription>
|
|
{t(
|
|
"msg.admin.tenants.sub.subtitle",
|
|
"현재 테넌트 하위에 생성된 조직입니다.",
|
|
)}
|
|
</CardDescription>
|
|
</div>
|
|
<Button size="sm" asChild>
|
|
<Link to={`/tenants/new?parentId=${tenantId}`}>
|
|
<Plus size={14} className="mr-1" />
|
|
{t("ui.admin.tenants.sub.add", "하위 테넌트 추가")}
|
|
</Link>
|
|
</Button>
|
|
</CardHeader>
|
|
<CardContent className="flex-1 flex flex-col min-h-0 pt-0">
|
|
<div className={commonTableShellClass}>
|
|
<div className={commonTableViewportClass}>
|
|
<Table>
|
|
<TableHeader className={commonStickyTableHeaderClass}>
|
|
<TableRow>
|
|
<TableHead>
|
|
{t("ui.admin.tenants.sub.table.name", "NAME")}
|
|
</TableHead>
|
|
<TableHead>
|
|
{t("ui.admin.tenants.sub.table.slug", "SLUG")}
|
|
</TableHead>
|
|
<TableHead>
|
|
{t("ui.admin.tenants.sub.table.status", "STATUS")}
|
|
</TableHead>
|
|
</TableRow>
|
|
</TableHeader>
|
|
<TableBody>
|
|
{subTenants.length === 0 && (
|
|
<TableRow>
|
|
<TableCell
|
|
colSpan={3}
|
|
className="text-center py-8 text-muted-foreground"
|
|
>
|
|
{t(
|
|
"msg.admin.tenants.sub.empty",
|
|
"하위 테넌트가 없습니다.",
|
|
)}
|
|
</TableCell>
|
|
</TableRow>
|
|
)}
|
|
{subTenants.map((tenant) => (
|
|
<TableRow
|
|
key={tenant.id}
|
|
className="cursor-pointer hover:bg-muted/50 transition-colors"
|
|
onClick={() => navigate(`/tenants/${tenant.id}`)}
|
|
>
|
|
<TableCell className="font-semibold">
|
|
{tenant.name}
|
|
</TableCell>
|
|
<TableCell className="text-xs font-mono">
|
|
{tenant.slug}
|
|
</TableCell>
|
|
<TableCell>
|
|
<Badge
|
|
variant={
|
|
tenant.status === "active" ? "default" : "secondary"
|
|
}
|
|
>
|
|
{t(`ui.common.status.${tenant.status}`, tenant.status)}
|
|
</Badge>
|
|
</TableCell>
|
|
</TableRow>
|
|
))}
|
|
</TableBody>
|
|
</Table>
|
|
</div>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
}
|
|
|
|
export default TenantSubTenantsPage;
|