diff --git a/apps/cs/app/site/register/[id]/page.tsx b/apps/cs/app/site/register/[id]/page.tsx index b1f4d3a16..685d77172 100644 --- a/apps/cs/app/site/register/[id]/page.tsx +++ b/apps/cs/app/site/register/[id]/page.tsx @@ -1,10 +1,10 @@ -import { RegisterPage as ViewRegisterPage } from "@/pages/site"; +import { ModifyPage as VModifyPage } from "@/pages/site"; -export default async function RegisterPage({ +export default async function ModifyPage({ params, }: { params: Promise<{ id: string }>; }) { const { id } = await params; - return ; + return ; } diff --git a/apps/cs/src/entities/site/api/site-service.ts b/apps/cs/src/entities/site/api/site-service.ts index 6091ecdca..0430377e6 100644 --- a/apps/cs/src/entities/site/api/site-service.ts +++ b/apps/cs/src/entities/site/api/site-service.ts @@ -5,7 +5,7 @@ import type { SiteService, ISiteDetail, ISiteParams, - ISiteData, + SiteFormData, } from "../model/site-interface"; export class SiteApiService implements SiteService { @@ -24,7 +24,7 @@ export class SiteApiService implements SiteService { return response.data; } - public async modifySite(siteId: string, data: ISiteData): Promise { + public async modifySite(siteId: string, data: SiteFormData): Promise { const response = await client.put( `${ENDPOINT.CMS_SERVICE.SITES}/${siteId}`, data, diff --git a/apps/cs/src/entities/site/model/site-interface.ts b/apps/cs/src/entities/site/model/site-interface.ts index 4f7879f74..fbf94bfd8 100644 --- a/apps/cs/src/entities/site/model/site-interface.ts +++ b/apps/cs/src/entities/site/model/site-interface.ts @@ -1,3 +1,5 @@ +import { z } from "zod"; + export interface ISiteParams { siteNm: string; siteKndCd: string; @@ -47,21 +49,7 @@ export interface ISiteInfo { empty: boolean; } -export interface ISiteData { - siteNm: string; - siteExpln: string; - siteKndCd: string; - siteAddr: string; - faxNo: string; - telNo: string; - lwndCn: string; - bscSiteYn: string; - bkmkIcon: string; - useYn: string; - siteSkn: string; -} - -export interface ISiteDetail extends ISiteData { +export interface ISiteDetail extends SiteFormData { siteId: string; siteKindNm: string; basicSiteYn: string; @@ -74,8 +62,25 @@ export interface ISiteDetail extends ISiteData { mdFrNm: string; } +export const siteFormSchema = z.object({ + siteId: z.string().max(2), + siteNm: z.string().max(100), + siteExpln: z.string().max(1000).optional(), + siteKndCd: z.string().max(10), + siteAddr: z.string().max(2000).optional(), + faxNo: z.string().max(100).optional(), + telNo: z.string().max(1000).optional(), + lwndCn: z.string().max(2000).optional(), + bscSiteYn: z.string().optional(), + bkmkIcon: z.string().max(100).optional(), + useYn: z.string().optional(), + siteSkn: z.string().max(10).optional(), +}); + +export type SiteFormData = z.infer; + export interface SiteService { siteInfo(query: ISiteParams): Promise; siteDetail(siteId: string): Promise; - modifySite(siteId: string, data: ISiteData): Promise; + modifySite(siteId: string, data: SiteFormData): Promise; } diff --git a/apps/cs/src/pages/site/index.ts b/apps/cs/src/pages/site/index.ts index 22c7fef7b..40c65cf04 100644 --- a/apps/cs/src/pages/site/index.ts +++ b/apps/cs/src/pages/site/index.ts @@ -1,2 +1,3 @@ -export { RegisterPage } from "./ui/register-page"; +export { CreatePage } from "./ui/create-page"; +export { ModifyPage } from "./ui/modify-page"; export { SitePage } from "./ui/site-page"; diff --git a/apps/cs/src/pages/site/model/form-schema.ts b/apps/cs/src/pages/site/model/form-schema.ts deleted file mode 100644 index edafd5253..000000000 --- a/apps/cs/src/pages/site/model/form-schema.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { ISiteData } from "@/entities/site"; - -const siteFormSchema: ISiteData = { - siteNm: "", - siteExpln: "", - siteKndCd: "", - siteAddr: "", - faxNo: "", - telNo: "", - lwndCn: "", - bscSiteYn: "", - bkmkIcon: "", - useYn: "", - siteSkn: "", -}; - -export { siteFormSchema }; diff --git a/apps/cs/src/pages/site/ui/modify-page.tsx b/apps/cs/src/pages/site/ui/modify-page.tsx new file mode 100644 index 000000000..a7bbc224d --- /dev/null +++ b/apps/cs/src/pages/site/ui/modify-page.tsx @@ -0,0 +1,72 @@ +"use client"; + +import { useEffect } from "react"; +import { useForm } from "react-hook-form"; +import { useMutation, useQuery } from "@tanstack/react-query"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { + SiteApi, + siteFormSchema, + type ISiteDetail, + type SiteFormData, +} from "@/entities/site"; +import { ENDPOINT } from "@/shared/config/api"; +import { SitePageLayout } from "./layout"; +import { SiteForm } from "./site-form"; + +function ModifyPage({ siteId }: { siteId: string }) { + const isModifyMode = !!siteId; + + const { data: siteDetail } = useQuery({ + queryKey: [ENDPOINT.CMS_SERVICE.SITES, siteId], + queryFn: () => SiteApi.siteDetail(siteId), + select: (data) => ({ + ...data, + faxNo: data.faxNumber, + bscSiteYn: data.basicSiteYn, + }), + enabled: isModifyMode, + }); + + const { mutateAsync: modifySite } = useMutation({ + mutationFn: (data: SiteFormData) => SiteApi.modifySite(siteId, data), + onSuccess: (data) => { + console.log("success!", data); + }, + }); + + const form = useForm({ + defaultValues: siteFormSchema.omit({ siteId: true }).parse({ + siteNm: "", + siteKndCd: "", + }), + resolver: zodResolver(siteFormSchema), + }); + + const handleSave = (data: SiteFormData) => { + console.log(data); + modifySite(data); + }; + + useEffect(() => { + if (!siteDetail) return; + + const keys = Object.keys(siteFormSchema.shape); + for (const key of keys) { + form.setValue( + key as keyof SiteFormData, + siteDetail[key as keyof ISiteDetail], + ); + } + }, [siteDetail]); + + console.log(form.watch()); + + return ( + + + + ); +} + +export { ModifyPage }; diff --git a/apps/cs/src/pages/site/ui/register-page.tsx b/apps/cs/src/pages/site/ui/register-page.tsx deleted file mode 100644 index 31e435f6d..000000000 --- a/apps/cs/src/pages/site/ui/register-page.tsx +++ /dev/null @@ -1,406 +0,0 @@ -"use client"; - -import { useState } from "react"; -import { useRouter } from "next/navigation"; -import { useForm } from "react-hook-form"; -import { useQuery } from "@tanstack/react-query"; -import { - Button, - Input, - Label, - RadioGroup, - RadioGroupItem, - Table, - TableBody, - TableCell, - TableHead, - TableRow, -} from "@common/components"; -import { SiteApi, type ISiteDetail } from "@/entities/site"; -import { CodeSelect } from "@/entities/code"; -import { FormItem, FormControl, FormField, Form } from "@/shared/ui/form"; -import { ENDPOINT } from "@/shared/config/api"; -import { SitePageLayout } from "./layout"; -import { IPManagementDialog } from "./ip-management-dialog"; -import { - DomainManagementDialog, - type Domain, -} from "./domain-management-dialog"; -import { siteFormSchema } from "../model/form-schema"; - -type CreateFormData = typeof siteFormSchema & { - siteId: string; -}; -type ModifyFormData = typeof siteFormSchema; -type FormData = CreateFormData | ModifyFormData; -type ViewState = Partial; - -function RegisterPage({ siteId }: { siteId: string }) { - const isModifyMode = !!siteId; - - const router = useRouter(); - const { data: siteDetail } = useQuery({ - queryKey: [ENDPOINT.CMS_SERVICE.SITES, siteId], - queryFn: () => SiteApi.siteDetail(siteId), - select: (data) => { - const newData = { - ...data, - faxNo: data.faxNumber, - bscSiteYn: data.basicSiteYn, - }; - handleViewStateChange("siteKndCd")(data.siteKndCd); - handleViewStateChange("siteSkn")(data.siteSkn); - return newData; - }, - enabled: isModifyMode, - }); - - const form = useForm({ - defaultValues: isModifyMode - ? siteFormSchema - : { ...siteFormSchema, siteId: "" }, - }); - - const [viewState, setViewState] = useState({}); - const [representativeDomain, setRepresentativeDomain] = useState(""); - - const handleViewStateChange = (key: keyof ISiteDetail) => (value: string) => { - setViewState({ ...viewState, [key]: value }); - }; - - const handleDomainSave = (rows: Domain[]) => { - setRepresentativeDomain( - rows.find((row) => row.isRepresentative)?.domainUrl || "", - ); - }; - - const onSubmit = (data: FormData) => { - console.log(data); - }; - - return ( - - - - - - - 사이트 등록/수정 - - - - - - - - - - - 사이트 코드 - - ( - - - - - - )} - /> - - - - 사이트 구분 - - - ( - - - { - handleViewStateChange("siteKndCd")(value); - field.onChange(value); - }} - /> - - - )} - /> - {isModifyMode && ( - - )} - - - - - 사이트 디자인 - - ( - - - - - - )} - /> - - - - 사이트명 - - ( - - - - - - )} - /> - - - - 사이트 설명 - - ( - - - - - - )} - /> - - - - 사이트 도메인 - - - - {representativeDomain} - - - - - - - 사이트 하단 표기 주소 - - ( - - - - - - )} - /> - - - - 사이트 하단 표기 전화번호 - - ( - - - - - - )} - /> - - - - 사이트 하단 표기 팩스번호 - - ( - - - - - - )} - /> - - - - 사이트 하단 표기 내용 - - ( - - - - - - )} - /> - - - - 북마크 아이콘 - - ( - - - - - - )} - /> - - - - 기본 사이트 여부 - - ( - - - - - - 예 - - - - 아니오 - - - - - )} - /> - - - - 사용 여부 - - ( - - - - - - 사용 - - - - 사용안함 - - - - - )} - /> - - - - - - - - - 저장 - - router.back()}> - 취소 - - - 삭제 - - - - - - ); -} - -export { RegisterPage }; diff --git a/apps/cs/src/pages/site/ui/site-form.tsx b/apps/cs/src/pages/site/ui/site-form.tsx new file mode 100644 index 000000000..8bbeee156 --- /dev/null +++ b/apps/cs/src/pages/site/ui/site-form.tsx @@ -0,0 +1,386 @@ +import { useState } from "react"; +import { useRouter } from "next/navigation"; +import { type UseFormReturn } from "react-hook-form"; +import { + Button, + Input, + Label, + RadioGroup, + RadioGroupItem, + Table, + TableBody, + TableCell, + TableHead, + TableRow, +} from "@common/components"; +import { CodeSelect } from "@/entities/code"; +import { type ISiteDetail, type SiteFormData } from "@/entities/site"; +import { + FormItem, + FormControl, + FormField, + Form, + FormMessage, +} from "@/shared/ui/form"; +import { IPManagementDialog } from "./ip-management-dialog"; +import { + DomainManagementDialog, + type Domain, +} from "./domain-management-dialog"; + +type SiteFormProps = { + form: UseFormReturn; + siteId?: string; + handleSave: (data: SiteFormData) => void; +}; + +function SiteForm({ form, siteId, handleSave }: SiteFormProps) { + const router = useRouter(); + + const [viewState, setViewState] = useState>({}); + const [representativeDomain, setRepresentativeDomain] = useState(""); + + const isModifyMode = !!siteId; + + const handleViewStateChange = (key: keyof ISiteDetail) => (value: string) => { + setViewState({ ...viewState, [key]: value }); + }; + + const handleDomainSave = (rows: Domain[]) => { + setRepresentativeDomain( + rows.find((row) => row.isRepresentative)?.domainUrl || "", + ); + }; + + const onSubmit = (data: SiteFormData) => { + handleSave(data); + }; + + return ( + + + + + + 사이트 등록/수정 + + + + + + + + + + + 사이트 코드 + + ( + + + + + + + )} + /> + + + + 사이트 구분 + + + ( + + + { + handleViewStateChange("siteKndCd")(value); + field.onChange(value); + }} + /> + + + + )} + /> + {isModifyMode && ( + + )} + + + + + 사이트 디자인 + + ( + + + + + + + )} + /> + + + + 사이트명 + + ( + + + + + + + )} + /> + + + + 사이트 설명 + + ( + + + + + + + )} + /> + + + + 사이트 도메인 + + + + {representativeDomain} + + + + + + + 사이트 하단 표기 주소 + + ( + + + + + + + )} + /> + + + + 사이트 하단 표기 전화번호 + + ( + + + + + + + )} + /> + + + + 사이트 하단 표기 팩스번호 + + ( + + + + + + + )} + /> + + + + 사이트 하단 표기 내용 + + ( + + + + + + + )} + /> + + + + 북마크 아이콘 + + ( + + + + + + + )} + /> + + + + 기본 사이트 여부 + + ( + + + + + + 예 + + + + 아니오 + + + + + + )} + /> + + + + 사용 여부 + + ( + + + + + + 사용 + + + + 사용안함 + + + + + + )} + /> + + + + + + + + + 저장 + + router.back()}> + 취소 + + + 삭제 + + + + + ); +} + +export { SiteForm }; diff --git a/apps/cs/src/shared/ui/form.tsx b/apps/cs/src/shared/ui/form.tsx index 6d379038f..bd579d263 100644 --- a/apps/cs/src/shared/ui/form.tsx +++ b/apps/cs/src/shared/ui/form.tsx @@ -154,7 +154,7 @@ const FormMessage = React.forwardRef< {body}
{body}