feat: useAlertStore 적용
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState } from "react";
|
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { useMutation } from "@tanstack/react-query";
|
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 { siteFormSchema, type SiteFormData } from "../model/site-interface";
|
||||||
import { SitePageLayout } from "./layout";
|
import { SitePageLayout } from "./layout";
|
||||||
import { SiteForm } from "./site-form";
|
import { SiteForm } from "./site-form";
|
||||||
import {
|
import { useAlertStore } from "@/shared/lib/use-alert-store";
|
||||||
Button,
|
|
||||||
Dialog,
|
|
||||||
DialogClose,
|
|
||||||
DialogContent,
|
|
||||||
DialogFooter,
|
|
||||||
} from "@common/components/ui";
|
|
||||||
|
|
||||||
function CreatePage() {
|
function CreatePage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const { setMessage: alert } = useAlertStore((state) => state);
|
||||||
const { mutateAsync: createSite } = useMutation({
|
const { mutateAsync: createSite } = useMutation({
|
||||||
mutationFn: (data: SiteFormData) => SiteApi.createSite(data),
|
mutationFn: (data: SiteFormData) => SiteApi.createSite(data),
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
setIsCreateSuccess(true);
|
alert("등록되었습니다.", router.back);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const [isCreateSuccess, setIsCreateSuccess] = useState(false);
|
|
||||||
|
|
||||||
const form = useForm<SiteFormData>({
|
const form = useForm<SiteFormData>({
|
||||||
resolver: zodResolver(siteFormSchema),
|
resolver: zodResolver(siteFormSchema),
|
||||||
});
|
});
|
||||||
@@ -35,18 +27,6 @@ function CreatePage() {
|
|||||||
return (
|
return (
|
||||||
<SitePageLayout>
|
<SitePageLayout>
|
||||||
<SiteForm form={form} handleSave={createSite} />
|
<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>
|
</SitePageLayout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ function IPManagementDialog({
|
|||||||
...props
|
...props
|
||||||
}: IPManagementDialogProps) {
|
}: IPManagementDialogProps) {
|
||||||
const { confirm } = useConfirm();
|
const { confirm } = useConfirm();
|
||||||
const { setAlertMessage } = useAlertStore((state) => state);
|
const { setMessage: alert } = useAlertStore((state) => state);
|
||||||
|
|
||||||
useQuery({
|
useQuery({
|
||||||
queryKey: [ENDPOINT.CMS_SERVICE.IPS, props.open],
|
queryKey: [ENDPOINT.CMS_SERVICE.IPS, props.open],
|
||||||
@@ -74,20 +74,15 @@ function IPManagementDialog({
|
|||||||
name: "ips",
|
name: "ips",
|
||||||
});
|
});
|
||||||
|
|
||||||
const [isOpen, setIsOpen] = useState<boolean>(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const [selectedRows, setSelectedRows] = useState<number[]>([]);
|
const [selectedRows, setSelectedRows] = useState<number[]>([]);
|
||||||
|
|
||||||
const onSubmit = async (data: IPFormData) => {
|
const onSubmit = async (data: IPFormData) => {
|
||||||
setIsOpen(true);
|
setIsOpen(true);
|
||||||
if (await confirm("저장하시겠습니까?")) {
|
if (await confirm("저장하시겠습니까?")) {
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
try {
|
await mutateAsync(data.ips);
|
||||||
await mutateAsync(data.ips);
|
alert("저장되었습니다.");
|
||||||
setAlertMessage("저장되었습니다.");
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
setAlertMessage("저장에 실패했습니다.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect } from "react";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { ENDPOINT } from "@/shared/config";
|
import { ENDPOINT } from "@/shared/config";
|
||||||
|
import { useAlertStore } from "@/shared/lib/use-alert-store";
|
||||||
import { SiteApi } from "../api/site-service";
|
import { SiteApi } from "../api/site-service";
|
||||||
import {
|
import {
|
||||||
siteFormSchema,
|
siteFormSchema,
|
||||||
@@ -14,18 +15,12 @@ import {
|
|||||||
} from "../model/site-interface";
|
} from "../model/site-interface";
|
||||||
import { SitePageLayout } from "./layout";
|
import { SitePageLayout } from "./layout";
|
||||||
import { SiteForm } from "./site-form";
|
import { SiteForm } from "./site-form";
|
||||||
import {
|
|
||||||
Button,
|
|
||||||
Dialog,
|
|
||||||
DialogClose,
|
|
||||||
DialogContent,
|
|
||||||
DialogFooter,
|
|
||||||
} from "@common/components/ui";
|
|
||||||
|
|
||||||
function ModifyPage({ siteId }: { siteId: string }) {
|
function ModifyPage({ siteId }: { siteId: string }) {
|
||||||
const isModifyMode = !!siteId;
|
const isModifyMode = !!siteId;
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const { setMessage: alert } = useAlertStore((state) => state);
|
||||||
const { data: siteDetail } = useQuery({
|
const { data: siteDetail } = useQuery({
|
||||||
queryKey: [ENDPOINT.CMS_SERVICE.SITES, siteId],
|
queryKey: [ENDPOINT.CMS_SERVICE.SITES, siteId],
|
||||||
queryFn: () => SiteApi.siteDetail(siteId),
|
queryFn: () => SiteApi.siteDetail(siteId),
|
||||||
@@ -40,17 +35,16 @@ function ModifyPage({ siteId }: { siteId: string }) {
|
|||||||
const { mutateAsync: modifySite } = useMutation({
|
const { mutateAsync: modifySite } = useMutation({
|
||||||
mutationFn: (data: SiteFormData) => SiteApi.modifySite(siteId, data),
|
mutationFn: (data: SiteFormData) => SiteApi.modifySite(siteId, data),
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
setMessage("수정되었습니다.");
|
alert("수정되었습니다.", router.back);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const { mutateAsync: deleteSite } = useMutation({
|
const { mutateAsync: deleteSite } = useMutation({
|
||||||
mutationFn: () => SiteApi.deleteSite(siteId),
|
mutationFn: () => SiteApi.deleteSite(siteId),
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
setMessage("삭제되었습니다.");
|
alert("삭제되었습니다.", router.back);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const [message, setMessage] = useState("");
|
|
||||||
|
|
||||||
const form = useForm<SiteFormData>({
|
const form = useForm<SiteFormData>({
|
||||||
resolver: zodResolver(siteFormSchema),
|
resolver: zodResolver(siteFormSchema),
|
||||||
@@ -76,18 +70,6 @@ function ModifyPage({ siteId }: { siteId: string }) {
|
|||||||
handleSave={modifySite}
|
handleSave={modifySite}
|
||||||
handleDelete={deleteSite}
|
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>
|
</SitePageLayout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,6 @@ import { useConfirm } from "@frontend-opensource/use-react-hooks";
|
|||||||
import { type UseFormReturn } from "react-hook-form";
|
import { type UseFormReturn } from "react-hook-form";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Dialog,
|
|
||||||
DialogClose,
|
|
||||||
DialogContent,
|
|
||||||
DialogFooter,
|
|
||||||
Input,
|
Input,
|
||||||
Label,
|
Label,
|
||||||
RadioGroup,
|
RadioGroup,
|
||||||
@@ -26,7 +22,8 @@ import {
|
|||||||
Form,
|
Form,
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "@/shared/ui/form";
|
} 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 { IPManagementDialog } from "./ip-management-dialog";
|
||||||
import {
|
import {
|
||||||
DomainManagementDialog,
|
DomainManagementDialog,
|
||||||
@@ -36,22 +33,17 @@ import {
|
|||||||
type SiteFormProps = {
|
type SiteFormProps = {
|
||||||
form: UseFormReturn<SiteFormData>;
|
form: UseFormReturn<SiteFormData>;
|
||||||
siteId?: string;
|
siteId?: string;
|
||||||
handleSave: (data: SiteFormData) => void;
|
handleSave: (data: SiteFormData) => Promise<void>;
|
||||||
handleDelete?: () => void;
|
handleDelete?: () => Promise<void>;
|
||||||
};
|
};
|
||||||
|
|
||||||
function SiteForm({ form, siteId, handleSave, handleDelete }: SiteFormProps) {
|
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 isModifyMode = !!siteId;
|
||||||
|
|
||||||
const handleViewStateChange = (key: keyof ISiteDetail) => (value: string) => {
|
const router = useRouter();
|
||||||
setViewState({ ...viewState, [key]: value });
|
const { confirm } = useConfirm();
|
||||||
};
|
const [representativeDomain, setRepresentativeDomain] = useState("");
|
||||||
|
const [isConfirmOpen, setIsConfirmOpen] = useState(false);
|
||||||
|
|
||||||
const handleDomainSave = (rows: Domain[]) => {
|
const handleDomainSave = (rows: Domain[]) => {
|
||||||
setRepresentativeDomain(
|
setRepresentativeDomain(
|
||||||
@@ -59,12 +51,22 @@ function SiteForm({ form, siteId, handleSave, handleDelete }: SiteFormProps) {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onSubmit = (data: SiteFormData) => {
|
const onSubmit = async (data: SiteFormData) => {
|
||||||
handleSave(data);
|
const confirmMessage = isModifyMode
|
||||||
|
? "수정하시겠습니까?"
|
||||||
|
: "저장하시겠습니까?";
|
||||||
|
|
||||||
|
setIsConfirmOpen(true);
|
||||||
|
if (await confirm(confirmMessage)) {
|
||||||
|
setIsConfirmOpen(false);
|
||||||
|
handleSave(data);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onDelete = async () => {
|
const onDelete = async () => {
|
||||||
if (await confirm("정말 삭제하시겠습니까?")) {
|
setIsConfirmOpen(true);
|
||||||
|
if (await confirm("삭제하시겠습니까?")) {
|
||||||
|
setIsConfirmOpen(false);
|
||||||
handleDelete?.();
|
handleDelete?.();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -120,10 +122,7 @@ function SiteForm({ form, siteId, handleSave, handleDelete }: SiteFormProps) {
|
|||||||
<CodeSelect
|
<CodeSelect
|
||||||
{...field}
|
{...field}
|
||||||
upCd="SITEKNDCD"
|
upCd="SITEKNDCD"
|
||||||
onValueChange={(value) => {
|
onValueChange={field.onChange}
|
||||||
handleViewStateChange("siteKndCd")(value);
|
|
||||||
field.onChange(value);
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@@ -132,7 +131,7 @@ function SiteForm({ form, siteId, handleSave, handleDelete }: SiteFormProps) {
|
|||||||
/>
|
/>
|
||||||
{isModifyMode && (
|
{isModifyMode && (
|
||||||
<IPManagementDialog
|
<IPManagementDialog
|
||||||
triggerDisabled={viewState.siteKndCd === "O"}
|
triggerDisabled={form.watch("siteKndCd") === "O"}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -405,25 +404,7 @@ function SiteForm({ form, siteId, handleSave, handleDelete }: SiteFormProps) {
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
<Dialog open={!!message} onOpenChange={onCancel}>
|
<ConfirmDialog open={isConfirmOpen} />
|
||||||
<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>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,25 @@
|
|||||||
import { createStore } from "zustand/vanilla";
|
import { createStore } from "zustand/vanilla";
|
||||||
|
|
||||||
export type AlertState = {
|
export type AlertState = {
|
||||||
alertMessage: string;
|
message: string;
|
||||||
|
callback?: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type AlertActions = {
|
export type AlertActions = {
|
||||||
setAlertMessage: (message: string) => void;
|
setMessage: (message: string, callback?: () => void) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type AlertStore = AlertState & AlertActions;
|
export type AlertStore = AlertState & AlertActions;
|
||||||
|
|
||||||
export const defaultInitState: AlertState = {
|
export const defaultInitState: AlertState = {
|
||||||
alertMessage: "",
|
message: "",
|
||||||
|
callback: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const createAlertStore = (initState: AlertState = defaultInitState) => {
|
export const createAlertStore = (initState: AlertState = defaultInitState) => {
|
||||||
return createStore<AlertStore>()((set) => ({
|
return createStore<AlertStore>()((set) => ({
|
||||||
...initState,
|
...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";
|
import { useAlertStore } from "../lib/use-alert-store";
|
||||||
|
|
||||||
function AlertDialog() {
|
function AlertDialog() {
|
||||||
const { alertMessage, setAlertMessage } = useAlertStore((state) => state);
|
const { message, callback, setMessage } = useAlertStore((state) => state);
|
||||||
|
const handleOpenChange = () => {
|
||||||
|
setMessage("");
|
||||||
|
callback?.();
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<Dialog open={!!alertMessage} onOpenChange={() => setAlertMessage("")}>
|
<Dialog open={!!message} onOpenChange={handleOpenChange}>
|
||||||
<DialogContent aria-describedby={undefined}>
|
<DialogContent aria-describedby={undefined}>
|
||||||
<div className="py-10">
|
<div className="py-10">
|
||||||
<p className="text-center text-[1.4rem]">{alertMessage}</p>
|
<p className="text-center text-[1.4rem]">{message}</p>
|
||||||
</div>
|
</div>
|
||||||
<DialogFooter className="!justify-center">
|
<DialogFooter className="!justify-center">
|
||||||
<DialogClose asChild>
|
<DialogClose asChild>
|
||||||
|
|||||||
Reference in New Issue
Block a user