Merge commit 'a38a1315f2f4284d2618ea7f83d70412a30b233c' into iipbs/wr/form_fuction
This commit is contained in:
@@ -8,20 +8,25 @@ import {
|
||||
ContentsDiv,
|
||||
SearchBaseForm,
|
||||
Title,
|
||||
UiModal,
|
||||
UiTable,
|
||||
type ReturnType
|
||||
} from "@common/business_components/ui";
|
||||
import ListDiv from "@common/business_components/ui/list_div";
|
||||
import { Button } from "@common/components/ui";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import SdmInsertForm, { type DemandCompType } from "@common/business_components/ui/sdmInsertForm";
|
||||
|
||||
|
||||
export default function coSttn() {
|
||||
const [bdstTable, setBdstTable] = useState<customCoSttnBdst[]>();
|
||||
const [pageNation, setPageNation] = useState(1);
|
||||
const { code, coSttn, coSttnInit } = useWrStore((state) => state);
|
||||
const { coSttnRes } = coSttn;
|
||||
|
||||
|
||||
const [pageNation, setPageNation] = useState(1);
|
||||
const { code, coSttn, coSttnInit, getDemandCompList,regDemandCompany,demandCompList} = useWrStore((state) => state);
|
||||
const { coSttnRes } = coSttn;
|
||||
const [isDmdModal, setIsDmdModal] = useState<{isMoal: boolean, data: DemandCompType}>({isMoal: false, data: {} as DemandCompType})
|
||||
|
||||
const ref = useRef<ReturnType>({} as ReturnType);
|
||||
const codeData = getCityOrSgg(ref);
|
||||
|
||||
@@ -64,7 +69,7 @@ export default function coSttn() {
|
||||
<Button
|
||||
className={btnClass}
|
||||
onClick={() => {
|
||||
/* 등록 로직 */
|
||||
setIsDmdModal({ ...isDmdModal, isMoal:true });
|
||||
}}
|
||||
>
|
||||
등록
|
||||
@@ -112,7 +117,29 @@ export default function coSttn() {
|
||||
</ListDiv>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<UiModal
|
||||
bodyClass={"w-[40vw] max-w-none h-[90vh]"}
|
||||
open={isDmdModal.isMoal}
|
||||
onOpenChange={() => {
|
||||
setIsDmdModal({ isMoal: false, data: {} as DemandCompType });
|
||||
}}
|
||||
body={
|
||||
<SdmInsertForm
|
||||
selectSidoData={code.cityCd}
|
||||
selectSigunData={code.sggCd}
|
||||
dataList={demandCompList}
|
||||
rtnValue={(searchText: string, pageCnt: number) => {
|
||||
getDemandCompList(searchText, pageCnt);
|
||||
}}
|
||||
rtnInputData={(data) => {
|
||||
console.log(" rtn data ", data);
|
||||
regDemandCompany(data as DemandCompType);
|
||||
setIsDmdModal({ isMoal: false, data: data as DemandCompType });
|
||||
}}
|
||||
bodyClassNm={"w-full mx-auto bg-white rounded-lg shadow-md p-6"}
|
||||
></SdmInsertForm>
|
||||
}
|
||||
></UiModal>
|
||||
</ContentsDiv>
|
||||
</>
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import { z } from "zod";
|
||||
import { PbnstRegModal } from "@/components/ui/modal/fcltReg/pbnstRegModal/pbnstRegModal";
|
||||
import { Toaster } from "react-hot-toast";
|
||||
import { ToastFormUi } from "@/components/ui/toast/toastFromUi";
|
||||
import { writeRgtrAndMdfr } from "@/app/store/ruseFcltMng/fcltReg/pbnstReg";
|
||||
|
||||
export default function PublicReuseFaciltyInsert() {
|
||||
const {
|
||||
@@ -38,6 +39,8 @@ export default function PublicReuseFaciltyInsert() {
|
||||
pbnstRegClick,
|
||||
getSwtrmtFcltNm,
|
||||
pbnstMngData,
|
||||
pbnstRuseFcltUpdate,
|
||||
pbnstRuseBizUpdate,
|
||||
} = useWrStore((state) => state);
|
||||
const { pubFacHeadList, pbnstHasuRes, pbnstRes } = pbnst;
|
||||
const [currentTab, setCurrentTab] = useState<string>("mng");
|
||||
@@ -51,12 +54,35 @@ export default function PublicReuseFaciltyInsert() {
|
||||
const [bdstTable, setbdstTable] = useState<pubHasuType[]>();
|
||||
const [selectBdst, setSelectBdst] = useState<customPbnst | null>(null);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (!pbnst.isInit) {
|
||||
pubHasuInit("1", "11");
|
||||
}
|
||||
}, [pbnst.isInit, pubHasuInit]);
|
||||
|
||||
|
||||
|
||||
const saveRuseData = async ()=>{
|
||||
const data = writeRgtrAndMdfr(pbnst.pbnstMngRegData)
|
||||
let bizs =[] as fcBizType[]
|
||||
data.forEach((fclt) =>{
|
||||
bizs = [
|
||||
...bizs,
|
||||
...fclt.fcBizs
|
||||
]
|
||||
})
|
||||
|
||||
|
||||
await pbnstRuseFcltUpdate(data)
|
||||
console.log('bizs ', bizs)
|
||||
|
||||
await pbnstRuseBizUpdate(bizs)
|
||||
|
||||
console.log(' data ', data)
|
||||
}
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if(code.sggCd.length){
|
||||
if(searchFclts){
|
||||
@@ -156,7 +182,7 @@ export default function PublicReuseFaciltyInsert() {
|
||||
<TabsTrigger className="!text-xl" value="buse">
|
||||
차수별정보
|
||||
</TabsTrigger>
|
||||
<Button size={"sm"} className="!justify-end">
|
||||
<Button size={"sm"} onClick={ saveRuseData}className="!justify-end">
|
||||
저장
|
||||
</Button>
|
||||
</TabsList>
|
||||
|
||||
@@ -91,6 +91,18 @@ const chBuCd = [
|
||||
]
|
||||
|
||||
|
||||
|
||||
const dmdUszCd = [
|
||||
{ val: "조경용수", text: "조경용수" },
|
||||
{ val: "청소화장실용수", text: "청소화장실용수" },
|
||||
{ val: "농업용수", text: "농업용수" },
|
||||
{ val: "공업용수", text: "공업용수" },
|
||||
{ val: "친수용수", text: "친수용수" },
|
||||
{ val: "기타", text: "기타" },
|
||||
|
||||
]
|
||||
|
||||
|
||||
const pplQulity = [
|
||||
{ val: "도복장강관", text: "도복장강관" },
|
||||
{ val: "PE관", text: "PE관" },
|
||||
@@ -136,6 +148,7 @@ export type comCodeState = {
|
||||
yn: SelectDataType[];
|
||||
pplQulity: SelectDataType[];
|
||||
pplLenght: SelectDataType[];
|
||||
dmdUszCd:SelectDataType[]
|
||||
buildingType: {
|
||||
RST:string,
|
||||
RNB:string,
|
||||
@@ -277,6 +290,7 @@ export const comCodeStateExport: comCodeState = {
|
||||
pplQulity:pplQulity,
|
||||
pplLenght:pplLenght,
|
||||
yn: yn,
|
||||
dmdUszCd:dmdUszCd,
|
||||
buildingType:buildingType,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,29 +1,52 @@
|
||||
import { fetchType, getFetch, postFectch } from "@/components/lib/api"
|
||||
import type { pubHasuType } from "../../ruseFcltMng/fcltReg/pbnstReg/type"
|
||||
import { fetchType, getFetch, postFectch } from "@/components/lib/api";
|
||||
import type { pubHasuType } from "../../ruseFcltMng/fcltReg/pbnstReg/type";
|
||||
import type { DemandCompType } from "@common/business_components/ui";
|
||||
export type comFcltState = {
|
||||
searchFclts: pubHasuType
|
||||
}
|
||||
searchFclts: pubHasuType;
|
||||
demandCompList: DemandCompType[];
|
||||
};
|
||||
export type comFcltActions = {
|
||||
getSwtrmtFcltNm: (searchNm: string) => void
|
||||
}
|
||||
|
||||
getSwtrmtFcltNm: (searchNm: string) => void;
|
||||
getDemandCompList :(searchNm: string,cnt:number) => void
|
||||
regDemandCompany:(data:DemandCompType ) => void
|
||||
};
|
||||
|
||||
export const searchActions: (set: any) => comFcltActions = (set: any) => {
|
||||
return {
|
||||
getSwtrmtFcltNm: async (searchNm: string) => {
|
||||
const fcltNm = await getFetch("common", `/prcsFclt/info/1/20/${searchNm}`);
|
||||
const fcltNmCd: pubHasuType[] = fcltNm.map((item: any) => ({
|
||||
bscFctCd: item.bscFctCd,
|
||||
sido: item.sido,
|
||||
gugun: item.gugun,
|
||||
bscFctNm: item.bscFctNm,
|
||||
addr: item.addr,
|
||||
fctCpc: item.fctCpc
|
||||
}))
|
||||
return set((state: comFcltState) => ({
|
||||
...state,
|
||||
searchFclts: fcltNmCd
|
||||
}
|
||||
))
|
||||
},
|
||||
return {
|
||||
getSwtrmtFcltNm: async (searchNm: string) => {
|
||||
const fcltNm = await getFetch(
|
||||
"common",
|
||||
`/prcsFclt/info/1/20/${searchNm}`
|
||||
);
|
||||
const fcltNmCd: pubHasuType[] = fcltNm.map((item: any) => ({
|
||||
bscFctCd: item.bscFctCd,
|
||||
sido: item.sido,
|
||||
gugun: item.gugun,
|
||||
bscFctNm: item.bscFctNm,
|
||||
addr: item.addr,
|
||||
fctCpc: item.fctCpc,
|
||||
}));
|
||||
return set((state: comFcltState) => ({
|
||||
...state,
|
||||
searchFclts: fcltNmCd,
|
||||
}));
|
||||
},
|
||||
getDemandCompList: async (searchNm: string ,cnt:number) => {
|
||||
const coList = await getFetch(
|
||||
fetchType.WR,
|
||||
`/reuseFc/request/${searchNm}/${cnt}`
|
||||
);
|
||||
return set((state: comFcltState) => ({
|
||||
...state,
|
||||
demandCompList: coList,
|
||||
}));
|
||||
},regDemandCompany: async (data:DemandCompType)=>{
|
||||
|
||||
try{
|
||||
const response = await postFectch('/reuseFc/request',data,fetchType.WR )
|
||||
}catch(err){
|
||||
console.log(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
fetchType,
|
||||
getFetch,
|
||||
postFectch,
|
||||
putFectch,
|
||||
} from "@/components/lib/api";
|
||||
import type { chHeadType } from "@/app/store/prfmncReg/chkgdnReg/rainChkgdn/headList";
|
||||
import {
|
||||
@@ -66,9 +67,9 @@ type pubFacActions = {
|
||||
pbnstMngData: (data: customPbnst[]) => void;
|
||||
pbnstBizData(data: fcBizType): void;
|
||||
getBizCycle: (pbnstObj: customPbnst) => void;
|
||||
getDmdCompany: (txt: string) => void;
|
||||
getpbnstInsertIndex: (data: pbnstInsertIndex) => void;
|
||||
searchDmdColist:(txt:string) =>void
|
||||
pbnstRuseFcltUpdate: (ruseRes: customPbnst[]) => void;
|
||||
pbnstRuseBizUpdate: (ruseRes: fcBizType[]) => void;
|
||||
};
|
||||
|
||||
export type pubFacType = pubFacState & pubFacActions;
|
||||
@@ -123,30 +124,40 @@ const initFetch = async (ruseFcltPk: string | undefined) => {
|
||||
return pbnstRes;
|
||||
};
|
||||
|
||||
const writeRgtrAndMdfr = (data: customPbnst) => {
|
||||
data.rgtr = TEST_UUID;
|
||||
data.mdfr = TEST_UUID;
|
||||
data.fcBizs = data.fcBizs.map((item) => {
|
||||
export const writeRgtrAndMdfr = (data: customPbnst[]) => {
|
||||
|
||||
data.forEach((pbnst) => {
|
||||
pbnst.rgtr = TEST_UUID;
|
||||
pbnst.mdfr = TEST_UUID;
|
||||
|
||||
pbnst.fcBizs = pbnst.fcBizs?.map((item) => {
|
||||
item.rgtr = TEST_UUID;
|
||||
item.mdfr = TEST_UUID;
|
||||
item.fcOrgwts = item.fcOrgwts?.map((item) => {
|
||||
item.mdfr = TEST_UUID;
|
||||
item.rgtr = TEST_UUID;
|
||||
return item;
|
||||
item.fcOrgwts = item.fcOrgwts?.map((orgwt) => {
|
||||
orgwt.mdfr = TEST_UUID;
|
||||
orgwt.rgtr = TEST_UUID;
|
||||
return orgwt;
|
||||
});
|
||||
|
||||
item.fcDemands = item.fcDemands?.map((dmd) => {
|
||||
dmd.mdfr = TEST_UUID;
|
||||
dmd.rgtr = TEST_UUID;
|
||||
return dmd;
|
||||
});
|
||||
|
||||
return item;
|
||||
});
|
||||
data.fcOpers = data.fcOpers.map((item) => {
|
||||
item.rgtr = TEST_UUID;
|
||||
item.mdfr = TEST_UUID;
|
||||
return item;
|
||||
pbnst.fcOpers = pbnst.fcOpers.map((oper) => {
|
||||
oper.rgtr = TEST_UUID;
|
||||
oper.mdfr = TEST_UUID;
|
||||
return oper;
|
||||
});
|
||||
data.fcFiles = data.fcFiles.map((item) => {
|
||||
item.rgtr = TEST_UUID;
|
||||
item.mdfr = TEST_UUID;
|
||||
return item;
|
||||
pbnst.fcFiles = pbnst.fcFiles.map((file) => {
|
||||
file.rgtr = TEST_UUID;
|
||||
file.mdfr = TEST_UUID;
|
||||
return file;
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
return data;
|
||||
@@ -173,6 +184,7 @@ export const pubFacActionsExport: (set: any) => pubFacActions = (set: any) => {
|
||||
pbnstRegClick: async (pubHasuRes: pubHasuType) => {
|
||||
try {
|
||||
const pbnstRes = await initFetch(pubHasuRes.bscFctCd);
|
||||
console.log('pbnstRes ' , pbnstRes)
|
||||
return set((state: pubFacState) => ({
|
||||
...state,
|
||||
pbnst: {
|
||||
@@ -204,10 +216,9 @@ export const pubFacActionsExport: (set: any) => pubFacActions = (set: any) => {
|
||||
pbnstInsert: async (pbnstRes: customPbnst) => {
|
||||
try {
|
||||
|
||||
console.log('writeRgtrAndMdfr(pbnstRes) ', writeRgtrAndMdfr(pbnstRes))
|
||||
const response = await postFectch(
|
||||
`/reuseFc/pubFc`,
|
||||
JSON.stringify( writeRgtrAndMdfr(pbnstRes))
|
||||
JSON.stringify( writeRgtrAndMdfr([pbnstRes]))
|
||||
);
|
||||
|
||||
return set((state: pubFacState) => ({
|
||||
@@ -221,7 +232,39 @@ export const pubFacActionsExport: (set: any) => pubFacActions = (set: any) => {
|
||||
} catch (error) {
|
||||
console.error("Error updating pbnst:", error);
|
||||
}
|
||||
},
|
||||
},pbnstRuseFcltUpdate : async(ruseRes:customPbnst[])=>{
|
||||
try {
|
||||
|
||||
const response = await putFectch(
|
||||
`/reuseFc/pubFc`,
|
||||
ruseRes
|
||||
);
|
||||
|
||||
} catch (error) {
|
||||
console.error("Error pbnstRuseFcltUpdate:", error);
|
||||
}
|
||||
} ,pbnstRuseBizUpdate : async(ruseRes:fcBizType[])=>{
|
||||
try {
|
||||
|
||||
console.log('ruseRes ', ruseRes)
|
||||
const response = await putFectch(
|
||||
`/reuseFc/pubFcBiz`,
|
||||
ruseRes
|
||||
);
|
||||
const pbnstRes = await hasuListFetch("11", "11");
|
||||
|
||||
return set((state: pubFacState) => ({
|
||||
...state,
|
||||
pbnst: {
|
||||
...state.pbnst,
|
||||
pbnstRes: pbnstRes,
|
||||
isInit: false,
|
||||
},
|
||||
}));
|
||||
} catch (error) {
|
||||
console.error("Error pbnstRuseFcltUpdate:", error);
|
||||
}
|
||||
} ,
|
||||
getBizCycle: async (pbnstObj: customPbnst) => {
|
||||
const pbnstBizCycle = pbnstObj.fcBizs.map((item) => {
|
||||
return {
|
||||
@@ -303,23 +346,15 @@ export const pubFacActionsExport: (set: any) => pubFacActions = (set: any) => {
|
||||
|
||||
if (bizIdx >= 0) {
|
||||
regData.fcBizs[bizIdx] = data;
|
||||
const pbnstData = state.pbnst.pbnstMngRegData
|
||||
state.pbnst.pbnstMngRegData= [...pbnstData]
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return state;
|
||||
});
|
||||
},
|
||||
getDmdCompany: async (txt: string) => {
|
||||
const company = await getFetch(fetchType.WR, `/reuseFc/request/${txt}/3`);
|
||||
|
||||
return set((state: pubFacState) => ({
|
||||
...state,
|
||||
pbnst: {
|
||||
...state.pbnst,
|
||||
isInit: false,
|
||||
},
|
||||
}));
|
||||
},
|
||||
getpbnstInsertIndex: async (data: pbnstInsertIndex) => {
|
||||
return set((state: pubFacState) => {
|
||||
state.pbnst.pbnsUpdateIndex = data;
|
||||
@@ -339,24 +374,6 @@ export const pubFacActionsExport: (set: any) => pubFacActions = (set: any) => {
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
},searchDmdColist:async (txt:string)=>{
|
||||
|
||||
try{
|
||||
console.log(' txt ', txt)
|
||||
const coList = await getFetch(fetchType.WR, `reuseFc/request/${txt}/{3}`);
|
||||
return set((state: pubFacState) => ({
|
||||
...state,
|
||||
pbnst: {
|
||||
...state.pbnst,
|
||||
dmdCoList: coList,
|
||||
isInit: false,
|
||||
},
|
||||
}));
|
||||
}catch(e){
|
||||
console.log(e)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -44,6 +44,25 @@ export type ruseFcltType = {
|
||||
splyExtraCpct: number;
|
||||
};
|
||||
|
||||
export type PbnstDemandComType = {
|
||||
dmdInfoPk : string | '';
|
||||
bzmnNo : string | '';
|
||||
dmdCoNm : string | '';
|
||||
daddr : string | '';
|
||||
telno : string | '';
|
||||
rgtr : string | '';
|
||||
useUsgCd : string | '';
|
||||
ctpvCd : string | '';
|
||||
sggCd : string | '';
|
||||
dmdAplyPswd: string | '';
|
||||
splyCpct: number | 0;
|
||||
splyFmYn:string|'Y'
|
||||
dmdInfoFk:string|''
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
export type fcBizType = z.infer<typeof fcBizSchema>;
|
||||
export type fcOrgwtType = z.infer<typeof fcOrgwtSchema>;
|
||||
export type ppInstlType = z.infer<typeof pplInstlSchema>;
|
||||
@@ -53,7 +72,7 @@ export type fcFileType = z.infer<typeof fcFileSchema>;
|
||||
|
||||
|
||||
const pplInstlSchema = z.object({
|
||||
ruseFcltBizFk: z.string(),
|
||||
ruseFcltBizFk: z.number(),
|
||||
choose:z.boolean().default(false),
|
||||
pdmt: z.string().default(''),
|
||||
ppMqlt: z.string().default(""),
|
||||
@@ -72,7 +91,7 @@ const fcFileSchema = z.object({
|
||||
|
||||
const fcOperSchema = z.object({
|
||||
pbnstRuseFcltOperInfoPk: z.number().nullish(),
|
||||
pbnstRuseFcltFk: z.number().nullish(),
|
||||
pbnstRuseFcltFk: z.string().nullish(),
|
||||
operMthd: z.string(),
|
||||
rprtvBzenty: z.string(),
|
||||
bgngDt: z.date().default(new Date()),
|
||||
@@ -121,13 +140,18 @@ export type pubHasuType = z.infer<typeof pubHasuZod>;
|
||||
|
||||
|
||||
const dmdColist = z.object({
|
||||
dmdInfoFk:z.string().default(''),
|
||||
dmdCoNm: z.string().default(''),
|
||||
daddr: z.string(),
|
||||
useUsgCd: z.string().default(""),
|
||||
splyBgngDay: z.date().default(new Date()),
|
||||
splyEndDay: z.date().default(new Date()),
|
||||
splyCpct: z.string().default(""),
|
||||
splyFmYn: z.number().default(0),
|
||||
splyCpct: z.number().default(0),
|
||||
splyFmYn: z.string().default('Y'),
|
||||
rgtr: z.string().nullish(),
|
||||
mdfr: z.string().nullish(),
|
||||
pbnstRuseFcltBizPk: z.number(),
|
||||
pbnstRuseFcltFk: z.string(),
|
||||
//telno:z.string().default('')
|
||||
});
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ export const getFetch = async (type: string, url: string) => {
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`오류 발생: ${response.status}`);
|
||||
console.log(`오류 발생: ${response.status}`);
|
||||
}
|
||||
const contentType = response.headers.get("content-type") ?? "";
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
fcBizSchema,
|
||||
type customPbnst,
|
||||
type fcBizType,
|
||||
type PbnstDemandComType,
|
||||
type ppInstlType,
|
||||
} from "@/app/store/ruseFcltMng/fcltReg/pbnstReg/type";
|
||||
import { selectClass } from "@/app/store/ruseFcltMng/fcltReg/rainReg";
|
||||
@@ -31,16 +32,22 @@ import {
|
||||
type SelectDataType,
|
||||
} from "@common/business_components/ui";
|
||||
import { Form, FormField } from "@common/business_components/ui/form";
|
||||
import { Button, DatePicker, Input, Label } from "@common/components";
|
||||
import {
|
||||
Button,
|
||||
DataTable,
|
||||
DatePicker,
|
||||
Input,
|
||||
Label,
|
||||
} from "@common/components";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useFieldArray, useForm } from "react-hook-form";
|
||||
import MngRegFormDetail from "../mngReg/mngRegFormDetail/mngRegFormDetail";
|
||||
import {
|
||||
handleCommaNumberChange,
|
||||
formatCommaNumber,
|
||||
safeDate,
|
||||
} from "@/components/lib/func/commom";
|
||||
import { safeDate } from "@/components/lib/func/commom";
|
||||
import SearchInputText from "@/components/ui/searchInput/searchInput";
|
||||
import SdmInsertForm, {
|
||||
type DemandCompType,
|
||||
} from "@common/business_components/ui/sdmInsertForm";
|
||||
|
||||
export function PbnstBuseForm({
|
||||
formType,
|
||||
@@ -53,11 +60,13 @@ export function PbnstBuseForm({
|
||||
const {
|
||||
code,
|
||||
pbnst,
|
||||
demandCompList,
|
||||
pbnstBizData,
|
||||
getpbnstInsertIndex,
|
||||
appendRuseFclt,
|
||||
getBizCycle,
|
||||
searchDmdColist,
|
||||
getDemandCompList,
|
||||
regDemandCompany,
|
||||
} = useWrStore((state) => state);
|
||||
const { pbnstBizCycle, pbnstRes } = pbnst;
|
||||
const [bizCycle, setBizCycle] = useState("1");
|
||||
@@ -66,7 +75,10 @@ export function PbnstBuseForm({
|
||||
const [ppiYn, setPpiYn] = useState("Y");
|
||||
const [isFcOrgwts, setIsFcOrgwts] = useState<boolean>(false);
|
||||
const [sumCpct, setSumCpct] = useState<number>(0);
|
||||
const [searchDmdCo, setSeachDmdCo] = useState<String>();
|
||||
const [isDmdModal, setIsDmdModal] = useState<{
|
||||
isMoal: boolean;
|
||||
data: DemandCompType;
|
||||
}>({ isMoal: false, data: {} as DemandCompType });
|
||||
|
||||
const form = useForm<fcBizType>({
|
||||
resolver: zodResolver(fcBizSchema),
|
||||
@@ -143,6 +155,9 @@ export function PbnstBuseForm({
|
||||
|
||||
// 등록할때 신규 값을 계속 가지고 있으려고
|
||||
useEffect(() => {
|
||||
const formData = form.watch();
|
||||
|
||||
formData.pplInstls = ref.current ? [...ref.current] : []; // ← form 내부 상태 기준으로 복사
|
||||
if (formType === "reg") {
|
||||
if (
|
||||
firstBizData &&
|
||||
@@ -156,15 +171,16 @@ export function PbnstBuseForm({
|
||||
);
|
||||
form.setValue("cycl", firstBizData[0].cycl);
|
||||
}
|
||||
const formData = form.watch();
|
||||
formData.pplInstls = ref.current ? [...ref.current] : []; // ← form 내부 상태 기준으로 복사
|
||||
pbnstBizData(formData as fcBizType);
|
||||
}
|
||||
}, [firstBizData, form.formState, formType]);
|
||||
}else if(formType === "update"){
|
||||
|
||||
console.log('formdata ', formData)
|
||||
pbnstBizData(formData as fcBizType);
|
||||
|
||||
|
||||
}
|
||||
}, [firstBizData, form.formState, formType, pbnst.pbnstRes]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log("searchDmdCo ", searchDmdCo);
|
||||
}, [searchDmdCo]);
|
||||
|
||||
useEffect(() => {
|
||||
if (ppiYn === "N") {
|
||||
@@ -178,7 +194,7 @@ export function PbnstBuseForm({
|
||||
|
||||
const plusHist = () => {
|
||||
const regData = {
|
||||
ruseFcltBizFk: ref.current?.[0]?.ruseFcltBizFk ?? "",
|
||||
ruseFcltBizFk: ref.current?.[0]?.ruseFcltBizFk ?? form.getValues('pbnstRuseFcltBizPk'),
|
||||
choose: false,
|
||||
ppMqlt: "",
|
||||
pdmt: "",
|
||||
@@ -195,17 +211,17 @@ export function PbnstBuseForm({
|
||||
};
|
||||
|
||||
const plusArray = () => {
|
||||
|
||||
console
|
||||
.log('qweqwe ')
|
||||
appendDemand({
|
||||
dmdCoNm: "",
|
||||
daddr: "",
|
||||
useUsgCd: "",
|
||||
splyBgngDay: new Date(),
|
||||
splyEndDay: new Date(),
|
||||
splyCpct: "",
|
||||
splyFmYn: 0,
|
||||
splyCpct: 0,
|
||||
splyFmYn: "Y",
|
||||
pbnstRuseFcltBizPk: form.getValues('pbnstRuseFcltBizPk'),
|
||||
pbnstRuseFcltFk: form.getValues('pbnstRuseFcltFk')??'',
|
||||
dmdInfoFk: '',
|
||||
//telno: "",
|
||||
});
|
||||
};
|
||||
@@ -403,12 +419,27 @@ export function PbnstBuseForm({
|
||||
moClass="grid grid-cols-12 gap-4"
|
||||
sonClass="col-span-4"
|
||||
/>
|
||||
<div>
|
||||
<h1 className={formH1Class}>{'하수처리수 재이용수 수요처'}</h1>
|
||||
<div key={"hasu"}>
|
||||
<h1 className={formH1Class}>{"하수처리수 재이용수 수요처"}</h1>
|
||||
<div className="text-right mb-3">
|
||||
<Button
|
||||
type="button"
|
||||
onClick={plusArray}
|
||||
onClick={() => {
|
||||
plusArray();
|
||||
}}
|
||||
size={commonButonSize}
|
||||
className="mt-6 mr-3"
|
||||
>
|
||||
수요항목 추가
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
setIsDmdModal({
|
||||
isMoal: true,
|
||||
data: {} as DemandCompType,
|
||||
});
|
||||
}}
|
||||
size={commonButonSize}
|
||||
className="mt-6"
|
||||
>
|
||||
@@ -416,31 +447,72 @@ export function PbnstBuseForm({
|
||||
</Button>
|
||||
</div>
|
||||
{fcDemands.map((field, index) => (
|
||||
<div className="grid grid-cols-12 gap-4 mt-3">
|
||||
<div className="col-span-4">
|
||||
<div
|
||||
key={index + "loot"}
|
||||
className="grid grid-cols-12 gap-4 mt-3"
|
||||
>
|
||||
<div key={index + "keySon1"} className="col-span-4">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={`fcDemands.${index}.dmdCoNm`}
|
||||
render={({ field: f }) => (
|
||||
<FormUi label="수요처명">
|
||||
<SearchInputSelect
|
||||
className={""}
|
||||
label={""}
|
||||
selectData={[]}
|
||||
onSelectValue={(val) => {
|
||||
searchDmdColist(val);
|
||||
<SearchInputText
|
||||
label={undefined}
|
||||
initValue={f.value}
|
||||
setValue={(val) => {
|
||||
f.onChange(val);
|
||||
|
||||
if (val) getDemandCompList(val, 3);
|
||||
}}
|
||||
textValue={f.value}
|
||||
setText={(val) => {
|
||||
setSeachDmdCo(val);
|
||||
setRtnData={(valList: PbnstDemandComType[]) => {
|
||||
console.log('valList[0] ', index)
|
||||
if (
|
||||
valList.length > 0 &&
|
||||
valList['0']
|
||||
) {
|
||||
form.setValue(
|
||||
`fcDemands.${index}.pbnstRuseFcltBizPk`,
|
||||
form.getValues('pbnstRuseFcltBizPk')
|
||||
);
|
||||
form.setValue(
|
||||
`fcDemands.${index}.pbnstRuseFcltFk`,
|
||||
form.getValues('pbnstRuseFcltFk')??''
|
||||
|
||||
);
|
||||
form.setValue(
|
||||
`fcDemands.${index}.dmdCoNm`,
|
||||
valList['0'].dmdCoNm
|
||||
);
|
||||
form.setValue(
|
||||
`fcDemands.${index}.daddr`,
|
||||
valList['0'].daddr
|
||||
);
|
||||
form.setValue(
|
||||
`fcDemands.${index}.useUsgCd`,
|
||||
valList['0'].useUsgCd
|
||||
);
|
||||
form.setValue(
|
||||
`fcDemands.${index}.splyCpct`,
|
||||
valList['0'].splyCpct
|
||||
);
|
||||
form.setValue(
|
||||
`fcDemands.${index}.splyFmYn`,
|
||||
valList['0'].splyFmYn ?? "Y"
|
||||
);
|
||||
form.setValue(
|
||||
`fcDemands.${index}.dmdInfoFk`,
|
||||
valList['0'].dmdInfoPk?.toString() ?? ""
|
||||
);
|
||||
}
|
||||
|
||||
}}
|
||||
selectValue={searchDmdCo}
|
||||
></SearchInputSelect>
|
||||
></SearchInputText>
|
||||
</FormUi>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-4">
|
||||
<div key={index + "keySon2"} className="col-span-4">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={`fcDemands.${index}.daddr`}
|
||||
@@ -449,6 +521,7 @@ export function PbnstBuseForm({
|
||||
<Input
|
||||
placeholder="-"
|
||||
type="text"
|
||||
readOnly
|
||||
onChange={(e) => f.onChange(e.target.value)}
|
||||
value={f.value}
|
||||
className={selectClass}
|
||||
@@ -457,24 +530,25 @@ export function PbnstBuseForm({
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-4">
|
||||
<div key={index + "keySon3"} className="col-span-4">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={`fcDemands.${index}.useUsgCd`}
|
||||
render={({ field: f }) => (
|
||||
<FormUi label="사용용도">
|
||||
<Input
|
||||
placeholder="-"
|
||||
type="text"
|
||||
onChange={(e) => f.onChange(e.target.value)}
|
||||
value={f.value}
|
||||
className={selectClass}
|
||||
<SelectBox
|
||||
label={""}
|
||||
selectClass={""}
|
||||
className="w-full"
|
||||
selectArray={code.dmdUszCd}
|
||||
onSelectValue={f.onChange}
|
||||
value={f.value?? code.dmdUszCd[0]?.val}
|
||||
/>
|
||||
</FormUi>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-3">
|
||||
<div key={index + "keySon4"} className="col-span-3">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={`fcDemands.${index}.splyBgngDay`}
|
||||
@@ -492,7 +566,7 @@ export function PbnstBuseForm({
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-3">
|
||||
<div key={index + "keySon5"} className="col-span-3">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={`fcDemands.${index}.splyEndDay`}
|
||||
@@ -510,7 +584,7 @@ export function PbnstBuseForm({
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-3">
|
||||
<div key={index + "keySon6"} className="col-span-3">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={`fcDemands.${index}.splyCpct`}
|
||||
@@ -528,7 +602,7 @@ export function PbnstBuseForm({
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-3">
|
||||
<div key={index + "keySon7"} className="col-span-3">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={`fcDemands.${index}.splyFmYn`}
|
||||
@@ -570,6 +644,30 @@ export function PbnstBuseForm({
|
||||
></FcOrgwtsRegModal>
|
||||
}
|
||||
></UiModal>
|
||||
|
||||
<UiModal
|
||||
bodyClass={"w-[40vw] max-w-none h-[90vh]"}
|
||||
open={isDmdModal.isMoal}
|
||||
onOpenChange={() => {
|
||||
setIsDmdModal({ isMoal: false, data: {} as DemandCompType });
|
||||
}}
|
||||
body={
|
||||
<SdmInsertForm
|
||||
selectSidoData={code.cityCd}
|
||||
selectSigunData={code.sggCd}
|
||||
dataList={demandCompList}
|
||||
rtnValue={(searchText: string, pageCnt: number) => {
|
||||
getDemandCompList(searchText, pageCnt);
|
||||
}}
|
||||
rtnInputData={(data) => {
|
||||
console.log(" rtn data ", data);
|
||||
regDemandCompany(data as DemandCompType);
|
||||
setIsDmdModal({ isMoal: false, data: data as DemandCompType });
|
||||
}}
|
||||
bodyClassNm={"w-full mx-auto bg-white rounded-lg shadow-md p-6"}
|
||||
></SdmInsertForm>
|
||||
}
|
||||
></UiModal>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -91,9 +91,13 @@ export function PbnstMngForm({
|
||||
getpbnstInsertIndex({ ...pbnst.pbnsUpdateIndex, mng: val });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const plusHist = () => {
|
||||
const currentTableDataFromRef = ref.current ? [...ref.current] : [];
|
||||
const regData = {
|
||||
choose: false,
|
||||
pbnstRuseFcltFk:form.getValues('pbnstRuseFcltPk')??"",
|
||||
rgtr: "",
|
||||
mdfr: "",
|
||||
operMthd: "",
|
||||
@@ -101,7 +105,6 @@ export function PbnstMngForm({
|
||||
bgngDt: new Date(),
|
||||
endDt: new Date(),
|
||||
};
|
||||
const currentTableDataFromRef = ref.current ? [...ref.current] : [];
|
||||
const newDataForRHF = [...currentTableDataFromRef, regData];
|
||||
form.setValue("fcOpers", newDataForRHF, {
|
||||
shouldValidate: true, // 필요하다면 유효성 검사 실행
|
||||
@@ -246,27 +249,37 @@ export function PbnstMngForm({
|
||||
}
|
||||
}
|
||||
}, [pbnst.pbnsUpdateIndex, pbnst.pbnstRes, formType, getBizCycle]);
|
||||
|
||||
//신규 등록시 입력할때 데이터 넣기
|
||||
useEffect(() => {
|
||||
const formData = form.watch();
|
||||
formData.fcOpers = ref.current ? [...ref.current] : [];
|
||||
formData.fcFiles = regFileList ? [...regFileList] : [];
|
||||
if (formType === "reg") {
|
||||
const formData = form.watch();
|
||||
formData.fcOpers = ref.current ? [...ref.current] : [];
|
||||
formData.fcFiles = regFileList ? [...regFileList] : [];
|
||||
pbnstMngData([formData] as customPbnst[]);
|
||||
} else if (formType === "update"){
|
||||
const updateRes = pbnst.pbnstRes?.map((item)=>{
|
||||
if(item.pbnstRuseFcltPk === item.pbnstRuseFcltPk){
|
||||
item=formData as customPbnst
|
||||
}
|
||||
return item
|
||||
})
|
||||
pbnstMngData(updateRes as customPbnst[]);
|
||||
}
|
||||
}, [form.formState, regFileList, formType]);
|
||||
}, [form.formState, regFileList, formType, pbnst.pbnstRes]);
|
||||
|
||||
useEffect(() => {
|
||||
pbnstMngData(pbnst.pbnstMngRegData);
|
||||
}, [pbnst.pbnstMngRegData]);
|
||||
|
||||
useEffect(() => {
|
||||
if ( pbnst.pbnstRes && pbnst.pbnstRes?.length> 0) return;
|
||||
|
||||
if ( pbnst.pbnstRes && pbnst.pbnstRes?.length<= 0) return;
|
||||
const fcltNmList = pbnst.pbnstRes?.map((item, index) => ({
|
||||
text: item.ruseUtztnFcltNm,
|
||||
val: String(index),
|
||||
}));
|
||||
|
||||
|
||||
if(fcltNmList)
|
||||
setFcltNm(fcltNmList);
|
||||
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
|
||||
import { useWrStore } from '@/app/store';
|
||||
import type { PbnstDemandComType } from '@/app/store/ruseFcltMng/fcltReg/pbnstReg/type';
|
||||
import type { DemandCompType } from '@common/business_components/ui';
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
|
||||
type thisProps = {
|
||||
label: string | undefined;
|
||||
initValue: string | undefined;
|
||||
setValue : (dmdCoNm?: string) => void;
|
||||
setRtnData : (rtnData: PbnstDemandComType[]) => void;
|
||||
}
|
||||
|
||||
|
||||
export default function SearchInputText({label=undefined, initValue=undefined, setValue=()=>{}, setRtnData=()=>{}} :thisProps) {
|
||||
|
||||
const { demandCompList } = useWrStore((state) => state);
|
||||
|
||||
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [textValue, setTextValue] = useState(initValue || '');
|
||||
const wrapperRef = useRef<HTMLDivElement>(null);
|
||||
const handleInputChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = e.target.value;
|
||||
setTextValue(value);
|
||||
setValue(value);
|
||||
if (value) {
|
||||
setIsOpen(true);
|
||||
} else {
|
||||
setIsOpen(false);
|
||||
}
|
||||
}, [ setValue]);
|
||||
|
||||
const handleSuggestionClick = useCallback((dmdCoNm: string) => {
|
||||
setTextValue(dmdCoNm);
|
||||
setValue(dmdCoNm);
|
||||
setIsOpen(false);
|
||||
setRtnData(demandCompList);
|
||||
}, [demandCompList, setRtnData, setValue]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
if (wrapperRef.current && !wrapperRef.current.contains(event.target as Node)) {
|
||||
setIsOpen(false);
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div ref={wrapperRef}>
|
||||
<input
|
||||
type="text"
|
||||
value={textValue}
|
||||
onChange={handleInputChange}
|
||||
/* onFocus={() => setIsOpen(true)} */
|
||||
className="w-full h-[3.2rem] !text-xl pl-3 text-gray-600 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
placeholder={`${label}을(를) 입력하세요`}
|
||||
/>
|
||||
{isOpen && (
|
||||
<div className=" z-1 w-full mt-2 bg-white border border-gray-300 rounded-md shadow-lg h-90 overflow-auto">
|
||||
<div className="max-h-72">
|
||||
{demandCompList && demandCompList.length > 0 ? demandCompList.map((item : DemandCompType, index : number) => (
|
||||
<div
|
||||
key={index}
|
||||
className="!text-xl w-full text-left px-5 py-3 hover:bg-gray-100 cursor-pointer overflow-auto"
|
||||
onClick={() => handleSuggestionClick(item.dmdCoNm)}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
handleSuggestionClick(item.dmdCoNm);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{item.dmdInfoPk.substring(0,10)} <span className="float-right">{item.dmdCoNm}</span>
|
||||
</div>
|
||||
)) : (
|
||||
<div className="!text-xl w-full px-5 py-3 hover:bg-gray-100 cursor-pointer overflow-auto">
|
||||
검색 결과가 없습니다.
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useCallback, useState } from "react";
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
import { FormControl, FormItem, FormLabel, FormMessage } from "../form";
|
||||
import { Button, Checkbox } from "@common/components/ui";
|
||||
|
||||
@@ -17,7 +17,11 @@ interface FormElementProps extends React.HTMLAttributes<HTMLElement> {
|
||||
|
||||
const FormUi = React.forwardRef<HTMLDivElement, FormUiProps>(
|
||||
({ children, label, onCheckboxChange, isDisabled }, ref) => {
|
||||
const [isChecked, setIsChecked] = useState(false);
|
||||
const [isChecked, setIsChecked] = useState(isDisabled);
|
||||
|
||||
useEffect(() => {
|
||||
setIsChecked(isDisabled);
|
||||
}, [isDisabled]);
|
||||
|
||||
const handleCheckboxChange = useCallback((checked: boolean) => {
|
||||
setIsChecked(checked);
|
||||
@@ -50,7 +54,7 @@ const FormUi = React.forwardRef<HTMLDivElement, FormUiProps>(
|
||||
<FormControl>
|
||||
{React.isValidElement(children) && isDisabled
|
||||
? React.cloneElement(children, {
|
||||
disabled: true,
|
||||
disabled: isDisabled,
|
||||
...(children.props as FormElementProps)
|
||||
})
|
||||
: children}
|
||||
|
||||
@@ -19,4 +19,4 @@ export * from "./tab";
|
||||
export * from "./table";
|
||||
export * from "./table_div";
|
||||
export * from "./title";
|
||||
|
||||
export * from "./sdmInsertForm";
|
||||
@@ -0,0 +1,287 @@
|
||||
import { FormField } from "../form";
|
||||
import { SelectBox } from "../select";
|
||||
import { Input } from "@common/components";
|
||||
import { FormUi } from "../form_ui";
|
||||
import { useCallback, useState } from "react";
|
||||
import type { ControllerRenderProps, UseFormReturn } from "react-hook-form";
|
||||
import { SdmSearchForm } from "./sdmNameBox";
|
||||
import type { DemandCompType } from "../../../../../../apps/dm/app/store/sdmMng";
|
||||
|
||||
type SelectDataType = {
|
||||
text: string;
|
||||
val: string;
|
||||
};
|
||||
|
||||
interface FormSchema {
|
||||
ctpvCd: string;
|
||||
sggCd: string;
|
||||
dmdCoNm: string;
|
||||
dmdInfoPk: string;
|
||||
daddr: string;
|
||||
telno: string;
|
||||
bznmTotNo?: string;
|
||||
rgtr?: string;
|
||||
dmdAplyPswd?: string;
|
||||
}
|
||||
|
||||
interface SdmRegFormProps {
|
||||
form: UseFormReturn<FormSchema>;
|
||||
onCheckboxChange?: (checked: boolean) => void;
|
||||
selectSidoData: SelectDataType[];
|
||||
selectSigunData: SelectDataType[];
|
||||
dataList: DemandCompType[];
|
||||
rtnValue: (searchText: string, pageCnt: number) => void;
|
||||
setIsDuplicate: (value: boolean) => void;
|
||||
}
|
||||
|
||||
type FieldComponent = (field: ControllerRenderProps<FormSchema, keyof FormSchema>) => JSX.Element;
|
||||
|
||||
export function SdmRegForm({ form, onCheckboxChange, selectSidoData, selectSigunData, dataList, rtnValue, setIsDuplicate }: SdmRegFormProps) {
|
||||
const [sidoValue, setSidoValue] = useState<string>('');
|
||||
const [sigunValue, setSigunValue] = useState<string>('');
|
||||
const [filteredSigunData, setFilteredSigunData] = useState<SelectDataType[]>([{ text: "전체", val: '0' }]);
|
||||
const [isBznmTotNoDisabled, setIsBznmTotNoDisabled] = useState(true);
|
||||
const [orgBznmNo, setOrgBznmNo] = useState<string>('');
|
||||
|
||||
const initializeSigunData = useCallback((sidoCd: string) => {
|
||||
if (sidoCd === '0') {
|
||||
setSigunValue('0');
|
||||
setFilteredSigunData([{ text: "전체", val: '0' }]);
|
||||
} else {
|
||||
const newFilteredData = [
|
||||
{ text: "전체", val: '0' },
|
||||
...selectSigunData.filter((item: SelectDataType) => item.val.substring(0, 2) === sidoCd)
|
||||
];
|
||||
setSigunValue('0');
|
||||
setFilteredSigunData(newFilteredData);
|
||||
}
|
||||
}, [selectSigunData]);
|
||||
|
||||
const onSelectValue = useCallback((
|
||||
val: string,
|
||||
type: string,
|
||||
field: ControllerRenderProps<FormSchema, keyof FormSchema> | undefined
|
||||
) => {
|
||||
switch (type) {
|
||||
case "ctpvCd":
|
||||
initializeSigunData(val);
|
||||
setSidoValue(val);
|
||||
field?.onChange(val);
|
||||
form.setValue('dmdInfoPk', '');
|
||||
form.setValue('bznmTotNo', '');
|
||||
break;
|
||||
case "sggCd":
|
||||
setSigunValue(val);
|
||||
field?.onChange(val);
|
||||
form.setValue('dmdInfoPk', '');
|
||||
form.setValue('bznmTotNo', '');
|
||||
break;
|
||||
}
|
||||
}, [initializeSigunData, form]);
|
||||
|
||||
const handleCheckboxChange = useCallback((checked: boolean) => {
|
||||
setIsBznmTotNoDisabled(checked);
|
||||
onCheckboxChange?.(checked);
|
||||
}, [onCheckboxChange]);
|
||||
|
||||
const setRtnValue = useCallback((searchText: string, pageCnt: number) => {
|
||||
rtnValue(searchText, pageCnt);
|
||||
}, [rtnValue]);
|
||||
|
||||
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));
|
||||
|
||||
// 수요처 불러온 후 사업자번호를 바꿀경우를 대비함
|
||||
setOrgBznmNo(rtnCompData?.dmdInfoPk);
|
||||
const sidoCd = rtnCompData?.ctpvCd.trim() || '';
|
||||
setSidoValue(sidoCd);
|
||||
form.setValue('ctpvCd', sidoCd);
|
||||
initializeSigunData(sidoCd);
|
||||
|
||||
setTimeout(() => {
|
||||
const sigunCd = rtnCompData?.sggCd.trim() || '';
|
||||
setSigunValue(sigunCd);
|
||||
form.setValue('sggCd', sigunCd);
|
||||
}, 100);
|
||||
|
||||
if(rtnCompData?.dmdInfoPk.substring(10,14) === '0000') {
|
||||
handleCheckboxChange(true);
|
||||
} else {
|
||||
handleCheckboxChange(false);
|
||||
}
|
||||
|
||||
form.setValue('daddr', rtnCompData?.daddr || '');
|
||||
form.setValue('telno', rtnCompData?.telno || '');
|
||||
|
||||
// 선택을 했을 때 중복 상태를 true로 설정
|
||||
setIsDuplicate(true);
|
||||
}, [form, handleCheckboxChange, initializeSigunData, setIsDuplicate]);
|
||||
|
||||
const setRtnText = useCallback((text: string) => {
|
||||
form.setValue('dmdCoNm', text);
|
||||
}, [form]);
|
||||
|
||||
const bznNoChange = useCallback((e: React.ChangeEvent<HTMLInputElement>, noType: string) => {
|
||||
const value = e.target.value;
|
||||
console.log('form value : '+form.getValues('dmdInfoPk'));
|
||||
console.log('org value : '+orgBznmNo);
|
||||
|
||||
if(noType === 'dmdInfoPk') {
|
||||
if(orgBznmNo.substring(0,10) === value) {
|
||||
setIsDuplicate(true);
|
||||
} else {
|
||||
setIsDuplicate(false);
|
||||
}
|
||||
form.setValue('dmdInfoPk', value);
|
||||
} else {
|
||||
if(orgBznmNo.substring(10,14) === value) {
|
||||
setIsDuplicate(true);
|
||||
} else {
|
||||
setIsDuplicate(false);
|
||||
}
|
||||
form.setValue('bznmTotNo', value);
|
||||
}
|
||||
|
||||
}, [form, orgBznmNo, setIsDuplicate]);
|
||||
|
||||
const formFields: Array<{
|
||||
name: keyof FormSchema;
|
||||
label: string;
|
||||
component: FieldComponent;
|
||||
}> = [
|
||||
{
|
||||
name: "ctpvCd",
|
||||
label: "시도",
|
||||
component: (field) => (
|
||||
<SelectBox
|
||||
selectClass={undefined}
|
||||
label=""
|
||||
selectArray={selectSidoData}
|
||||
onSelectValue={(val) => onSelectValue(val.toString(), 'ctpvCd', field)}
|
||||
className=""
|
||||
value={sidoValue}
|
||||
/>
|
||||
)
|
||||
},
|
||||
{
|
||||
name: "sggCd",
|
||||
label: "시군구",
|
||||
component: (field) => (
|
||||
<SelectBox
|
||||
selectClass={undefined}
|
||||
label=""
|
||||
selectArray={filteredSigunData}
|
||||
onSelectValue={(val) => onSelectValue(val.toString(), 'sggCd', field)}
|
||||
className=""
|
||||
value={sigunValue}
|
||||
/>
|
||||
)
|
||||
},
|
||||
{
|
||||
name: "dmdCoNm",
|
||||
label: "회사명",
|
||||
component: (field) => (
|
||||
<SdmSearchForm
|
||||
rtnData={setRtnData}
|
||||
label="수요처명"
|
||||
initValue={''}
|
||||
dataList={dataList}
|
||||
rtnValue={setRtnValue}
|
||||
rtnText={setRtnText}
|
||||
{...field}
|
||||
/>
|
||||
)
|
||||
},
|
||||
{
|
||||
name: "dmdInfoPk",
|
||||
label: "사업자등록번호",
|
||||
component: (field) => (
|
||||
<Input
|
||||
placeholder="사업자등록번호를 입력하세요"
|
||||
type="text"
|
||||
className="!text-xl text-gray-600"
|
||||
{...field}
|
||||
onChange={(e) => bznNoChange(e, 'dmdInfoPk')}
|
||||
/>
|
||||
)
|
||||
},
|
||||
{
|
||||
name: "bznmTotNo",
|
||||
label: "종사업자등록번호",
|
||||
component: (field) => (
|
||||
<FormUi
|
||||
label="종사업자등록번호"
|
||||
onCheckboxChange={handleCheckboxChange}
|
||||
isDisabled={isBznmTotNoDisabled}
|
||||
>
|
||||
<Input
|
||||
placeholder="여러사업장이 있을 경우 입력해주세요"
|
||||
type="text"
|
||||
className="!mt-5 !text-xl text-gray-600"
|
||||
disabled={isBznmTotNoDisabled}
|
||||
{...field}
|
||||
onChange={(e) => bznNoChange(e, 'bznmTotNo')}
|
||||
/>
|
||||
</FormUi>
|
||||
)
|
||||
},
|
||||
{
|
||||
name: "daddr",
|
||||
label: "사업자주소",
|
||||
component: (field) => (
|
||||
<Input
|
||||
placeholder="주소를 입력하세요"
|
||||
type="text"
|
||||
className="!text-xl text-gray-600"
|
||||
{...field}
|
||||
/>
|
||||
)
|
||||
},
|
||||
{
|
||||
name: "telno",
|
||||
label: "전화번호",
|
||||
component: (field) => (
|
||||
<Input
|
||||
placeholder="전화번호를 입력하세요"
|
||||
type="text"
|
||||
className="!text-xl text-gray-600"
|
||||
{...field}
|
||||
/>
|
||||
)
|
||||
},
|
||||
{
|
||||
name: "dmdAplyPswd",
|
||||
label: "패스워드",
|
||||
component: (field) => (
|
||||
<Input
|
||||
placeholder="패스워드를 입력하세요"
|
||||
type="password"
|
||||
className="!text-xl text-gray-600"
|
||||
{...field}
|
||||
/>
|
||||
)
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
{formFields.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>
|
||||
)
|
||||
)}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
"use client";
|
||||
|
||||
/* import { useDmStore } from "@/app/store"; */
|
||||
import { SdmRegForm } from "./form";
|
||||
import { Button } from "@common/components/ui";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
/* import { useRouter } from "next/navigation"; */
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { FormProvider, useForm, type SubmitHandler } from "react-hook-form";
|
||||
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 | '';
|
||||
}
|
||||
|
||||
|
||||
type thisProps = {
|
||||
selectSidoData: SelectDataType[];
|
||||
selectSigunData: SelectDataType[];
|
||||
dataList: DemandCompType[];
|
||||
rtnValue: (searchText: string, pageCnt: number) => void;
|
||||
rtnInputData: (data: DemandCompType) => void;
|
||||
bodyClassNm?: string;
|
||||
}
|
||||
|
||||
const createFormSchema = (isBznmTotNoDisabled: boolean, isDuplicate: boolean) => z.object({
|
||||
ctpvCd: z.string().min(1, "시/도를 선택해주세요"),
|
||||
sggCd: z.string().min(1, "시/군/구를 선택해주세요"),
|
||||
dmdCoNm: z.string()
|
||||
.min(1, "회사명을 입력해주세요")
|
||||
.max(20, "회사명은 20자 이내로 입력해주세요"),
|
||||
dmdInfoPk: z.string()
|
||||
.min(1, "사업자등록번호를 입력해주세요")
|
||||
.regex(/^\d{10}$/, "사업자등록번호는 10자리 숫자만 입력 가능합니다")
|
||||
.refine(() => isBznmTotNoDisabled ? !isDuplicate : true, "이미 등록된 사업자등록번호입니다"),
|
||||
bznmTotNo: isBznmTotNoDisabled
|
||||
? z.string().optional()
|
||||
: z.string()
|
||||
.length(4, "종사업자등록번호는 4자리 숫자만 입력 가능합니다")
|
||||
.refine(() => !isDuplicate, "이미 등록된 사업자등록번호입니다"),
|
||||
daddr: z.string()
|
||||
.min(1, "주소를 입력해주세요")
|
||||
.min(6, "주소는 6자 이상 입력해주세요")
|
||||
.max(40, "주소는 40자 이내로 입력해주세요"),
|
||||
telno: z.string()
|
||||
.min(8, "전화번호는 8자 이상 입력해주세요")
|
||||
.max(12, "전화번호는 12자 이내로 입력해주세요")
|
||||
.regex(/^[0-9-]+$/, "전화번호는 숫자와 하이픈(-)만 입력 가능합니다"),
|
||||
rgtr: z.string().optional(),
|
||||
dmdAplyPswd : z.string()
|
||||
.min(1, "패스워드를 입력해주세요")
|
||||
.min(8, "패스워드는 8자 이상 입력해주세요")
|
||||
.max(16, "패스워드는 16자 이내로 입력해주세요"),
|
||||
});
|
||||
|
||||
type FormSchema = ReturnType<typeof createFormSchema>;
|
||||
export type FormData = z.infer<FormSchema>;
|
||||
|
||||
const defaultValues: FormData = {
|
||||
ctpvCd: '',
|
||||
sggCd: '',
|
||||
dmdCoNm: '',
|
||||
dmdInfoPk: '',
|
||||
bznmTotNo: '',
|
||||
daddr: '',
|
||||
telno: '',
|
||||
rgtr: "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||
dmdAplyPswd : '',
|
||||
};
|
||||
|
||||
/**
|
||||
* 수요처 등록 폼
|
||||
* @param selectSidoData 시/도 데이터
|
||||
* @param selectSigunData 시/군/구 데이터
|
||||
* @param dataList 수요처 목록
|
||||
* @param rtnValue 검색 결과(텍스트) 콜백
|
||||
* @param rtnInputData 수요처 리스트 콜백
|
||||
* @returns
|
||||
*/
|
||||
|
||||
/**
|
||||
* 페이지에서 작업
|
||||
const {Common, initializeCommonData, getDemandCompList, insertSdmData, Sdm} = useDmStore((state) => state);
|
||||
const { selectSidoData, selectSigunData } = Common;
|
||||
const { demandCompList } = Sdm;
|
||||
|
||||
// 공통데이터 (시도, 시군구 데이터 호출)
|
||||
useEffect(() => {
|
||||
initializeCommonData();
|
||||
}, [initializeCommonData]);
|
||||
|
||||
// 컴포넌트에서 텍스트 검색 호출
|
||||
const callback = useCallback((searchText: string, pageCnt: number) => {
|
||||
searchText = searchText.trim();
|
||||
if(searchText.length > 0) {
|
||||
getDemandCompList(searchText, pageCnt);
|
||||
}
|
||||
}, [getDemandCompList]);
|
||||
|
||||
// 컴포넌트에서 수요처 등록 호출
|
||||
const handleInsertSdmData = useCallback((data: DemandCompType) => {
|
||||
insertSdmData(data);
|
||||
|
||||
}, [insertSdmData]);
|
||||
*/
|
||||
|
||||
export default function SdmInsertForm({selectSidoData, selectSigunData, dataList, rtnValue, rtnInputData,bodyClassNm}: thisProps) {
|
||||
/* const { insertSdmData } = useDmStore((state) => state);
|
||||
const router = useRouter(); */
|
||||
|
||||
const [isBznmTotNoDisabled, setIsBznmTotNoDisabled] = useState(true);
|
||||
const [isDuplicate, setIsDuplicate] = useState(false);
|
||||
const formSchema = createFormSchema(isBznmTotNoDisabled, isDuplicate);
|
||||
|
||||
const form = useForm<z.infer<FormSchema>>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues,
|
||||
mode: "onChange",
|
||||
criteriaMode: "all",
|
||||
shouldFocusError: false,
|
||||
shouldUnregister: false
|
||||
});
|
||||
|
||||
// 체크박스 상태가 변경될 때마다 bznmTotNo 필드의 에러를 초기화
|
||||
useEffect(() => {
|
||||
if (isBznmTotNoDisabled) {
|
||||
form.clearErrors('bznmTotNo');
|
||||
form.setValue('bznmTotNo', '');
|
||||
}
|
||||
}, [isBznmTotNoDisabled, form]);
|
||||
|
||||
const setRtnValue = useCallback((searchText: string, pageCnt: number) => {
|
||||
rtnValue(searchText, pageCnt);
|
||||
}, [rtnValue]);
|
||||
|
||||
const onSubmit: SubmitHandler<z.infer<FormSchema>> = async (data) => {
|
||||
try {
|
||||
// form 에러 체크
|
||||
const formErrors = form.formState.errors;
|
||||
if (Object.keys(formErrors).length > 0) {
|
||||
const errorMessage = Object.values(formErrors)[0]?.message || '입력값을 확인해주세요.';
|
||||
toast.error(errorMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
const dmdInfoPk = data.dmdInfoPk + (data.bznmTotNo || '0000');
|
||||
const formData = {
|
||||
...data,
|
||||
dmdInfoPk,
|
||||
};
|
||||
|
||||
console.log(formData);
|
||||
/* await insertSdmData(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,
|
||||
});
|
||||
|
||||
//router.push(`/pages/sdmMng/sdmInfoInsert?${queryParams.toString()}`);
|
||||
toast.success('수요처가 성공적으로 등록되었습니다.');
|
||||
} catch (error) {
|
||||
console.error('Error submitting form:', error);
|
||||
toast.error('수요처 등록에 실패했습니다.');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="text-center mb-8">
|
||||
<h1 className="text-4xl font-bold text-gray-900 underline">
|
||||
수요처등록
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div className= {bodyClassNm?bodyClassNm:"!max-w-3xl mx-auto bg-white rounded-lg shadow-md p-6"}>
|
||||
<FormProvider {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
|
||||
<SdmRegForm
|
||||
form={form}
|
||||
onCheckboxChange={setIsBznmTotNoDisabled}
|
||||
selectSidoData={selectSidoData}
|
||||
selectSigunData={selectSigunData}
|
||||
dataList={dataList}
|
||||
rtnValue={setRtnValue}
|
||||
setIsDuplicate={setIsDuplicate}
|
||||
/>
|
||||
<div className="flex justify-center pt-4">
|
||||
<Button
|
||||
type="submit"
|
||||
className="w-32 bg-blue-600 hover:bg-blue-700 text-white font-semibold py-2 px-4 rounded-md transition-colors duration-200"
|
||||
>
|
||||
수요처등록
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</FormProvider>
|
||||
</div>
|
||||
<Toaster position="top-center" />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import type { DemandCompType } from "../../../../../../apps/dm/app/store/sdmMng";
|
||||
|
||||
export type thisProps = {
|
||||
label: string | undefined;
|
||||
initValue: string | undefined;
|
||||
dataList : DemandCompType[];
|
||||
rtnValue : (searchText: string, pageCnt: number) => void;
|
||||
rtnData : (item: DemandCompType) => void;
|
||||
rtnText : (text: string) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* 수요처 검색 컴포넌트
|
||||
* @param label 라벨
|
||||
* @param initValue 초기값
|
||||
* @param rtnValue 검색 결과 반환 함수
|
||||
* @param dataList 검색할 때 넘기는 데이터 리스트
|
||||
* @param rtnData 검색 결과 반환 함수
|
||||
*/
|
||||
export const SdmSearchForm = ({label=undefined, initValue=undefined, rtnValue=()=>{}, dataList=[], rtnData=()=>{}, rtnText=()=>{} } :thisProps) => {
|
||||
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [textValue, setTextValue] = useState(initValue || '');
|
||||
const wrapperRef = useRef<HTMLDivElement>(null);
|
||||
const handleInputChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = e.target.value;
|
||||
setTextValue(value);
|
||||
rtnValue(value, 10);
|
||||
rtnText(value);
|
||||
if (value) {
|
||||
setIsOpen(true);
|
||||
} else {
|
||||
setIsOpen(false);
|
||||
}
|
||||
}, [rtnValue, rtnText]);
|
||||
|
||||
const handleSuggestionClick = useCallback((item: DemandCompType) => {
|
||||
setTextValue(item.dmdCoNm);
|
||||
rtnData(item);
|
||||
setIsOpen(false);
|
||||
}, [rtnData]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
if (wrapperRef.current && !wrapperRef.current.contains(event.target as Node)) {
|
||||
setIsOpen(false);
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div ref={wrapperRef}>
|
||||
<input
|
||||
type="text"
|
||||
value={textValue}
|
||||
onChange={handleInputChange}
|
||||
/* onFocus={() => setIsOpen(true)} */
|
||||
className="w-full h-[3.2rem] !text-xl pl-3 text-gray-600 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
placeholder={`${label}을(를) 입력하세요`}
|
||||
/>
|
||||
{isOpen && (
|
||||
<div className=" z-1 w-full mt-2 bg-white border border-gray-300 rounded-md shadow-lg h-90 overflow-auto">
|
||||
<div className="max-h-72">
|
||||
{dataList && dataList.length > 0 ? dataList.map((item : DemandCompType, index : number) => (
|
||||
<div
|
||||
key={index}
|
||||
className="!text-xl w-full text-left px-5 py-3 hover:bg-gray-100 cursor-pointer overflow-auto"
|
||||
onClick={() => handleSuggestionClick(item)}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
handleSuggestionClick(item);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{item.dmdInfoPk.substring(10,14) !== '0000' ? (
|
||||
<>
|
||||
<span className="text-gray-500">사업자번호 : </span> {item.dmdInfoPk.substring(0,10)}
|
||||
<span className="text-gray-500">종사업자번호 : </span> {item.dmdInfoPk.substring(10,14)}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<span className="text-gray-500">사업자번호 : </span> {item.dmdInfoPk.substring(0,10)}
|
||||
</>
|
||||
)}
|
||||
<span className="float-right">{item.dmdCoNm}</span>
|
||||
</div>
|
||||
)) : (
|
||||
<div className="!text-xl w-full px-5 py-3 hover:bg-gray-100 cursor-pointer overflow-auto">
|
||||
검색 결과가 없습니다.
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user