import { useMutation, useQuery } from "@tanstack/react-query"; import type { AxiosError } from "axios"; import { Building2, Sparkles } from "lucide-react"; import { useCallback, useMemo, useState } from "react"; import { useNavigate, useSearchParams } 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 { createTenant, fetchAllTenants } from "../../../lib/adminApi"; import { t } from "../../../lib/i18n"; import { DomainTagInput } from "../components/DomainTagInput"; import { ParentTenantSelector } from "../components/ParentTenantSelector"; import { type ServerDomainConflict, formatDomainConflictMessage, } from "../utils/domainTags"; import { ORG_UNIT_TYPE_OPTIONS, TENANT_VISIBILITY_OPTIONS, type TenantVisibility, mergeTenantOrgConfig, shouldAllowHanmacOrgConfig, } from "../utils/orgConfig"; type AdminFrontTestHooks = { selectTenantParent?: (tenantId: string) => Promise; }; function TenantCreatePage() { const navigate = useNavigate(); const [searchParams] = useSearchParams(); const [name, setName] = useState(""); const [type, setType] = useState("COMPANY"); const [slug, setSlug] = useState(""); const [parentId, setParentId] = useState( () => searchParams.get("parentId") ?? "", ); const [parentStepConfirmed, setParentStepConfirmed] = useState(false); const [orgUnitType, setOrgUnitType] = useState(""); const [visibility, setVisibility] = useState("public"); const [description, setDescription] = useState(""); const [status, setStatus] = useState("active"); const [domains, setDomains] = useState([]); const [forceDomainConflicts, setForceDomainConflicts] = useState( [], ); const parentQuery = useQuery({ queryKey: ["tenants", "all"], queryFn: () => fetchAllTenants(), }); const tenants = parentQuery.data?.items ?? []; const selectedParentTenant = tenants.find((tenant) => tenant.id === parentId); const canConfigureHanmacOrg = useMemo(() => { if (!selectedParentTenant) return false; if (selectedParentTenant.slug.toLowerCase() === "hanmac-family") { return true; } return shouldAllowHanmacOrgConfig(selectedParentTenant, tenants); }, [selectedParentTenant, tenants]); const canEditTenantDetails = parentStepConfirmed || Boolean(selectedParentTenant); const parentContextLabel = selectedParentTenant ? canConfigureHanmacOrg ? t( "ui.admin.tenants.create.parent_context.hanmac", "한맥가족 하위 테넌트", ) : t("ui.admin.tenants.create.parent_context.general", "일반 하위 테넌트") : parentStepConfirmed ? t("ui.admin.tenants.create.parent_context.root", "최상위 테넌트") : t( "ui.admin.tenants.create.parent_context.pick_required", "상위 테넌트 선택 필요", ); const handleParentChange = useCallback((nextParentId: string) => { setParentId(nextParentId); setParentStepConfirmed(false); }, []); if (typeof window !== "undefined") { const testWindow = window as Window & typeof globalThis & { __adminfrontTestHooks?: AdminFrontTestHooks; }; const hooks = testWindow.__adminfrontTestHooks ?? {}; hooks.selectTenantParent = async (tenantId: string) => { handleParentChange(tenantId); }; testWindow.__adminfrontTestHooks = hooks; } const mutation = useMutation({ mutationFn: (overrideForceDomains?: string[]) => createTenant({ name, type, slug: slug || undefined, parentId: parentId || undefined, description: description || undefined, status, domains, config: canConfigureHanmacOrg ? mergeTenantOrgConfig(undefined, { orgUnitType, visibility }) : undefined, forceDomainConflicts: overrideForceDomains ?? forceDomainConflicts, }), onSuccess: () => { navigate("/tenants"); }, onError: ( err: AxiosError<{ code?: string; error?: string; conflicts?: ServerDomainConflict[]; }>, ) => { const conflicts = err.response?.data?.conflicts ?? []; if ( err.response?.data?.code === "tenant_domain_conflict" && conflicts.length > 0 ) { const nextForceDomains = Array.from( new Set([...forceDomainConflicts, ...conflicts.map((c) => c.domain)]), ); const message = conflicts.map(formatDomainConflictMessage).join("\n"); if (window.confirm(message)) { setForceDomainConflicts(nextForceDomains); mutation.mutate(nextForceDomains); } } }, }); const errorMsg = (mutation.error as AxiosError<{ error?: string }>)?.response ?.data?.error; return (

{t("ui.admin.tenants.create.title", "테넌트 생성")}

{t( "msg.admin.tenants.create.subtitle", "새로운 테넌트를 시스템에 등록합니다.", )}

{t("ui.admin.tenants.create.profile.title", "Tenant Profile")} {t( "msg.admin.tenants.create.profile.subtitle", "필수 정보만 입력해도 생성 가능합니다. Slug는 없으면 자동 생성됩니다.", )}
tenant.slug.toLowerCase() !== "hanmac-family" && !shouldAllowHanmacOrgConfig(tenant, tenants) } labelAction={ !selectedParentTenant ? ( ) : null } />
{canConfigureHanmacOrg && ( <>
)}
{canEditTenantDetails && ( <>
setName(e.target.value)} placeholder={t( "ui.admin.tenants.create.form.name_placeholder", "테넌트 이름을 입력하세요", )} />
setSlug(e.target.value)} placeholder={t( "ui.admin.tenants.create.form.slug_placeholder", "tenant-slug", )} />