feat: useAlertStore 적용
This commit is contained in:
@@ -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<SiteFormData>({
|
||||
resolver: zodResolver(siteFormSchema),
|
||||
});
|
||||
@@ -35,18 +27,6 @@ function CreatePage() {
|
||||
return (
|
||||
<SitePageLayout>
|
||||
<SiteForm form={form} handleSave={createSite} />
|
||||
<Dialog open={isCreateSuccess} onOpenChange={() => router.back()}>
|
||||
<DialogContent aria-describedby={undefined}>
|
||||
<div className="py-10">
|
||||
<p className="text-center text-[1.4rem]">등록되었습니다.</p>
|
||||
</div>
|
||||
<DialogFooter className="!justify-center">
|
||||
<DialogClose asChild>
|
||||
<Button>확인</Button>
|
||||
</DialogClose>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</SitePageLayout>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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<boolean>(false);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [selectedRows, setSelectedRows] = useState<number[]>([]);
|
||||
|
||||
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("저장되었습니다.");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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<SiteFormData>({
|
||||
resolver: zodResolver(siteFormSchema),
|
||||
@@ -76,18 +70,6 @@ function ModifyPage({ siteId }: { siteId: string }) {
|
||||
handleSave={modifySite}
|
||||
handleDelete={deleteSite}
|
||||
/>
|
||||
<Dialog open={!!message} onOpenChange={() => router.back()}>
|
||||
<DialogContent aria-describedby={undefined}>
|
||||
<div className="py-10">
|
||||
<p className="text-center text-[1.4rem]">{message}</p>
|
||||
</div>
|
||||
<DialogFooter className="!justify-center">
|
||||
<DialogClose asChild>
|
||||
<Button>확인</Button>
|
||||
</DialogClose>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</SitePageLayout>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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<SiteFormData>;
|
||||
siteId?: string;
|
||||
handleSave: (data: SiteFormData) => void;
|
||||
handleDelete?: () => void;
|
||||
handleSave: (data: SiteFormData) => Promise<void>;
|
||||
handleDelete?: () => Promise<void>;
|
||||
};
|
||||
|
||||
function SiteForm({ form, siteId, handleSave, handleDelete }: SiteFormProps) {
|
||||
const router = useRouter();
|
||||
const { message, confirm, onConfirm, onCancel } = useConfirm();
|
||||
|
||||
const [viewState, setViewState] = useState<Partial<ISiteDetail>>({});
|
||||
const [representativeDomain, setRepresentativeDomain] = useState<string>("");
|
||||
|
||||
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) {
|
||||
<CodeSelect
|
||||
{...field}
|
||||
upCd="SITEKNDCD"
|
||||
onValueChange={(value) => {
|
||||
handleViewStateChange("siteKndCd")(value);
|
||||
field.onChange(value);
|
||||
}}
|
||||
onValueChange={field.onChange}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
@@ -132,7 +131,7 @@ function SiteForm({ form, siteId, handleSave, handleDelete }: SiteFormProps) {
|
||||
/>
|
||||
{isModifyMode && (
|
||||
<IPManagementDialog
|
||||
triggerDisabled={viewState.siteKndCd === "O"}
|
||||
triggerDisabled={form.watch("siteKndCd") === "O"}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
@@ -405,25 +404,7 @@ function SiteForm({ form, siteId, handleSave, handleDelete }: SiteFormProps) {
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
<Dialog open={!!message} onOpenChange={onCancel}>
|
||||
<DialogContent aria-describedby={undefined}>
|
||||
<div className="py-10">
|
||||
<p className="text-center text-[1.4rem]">{message}</p>
|
||||
</div>
|
||||
<DialogFooter className="!justify-center">
|
||||
<DialogClose asChild>
|
||||
<Button color="red" onClick={onConfirm}>
|
||||
삭제
|
||||
</Button>
|
||||
</DialogClose>
|
||||
<DialogClose asChild>
|
||||
<Button color="white" onClick={onCancel}>
|
||||
취소
|
||||
</Button>
|
||||
</DialogClose>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
<ConfirmDialog open={isConfirmOpen} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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<AlertStore>()((set) => ({
|
||||
...initState,
|
||||
setAlertMessage: (alertMessage: string) => set(() => ({ alertMessage })),
|
||||
setMessage: (message: string, callback?: () => void) =>
|
||||
set(() => ({ message, callback })),
|
||||
}));
|
||||
};
|
||||
|
||||
@@ -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 (
|
||||
<Dialog open={!!alertMessage} onOpenChange={() => setAlertMessage("")}>
|
||||
<Dialog open={!!message} onOpenChange={handleOpenChange}>
|
||||
<DialogContent aria-describedby={undefined}>
|
||||
<div className="py-10">
|
||||
<p className="text-center text-[1.4rem]">{alertMessage}</p>
|
||||
<p className="text-center text-[1.4rem]">{message}</p>
|
||||
</div>
|
||||
<DialogFooter className="!justify-center">
|
||||
<DialogClose asChild>
|
||||
|
||||
Reference in New Issue
Block a user