Merge branch 'iipbs/common/main' into iipbs/sn/ii

This commit is contained in:
swcho
2025-07-08 19:21:17 +09:00
4 changed files with 98 additions and 32 deletions
@@ -75,7 +75,7 @@ const CustomLegend = (props: any) => {
};
export default function Chart({chartConfig=undefined, chartData=[], chartTitle='차트', chartClassName='w-full h-full', graphSize=40, yFieldText='', showLegend=false} : BarChartProps) {
const colors = ["#FF6B6B", "#4ECDC4", "#45B7D1", "#96CEB4", "#FFEEAD", "#D4A5A5"];
const colors = ["#FF6B6B", "#4ECDC4", "#45B7D1", "#FED16A", "#FFEEAD", "#D4A5A5"];
const getMaxValue = (data: any[], keyPrefix: string) => {
return Math.max(...data.map(item =>
Object.keys(item)
@@ -1,4 +1,5 @@
import { FormField } from "../form";
import React from 'react';
import { FormField } from "../form";
import { SelectBox } from "../select";
import { Input } from "@common/components";
import { FormUi } from "../form_ui";
@@ -55,6 +56,7 @@ interface FormSchema {
bznmTotNo?: string;
rgtr?: string;
dmdAplyPswd?: string;
dmdAplyPswdConfirm?: string;
}
interface SdmRegFormProps {
@@ -85,12 +87,27 @@ export function SdmRegForm({ form, onCheckboxChange, selectSidoData, selectSigun
const formatter = new AsYouType("KR");
const formatted = formatter.input(input);
// 저장할 값 처리: 숫자만 추출
const digitsOnly = input.replace(/\D/g, "");
return formatted
};
// 사업자등록번호 포맷팅 함수 (3-2-5 형식)
const formatBusinessNumber = (value: string) => {
// 숫자만 추출
const digitsOnly = value.replace(/\D/g, "");
// 10자리까지만 처리
const limitedDigits = digitsOnly.slice(0, 10);
// 3-2-5 형식으로 포맷팅
if (limitedDigits.length <= 3) {
return limitedDigits;
} else if (limitedDigits.length <= 5) {
return `${limitedDigits.slice(0, 3)}-${limitedDigits.slice(3)}`;
} else {
return `${limitedDigits.slice(0, 3)}-${limitedDigits.slice(3, 5)}-${limitedDigits.slice(5)}`;
}
};
const initializeSigunData = useCallback((sidoCd: string) => {
if (sidoCd === '0') {
@@ -179,12 +196,15 @@ export function SdmRegForm({ form, onCheckboxChange, selectSidoData, selectSigun
const value = e.target.value;
if(noType === 'dmdInfoPk') {
if(orgBznmNo.substring(0,10) === value) {
// 숫자만 추출하여 저장 (포맷팅 제거)
const digitsOnly = value.replace(/\D/g, "");
if(orgBznmNo.substring(0,10) === digitsOnly) {
setIsDuplicate(true);
} else {
setIsDuplicate(false);
}
field?.onChange(value);
field?.onChange(digitsOnly);
} else {
if(orgBznmNo.substring(10,14) === value) {
setIsDuplicate(true);
@@ -296,7 +316,7 @@ export function SdmRegForm({ form, onCheckboxChange, selectSidoData, selectSigun
type="text"
className="!text-xl text-gray-600"
onChange={(e) => bznNoChange(e, 'dmdInfoPk', field)}
value={field.value}
value={formatBusinessNumber(field.value || '')}
readOnly={!!updateList?.dmdInfoPk}
/>
)
@@ -368,32 +388,60 @@ export function SdmRegForm({ form, onCheckboxChange, selectSidoData, selectSigun
{...field}
/>
)
},
{
name: "dmdAplyPswdConfirm",
label: "패스워드확인",
component: (field) => (
<Input
placeholder="패스워드를 입력하세요"
type="password"
className="!text-xl text-gray-600"
{...field}
/>
)
}
]
return (
<>
{formFields.filter((item)=>
{if(updateList?.dmdInfoPk){
return item.name !== 'dmdAplyPswd'
}else{
return item
}
})
.map(({ name, label, component }) => (
<FormField
key={String(name)}
control={form.control}
name={name}
render={({ field }) => (
name === 'bznmTotNo' ? component(field) : (
<FormUi label={label}>
{component(field)}
</FormUi>
)
)}
/>
))}
{formFields
.filter(({ name }) => !(updateList?.dmdInfoPk && (name === "dmdAplyPswd" || name === "dmdAplyPswdConfirm")))
.map(({ name, label, component }) => {
const error = form.formState.errors[name];
const inputId = `${name}-input`;
const errorId = `${name}-error`;
const isRequired = ["ctpvCd", "sggCd", "dmdCoNm", "dmdInfoPk", "daddr", "telno", "dmdAplyPswd", "dmdAplyPswdConfirm"].includes(name);
return (
<FormField
key={String(name)}
control={form.control}
name={name}
render={({ field }) => (
<div className="mb-4">
<label htmlFor={inputId} className="block text-gray-800 font-medium">
{label}
{isRequired && <span className="text-red-500 ml-1">*</span>}
</label>
{React.cloneElement(component(field), {
id: inputId,
"aria-required": isRequired,
"aria-invalid": !!error,
"aria-describedby": error ? errorId : undefined
})}
{error?.message && (
<p id={errorId} role="alert" className="text-red-500 text-sm mt-1">
{error.message}
</p>
)}
</div>
)}
/>
);
})}
</>
);
}
@@ -47,7 +47,17 @@ const createFormSchema = (isBznmTotNoDisabled: boolean, isDuplicate: boolean ,up
? z.string().optional() // 패스워드는 선택 사항이며 길이 제한 없음
: z.string().optional()
.refine((val) => !val || (val.length >= 8 && val.length <= 16), "패스워드는 8자 이상 16자 이내로 입력해주세요"),
dmdAplyPswdConfirm: z.string()
.min(1, "패스워드확인을 입력해주세요"),
}).refine((data) => {
// 패스워드 확인 검증
if (data.dmdAplyPswd && data.dmdAplyPswdConfirm) {
return data.dmdAplyPswd === data.dmdAplyPswdConfirm;
}
return true;
}, {
message: "패스워드가 일치하지 않습니다",
path: ["dmdAplyPswdConfirm"], // 에러를 패스워드 확인 필드에 표시
});
type FormSchema = z.infer<ReturnType<typeof createFormSchema>>;
@@ -62,6 +72,7 @@ const defaultValues: FormSchema = {
telno: '',
rgtr: '',
dmdAplyPswd: '',
dmdAplyPswdConfirm: '',
};
/**
@@ -149,7 +160,7 @@ export default function SdmInsertForm({selectSidoData, selectSigunData, dataList
console.log(' formData ', formData)
/* await insertSdmData(formData); */
rtnInputData(formData as DemandCompType);
rtnInputData(formData as unknown as DemandCompType);
//router.push(`/pages/sdmMng/sdmInfoInsert?${queryParams.toString()}`);
@@ -13,12 +13,14 @@ type DatePickerProps = {
placeholder?: string;
disabled?: boolean;
selected?: Date;
zIndex?: number; // z-index prop 추가
} & React.ComponentProps<typeof DayPicker>;
export function DatePicker({
className,
placeholder = "날짜 선택",
disabled,
zIndex, // zIndex prop 받기
...props
}: DatePickerProps) {
return (
@@ -37,7 +39,12 @@ export function DatePicker({
)}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0">
<PopoverContent
className={cn(
"w-auto p-0",
zIndex ? `z-[${zIndex}]` : "" // zIndex가 있으면 적용, 없으면 기본값
)}
>
<Calendar classNames={{ cell: "rounded-md" }} {...props} />
</PopoverContent>
</Popover>