1
0
forked from baron/baron-sso

tenants 레지스트리 가독성/로케일 적용

This commit is contained in:
2026-06-04 15:15:05 +09:00
parent 47d2f15283
commit f6c7cb3b22
6 changed files with 138 additions and 38 deletions

View File

@@ -69,7 +69,6 @@ import {
SelectTrigger,
SelectValue,
} from "../../../components/ui/select";
import { Switch } from "../../../components/ui/switch";
import {
Table,
TableBody,
@@ -80,7 +79,6 @@ import {
} from "../../../components/ui/table";
import { Tabs, TabsList, TabsTrigger } from "../../../components/ui/tabs";
import { toast } from "../../../components/ui/use-toast";
import type { UserProfileResponse } from "../../../lib/adminApi";
import {
deleteTenantsBulk,
exportTenantsCSV,
@@ -142,6 +140,51 @@ const getTenantIcon = (type?: string) => {
}
};
function getTenantTypeLabel(type?: string) {
if (!type) return "-";
return t(`domain.tenant_type.${type.toLowerCase()}`, type);
}
function getTenantTypeTextClass(type?: string) {
switch (type?.toUpperCase()) {
case "COMPANY_GROUP":
return "text-sky-700";
case "COMPANY":
return "text-violet-700";
case "ORGANIZATION":
return "text-emerald-700";
case "USER_GROUP":
return "text-amber-700";
case "PERSONAL":
return "text-slate-700";
default:
return "text-muted-foreground";
}
}
function buildTenantParentPathMap(tenants: TenantSummary[]) {
const tenantById = new Map(tenants.map((tenant) => [tenant.id, tenant]));
const pathMap = new Map<string, string[]>();
for (const tenant of tenants) {
const names: string[] = [];
const visited = new Set<string>();
let currentParentId = tenant.parentId;
while (currentParentId && !visited.has(currentParentId)) {
visited.add(currentParentId);
const parent = tenantById.get(currentParentId);
if (!parent) break;
names.unshift(parent.name);
currentParentId = parent.parentId;
}
pathMap.set(tenant.id, names);
}
return pathMap;
}
const noImportParentRef = "__none__";
function tenantParentRef(tenantId: string) {
@@ -339,19 +382,6 @@ function TenantListPage() {
},
});
const statusMutation = useMutation({
mutationFn: ({ tenantId, status }: { tenantId: string; status: string }) =>
updateTenant(tenantId, { status }),
onSuccess: () => {
query.refetch();
},
onError: () => {
toast.error(
t("msg.admin.tenants.status_error", "테넌트 상태 변경에 실패했습니다."),
);
},
});
const bulkUpdateStatusMutation = useMutation({
mutationFn: async ({
tenantIds,
@@ -935,8 +965,6 @@ function TenantListPage() {
onSelectAll={handleSelectAll}
search={search}
deletableTenants={deletableTenants}
statusMutation={statusMutation}
profile={profile}
sortConfig={sortConfig}
requestSort={requestSort}
getSortIcon={getSortIcon}
@@ -1513,13 +1541,6 @@ const TenantHierarchyView: React.FC<{
onSelectAll: (checked: boolean) => void;
search: string;
deletableTenants: TenantSummary[];
statusMutation: UseMutationResult<
TenantSummary,
Error,
{ tenantId: string; status: string },
unknown
>;
profile: UserProfileResponse | undefined;
sortConfig: SortConfig<TenantSortKey> | null;
requestSort: (key: TenantSortKey) => void;
getSortIcon: (key: TenantSortKey) => React.ReactNode;
@@ -1536,8 +1557,6 @@ const TenantHierarchyView: React.FC<{
onSelectAll,
search,
deletableTenants,
statusMutation,
profile,
sortConfig,
requestSort,
getSortIcon,
@@ -1558,6 +1577,10 @@ const TenantHierarchyView: React.FC<{
() => buildTenantFullTree(tenants, scopeTenantId || undefined, !!search),
[scopeTenantId, tenants, search],
);
const tenantParentPathMap = React.useMemo(
() => buildTenantParentPathMap(tenants),
[tenants],
);
// Initial expanded state: everything open
const [expandedIds, setExpandedIds] = React.useState<Set<string>>(() => {
@@ -1682,6 +1705,22 @@ const TenantHierarchyView: React.FC<{
const visibleSelectedCount = selectedIds.filter((id) =>
visibleSelectableIds.has(id),
).length;
const normalizedSearch = search.trim();
const emptyMessage = React.useMemo(() => {
if (normalizedSearch) {
return t(
"msg.admin.tenants.empty_search",
"검색 조건에 맞는 테넌트가 없습니다.",
);
}
if (scopeTenantId) {
return t(
"msg.admin.tenants.empty_scope",
"선택한 범위에 표시할 하위 테넌트가 없습니다.",
);
}
return t("msg.admin.tenants.empty", "아직 등록된 테넌트가 없습니다.");
}, [normalizedSearch, scopeTenantId]);
const renderRow = (
node: TenantViewRow,
@@ -1923,10 +1962,7 @@ const TenantHierarchyView: React.FC<{
colSpan={8}
className="py-8 text-center text-muted-foreground"
>
{t(
"msg.admin.tenants.empty",
"아직 등록된 테넌트가 없습니다.",
)}
{emptyMessage}
</TableCell>
</TableRow>
)}