- 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.
89 lines
2.7 KiB
TypeScript
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>
|
|
);
|
|
}
|