98 lines
2.4 KiB
TypeScript
98 lines
2.4 KiB
TypeScript
|
|
"use client";
|
||
|
|
|
||
|
|
import React from "react";
|
||
|
|
import {
|
||
|
|
Dialog,
|
||
|
|
DialogContent,
|
||
|
|
DialogDescription,
|
||
|
|
DialogFooter,
|
||
|
|
DialogHeader,
|
||
|
|
DialogTitle,
|
||
|
|
} from "@/components/ui/dialog";
|
||
|
|
import { Button } from "@/components/ui/button";
|
||
|
|
import { CheckCircle, XCircle, AlertTriangle, Info } from "lucide-react";
|
||
|
|
|
||
|
|
export type AlertType = "success" | "error" | "warning" | "info";
|
||
|
|
|
||
|
|
interface AlertModalProps {
|
||
|
|
isOpen: boolean;
|
||
|
|
onClose: () => void;
|
||
|
|
type: AlertType;
|
||
|
|
title: string;
|
||
|
|
message: string;
|
||
|
|
confirmText?: string;
|
||
|
|
onConfirm?: () => void;
|
||
|
|
}
|
||
|
|
|
||
|
|
const alertConfig = {
|
||
|
|
success: {
|
||
|
|
icon: CheckCircle,
|
||
|
|
iconColor: "text-green-500",
|
||
|
|
titleColor: "text-green-700",
|
||
|
|
},
|
||
|
|
error: {
|
||
|
|
icon: XCircle,
|
||
|
|
iconColor: "text-red-500",
|
||
|
|
titleColor: "text-red-700",
|
||
|
|
},
|
||
|
|
warning: {
|
||
|
|
icon: AlertTriangle,
|
||
|
|
iconColor: "text-yellow-500",
|
||
|
|
titleColor: "text-yellow-700",
|
||
|
|
},
|
||
|
|
info: {
|
||
|
|
icon: Info,
|
||
|
|
iconColor: "text-blue-500",
|
||
|
|
titleColor: "text-blue-700",
|
||
|
|
},
|
||
|
|
};
|
||
|
|
|
||
|
|
export function AlertModal({
|
||
|
|
isOpen,
|
||
|
|
onClose,
|
||
|
|
type,
|
||
|
|
title,
|
||
|
|
message,
|
||
|
|
confirmText = "확인",
|
||
|
|
onConfirm,
|
||
|
|
}: AlertModalProps) {
|
||
|
|
const config = alertConfig[type];
|
||
|
|
const IconComponent = config.icon;
|
||
|
|
|
||
|
|
const handleConfirm = () => {
|
||
|
|
if (onConfirm) {
|
||
|
|
onConfirm();
|
||
|
|
}
|
||
|
|
onClose();
|
||
|
|
};
|
||
|
|
|
||
|
|
return (
|
||
|
|
<Dialog open={isOpen} onOpenChange={(open) => !open && onClose()}>
|
||
|
|
<DialogContent className="sm:max-w-md">
|
||
|
|
<DialogHeader>
|
||
|
|
<div className="mb-2 flex items-center gap-3">
|
||
|
|
<IconComponent className={`h-6 w-6 ${config.iconColor}`} />
|
||
|
|
<DialogTitle className={config.titleColor}>{title}</DialogTitle>
|
||
|
|
</div>
|
||
|
|
<DialogDescription className="text-left">{message}</DialogDescription>
|
||
|
|
</DialogHeader>
|
||
|
|
|
||
|
|
<DialogFooter>
|
||
|
|
<Button onClick={handleConfirm} className="w-full">
|
||
|
|
{confirmText}
|
||
|
|
</Button>
|
||
|
|
</DialogFooter>
|
||
|
|
</DialogContent>
|
||
|
|
</Dialog>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
// 편의를 위한 래퍼 함수들
|
||
|
|
export const SuccessModal = (props: Omit<AlertModalProps, "type">) => <AlertModal {...props} type="success" />;
|
||
|
|
|
||
|
|
export const ErrorModal = (props: Omit<AlertModalProps, "type">) => <AlertModal {...props} type="error" />;
|
||
|
|
|
||
|
|
export const WarningModal = (props: Omit<AlertModalProps, "type">) => <AlertModal {...props} type="warning" />;
|
||
|
|
|
||
|
|
export const InfoModal = (props: Omit<AlertModalProps, "type">) => <AlertModal {...props} type="info" />;
|