fix: 빗물펌프장 자체 입력정보에서 '설계빈도(년)'에 숫자만 입력되게끔 수정 (placeholder 추가, alert, validation)
This commit is contained in:
@@ -4,7 +4,7 @@ import React, { useState, useEffect } from 'react'
|
||||
const exclnInputColumn = [
|
||||
{ id: "swtrmtZoneNm", title: "배수구역", type: "input" },
|
||||
{ id: "mltvDtdvNm", title: "배수분구", type: "input" },
|
||||
{ id: "designFrqYr", title: "설계빈도(년)", type: "input" },
|
||||
{ id: "designFrqYr", title: "설계빈도(년)", type: "input", placeholder: "예: 10", isNumber: true, length: 4 },
|
||||
]
|
||||
// 오수펌프장 자체 입력 정보
|
||||
const drtwInputColumn = [
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import UiPageNations from "@common/business_components/ui/table/uiPageNations";
|
||||
import { Table, TableBody, TableCell, TableRow, Button } from "@common/components";
|
||||
import { useEffect, useState } from "react";
|
||||
import { confirmToast, showConfirmToast } from '@/components/ui/toast'
|
||||
import { toast, Toaster } from "react-hot-toast";
|
||||
|
||||
type UiTableProps = {
|
||||
headName: React.ReactNode | undefined;
|
||||
@@ -39,6 +41,8 @@ type UiHeadProps = {
|
||||
type?: string;
|
||||
options?: string[];
|
||||
placeholder?: string;
|
||||
isNumber?: boolean;
|
||||
length?: number;
|
||||
};
|
||||
|
||||
export function VerticalTable({
|
||||
@@ -63,6 +67,16 @@ export function VerticalTable({
|
||||
}: UiTableProps) {
|
||||
const [cur, setCur] = useState<number>(1);
|
||||
const [formData, setFormData] = useState<{ [key: string]: string | number | boolean }>({});
|
||||
const [errors, setErrors] = useState<{ [key: string]: string }>({}); // 에러 상태 추가
|
||||
|
||||
// 컴포넌트 언마운트 시 confirmToast 정리
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
// 컴포넌트가 언마운트될 때 global-confirm-toast ID를 가진 Toast 제거
|
||||
toast.dismiss("global-confirm-toast");
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (resetPageNo) {
|
||||
setCur(1);
|
||||
@@ -88,16 +102,33 @@ export function VerticalTable({
|
||||
console.log("New form data:", newFormData); // 디버깅용
|
||||
setFormData(newFormData);
|
||||
|
||||
// 에러 메시지 초기화 (입력이 성공하면 에러 제거)
|
||||
if (errors[id]) {
|
||||
setErrors(prev => {
|
||||
const newErrors = { ...prev };
|
||||
delete newErrors[id];
|
||||
return newErrors;
|
||||
});
|
||||
}
|
||||
|
||||
// 폼 데이터가 변경될 때마다 부모에게 알림
|
||||
if (onFormDataChange) {
|
||||
onFormDataChange(newFormData);
|
||||
}
|
||||
};
|
||||
|
||||
const handlePageChange = (page: number) => {
|
||||
setCur(page);
|
||||
onPageChange(page);
|
||||
};
|
||||
|
||||
const showError = (fieldId: string, message: string) => {
|
||||
setErrors(prev => ({
|
||||
...prev,
|
||||
[fieldId]: message
|
||||
}));
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{headName ? (
|
||||
@@ -142,13 +173,55 @@ export function VerticalTable({
|
||||
))}
|
||||
</select>
|
||||
) : head.type === "input" ? (
|
||||
<input
|
||||
id={head.id}
|
||||
type="text"
|
||||
value={String(formData[head.id] ?? "")}
|
||||
onChange={(e) => handleInputChange(head.id, e.target.value)}
|
||||
className="w-full text-xl border-radius-0 border border-gray-300 rounded-sm px-2 py-1"
|
||||
/>
|
||||
<div className="w-full">
|
||||
<input
|
||||
id={head.id}
|
||||
type="text"
|
||||
value={String(formData[head.id] ?? "")}
|
||||
onChange={(e) => {
|
||||
if (head.isNumber) {
|
||||
const newValue = e.target.value;
|
||||
|
||||
if (newValue === "") {
|
||||
handleInputChange(head.id, newValue);
|
||||
return;
|
||||
}
|
||||
|
||||
const isValidNumber = /^[0-9]+$/.test(newValue);
|
||||
if (!isValidNumber) {
|
||||
showError(head.id, `${head.title}는 숫자만 입력 가능합니다.`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (head.length && newValue.length > head.length) {
|
||||
showError(head.id, `${head.title}는 최대 ${head.length}자까지 입력 가능합니다.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const numericValue = parseInt(newValue);
|
||||
if (isNaN(numericValue) || numericValue < 0) return;
|
||||
|
||||
handleInputChange(head.id, numericValue);
|
||||
} else {
|
||||
const newValue = e.target.value;
|
||||
|
||||
if (head.length && newValue.length > head.length) {
|
||||
showError(head.id, `${head.title}는 최대 ${head.length}자까지 입력 가능합니다.`);
|
||||
return;
|
||||
}
|
||||
|
||||
handleInputChange(head.id, e.target.value);
|
||||
}
|
||||
}}
|
||||
className="w-full text-xl border-radius-0 border border-gray-300 rounded-sm px-2 py-1"
|
||||
placeholder={head.placeholder}
|
||||
/>
|
||||
{errors[head.id] && (
|
||||
<div className="text-red-500 font-bold text-xl mt-1 text-left">
|
||||
{errors[head.id]}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<span>{formData[head.id] ?? "-"}</span>
|
||||
)
|
||||
@@ -189,14 +262,55 @@ export function VerticalTable({
|
||||
))}
|
||||
</select>
|
||||
) : head.type === "input" ? (
|
||||
<input
|
||||
id={head.id}
|
||||
type="text"
|
||||
value={formData[head.id] !== undefined ? String(formData[head.id]) : ""}
|
||||
onChange={(e) => handleInputChange(head.id, e.target.value)}
|
||||
className="w-full text-xl border-radius-0 border border-gray-300 rounded-sm px-2 py-1"
|
||||
placeholder={head.placeholder}
|
||||
/>
|
||||
<div className="w-full">
|
||||
<input
|
||||
id={head.id}
|
||||
type={head.isNumber ? "number" : "text"}
|
||||
value={formData[head.id] !== undefined ? String(formData[head.id]) : ""}
|
||||
onChange={(e) => {
|
||||
if (head.isNumber) {
|
||||
const newValue = e.target.value;
|
||||
|
||||
if (newValue === "") {
|
||||
handleInputChange(head.id, newValue);
|
||||
return;
|
||||
}
|
||||
|
||||
const isValidNumber = /^[0-9]+$/.test(newValue);
|
||||
if (!isValidNumber) {
|
||||
showError(head.id, `${head.title}는 숫자만 입력 가능합니다.`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (head.length && newValue.length > head.length) {
|
||||
showError(head.id, `${head.title}는 최대 ${head.length}자까지 입력 가능합니다.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const numericValue = parseInt(newValue);
|
||||
if (isNaN(numericValue) || numericValue < 0) return;
|
||||
|
||||
handleInputChange(head.id, numericValue);
|
||||
} else {
|
||||
const newValue = e.target.value;
|
||||
|
||||
if (head.length && newValue.length > head.length) {
|
||||
showError(head.id, `${head.title}는 최대 ${head.length}자까지 입력 가능합니다.`);
|
||||
return;
|
||||
}
|
||||
|
||||
handleInputChange(head.id, e.target.value);
|
||||
}
|
||||
}}
|
||||
className="w-full text-xl border-radius-0 border border-gray-300 rounded-sm px-2 py-1"
|
||||
placeholder={head.placeholder}
|
||||
/>
|
||||
{errors[head.id] && (
|
||||
<div className="text-red-500 font-bold text-xl mt-1 text-left">
|
||||
{errors[head.id]}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<span>{formData[head.id] ?? "-"}</span>
|
||||
)
|
||||
@@ -218,6 +332,7 @@ export function VerticalTable({
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<Toaster position="top-center"></Toaster>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user