Files
vexplor/frontend/components/common/FullscreenDialog.tsx
kjs 1c562fa854 Update item info and sales order pages with new components and functionality
- Updated the item information page to include category code to label conversion for better data representation.
- Enhanced the sales order page by integrating a fullscreen dialog for improved user experience during order registration and editing.
- Added dynamic loading of delivery options based on selected customers to streamline the order process.
- Introduced a new FullscreenDialog component for consistent fullscreen behavior across modals.
- Implemented validation utilities for form fields to ensure data integrity during user input.
2026-03-24 15:32:56 +09:00

89 lines
2.7 KiB
TypeScript

"use client";
/**
* FullscreenDialog — 전체화면 토글이 포함된 공통 Dialog
*
* 사용법:
* <FullscreenDialog open={open} onOpenChange={setOpen} title="제목" description="설명">
* {children}
* </FullscreenDialog>
*
* footer prop으로 하단 버튼 영역 커스텀 가능
*/
import React, { useState } from "react";
import {
Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Maximize2, Minimize2 } from "lucide-react";
import { cn } from "@/lib/utils";
interface FullscreenDialogProps {
open: boolean;
onOpenChange: (open: boolean) => void;
title: React.ReactNode;
description?: React.ReactNode;
children: React.ReactNode;
footer?: React.ReactNode;
/** 기본 모달 최대 너비 (기본: "max-w-5xl") */
defaultMaxWidth?: string;
/** 기본 모달 너비 (기본: "w-[95vw]") */
defaultWidth?: string;
className?: string;
}
export function FullscreenDialog({
open, onOpenChange, title, description, children, footer,
defaultMaxWidth = "max-w-5xl",
defaultWidth = "w-[95vw]",
className,
}: FullscreenDialogProps) {
const [isFullscreen, setIsFullscreen] = useState(false);
const handleOpenChange = (v: boolean) => {
if (!v) setIsFullscreen(false);
onOpenChange(v);
};
return (
<Dialog open={open} onOpenChange={handleOpenChange}>
<DialogContent className={cn(
"overflow-auto flex flex-col transition-all duration-200",
isFullscreen
? "max-w-screen max-h-screen w-screen h-screen rounded-none"
: `${defaultMaxWidth} ${defaultWidth} max-h-[90vh]`,
className,
)}>
<DialogHeader className="shrink-0">
<div className="flex items-center justify-between pr-8">
<div>
{typeof title === "string" ? <DialogTitle>{title}</DialogTitle> : title}
{description && (
typeof description === "string"
? <DialogDescription>{description}</DialogDescription>
: description
)}
</div>
<Button variant="ghost" size="sm" className="h-8 w-8 p-0"
onClick={() => setIsFullscreen((p) => !p)}
title={isFullscreen ? "기본 크기" : "전체 화면"}>
{isFullscreen ? <Minimize2 className="h-4 w-4" /> : <Maximize2 className="h-4 w-4" />}
</Button>
</div>
</DialogHeader>
<div className="flex-1 overflow-auto">
{children}
</div>
{footer && (
<DialogFooter className="shrink-0">
{footer}
</DialogFooter>
)}
</DialogContent>
</Dialog>
);
}