ERP-node/frontend/components/admin/CompanyFormModal.tsx

143 lines
4.3 KiB
TypeScript
Raw Normal View History

2025-08-21 09:41:46 +09:00
import { useState } from "react";
import { CompanyModalState, CompanyFormData } from "@/types/company";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
import { LoadingSpinner } from "@/components/common/LoadingSpinner";
interface CompanyFormModalProps {
modalState: CompanyModalState;
isLoading: boolean;
error: string | null;
onClose: () => void;
onSave: () => Promise<boolean>;
onFormChange: (field: keyof CompanyFormData, value: string) => void;
onClearError: () => void;
}
/**
* /
*/
export function CompanyFormModal({
modalState,
isLoading,
error,
onClose,
onSave,
onFormChange,
onClearError,
}: CompanyFormModalProps) {
const [isSaving, setIsSaving] = useState(false);
// 모달이 열려있지 않으면 렌더링하지 않음
if (!modalState.isOpen) return null;
const { mode, formData, selectedCompany } = modalState;
const isEditMode = mode === "edit";
// 저장 처리
const handleSave = async () => {
// 입력값 검증
if (!formData.company_name.trim()) {
return;
}
setIsSaving(true);
onClearError();
try {
const success = await onSave();
if (success) {
// 성공 시 모달 닫기
onClose();
}
} catch (err) {
// 에러는 부모 컴포넌트에서 처리
} finally {
setIsSaving(false);
}
};
// 취소 처리
const handleCancel = () => {
onClearError();
onClose();
};
// Enter 키 처리
const handleKeyDown = (e: React.KeyboardEvent) => {
if (e.key === "Enter" && !isLoading && !isSaving) {
e.preventDefault();
handleSave();
}
};
return (
<Dialog open={modalState.isOpen} onOpenChange={handleCancel}>
<DialogContent className="sm:max-w-[425px]" onKeyDown={handleKeyDown}>
<DialogHeader>
<DialogTitle>{isEditMode ? "회사 정보 수정" : "새 회사 등록"}</DialogTitle>
</DialogHeader>
<div className="space-y-4 py-4">
{/* 회사명 입력 */}
<div className="space-y-2">
<Label htmlFor="company_name">
<span className="text-destructive">*</span>
</Label>
<Input
id="company_name"
value={formData.company_name}
onChange={(e) => onFormChange("company_name", e.target.value)}
placeholder="회사명을 입력하세요"
disabled={isLoading || isSaving}
className={error ? "border-destructive" : ""}
autoFocus
/>
</div>
{/* 에러 메시지 */}
{error && (
<div className="bg-destructive/10 rounded-md p-3">
<p className="text-destructive text-sm">{error}</p>
</div>
)}
{/* 수정 모드일 때 추가 정보 표시 */}
{isEditMode && modalState.selectedCompany && (
<div className="bg-muted/50 rounded-md p-3">
<div className="space-y-1 text-sm">
<p>
<span className="font-medium"> :</span> {modalState.selectedCompany.company_code}
</p>
<p>
<span className="font-medium">:</span> {modalState.selectedCompany.writer}
</p>
<p>
<span className="font-medium">:</span>{" "}
{new Date(modalState.selectedCompany.regdate).toLocaleDateString("ko-KR")}
</p>
</div>
</div>
)}
</div>
<DialogFooter>
<Button variant="outline" onClick={handleCancel} disabled={isLoading || isSaving}>
</Button>
<Button
onClick={handleSave}
disabled={isLoading || isSaving || !formData.company_name.trim()}
className="min-w-[80px]"
>
{(isLoading || isSaving) && <LoadingSpinner className="mr-2 h-4 w-4" />}
{isEditMode ? "수정" : "등록"}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}