feat(ui): migrate SSOSettings/RoleMappings to shadcn

- antd Card/Divider/Table/Tag/Typography \u2192 shadcn Card/Separator/Table/
  Badge + plain headings.
- Inlines the table render columns since shadcn Table doesn't take a
  ColumnsType array.

Gates: TS \u2713 | Vitest 4/4 \u2713 | Build \u2713.

Co-authored-by: yuneng-jiang <yuneng-berri@users.noreply.github.com>
This commit is contained in:
Cursor Agent 2026-04-23 09:18:15 +00:00
parent 2e4b3929d1
commit 13fcb52ceb
No known key found for this signature in database

View file

@ -1,73 +1,85 @@
import type { RoleMappings as RoleMappingsType } from "@/app/(dashboard)/hooks/sso/useSSOSettings";
import { Card, Divider, Table, Tag, Typography } from "antd";
import { Badge } from "@/components/ui/badge";
import { Card } from "@/components/ui/card";
import { Separator } from "@/components/ui/separator";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { Users } from "lucide-react";
import { defaultRoleDisplayNames } from "./constants";
const { Title, Text } = Typography;
export default function RoleMappings({ roleMappings }: { roleMappings: RoleMappingsType | undefined }) {
if (!roleMappings) {
return null;
}
export default function RoleMappings({
roleMappings,
}: {
roleMappings: RoleMappingsType | undefined;
}) {
if (!roleMappings) return null;
const roleMappingsColumns = [
{
title: "Role",
dataIndex: "role",
key: "role",
render: (text: string) => <Text strong>{defaultRoleDisplayNames[text]}</Text>,
},
{
title: "Mapped Groups",
dataIndex: "groups",
key: "groups",
render: (groups: string[]) => (
<>
{groups.length > 0 ? (
groups.map((group, index) => (
<Tag key={index} color="blue">
{group}
</Tag>
))
) : (
<Text className="text-gray-400 italic">No groups mapped</Text>
)}
</>
),
},
];
return (
<Card>
<Card className="p-6">
<div className="flex items-center gap-3">
<Users className="w-6 h-6 text-gray-400 mb-2" />
<Title level={3}>Role Mappings</Title>
<Users className="w-6 h-6 text-muted-foreground mb-2" />
<h3 className="text-lg font-semibold">Role Mappings</h3>
</div>
<div className="space-y-8">
<div className="grid grid-cols-2 gap-4">
<div>
<Title level={5}>Group Claim</Title>
<h5 className="text-base font-semibold">Group Claim</h5>
<div>
<Text code>{roleMappings.group_claim}</Text>
<code className="bg-muted px-1.5 py-0.5 rounded text-sm">
{roleMappings.group_claim}
</code>
</div>
</div>
<div>
<Title level={5}>Default Role</Title>
<h5 className="text-base font-semibold">Default Role</h5>
<div>
<Text strong>{defaultRoleDisplayNames[roleMappings.default_role]}</Text>
<span className="font-semibold">
{defaultRoleDisplayNames[roleMappings.default_role]}
</span>
</div>
</div>
</div>
<Divider />
<Table
columns={roleMappingsColumns}
dataSource={Object.entries(roleMappings.roles).map(([role, groups]) => ({
role,
groups,
}))}
pagination={false}
bordered
size="small"
className="w-full"
/>
<Separator />
<Table className="border border-border rounded-md w-full">
<TableHeader>
<TableRow>
<TableHead>Role</TableHead>
<TableHead>Mapped Groups</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{Object.entries(roleMappings.roles).map(([role, groups]) => (
<TableRow key={role}>
<TableCell>
<span className="font-semibold">
{defaultRoleDisplayNames[role]}
</span>
</TableCell>
<TableCell>
{groups.length > 0 ? (
<div className="flex flex-wrap gap-1">
{groups.map((group, index) => (
<Badge key={index} variant="default">
{group}
</Badge>
))}
</div>
) : (
<span className="text-muted-foreground italic">
No groups mapped
</span>
)}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
</Card>
);