Files
sam-react-prod/src/components/molecules/StandardDialog.tsx

219 lines
4.8 KiB
TypeScript
Raw Normal View History

"use client";
/**
*
*
* ->
* - (/릿/)
* - (DialogTitle )
* -
* - ///
*/
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
export interface StandardDialogProps {
open: boolean;
onOpenChange: (open: boolean) => void;
title: string;
description?: string;
children: React.ReactNode;
footer?: React.ReactNode;
size?: "sm" | "md" | "lg" | "xl" | "full";
showClose?: boolean;
className?: string;
}
const sizeClasses = {
sm: "sm:max-w-sm",
md: "sm:max-w-md",
lg: "sm:max-w-lg",
xl: "sm:max-w-xl",
full: "sm:max-w-[95vw]",
};
/**
*
*
* @example
* ```tsx
* <StandardDialog
* open={isOpen}
* onOpenChange={setIsOpen}
* title="품목 등록"
* description="새로운 품목을 등록합니다"
* size="lg"
* >
* <div></div>
* </StandardDialog>
* ```
*/
export function StandardDialog({
open,
onOpenChange,
title,
description,
children,
footer,
size = "md",
showClose = true,
className,
}: StandardDialogProps) {
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className={cn(sizeClasses[size], className)}>
<DialogHeader className="px-6 pt-6">
<DialogTitle>{title}</DialogTitle>
{description && <DialogDescription>{description}</DialogDescription>}
</DialogHeader>
<div className="px-6 pb-6 overflow-y-auto max-h-[60vh]">{children}</div>
{footer && <DialogFooter>{footer}</DialogFooter>}
</DialogContent>
</Dialog>
);
}
/**
*
*/
export interface ConfirmDialogProps {
open: boolean;
onOpenChange: (open: boolean) => void;
title: string;
description: string;
onConfirm: () => void;
confirmText?: string;
cancelText?: string;
confirmVariant?:
| "default"
| "destructive"
| "outline"
| "secondary"
| "ghost"
| "link";
loading?: boolean;
}
export function ConfirmDialog({
open,
onOpenChange,
title,
description,
onConfirm,
confirmText = "확인",
cancelText = "취소",
confirmVariant = "default",
loading = false,
}: ConfirmDialogProps) {
const handleConfirm = () => {
onConfirm();
onOpenChange(false);
};
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="sm:max-w-md">
<DialogHeader className="px-6 pt-6">
<DialogTitle>{title}</DialogTitle>
<DialogDescription>{description}</DialogDescription>
</DialogHeader>
<div className="px-6 pb-4"></div>
<DialogFooter>
<Button
variant="outline"
onClick={() => onOpenChange(false)}
disabled={loading}
>
{cancelText}
</Button>
<Button
variant={confirmVariant}
onClick={handleConfirm}
disabled={loading}
>
{confirmText}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}
/**
*
*/
export interface FormDialogProps {
open: boolean;
onOpenChange: (open: boolean) => void;
title: string;
description?: string;
children: React.ReactNode;
onSave: () => void;
onCancel?: () => void;
saveText?: string;
cancelText?: string;
size?: "sm" | "md" | "lg" | "xl" | "full";
loading?: boolean;
disabled?: boolean;
}
export function FormDialog({
open,
onOpenChange,
title,
description,
children,
onSave,
onCancel,
saveText = "저장",
cancelText = "취소",
size = "md",
loading = false,
disabled = false,
}: FormDialogProps) {
const handleCancel = () => {
if (onCancel) {
onCancel();
}
onOpenChange(false);
};
const handleSave = () => {
onSave();
};
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className={cn(sizeClasses[size])}>
<DialogHeader className="px-6 pt-6">
<DialogTitle>{title}</DialogTitle>
{description && <DialogDescription>{description}</DialogDescription>}
</DialogHeader>
<div className="px-6 pb-4 overflow-y-auto max-h-[60vh]">{children}</div>
<DialogFooter>
<Button variant="outline" onClick={handleCancel} disabled={loading}>
{cancelText}
</Button>
<Button onClick={handleSave} disabled={loading || disabled}>
{saveText}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}