1
0
forked from baron/baron-sso

샘플 adminfront, devfront 구성. ory-keto-migrate 오류 해결

This commit is contained in:
Lectom C Han
2026-01-28 14:03:42 +09:00
parent b7a0397ef9
commit e573f4ca50
21 changed files with 1293 additions and 213 deletions

View File

@@ -1,4 +1,5 @@
import { useQuery } from "@tanstack/react-query";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import type { AxiosError } from "axios";
import {
Activity,
BookOpenText,
@@ -9,7 +10,7 @@ import {
ServerCog,
ShieldHalf,
} from "lucide-react";
import { Link } from "react-router-dom";
import { Link, useNavigate } from "react-router-dom";
import {
Avatar,
AvatarFallback,
@@ -26,6 +27,7 @@ import {
} from "../../components/ui/card";
import { Input } from "../../components/ui/input";
import { Separator } from "../../components/ui/separator";
import { Switch } from "../../components/ui/switch";
import {
Table,
TableBody,
@@ -34,14 +36,29 @@ import {
TableHeader,
TableRow,
} from "../../components/ui/table";
import { fetchClients } from "../../lib/devApi";
import {
deleteClient,
fetchClients,
updateClientStatus,
} from "../../lib/devApi";
import { cn } from "../../lib/utils";
function ClientsPage() {
const navigate = useNavigate();
const queryClient = useQueryClient();
const { data, isLoading, error } = useQuery({
queryKey: ["clients"],
queryFn: fetchClients,
});
const updateStatusMutation = useMutation({
mutationFn: (payload: { id: string; status: "active" | "inactive" }) =>
updateClientStatus(payload.id, payload.status),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ["clients"] }),
});
const deleteMutation = useMutation({
mutationFn: (clientId: string) => deleteClient(clientId),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ["clients"] }),
});
const clients = data?.items || [];
const totalClients = clients.length;
@@ -73,7 +90,8 @@ function ClientsPage() {
if (error) {
const errMsg =
(error as any).response?.data?.error || (error as Error).message;
(error as AxiosError<{ error?: string }>).response?.data?.error ??
(error as Error).message;
return (
<div className="p-8 text-center text-red-500">
Error loading clients: {errMsg}
@@ -102,7 +120,11 @@ function ClientsPage() {
<Button variant="outline" size="sm">
</Button>
<Button size="sm" className="shadow-lg shadow-primary/30">
<Button
size="sm"
className="shadow-lg shadow-primary/30"
onClick={() => navigate("/clients/new")}
>
<Plus className="h-4 w-4" />
</Button>
</div>
@@ -164,7 +186,7 @@ function ClientsPage() {
<Button variant="outline" size="sm">
</Button>
<Button size="sm">
<Button size="sm" onClick={() => navigate("/clients/new")}>
<Plus className="h-4 w-4" />
</Button>
</div>
@@ -214,9 +236,7 @@ function ClientsPage() {
size="icon"
className="h-8 w-8 text-muted-foreground hover:text-primary"
aria-label="Copy client id"
onClick={() =>
navigator.clipboard.writeText(client.id)
}
onClick={() => navigator.clipboard.writeText(client.id)}
>
<Copy className="h-4 w-4" />
</Button>
@@ -234,24 +254,16 @@ function ClientsPage() {
</Badge>
</TableCell>
<TableCell>
<div className="flex items-center gap-2">
<div
className={cn(
"flex h-5 w-10 items-center rounded-full p-1",
client.status === "active"
? "bg-primary/40"
: "bg-muted/50",
)}
>
<div
className={cn(
"h-3 w-3 rounded-full bg-background transition",
client.status === "active"
? "translate-x-5"
: "translate-x-0",
)}
/>
</div>
<div className="flex items-center gap-3">
<Switch
checked={client.status === "active"}
onCheckedChange={(checked) =>
updateStatusMutation.mutate({
id: client.id,
status: checked ? "active" : "inactive",
})
}
/>
<span
className={cn(
"text-sm font-medium",
@@ -279,6 +291,7 @@ function ClientsPage() {
size="icon"
className="h-8 w-8 text-muted-foreground hover:text-destructive"
aria-label="Delete client"
onClick={() => deleteMutation.mutate(client.id)}
>
<Activity className="h-4 w-4" />
</Button>