import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import type { AxiosError } from "axios"; import { ArrowLeft, ClipboardCopy, Loader2, Save } from "lucide-react"; import * as React from "react"; import { useForm } from "react-hook-form"; import { Link, useNavigate } 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 { createUser, fetchTenants, type UserCreateRequest, type UserCreateResponse, } from "../../lib/adminApi"; function UserCreatePage() { const navigate = useNavigate(); const queryClient = useQueryClient(); const [error, setError] = React.useState(null); const [generatedPassword, setGeneratedPassword] = React.useState(null); const [createdEmail, setCreatedEmail] = React.useState(null); const [autoPassword, setAutoPassword] = React.useState(true); const { data: tenantsData } = useQuery({ queryKey: ["tenants", { limit: 100 }], queryFn: () => fetchTenants(100, 0), }); const tenants = tenantsData?.items ?? []; const { register, handleSubmit, watch, formState: { errors }, } = useForm }>({ defaultValues: { email: "", password: "", name: "", phone: "", role: "user", companyCode: "", department: "", metadata: {}, }, }); const selectedCompanyCode = watch("companyCode"); const selectedTenant = tenants.find((t) => t.slug === selectedCompanyCode); const { data: tenantDetail } = useQuery({ queryKey: ["tenant", selectedTenant?.id], queryFn: () => fetchTenant(selectedTenant!.id), enabled: !!selectedTenant?.id, }); const userSchema = (tenantDetail?.config?.userSchema as any[]) ?? []; const mutation = useMutation({ mutationFn: createUser, onSuccess: (data: UserCreateResponse) => { queryClient.invalidateQueries({ queryKey: ["users"] }); if (data.initialPassword) { setGeneratedPassword(data.initialPassword); setCreatedEmail(data.email); return; } navigate("/users"); }, onError: (err: AxiosError<{ error?: string }>) => { setError(err.response?.data?.error || "사용자 생성에 실패했습니다."); }, }); const onSubmit = (data: UserCreateRequest) => { setError(null); setGeneratedPassword(null); setCreatedEmail(null); if (autoPassword) { mutation.mutate({ ...data, password: "" }); return; } if (!data.password) { setError("비밀번호를 입력하거나 자동 생성을 사용해 주세요."); return; } mutation.mutate(data); }; const onCopyPassword = async () => { if (!generatedPassword) return; try { await navigator.clipboard.writeText(generatedPassword); } catch (_) { // ignore } }; return (
Users / New

사용자 추가

{generatedPassword && ( 초기 비밀번호 생성 완료 {createdEmail ? `${createdEmail} 계정의 초기 비밀번호입니다.` : "초기 비밀번호가 생성되었습니다."}
{generatedPassword}
)} 계정 정보 새로운 사용자를 시스템에 등록합니다.
{error && (
{error}
)}
{errors.email && (

{errors.email.message}

)}

{autoPassword ? "비워두면 시스템이 초기 비밀번호를 자동 생성합니다." : "초기 비밀번호를 직접 설정합니다."}

{errors.name && (

{errors.name.message}

)}
{userSchema.length > 0 && (

테넌트 확장 정보 (Custom Fields)

{userSchema.map((field) => (
))}
)}

시스템 접근 권한을 결정합니다.

); } export default UserCreatePage;