forked from baron/baron-sso
105 lines
3.3 KiB
TypeScript
105 lines
3.3 KiB
TypeScript
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
|
import type { AxiosError } from "axios";
|
|
import { useState } from "react";
|
|
import { useOutletContext } from "react-router-dom";
|
|
import { Button } from "../../../components/ui/button";
|
|
import {
|
|
Card,
|
|
CardContent,
|
|
CardDescription,
|
|
CardHeader,
|
|
CardTitle,
|
|
} from "../../../components/ui/card";
|
|
import { Input } from "../../../components/ui/input";
|
|
import { Label } from "../../../components/ui/label";
|
|
import { Textarea } from "../../../components/ui/textarea";
|
|
import {
|
|
type TenantGroupSummary,
|
|
updateTenantGroup,
|
|
} from "../../../lib/adminApi";
|
|
|
|
function TenantGroupProfileTab() {
|
|
const { group, refetch } = useOutletContext<{
|
|
group: TenantGroupSummary;
|
|
refetch: () => void;
|
|
}>();
|
|
const queryClient = useQueryClient();
|
|
|
|
const [name, setName] = useState(group?.name ?? "");
|
|
const [description, setDescription] = useState(group?.description ?? "");
|
|
|
|
const mutation = useMutation({
|
|
mutationFn: () => updateTenantGroup(group.id, { name, description }),
|
|
onSuccess: () => {
|
|
refetch();
|
|
queryClient.invalidateQueries({ queryKey: ["tenant-groups"] });
|
|
},
|
|
});
|
|
|
|
const errorMsg = (mutation.error as AxiosError<{ error?: string }>)?.response
|
|
?.data?.error;
|
|
|
|
if (!group) return null;
|
|
|
|
return (
|
|
<div className="max-w-2xl space-y-6">
|
|
<Card className="bg-[var(--color-panel)]">
|
|
<CardHeader>
|
|
<CardTitle>그룹 정보 수정</CardTitle>
|
|
<CardDescription>
|
|
그룹의 기본 이름과 설명을 변경할 수 있습니다. 식별자(Slug)는 변경할
|
|
수 없습니다.
|
|
</CardDescription>
|
|
</CardHeader>
|
|
<CardContent className="space-y-4">
|
|
<div className="space-y-2">
|
|
<Label>그룹 ID (고유 식별자)</Label>
|
|
<Input value={group.id} disabled className="bg-muted" />
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label>Slug</Label>
|
|
<Input value={group.slug} disabled className="bg-muted" />
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label htmlFor="groupName">Group Name</Label>
|
|
<Input
|
|
id="groupName"
|
|
value={name}
|
|
onChange={(e) => setName(e.target.value)}
|
|
/>
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label htmlFor="groupDesc">Description</Label>
|
|
<Textarea
|
|
id="groupDesc"
|
|
rows={4}
|
|
value={description}
|
|
onChange={(e) => setDescription(e.target.value)}
|
|
/>
|
|
</div>
|
|
|
|
{errorMsg && (
|
|
<div className="rounded-lg border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive">
|
|
{errorMsg}
|
|
</div>
|
|
)}
|
|
|
|
<div className="flex justify-end pt-4">
|
|
<Button
|
|
onClick={() => mutation.mutate()}
|
|
disabled={
|
|
mutation.isPending ||
|
|
(name === group.name && description === group.description)
|
|
}
|
|
>
|
|
{mutation.isPending ? "저장 중..." : "변경사항 저장"}
|
|
</Button>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default TenantGroupProfileTab;
|