From e49e3d3b36e0766d21730d1308dff128fb1e60dd Mon Sep 17 00:00:00 2001 From: bicochan Date: Wed, 19 Mar 2025 18:43:58 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20useAlertStore=20=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/cs/src/pages/site/ui/create-page.tsx | 26 +------ .../pages/site/ui/ip-management-dialog.tsx | 13 ++-- apps/cs/src/pages/site/ui/modify-page.tsx | 28 ++------ apps/cs/src/pages/site/ui/site-form.tsx | 67 +++++++------------ apps/cs/src/shared/store/alert-store.ts | 11 +-- apps/cs/src/shared/ui/alert-dialog.tsx | 10 ++- 6 files changed, 50 insertions(+), 105 deletions(-) diff --git a/apps/cs/src/pages/site/ui/create-page.tsx b/apps/cs/src/pages/site/ui/create-page.tsx index a79c16022..5170b85a9 100644 --- a/apps/cs/src/pages/site/ui/create-page.tsx +++ b/apps/cs/src/pages/site/ui/create-page.tsx @@ -1,6 +1,5 @@ "use client"; -import { useState } from "react"; import { useRouter } from "next/navigation"; import { useForm } from "react-hook-form"; import { useMutation } from "@tanstack/react-query"; @@ -9,25 +8,18 @@ import { SiteApi } from "../api/site-service"; import { siteFormSchema, type SiteFormData } from "../model/site-interface"; import { SitePageLayout } from "./layout"; import { SiteForm } from "./site-form"; -import { - Button, - Dialog, - DialogClose, - DialogContent, - DialogFooter, -} from "@common/components/ui"; +import { useAlertStore } from "@/shared/lib/use-alert-store"; function CreatePage() { const router = useRouter(); + const { setMessage: alert } = useAlertStore((state) => state); const { mutateAsync: createSite } = useMutation({ mutationFn: (data: SiteFormData) => SiteApi.createSite(data), onSuccess: () => { - setIsCreateSuccess(true); + alert("등록되었습니다.", router.back); }, }); - const [isCreateSuccess, setIsCreateSuccess] = useState(false); - const form = useForm({ resolver: zodResolver(siteFormSchema), }); @@ -35,18 +27,6 @@ function CreatePage() { return ( - router.back()}> - -
-

등록되었습니다.

-
- - - - - -
-
); } diff --git a/apps/cs/src/pages/site/ui/ip-management-dialog.tsx b/apps/cs/src/pages/site/ui/ip-management-dialog.tsx index 35166d0de..c62d136b2 100644 --- a/apps/cs/src/pages/site/ui/ip-management-dialog.tsx +++ b/apps/cs/src/pages/site/ui/ip-management-dialog.tsx @@ -47,7 +47,7 @@ function IPManagementDialog({ ...props }: IPManagementDialogProps) { const { confirm } = useConfirm(); - const { setAlertMessage } = useAlertStore((state) => state); + const { setMessage: alert } = useAlertStore((state) => state); useQuery({ queryKey: [ENDPOINT.CMS_SERVICE.IPS, props.open], @@ -74,20 +74,15 @@ function IPManagementDialog({ name: "ips", }); - const [isOpen, setIsOpen] = useState(false); + const [isOpen, setIsOpen] = useState(false); const [selectedRows, setSelectedRows] = useState([]); const onSubmit = async (data: IPFormData) => { setIsOpen(true); if (await confirm("저장하시겠습니까?")) { setIsOpen(false); - try { - await mutateAsync(data.ips); - setAlertMessage("저장되었습니다."); - } catch (error) { - console.error(error); - setAlertMessage("저장에 실패했습니다."); - } + await mutateAsync(data.ips); + alert("저장되었습니다."); } }; diff --git a/apps/cs/src/pages/site/ui/modify-page.tsx b/apps/cs/src/pages/site/ui/modify-page.tsx index 8c3bbd093..ebd8f36c5 100644 --- a/apps/cs/src/pages/site/ui/modify-page.tsx +++ b/apps/cs/src/pages/site/ui/modify-page.tsx @@ -1,11 +1,12 @@ "use client"; -import { useEffect, useState } from "react"; +import { useEffect } from "react"; import { useRouter } from "next/navigation"; import { useForm } from "react-hook-form"; import { useMutation, useQuery } from "@tanstack/react-query"; import { zodResolver } from "@hookform/resolvers/zod"; import { ENDPOINT } from "@/shared/config"; +import { useAlertStore } from "@/shared/lib/use-alert-store"; import { SiteApi } from "../api/site-service"; import { siteFormSchema, @@ -14,18 +15,12 @@ import { } from "../model/site-interface"; import { SitePageLayout } from "./layout"; import { SiteForm } from "./site-form"; -import { - Button, - Dialog, - DialogClose, - DialogContent, - DialogFooter, -} from "@common/components/ui"; function ModifyPage({ siteId }: { siteId: string }) { const isModifyMode = !!siteId; const router = useRouter(); + const { setMessage: alert } = useAlertStore((state) => state); const { data: siteDetail } = useQuery({ queryKey: [ENDPOINT.CMS_SERVICE.SITES, siteId], queryFn: () => SiteApi.siteDetail(siteId), @@ -40,17 +35,16 @@ function ModifyPage({ siteId }: { siteId: string }) { const { mutateAsync: modifySite } = useMutation({ mutationFn: (data: SiteFormData) => SiteApi.modifySite(siteId, data), onSuccess: () => { - setMessage("수정되었습니다."); + alert("수정되었습니다.", router.back); }, }); const { mutateAsync: deleteSite } = useMutation({ mutationFn: () => SiteApi.deleteSite(siteId), onSuccess: () => { - setMessage("삭제되었습니다."); + alert("삭제되었습니다.", router.back); }, }); - const [message, setMessage] = useState(""); const form = useForm({ resolver: zodResolver(siteFormSchema), @@ -76,18 +70,6 @@ function ModifyPage({ siteId }: { siteId: string }) { handleSave={modifySite} handleDelete={deleteSite} /> - router.back()}> - -
-

{message}

-
- - - - - -
-
); } diff --git a/apps/cs/src/pages/site/ui/site-form.tsx b/apps/cs/src/pages/site/ui/site-form.tsx index c554a868c..b1f8c3eed 100644 --- a/apps/cs/src/pages/site/ui/site-form.tsx +++ b/apps/cs/src/pages/site/ui/site-form.tsx @@ -4,10 +4,6 @@ import { useConfirm } from "@frontend-opensource/use-react-hooks"; import { type UseFormReturn } from "react-hook-form"; import { Button, - Dialog, - DialogClose, - DialogContent, - DialogFooter, Input, Label, RadioGroup, @@ -26,7 +22,8 @@ import { Form, FormMessage, } from "@/shared/ui/form"; -import { type ISiteDetail, type SiteFormData } from "../model/site-interface"; +import { ConfirmDialog } from "@/shared/ui/confirm-dialog"; +import { type SiteFormData } from "../model/site-interface"; import { IPManagementDialog } from "./ip-management-dialog"; import { DomainManagementDialog, @@ -36,22 +33,17 @@ import { type SiteFormProps = { form: UseFormReturn; siteId?: string; - handleSave: (data: SiteFormData) => void; - handleDelete?: () => void; + handleSave: (data: SiteFormData) => Promise; + handleDelete?: () => Promise; }; function SiteForm({ form, siteId, handleSave, handleDelete }: SiteFormProps) { - const router = useRouter(); - const { message, confirm, onConfirm, onCancel } = useConfirm(); - - const [viewState, setViewState] = useState>({}); - const [representativeDomain, setRepresentativeDomain] = useState(""); - const isModifyMode = !!siteId; - const handleViewStateChange = (key: keyof ISiteDetail) => (value: string) => { - setViewState({ ...viewState, [key]: value }); - }; + const router = useRouter(); + const { confirm } = useConfirm(); + const [representativeDomain, setRepresentativeDomain] = useState(""); + const [isConfirmOpen, setIsConfirmOpen] = useState(false); const handleDomainSave = (rows: Domain[]) => { setRepresentativeDomain( @@ -59,12 +51,22 @@ function SiteForm({ form, siteId, handleSave, handleDelete }: SiteFormProps) { ); }; - const onSubmit = (data: SiteFormData) => { - handleSave(data); + const onSubmit = async (data: SiteFormData) => { + const confirmMessage = isModifyMode + ? "수정하시겠습니까?" + : "저장하시겠습니까?"; + + setIsConfirmOpen(true); + if (await confirm(confirmMessage)) { + setIsConfirmOpen(false); + handleSave(data); + } }; const onDelete = async () => { - if (await confirm("정말 삭제하시겠습니까?")) { + setIsConfirmOpen(true); + if (await confirm("삭제하시겠습니까?")) { + setIsConfirmOpen(false); handleDelete?.(); } }; @@ -120,10 +122,7 @@ function SiteForm({ form, siteId, handleSave, handleDelete }: SiteFormProps) { { - handleViewStateChange("siteKndCd")(value); - field.onChange(value); - }} + onValueChange={field.onChange} /> @@ -132,7 +131,7 @@ function SiteForm({ form, siteId, handleSave, handleDelete }: SiteFormProps) { /> {isModifyMode && ( )} @@ -405,25 +404,7 @@ function SiteForm({ form, siteId, handleSave, handleDelete }: SiteFormProps) { - - -
-

{message}

-
- - - - - - - - -
-
+ ); } diff --git a/apps/cs/src/shared/store/alert-store.ts b/apps/cs/src/shared/store/alert-store.ts index a6e22d441..3bba65848 100644 --- a/apps/cs/src/shared/store/alert-store.ts +++ b/apps/cs/src/shared/store/alert-store.ts @@ -1,22 +1,25 @@ import { createStore } from "zustand/vanilla"; export type AlertState = { - alertMessage: string; + message: string; + callback?: () => void; }; export type AlertActions = { - setAlertMessage: (message: string) => void; + setMessage: (message: string, callback?: () => void) => void; }; export type AlertStore = AlertState & AlertActions; export const defaultInitState: AlertState = { - alertMessage: "", + message: "", + callback: undefined, }; export const createAlertStore = (initState: AlertState = defaultInitState) => { return createStore()((set) => ({ ...initState, - setAlertMessage: (alertMessage: string) => set(() => ({ alertMessage })), + setMessage: (message: string, callback?: () => void) => + set(() => ({ message, callback })), })); }; diff --git a/apps/cs/src/shared/ui/alert-dialog.tsx b/apps/cs/src/shared/ui/alert-dialog.tsx index 68805ce2f..f7907e0e4 100644 --- a/apps/cs/src/shared/ui/alert-dialog.tsx +++ b/apps/cs/src/shared/ui/alert-dialog.tsx @@ -8,12 +8,16 @@ import { import { useAlertStore } from "../lib/use-alert-store"; function AlertDialog() { - const { alertMessage, setAlertMessage } = useAlertStore((state) => state); + const { message, callback, setMessage } = useAlertStore((state) => state); + const handleOpenChange = () => { + setMessage(""); + callback?.(); + }; return ( - setAlertMessage("")}> +
-

{alertMessage}

+

{message}