From b00e5c48435a3507ad24cf5c8fab12f1d86e5ced Mon Sep 17 00:00:00 2001 From: YangJinSoo94 Date: Tue, 10 Jun 2025 15:50:25 +0900 Subject: [PATCH 1/7] =?UTF-8?q?=EB=8F=84=EB=84=9B=EB=B0=94=20=EC=83=89?= =?UTF-8?q?=EC=83=81=EC=9E=85=ED=9E=88=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/ui/chart/DoughnutChart.tsx | 125 +++++++++++++++--- .../src/ui/chart/LineBarChart.tsx | 3 - 2 files changed, 109 insertions(+), 19 deletions(-) diff --git a/packages/common/business_components/src/ui/chart/DoughnutChart.tsx b/packages/common/business_components/src/ui/chart/DoughnutChart.tsx index f88b35476..d666f1d14 100644 --- a/packages/common/business_components/src/ui/chart/DoughnutChart.tsx +++ b/packages/common/business_components/src/ui/chart/DoughnutChart.tsx @@ -1,27 +1,116 @@ "use client" import { Pie, PieChart } from "recharts"; - +import type { CSSProperties } from "react"; import { Card, CardContent } from "./lib/card"; -import { - ChartContainer, - ChartTooltip, - ChartTooltipContent, - type ChartConfig -} from "./lib/chart"; +import { ChartContainer, ChartTooltip } from "./lib/chart"; -// eslint-disable-next-line react-refresh/only-export-components -export default (props: { chartConfig: ChartConfig; chartData: never[] | undefined; chartTitle:string}) =>{ +type ChartDataItem = { + label: string; + val: number; +}; + +type ChartConfigItem = { + label: string; + fill: string; +}; + +type ChartConfig = { + [key: string]: ChartConfigItem; +}; + +type TooltipPayloadItem = { + name: string; + value: number; + payload: { + label: string; + val: number; + fill: string; + }; +}; + +type LegendEntry = { + value: string; + fill: string; + type?: string; + payload: { + label: string; + val: number; + fill: string; + }; +}; + +type LegendProps = { + payload?: LegendEntry[]; +}; + +/** 차트 기본 스타일 */ +const customStyles = { + legendContainer: { + display: "flex", + justifyContent: "center", + gap: "20px", + fontSize: "9px", + fontWeight: "bold", + marginTop: "10px", + } as CSSProperties, +}; + +// 커스텀 툴팁 +const CustomTooltip = ({ active, payload, label }: { + active?: boolean; + payload?: TooltipPayloadItem[]; + label?: string +}) => { + if (active && payload && payload.length) { + return ( +
+

{label}

+ {payload.map((item, index) => ( +
+
+ {` ${item.name} : ${item.value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}`} +
+ ))} +
+ ); + } + return null; +}; + +// 커스텀 범례 +const CustomLegend = (props: LegendProps) => { + const { payload } = props; + if (!payload) return null; + + return ( +
+ {payload.map((entry: LegendEntry, index: number) => ( +
+
+ {entry.value} +
+ ))} +
+ ); +}; + +export default function DoughnutChart(props: { + chartConfig: ChartConfig; + chartData: ChartDataItem[] | undefined; + chartTitle: string +}) { return ( - {props.chartTitle && props.chartTitle !== "" && props.chartTitle !== "undefined" ? ( -
- {props.chartTitle} -
): null} + {props.chartTitle && props.chartTitle !== "" && props.chartTitle !== "undefined" ? ( +
+ {props.chartTitle} +
+ ) : null}
} + content={} /> ({ + ...item, + fill: props.chartConfig[item.label]?.fill || 'blue' + }))} dataKey="val" nameKey="label" innerRadius={60} /> +
- ) + ); } diff --git a/packages/common/business_components/src/ui/chart/LineBarChart.tsx b/packages/common/business_components/src/ui/chart/LineBarChart.tsx index 2e83458d8..8c7202104 100644 --- a/packages/common/business_components/src/ui/chart/LineBarChart.tsx +++ b/packages/common/business_components/src/ui/chart/LineBarChart.tsx @@ -92,9 +92,6 @@ export default function LineBarchart({ return
데이터가 없습니다.
; } - const barConfig = chartConfig?.barVal; - const lineConfig = chartConfig?.lineVal; - // 데이터의 최대값 계산 const getMaxValue = (data: any[], keyPrefix: string) => { return Math.max(...data.map(item => From 068c6a08cd2669fa34daac1ce835c4a484f96b4b Mon Sep 17 00:00:00 2001 From: YangJinSoo94 Date: Tue, 10 Jun 2025 17:34:31 +0900 Subject: [PATCH 2/7] =?UTF-8?q?=EB=8D=94=EB=B8=94=EB=B0=94=20=EC=B0=A8?= =?UTF-8?q?=ED=8A=B8=20=EC=83=9D=EC=84=B1=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/ui/chart/DoubleBar.tsx | 137 ++++++++++++++++++ .../src/ui/chart/index.tsx | 9 +- 2 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 packages/common/business_components/src/ui/chart/DoubleBar.tsx diff --git a/packages/common/business_components/src/ui/chart/DoubleBar.tsx b/packages/common/business_components/src/ui/chart/DoubleBar.tsx new file mode 100644 index 000000000..5b136690a --- /dev/null +++ b/packages/common/business_components/src/ui/chart/DoubleBar.tsx @@ -0,0 +1,137 @@ +"use client" +import { Bar, BarChart, CartesianGrid, Legend, XAxis, YAxis } from "recharts"; +import { + ChartContainer, + ChartTooltip, + type ChartConfig +} from "./lib/chart"; +import type { CSSProperties } from "react"; + +const customStyles = { + legendContainer: { + display: "flex", + justifyContent: "center", + gap: "20px", + fontSize: "9px", + fontWeight : "bold", + marginTop: "10px", + } as CSSProperties, +}; + +type BarChartProps = { + chartConfig: ChartConfig | undefined; + chartData: any[] | undefined; + chartTitle: string; + chartClassName?: string; + graphSize?: number; + yFieldText?: string; + showLegend?: boolean; +} + +// 커스텀 툴팁 +const CustomTooltip = ({ + active, + payload, + label +}: { + active?: boolean; + payload?: Array<{ + name: string; + value: number; + color: string; + }>; + label?: string; +}) => { + if (active && payload && payload.length) { + return ( +
+

{label}

+ {payload.map((item, index) => ( +
+ {/* 색상 박스 추가 (범례 색상과 동일) */} +
+ {` ${item.name} : ${item.value}`} +
+ ))} +
+ ); + } + return null; +}; + +// 커스텀 범례 (글씨 크기 키우기 + 스타일 추가) +const CustomLegend = (props: any) => { + const { payload } = props; + return ( +
+ {payload.map((entry: unknown, index: number) => ( +
+
+ {(entry as {value: string}).value} +
+ ))} +
+ ); +}; + +export default function DoubleBarChart({chartConfig=undefined, chartData=[], chartTitle='차트', chartClassName='w-full h-full', graphSize=40, yFieldText='', showLegend=false} : BarChartProps) { + const colors = ["#FF6B6B", "#4ECDC4", "#45B7D1", "#96CEB4", "#FFEEAD", "#D4A5A5"]; + const getMaxValue = (data: any[], keyPrefix: string) => { + return Math.max(...data.map(item => + Object.keys(item) + .filter(key => key.includes(keyPrefix)) + .map(key => item[key]) + ).flat()); + }; + console.log(chartData); + const barMaxValue = getMaxValue(chartData, 'barVal'); + return ( + <> + {chartTitle && chartTitle !== "" && chartTitle !== "undefined" ? ( +
+ {chartTitle} +
): null} +
+ + + + + + }/> + {chartData && chartData.length > 0 && ( + Object.keys(chartData[0]) + .filter(key => key !== "label") + .map((key, idx) => ( + + )) + )} + {showLegend && } + + +
+ + ) +} \ No newline at end of file diff --git a/packages/common/business_components/src/ui/chart/index.tsx b/packages/common/business_components/src/ui/chart/index.tsx index 0d17a99b1..4c58549cc 100644 --- a/packages/common/business_components/src/ui/chart/index.tsx +++ b/packages/common/business_components/src/ui/chart/index.tsx @@ -5,6 +5,7 @@ import DoughnutChart from './DoughnutChart'; import { type ChartConfig } from './lib/chart'; import LineChart from './LineChart'; import LineBarchart from './LineBarChart'; +import DoubleBarChart from './DoubleBar'; /**차트 FORM */ const CHART_FORM = { @@ -15,7 +16,9 @@ const CHART_FORM = { /**도넛 차트 형태*/ DN :'daughnut', /**LINE,BAR차트 */ - LINEBAR : 'linebar' + LINEBAR : 'linebar', + /**더블바 차트 형태*/ + DOUBLEBAR : 'doublebar' }; /** @@ -61,6 +64,10 @@ function MainChart(props: MainChartProps) { return ( ); + } else if (props.chartForm == CHART_FORM.DOUBLEBAR){ + return ( + + ); } } From c2fae1bf4bbe18791d3777e8d6e11c2bc70acef6 Mon Sep 17 00:00:00 2001 From: YangJinSoo94 Date: Tue, 10 Jun 2025 18:59:56 +0900 Subject: [PATCH 3/7] =?UTF-8?q?=EB=8D=94=EB=B8=94=EB=B0=94=20=ED=83=80?= =?UTF-8?q?=EC=9D=B4=ED=8B=80=ED=81=AC=EA=B8=B0=20=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/business_components/src/ui/chart/DoubleBar.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/common/business_components/src/ui/chart/DoubleBar.tsx b/packages/common/business_components/src/ui/chart/DoubleBar.tsx index 5b136690a..9627485aa 100644 --- a/packages/common/business_components/src/ui/chart/DoubleBar.tsx +++ b/packages/common/business_components/src/ui/chart/DoubleBar.tsx @@ -88,8 +88,8 @@ export default function DoubleBarChart({chartConfig=undefined, chartData=[], cha return ( <> {chartTitle && chartTitle !== "" && chartTitle !== "undefined" ? ( -
- {chartTitle} +
+ {chartTitle}
): null}
From 7b8f76c78d5c765a2cf11eea947aab3f4e827fee Mon Sep 17 00:00:00 2001 From: YangJinSoo94 Date: Thu, 12 Jun 2025 09:35:27 +0900 Subject: [PATCH 4/7] =?UTF-8?q?-=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EB=AA=A8?= =?UTF-8?q?=EB=8B=AC=ED=99=94=20=EC=A7=84=ED=96=89=20-=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=EC=9D=B4=EB=82=98=20=EC=9D=B4=EC=A0=84=20?= =?UTF-8?q?=EC=88=98=EC=9A=94=EC=B2=98=EB=93=B1=EB=A1=9D=20=EC=9D=B4?= =?UTF-8?q?=ED=9B=84=20=EC=88=98=EC=9A=94=EC=B2=98=20=EC=84=B8=ED=8C=85?= =?UTF-8?q?=EC=99=84=EB=A3=8C(=EB=A1=9C=EA=B7=B8=EC=9D=B8=20>=20=EC=88=98?= =?UTF-8?q?=EC=9A=94=EC=B2=98=20=EB=93=B1=EB=A1=9D=20=ED=98=B9=EC=9D=80=20?= =?UTF-8?q?=EB=B9=88=EC=B9=B8)=20-=20=EC=88=98=EC=9A=94=EC=A0=95=EB=B3=B4?= =?UTF-8?q?=EB=93=B1=EB=A1=9D=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../business_components/src/ui/form_ui/index.tsx | 2 +- .../src/ui/sdmInsertForm/form.tsx | 13 ++++++------- .../src/ui/sdmInsertForm/index.tsx | 2 -- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/packages/common/business_components/src/ui/form_ui/index.tsx b/packages/common/business_components/src/ui/form_ui/index.tsx index de4b37f61..8f0ce136a 100644 --- a/packages/common/business_components/src/ui/form_ui/index.tsx +++ b/packages/common/business_components/src/ui/form_ui/index.tsx @@ -39,7 +39,7 @@ const FormUi = React.forwardRef( checked={isChecked} onCheckedChange={handleCheckboxChange} /> - +
{children} diff --git a/packages/common/business_components/src/ui/sdmInsertForm/form.tsx b/packages/common/business_components/src/ui/sdmInsertForm/form.tsx index c5c0ee0db..f5ff20e1d 100644 --- a/packages/common/business_components/src/ui/sdmInsertForm/form.tsx +++ b/packages/common/business_components/src/ui/sdmInsertForm/form.tsx @@ -124,7 +124,7 @@ export function SdmRegForm({ form, onCheckboxChange, selectSidoData, selectSigun form.setValue('dmdCoNm', text); }, [form]); - const bznNoChange = useCallback((e: React.ChangeEvent, noType: string) => { + const bznNoChange = useCallback((e: React.ChangeEvent, noType: string, field?: ControllerRenderProps) => { const value = e.target.value; if(noType === 'dmdInfoPk') { @@ -133,17 +133,16 @@ export function SdmRegForm({ form, onCheckboxChange, selectSidoData, selectSigun } else { setIsDuplicate(false); } - form.setValue('dmdInfoPk', value); + field?.onChange(value); } else { if(orgBznmNo.substring(10,14) === value) { setIsDuplicate(true); } else { setIsDuplicate(false); } - form.setValue('bznmTotNo', value); + field?.onChange(value); } - - }, [form, orgBznmNo, setIsDuplicate]); + }, [orgBznmNo, setIsDuplicate]); const formFields: Array<{ name: keyof FormSchema; @@ -202,7 +201,7 @@ export function SdmRegForm({ form, onCheckboxChange, selectSidoData, selectSigun type="text" className="!text-xl text-gray-600" {...field} - onChange={(e) => bznNoChange(e, 'dmdInfoPk')} + onChange={(e) => bznNoChange(e, 'dmdInfoPk', field)} /> ) }, @@ -221,7 +220,7 @@ export function SdmRegForm({ form, onCheckboxChange, selectSidoData, selectSigun className="!mt-5 !text-xl text-gray-600" disabled={isBznmTotNoDisabled} {...field} - onChange={(e) => bznNoChange(e, 'bznmTotNo')} + onChange={(e) => bznNoChange(e, 'bznmTotNo', field)} /> ) diff --git a/packages/common/business_components/src/ui/sdmInsertForm/index.tsx b/packages/common/business_components/src/ui/sdmInsertForm/index.tsx index 4b4a94648..767f3dd56 100644 --- a/packages/common/business_components/src/ui/sdmInsertForm/index.tsx +++ b/packages/common/business_components/src/ui/sdmInsertForm/index.tsx @@ -176,8 +176,6 @@ export default function SdmInsertForm({selectSidoData, selectSigunData, dataList telno: data.telno, }); - //router.push(`/pages/sdmMng/sdmInfoInsert?${queryParams.toString()}`); - toast.success('수요처가 성공적으로 등록되었습니다.'); } catch (error) { console.error('Error submitting form:', error); toast.error('수요처 등록에 실패했습니다.'); From 2fc50d614e8da5f0912360126e0a1c4c4770152f Mon Sep 17 00:00:00 2001 From: YangJinSoo94 Date: Thu, 12 Jun 2025 11:07:42 +0900 Subject: [PATCH 5/7] =?UTF-8?q?=EB=B9=8C=EB=93=9C=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/ui/sdmInsertForm/index.tsx | 64 +++++++++++++------ 1 file changed, 43 insertions(+), 21 deletions(-) diff --git a/packages/common/business_components/src/ui/sdmInsertForm/index.tsx b/packages/common/business_components/src/ui/sdmInsertForm/index.tsx index 767f3dd56..f66aadadf 100644 --- a/packages/common/business_components/src/ui/sdmInsertForm/index.tsx +++ b/packages/common/business_components/src/ui/sdmInsertForm/index.tsx @@ -14,16 +14,41 @@ import type { SelectDataType } from "../search_input_select"; export type DemandCompType = { - dmdInfoPk : string | ''; - bzmnNo : string | ''; - dmdCoNm : string | ''; - daddr : string | ''; - telno : string | ''; - rgtr : string | ''; - useUsgCd : string | ''; - ctpvCd : string | ''; - sggCd : string | ''; - dmdAplyPswd: string | ''; + dmdInfoPk: string; + bzmnNo: string; + dmdCoNm: string; + daddr: string; + telno: string; + rgtr: string; + useUsgCd: string; + ctpvCd: string; + sggCd: string; + dmdAplyPswd: string; + dmdInfoFk: string; + wntUntprc: number | ""; + dmndTmng: "" | Date; + dmndQty: number | ""; + bznmTotNo: string; + grssClfg: number | ""; + tn: number | ""; + combResdch: number | ""; + tph: number | ""; + useYn: string; + delYn: string; + regDt: string; + updtDt: string; + updtr: string; + trbt: number | ""; + ph: number | ""; + blgcOxygDmndQnt: number | ""; + clIonQnt: number | ""; + dmndQnt: number | ""; + dmndUntprc: number | ""; + dmndAmt: number | ""; + smll: number | ""; + cdtnv: number | ""; + crmty: number | ""; + rmrk: string; } @@ -60,16 +85,13 @@ const createFormSchema = (isBznmTotNoDisabled: boolean, isDuplicate: boolean) => .max(12, "전화번호는 12자 이내로 입력해주세요") .regex(/^[0-9-]+$/, "전화번호는 숫자와 하이픈(-)만 입력 가능합니다"), rgtr: z.string().optional(), - dmdAplyPswd : z.string() - .min(1, "패스워드를 입력해주세요") - .min(8, "패스워드는 8자 이상 입력해주세요") - .max(16, "패스워드는 16자 이내로 입력해주세요"), + dmdAplyPswd: z.string().optional() + .refine((val) => !val || (val.length >= 8 && val.length <= 16), "패스워드는 8자 이상 16자 이내로 입력해주세요"), }); -type FormSchema = ReturnType; -export type FormData = z.infer; +type FormSchema = z.infer>; -const defaultValues: FormData = { +const defaultValues: FormSchema = { ctpvCd: '', sggCd: '', dmdCoNm: '', @@ -78,7 +100,7 @@ const defaultValues: FormData = { daddr: '', telno: '', rgtr: "3fa85f64-5717-4562-b3fc-2c963f66afa6", - dmdAplyPswd : '', + dmdAplyPswd: '', }; /** @@ -125,7 +147,7 @@ export default function SdmInsertForm({selectSidoData, selectSigunData, dataList const [isDuplicate, setIsDuplicate] = useState(false); const formSchema = createFormSchema(isBznmTotNoDisabled, isDuplicate); - const form = useForm>({ + const form = useForm({ resolver: zodResolver(formSchema), defaultValues, mode: "onChange", @@ -146,7 +168,7 @@ export default function SdmInsertForm({selectSidoData, selectSigunData, dataList rtnValue(searchText, pageCnt); }, [rtnValue]); - const onSubmit: SubmitHandler> = async (data) => { + const onSubmit: SubmitHandler = async (data) => { try { // form 에러 체크 const formErrors = form.formState.errors; @@ -160,10 +182,10 @@ export default function SdmInsertForm({selectSidoData, selectSigunData, dataList const formData = { ...data, dmdInfoPk, + bzmnNo: data.dmdInfoPk, }; console.log(formData); - /* await insertSdmData(formData); */ rtnInputData(formData as DemandCompType); const queryParams = new URLSearchParams({ From aea80936e4a2bde6abb0a3fe7f3d607d667d4e67 Mon Sep 17 00:00:00 2001 From: YangJinSoo94 Date: Thu, 12 Jun 2025 13:40:47 +0900 Subject: [PATCH 6/7] =?UTF-8?q?=EB=B9=8C=EB=93=9C=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EC=88=98=EC=A0=95(=ED=94=84=EB=A1=9C=ED=8D=BC=ED=8B=B0=20?= =?UTF-8?q?=ED=83=80=EC=9E=85=20=EC=88=98=EC=A0=95)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/ui/sdmInsertForm/index.tsx | 51 +------------------ 1 file changed, 1 insertion(+), 50 deletions(-) diff --git a/packages/common/business_components/src/ui/sdmInsertForm/index.tsx b/packages/common/business_components/src/ui/sdmInsertForm/index.tsx index f66aadadf..451997cd2 100644 --- a/packages/common/business_components/src/ui/sdmInsertForm/index.tsx +++ b/packages/common/business_components/src/ui/sdmInsertForm/index.tsx @@ -11,46 +11,7 @@ import { toast, Toaster } from "sonner"; /* import { Toaster, toast } from "react-hot-toast"; */ import * as z from "zod"; import type { SelectDataType } from "../search_input_select"; - - -export type DemandCompType = { - dmdInfoPk: string; - bzmnNo: string; - dmdCoNm: string; - daddr: string; - telno: string; - rgtr: string; - useUsgCd: string; - ctpvCd: string; - sggCd: string; - dmdAplyPswd: string; - dmdInfoFk: string; - wntUntprc: number | ""; - dmndTmng: "" | Date; - dmndQty: number | ""; - bznmTotNo: string; - grssClfg: number | ""; - tn: number | ""; - combResdch: number | ""; - tph: number | ""; - useYn: string; - delYn: string; - regDt: string; - updtDt: string; - updtr: string; - trbt: number | ""; - ph: number | ""; - blgcOxygDmndQnt: number | ""; - clIonQnt: number | ""; - dmndQnt: number | ""; - dmndUntprc: number | ""; - dmndAmt: number | ""; - smll: number | ""; - cdtnv: number | ""; - crmty: number | ""; - rmrk: string; -} - +import type { DemandCompType } from "../../../../../../apps/dm/app/store/sdmMng"; type thisProps = { selectSidoData: SelectDataType[]; @@ -188,16 +149,6 @@ export default function SdmInsertForm({selectSidoData, selectSigunData, dataList console.log(formData); rtnInputData(formData as DemandCompType); - const queryParams = new URLSearchParams({ - dmdCoNm: data.dmdCoNm, - ctpvCd: data.ctpvCd, - sggCd: data.sggCd, - dmdInfoPk, - bznmTotNo: data.bznmTotNo || '', - daddr: data.daddr, - telno: data.telno, - }); - } catch (error) { console.error('Error submitting form:', error); toast.error('수요처 등록에 실패했습니다.'); From c80c9203d87967b71bc2868d7ee3dcd71a140f8f Mon Sep 17 00:00:00 2001 From: leedj312 Date: Thu, 12 Jun 2025 20:15:36 +0900 Subject: [PATCH 7/7] =?UTF-8?q?=EC=88=98=EC=9A=94=EC=B2=98=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=EB=B2=84?= =?UTF-8?q?=EC=A0=84=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/ui/sdmInsertForm/form.tsx | 119 ++++++++++++++++-- .../src/ui/sdmInsertForm/index.tsx | 34 ++--- .../src/ui/sdmInsertForm/sdmNameBox.tsx | 8 +- 3 files changed, 132 insertions(+), 29 deletions(-) diff --git a/packages/common/business_components/src/ui/sdmInsertForm/form.tsx b/packages/common/business_components/src/ui/sdmInsertForm/form.tsx index f5ff20e1d..6ccaac946 100644 --- a/packages/common/business_components/src/ui/sdmInsertForm/form.tsx +++ b/packages/common/business_components/src/ui/sdmInsertForm/form.tsx @@ -2,10 +2,43 @@ import { SelectBox } from "../select"; import { Input } from "@common/components"; import { FormUi } from "../form_ui"; -import { useCallback, useState } from "react"; +import { useCallback, useEffect, useState } from "react"; import type { ControllerRenderProps, UseFormReturn } from "react-hook-form"; import { SdmSearchForm } from "./sdmNameBox"; -import type { DemandCompType } from "../../../../../../apps/dm/app/store/sdmMng"; +import { set } from "date-fns"; + +// 수요처 정보 +export type DemandCompType = { + index : number | ''; + dmdInfoPk : string | ''; + dmdInfoFk : string | ''; + bzmnNo : string | ''; + dmdCoNm : string | ''; + daddr : string | ''; + telno : string | ''; + rgtr : string | ''; + useUsgCd : string | ''; + ctpvCd : string | ''; + sggCd : string | ''; + dmdAplyPswd : string | ''; + wntUntprc : number | ''; + dmndTmng : Date | ''; + dmndQty : number | ''; + grssClfg : number | ''; + tn : number | ''; + combResdch : number | ''; + tph : number | ''; + trbt : number | ''; + ph : number | ''; + blgcOxygDmndQnt : number | ''; + clIonQnt : number | ''; + smll : number | ''; + cdtnv : number | ''; + crmty : number | ''; + rmrk : string | ''; + reqDt : string | ''; +} + type SelectDataType = { text: string; @@ -32,16 +65,19 @@ interface SdmRegFormProps { dataList: DemandCompType[]; rtnValue: (searchText: string, pageCnt: number) => void; setIsDuplicate: (value: boolean) => void; + updateList?:DemandCompType } type FieldComponent = (field: ControllerRenderProps) => JSX.Element; -export function SdmRegForm({ form, onCheckboxChange, selectSidoData, selectSigunData, dataList, rtnValue, setIsDuplicate }: SdmRegFormProps) { +export function SdmRegForm({ form, onCheckboxChange, selectSidoData, selectSigunData, dataList, rtnValue, setIsDuplicate ,updateList}: SdmRegFormProps) { const [sidoValue, setSidoValue] = useState(''); const [sigunValue, setSigunValue] = useState(''); const [filteredSigunData, setFilteredSigunData] = useState([{ text: "전체", val: '0' }]); const [isBznmTotNoDisabled, setIsBznmTotNoDisabled] = useState(true); const [orgBznmNo, setOrgBznmNo] = useState(''); + const [updateCoNm, setUpdateNm] = useState('') + const initializeSigunData = useCallback((sidoCd: string) => { if (sidoCd === '0') { @@ -62,6 +98,7 @@ export function SdmRegForm({ form, onCheckboxChange, selectSidoData, selectSigun type: string, field: ControllerRenderProps | undefined ) => { + if(!updateList?.dmdInfoPk) switch (type) { case "ctpvCd": initializeSigunData(val); @@ -77,7 +114,7 @@ export function SdmRegForm({ form, onCheckboxChange, selectSidoData, selectSigun form.setValue('bznmTotNo', ''); break; } - }, [initializeSigunData, form]); + }, [initializeSigunData, form,updateList]); const handleCheckboxChange = useCallback((checked: boolean) => { setIsBznmTotNoDisabled(checked); @@ -90,6 +127,7 @@ export function SdmRegForm({ form, onCheckboxChange, selectSidoData, selectSigun const setRtnData = useCallback((item: DemandCompType) => { const rtnCompData = item; + form.setValue('dmdCoNm', rtnCompData?.dmdCoNm || ''); form.setValue('dmdInfoPk', rtnCompData?.dmdInfoPk.substring(0,10) || ''); form.setValue('bznmTotNo', rtnCompData?.dmdInfoPk.substring(10,14)==='0000' ? '' : rtnCompData?.dmdInfoPk.substring(10,14)); @@ -126,7 +164,7 @@ export function SdmRegForm({ form, onCheckboxChange, selectSidoData, selectSigun const bznNoChange = useCallback((e: React.ChangeEvent, noType: string, field?: ControllerRenderProps) => { const value = e.target.value; - + if(noType === 'dmdInfoPk') { if(orgBznmNo.substring(0,10) === value) { setIsDuplicate(true); @@ -144,6 +182,27 @@ export function SdmRegForm({ form, onCheckboxChange, selectSidoData, selectSigun } }, [orgBznmNo, setIsDuplicate]); + + useEffect(() => { + if(updateList?.dmdInfoPk){ + form.reset(updateList) + if(updateList?.dmdInfoPk.slice(10,14) !== '0000') { + handleCheckboxChange( false); + form.setValue('bznmTotNo', updateList?.dmdInfoPk.slice(10,14)); + } else { + handleCheckboxChange( true); + } + form.setValue('dmdInfoPk', updateList?.dmdInfoPk.slice(0,10)); + setUpdateNm(updateList?.dmdCoNm) + // setSigunValue(updateList?.sggCd) + }else{ + handleCheckboxChange( true); + } + }, [updateList,form]); + + useEffect(() => { + },[form.formState.errors]) + const formFields: Array<{ name: keyof FormSchema; label: string; @@ -153,28 +212,51 @@ export function SdmRegForm({ form, onCheckboxChange, selectSidoData, selectSigun name: "ctpvCd", label: "시도", component: (field) => ( - {field.onChange(e.target.value)} } + value={ selectSidoData.find(item => item.val === field.value?.trim() )?.text??''} + readOnly={!!updateList?.dmdInfoPk} + /> + ) : ( + onSelectValue(val.toString(), 'ctpvCd', field)} + onSelectValue={(val) => onSelectValue(val.toString(), 'ctpvCd', field??'')} className="" value={sidoValue} /> + ) ) }, { name: "sggCd", label: "시군구", component: (field) => ( + updateList?.dmdInfoPk ? ( + {field.onChange(e.target.value)} } + value={selectSigunData.find(item => item.val === field.value?.trim() )?.text??''} + readOnly={!!updateList?.dmdInfoPk} + /> + ) : ( onSelectValue(val.toString(), 'sggCd', field)} className="" value={sigunValue} /> + + ) ) }, { @@ -184,7 +266,7 @@ export function SdmRegForm({ form, onCheckboxChange, selectSidoData, selectSigun bznNoChange(e, 'dmdInfoPk', field)} + value={field.value} + readOnly={!!updateList?.dmdInfoPk} /> ) }, @@ -219,8 +302,10 @@ export function SdmRegForm({ form, onCheckboxChange, selectSidoData, selectSigun type="text" className="!mt-5 !text-xl text-gray-600" disabled={isBznmTotNoDisabled} - {...field} onChange={(e) => bznNoChange(e, 'bznmTotNo', field)} + // {...field} + value={ field.value} + readOnly={!!updateList?.dmdInfoPk} /> ) @@ -249,6 +334,7 @@ export function SdmRegForm({ form, onCheckboxChange, selectSidoData, selectSigun /> ) }, + { name: "dmdAplyPswd", label: "패스워드", @@ -261,11 +347,18 @@ export function SdmRegForm({ form, onCheckboxChange, selectSidoData, selectSigun /> ) } - ]; + ] return ( <> - {formFields.map(({ name, label, component }) => ( + {formFields.filter((item)=> + {if(updateList?.dmdInfoPk){ + return item.name !== 'dmdAplyPswd' + }else{ + return item + } + }) + .map(({ name, label, component }) => ( void; rtnInputData: (data: DemandCompType) => void; bodyClassNm?: string; + updateList?:DemandCompType } -const createFormSchema = (isBznmTotNoDisabled: boolean, isDuplicate: boolean) => z.object({ +const createFormSchema = (isBznmTotNoDisabled: boolean, isDuplicate: boolean ,updateList?:DemandCompType) => z.object({ ctpvCd: z.string().min(1, "시/도를 선택해주세요"), sggCd: z.string().min(1, "시/군/구를 선택해주세요"), dmdCoNm: z.string() @@ -43,11 +40,14 @@ const createFormSchema = (isBznmTotNoDisabled: boolean, isDuplicate: boolean) => .max(40, "주소는 40자 이내로 입력해주세요"), telno: z.string() .min(8, "전화번호는 8자 이상 입력해주세요") - .max(12, "전화번호는 12자 이내로 입력해주세요") + .max(11, "전화번호는 11자 이내로 입력해주세요") .regex(/^[0-9-]+$/, "전화번호는 숫자와 하이픈(-)만 입력 가능합니다"), rgtr: z.string().optional(), - dmdAplyPswd: z.string().optional() + dmdAplyPswd : updateList?.dmdInfoPk // 업데이트일경우 + ? z.string().optional() // 패스워드는 선택 사항이며 길이 제한 없음 + : z.string().optional() .refine((val) => !val || (val.length >= 8 && val.length <= 16), "패스워드는 8자 이상 16자 이내로 입력해주세요"), + }); type FormSchema = z.infer>; @@ -100,13 +100,13 @@ const defaultValues: FormSchema = { }, [insertSdmData]); */ -export default function SdmInsertForm({selectSidoData, selectSigunData, dataList, rtnValue, rtnInputData,bodyClassNm}: thisProps) { +export default function SdmInsertForm({selectSidoData, selectSigunData, dataList, rtnValue, rtnInputData,bodyClassNm, updateList}: thisProps) { /* const { insertSdmData } = useDmStore((state) => state); const router = useRouter(); */ - const [isBznmTotNoDisabled, setIsBznmTotNoDisabled] = useState(true); + const [isBznmTotNoDisabled, setIsBznmTotNoDisabled] = useState(false); const [isDuplicate, setIsDuplicate] = useState(false); - const formSchema = createFormSchema(isBznmTotNoDisabled, isDuplicate); + const formSchema = createFormSchema(isBznmTotNoDisabled, isDuplicate, updateList ); const form = useForm({ resolver: zodResolver(formSchema), @@ -119,7 +119,7 @@ export default function SdmInsertForm({selectSidoData, selectSigunData, dataList // 체크박스 상태가 변경될 때마다 bznmTotNo 필드의 에러를 초기화 useEffect(() => { - if (isBznmTotNoDisabled) { + if (isBznmTotNoDisabled===true) { form.clearErrors('bznmTotNo'); form.setValue('bznmTotNo', ''); } @@ -145,13 +145,16 @@ export default function SdmInsertForm({selectSidoData, selectSigunData, dataList dmdInfoPk, bzmnNo: data.dmdInfoPk, }; + + console.log(' formData ', formData) - console.log(formData); + /* await insertSdmData(formData); */ rtnInputData(formData as DemandCompType); + + //router.push(`/pages/sdmMng/sdmInfoInsert?${queryParams.toString()}`); } catch (error) { console.error('Error submitting form:', error); - toast.error('수요처 등록에 실패했습니다.'); } }; @@ -174,6 +177,7 @@ export default function SdmInsertForm({selectSidoData, selectSigunData, dataList dataList={dataList} rtnValue={setRtnValue} setIsDuplicate={setIsDuplicate} + updateList={updateList} />