feat: 조사매물 내 공통코드 동기화를 위한 surveyOptionStore 추가
This commit is contained in:
parent
7e2d93426f
commit
b571197ffc
@ -1,7 +1,8 @@
|
||||
import { useState } from 'react'
|
||||
import { useEffect, useState } from 'react'
|
||||
import type { Mode, SurveyDetailInfo, SurveyDetailRequest } from '@/types/Survey'
|
||||
import { useAlertMsg, WARNING_MESSAGE } from '@/hooks/useAlertMsg'
|
||||
import { radioEtcData, selectBoxOptions, supplementaryFacilities, roofMaterial } from '@/types/Survey'
|
||||
import { radioEtcData, supplementaryFacilities } from '@/types/Survey'
|
||||
import { useSurveyOptionStore } from '@/store/surveyOptionStore'
|
||||
|
||||
const makeNumArr = (value: string) => {
|
||||
return value
|
||||
@ -292,10 +293,15 @@ const SelectedBox = ({
|
||||
detailInfoData: SurveyDetailInfo
|
||||
setRoofInfo: (roofInfo: SurveyDetailRequest) => void
|
||||
}) => {
|
||||
const { selectBoxOptions, initialized, loading, loadOptions } = useSurveyOptionStore()
|
||||
const selectedId = detailInfoData?.[column as keyof SurveyDetailInfo]
|
||||
const etcValue = detailInfoData?.[`${column}Etc` as keyof SurveyDetailInfo]
|
||||
const [isEtcSelected, setIsEtcSelected] = useState<boolean>(Boolean(etcValue))
|
||||
|
||||
useEffect(() => {
|
||||
if (!initialized && !loading) loadOptions()
|
||||
}, [initialized, loading])
|
||||
|
||||
const isSpecialCase = column === 'constructionYear' || column === 'installationAvailability'
|
||||
const showEtcOption = !isSpecialCase
|
||||
|
||||
@ -509,10 +515,15 @@ const MultiCheck = ({
|
||||
setRoofInfo: (roofInfo: SurveyDetailRequest) => void
|
||||
}) => {
|
||||
const { showErrorAlert } = useAlertMsg()
|
||||
const { roofMaterial, initialized, loading, loadOptions } = useSurveyOptionStore()
|
||||
const multiCheckData = column === 'supplementaryFacilities' ? supplementaryFacilities : roofMaterial
|
||||
const etcValue = roofInfo?.[`${column}Etc` as keyof SurveyDetailInfo]
|
||||
const [isOtherCheck, setIsOtherCheck] = useState<boolean>(Boolean(etcValue))
|
||||
|
||||
useEffect(() => {
|
||||
if (!initialized && !loading) loadOptions()
|
||||
}, [initialized, loading])
|
||||
|
||||
const isRoofMaterial = column === 'roofMaterial'
|
||||
const selectedValues = makeNumArr(String(roofInfo[column as keyof SurveyDetailInfo] ?? ''))
|
||||
|
||||
|
||||
198
src/store/surveyOptionStore.ts
Normal file
198
src/store/surveyOptionStore.ts
Normal file
@ -0,0 +1,198 @@
|
||||
import { create } from 'zustand'
|
||||
import { axiosInstance } from '@/libs/axios'
|
||||
import { selectBoxOptions as defaultSelectBoxOptions, roofMaterial as defaultRoofMaterial, type SelectBoxKeys } from '@/types/Survey'
|
||||
import { type CommCode } from '@/types/CommCode'
|
||||
|
||||
export const SURVEY_OPTION_HEAD_ID: { [key: string]: string } = {
|
||||
/* 지붕재 종류 : HEAD_ID = 'ROOF_MATL' (HEAD_CD = 114200) */
|
||||
roofMaterial: 'ROOF_MATL',
|
||||
/* 건축 연수 : HEAD_ID = 'BUILDING' (HEAD_CD = 114000) */
|
||||
constructionYear: 'BUILDING',
|
||||
/* 서까래 피치 : HEAD_ID = 'RAFT_BASE_CD' (HEAD_CD = 203800) */
|
||||
rafterPitch: 'RAFT_BASE_CD',
|
||||
/* 골목판 종류 : HEAD_ID = 'ROOF_BOARD' (HEAD_CD = 114600) */
|
||||
openFieldPlateKind: 'ROOF_BOARD',
|
||||
}
|
||||
|
||||
/*
|
||||
* 2025-08-04 기준 공통코드 동기화 목록
|
||||
*
|
||||
* 옵션 데이터 공통코드 동기화 목록 : SURVEY_OPTION_HEAD_ID -> roofMaterial, constructionYear, rafterPitch, openFieldPlateKind
|
||||
* 제약사항 : BC_COMM_L.CODE 데이터 기준으로 code값 하드코딩 데이터 동기화 필요. 공통코드 테이블 내에 데이터가 없는 경우 null 처리.
|
||||
* 설명 : 공통코드 테이블 데이터로 하드코딩된 code값을 기준으로 code_jp(name)값 업데이트.
|
||||
* code가 null인 경우 name값 업데이트 하지 않음 (= 공통코드 데이터로 업데이트 하지 않고, 내부 데이터 유지)
|
||||
*
|
||||
* comm_cd : {
|
||||
* // 지붕재 종류 : HEAD_ID = 'ROOF_MATL' (HEAD_CD = 114200)
|
||||
* roofMaterial : [
|
||||
* // 슬레이트
|
||||
* {
|
||||
* head_cd: '114200',
|
||||
* code: '7',
|
||||
* code_jp: 'スレート',
|
||||
* },
|
||||
* // 아스팔트 싱글
|
||||
* {
|
||||
* head_cd: '114200',
|
||||
* code: '8',
|
||||
* code_jp: 'アスファルトシングル',
|
||||
* },
|
||||
* // 기와
|
||||
* {
|
||||
* head_cd: '114200',
|
||||
* code: null,
|
||||
* code_jp: '瓦',
|
||||
* },
|
||||
* // 금속지붕
|
||||
* {
|
||||
* head_cd: '114200',
|
||||
* code: null,
|
||||
* code_jp: '金属屋根',
|
||||
* },
|
||||
* ],
|
||||
* // 건축 연수 : HEAD_ID = 'BUILDING' (HEAD_CD = 114000)
|
||||
* constructionYear : [
|
||||
* // 신축
|
||||
* {
|
||||
* head_cd: '114000',
|
||||
* code: 'N',
|
||||
* code_jp: '新築',
|
||||
* },
|
||||
* // 기축
|
||||
* {
|
||||
* head_cd: '114000',
|
||||
* code: 'O',
|
||||
* code_jp: '既築',
|
||||
* },
|
||||
* ],
|
||||
* // 서까래 피치 : HEAD_ID = 'RAFT_BASE_CD' (HEAD_CD = 203800)
|
||||
* rafterPitch : [
|
||||
* // 455mm 이하
|
||||
* {
|
||||
* head_cd: '203800',
|
||||
* code: 'HEI_455',
|
||||
* code_jp: '455mm以下',
|
||||
* },
|
||||
* // 500mm 이하
|
||||
* {
|
||||
* head_cd: '203800',
|
||||
* code: 'HEI_500',
|
||||
* code_jp: '500mm以下',
|
||||
* },
|
||||
* // 606mm 이하
|
||||
* {
|
||||
* head_cd: '203800',
|
||||
* code: 'HEI_606',
|
||||
* code_jp: '606mm以下',
|
||||
* },
|
||||
* ],
|
||||
* // 골목판 종류 : HEAD_ID = 'ROOF_BOARD' (HEAD_CD = 114600)
|
||||
* openFieldPlateKind : [
|
||||
* // 구조용합판
|
||||
* {
|
||||
* head_cd: '114600',
|
||||
* code: null,
|
||||
* code_jp: '構造用合板',
|
||||
* },
|
||||
* // OSB
|
||||
* {
|
||||
* head_cd: '114600',
|
||||
* code: 'O',
|
||||
* code_jp: 'OSB',
|
||||
* },
|
||||
* // 파티클보드
|
||||
* {
|
||||
* head_cd: '114600',
|
||||
* code: 'A',
|
||||
* code_jp: 'パーティクルボード',
|
||||
* },
|
||||
* // 소판
|
||||
* {
|
||||
* head_cd: '114600',
|
||||
* code: 'S',
|
||||
* code_jp: '小幅板',
|
||||
* },
|
||||
* ]
|
||||
* }
|
||||
*/
|
||||
|
||||
interface SurveyOptionState {
|
||||
/* 지붕재종류 데이터 */
|
||||
roofMaterial: typeof defaultRoofMaterial
|
||||
/* 셀렉트박스 옵션 데이터 */
|
||||
selectBoxOptions: typeof defaultSelectBoxOptions
|
||||
/* 로딩 여부 */
|
||||
loading: boolean
|
||||
/* 옵션 로드 완료 여부 */
|
||||
initialized: boolean
|
||||
/* 옵션 로드 */
|
||||
loadOptions: () => Promise<void>
|
||||
}
|
||||
|
||||
export const useSurveyOptionStore = create<SurveyOptionState>((set, get) => ({
|
||||
roofMaterial: defaultRoofMaterial,
|
||||
selectBoxOptions: defaultSelectBoxOptions,
|
||||
loading: false,
|
||||
initialized: false,
|
||||
|
||||
loadOptions: async () => {
|
||||
if (get().initialized || get().loading) return
|
||||
|
||||
set({ loading: true })
|
||||
|
||||
try {
|
||||
const promises = Object.entries(SURVEY_OPTION_HEAD_ID).map(async ([optionKey, headId]) => {
|
||||
try {
|
||||
const response = await axiosInstance(process.env.NEXT_PUBLIC_API_URL).get<CommCode[]>('/api/comm-code', {
|
||||
params: { headId: headId },
|
||||
})
|
||||
const commCodeData = response.data
|
||||
return { optionKey, commCodeData }
|
||||
} catch (error) {
|
||||
console.error(`${optionKey} 로드 실패:`, error)
|
||||
return { optionKey, commCodeData: [] }
|
||||
}
|
||||
})
|
||||
const results: { optionKey: string; commCodeData: CommCode[] }[] = await Promise.all(promises)
|
||||
|
||||
set((prev) => {
|
||||
const newState = {
|
||||
roofMaterial: [...prev.roofMaterial],
|
||||
selectBoxOptions: { ...prev.selectBoxOptions },
|
||||
}
|
||||
|
||||
results.forEach(({ optionKey, commCodeData }) => {
|
||||
if (optionKey === 'roofMaterial') {
|
||||
// 지붕재 종류 업데이트
|
||||
newState.roofMaterial = newState.roofMaterial.map((item) => {
|
||||
if (item.code) {
|
||||
const commCode = commCodeData.find((c) => c.code === item.code)
|
||||
if (commCode) {
|
||||
return { ...item, code: commCode.code, name: commCode.codeJp }
|
||||
}
|
||||
}
|
||||
return item
|
||||
})
|
||||
} else {
|
||||
// 셀렉트박스 옵션 업데이트
|
||||
const key = optionKey as SelectBoxKeys
|
||||
newState.selectBoxOptions[key] = newState.selectBoxOptions[key].map((item) => {
|
||||
if (item.code) {
|
||||
const commCode = commCodeData.find((c) => c.code === item.code)
|
||||
if (commCode) {
|
||||
return { ...item, code: commCode.code, name: commCode.codeJp }
|
||||
}
|
||||
}
|
||||
return item
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
return { ...newState, initialized: true, loading: false }
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('옵션 데이터 로드 중 오류 발생:', error)
|
||||
set({ loading: false })
|
||||
}
|
||||
},
|
||||
}))
|
||||
@ -332,7 +332,7 @@ type RadioEtcKeys =
|
||||
| 'insulationPresence'
|
||||
| 'rafterDirection'
|
||||
| 'leakTrace'
|
||||
type SelectBoxKeys =
|
||||
export type SelectBoxKeys =
|
||||
| 'installationSystem'
|
||||
| 'constructionYear'
|
||||
| 'roofShape'
|
||||
@ -341,155 +341,187 @@ type SelectBoxKeys =
|
||||
| 'openFieldPlateKind'
|
||||
| 'installationAvailability'
|
||||
|
||||
export const supplementaryFacilities = [
|
||||
export const supplementaryFacilities: { id: number; code: string | null; name: string }[] = [
|
||||
/** 에코큐트 */
|
||||
{ id: 1, name: 'エコキュート' },
|
||||
{ id: 1, code: null, name: 'エコキュート' },
|
||||
/** 에네팜 */
|
||||
{ id: 2, name: 'エネパーム' },
|
||||
{ id: 2, code: null, name: 'エネパーム' },
|
||||
/** 축전지시스템 */
|
||||
{ id: 3, name: '蓄電池システム' },
|
||||
{ id: 3, code: null, name: '蓄電池システム' },
|
||||
/** 태양광발전 */
|
||||
{ id: 4, name: '太陽光発電' },
|
||||
{ id: 4, code: null, name: '太陽光発電' },
|
||||
]
|
||||
|
||||
export const roofMaterial = [
|
||||
// 지붕재 종류 : HEAD_ID = 'ROOF_MATL' (114200)
|
||||
export const roofMaterial: { id: number; code: string | null; name: string }[] = [
|
||||
/** 슬레이트 */
|
||||
{ id: 1, name: 'スレート' },
|
||||
{ id: 1, code: '7', name: 'スレート' },
|
||||
/** 아스팔트 싱글 */
|
||||
{ id: 2, name: 'アスファルトシングル' },
|
||||
{ id: 2, code: '8', name: 'アスファルトシングル' },
|
||||
/** 기와 */
|
||||
{ id: 3, name: '瓦' },
|
||||
{ id: 3, code: null, name: '瓦' },
|
||||
/** 금속지붕 */
|
||||
{ id: 4, name: '金属屋根' },
|
||||
{ id: 4, code: null, name: '金属屋根' },
|
||||
]
|
||||
|
||||
export const selectBoxOptions: Record<SelectBoxKeys, { id: number; name: string }[]> = {
|
||||
export const selectBoxOptions: Record<SelectBoxKeys, { id: number; code: string | null; name: string }[]> = {
|
||||
installationSystem: [
|
||||
{
|
||||
/** 태양광발전 */
|
||||
id: 1,
|
||||
code: null,
|
||||
name: '太陽光発電',
|
||||
},
|
||||
{
|
||||
/** 하이브리드축전지시스템 */
|
||||
id: 2,
|
||||
code: null,
|
||||
name: 'ハイブリッド蓄電システム',
|
||||
},
|
||||
{
|
||||
/** 축전지시스템 */
|
||||
id: 3,
|
||||
code: null,
|
||||
name: '蓄電池システム',
|
||||
},
|
||||
],
|
||||
|
||||
// 건축 연수 : HEAD_ID = 'BUILDING' (114000)
|
||||
constructionYear: [
|
||||
{
|
||||
/** 신축 */
|
||||
id: 1,
|
||||
code: 'N',
|
||||
name: '新築',
|
||||
},
|
||||
{
|
||||
/** 기축 */
|
||||
id: 2,
|
||||
code: 'O',
|
||||
name: '既築',
|
||||
},
|
||||
],
|
||||
|
||||
roofShape: [
|
||||
{
|
||||
/** 박공지붕 */
|
||||
id: 1,
|
||||
code: null,
|
||||
name: '切妻',
|
||||
},
|
||||
{
|
||||
/** 기동 */
|
||||
id: 2,
|
||||
code: null,
|
||||
name: '寄棟',
|
||||
},
|
||||
{
|
||||
/** 한쪽흐름 */
|
||||
id: 3,
|
||||
code: null,
|
||||
name: '片流れ',
|
||||
},
|
||||
],
|
||||
|
||||
rafterSize: [
|
||||
{
|
||||
/** 35mm 이상×48mm 이상 */
|
||||
id: 1,
|
||||
code: null,
|
||||
name: '幅35mm以上×高さ48mm以上',
|
||||
},
|
||||
{
|
||||
/** 36mm 이상×46mm 이상 */
|
||||
id: 2,
|
||||
code: null,
|
||||
name: '幅36mm以上×高さ46mm以上',
|
||||
},
|
||||
{
|
||||
/** 37mm 이상×43mm 이상 */
|
||||
id: 3,
|
||||
code: null,
|
||||
name: '幅37mm以上×高さ43mm以上',
|
||||
},
|
||||
{
|
||||
/** 38mm 이상×40mm 이상 */
|
||||
id: 4,
|
||||
code: null,
|
||||
name: '幅38mm以上×高さ40mm以上',
|
||||
},
|
||||
],
|
||||
|
||||
// 서까래 피치 : HEAD_ID = 'RAFT_BASE_CD' (203800)
|
||||
rafterPitch: [
|
||||
{
|
||||
/** 455mm 이하 */
|
||||
id: 1,
|
||||
code: 'HEI_455',
|
||||
name: '455mm以下',
|
||||
},
|
||||
{
|
||||
/** 500mm 이하 */
|
||||
id: 2,
|
||||
code: 'HEI_500',
|
||||
name: '500mm以下',
|
||||
},
|
||||
{
|
||||
/** 606mm 이하 */
|
||||
id: 3,
|
||||
code: 'HEI_606',
|
||||
name: '606mm以下',
|
||||
},
|
||||
],
|
||||
|
||||
// 골목판 종류 : HEAD_ID = 'ROOF_BOARD' (114600)
|
||||
openFieldPlateKind: [
|
||||
{
|
||||
/** 구조용합판 */
|
||||
id: 1,
|
||||
code: null,
|
||||
name: '構造用合板',
|
||||
},
|
||||
{
|
||||
/** OSB */
|
||||
id: 2,
|
||||
code: 'O',
|
||||
name: 'OSB',
|
||||
},
|
||||
{
|
||||
/** 파티클보드 */
|
||||
id: 3,
|
||||
code: 'A',
|
||||
name: 'パーティクルボード',
|
||||
},
|
||||
{
|
||||
/** 소판 */
|
||||
id: 4,
|
||||
code: 'S',
|
||||
name: '小幅板',
|
||||
},
|
||||
],
|
||||
|
||||
installationAvailability: [
|
||||
{
|
||||
/** 확인완료 */
|
||||
id: 1,
|
||||
code: null,
|
||||
name: '確認済み',
|
||||
},
|
||||
{
|
||||
/** 미확인 */
|
||||
id: 2,
|
||||
code: null,
|
||||
name: '未確認',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
export const radioEtcData: Record<RadioEtcKeys, { id: number; label: string }[]> = {
|
||||
export const radioEtcData: Record<RadioEtcKeys, { id: number; code: string | null; label: string }[]> = {
|
||||
structureOrder: [
|
||||
{
|
||||
/** 지붕재 - 방수재 - 지붕의기초 - 서까래 */
|
||||
id: 1,
|
||||
code: null,
|
||||
label: '屋根材 > 防水材 > 屋根の基礎 > 垂木',
|
||||
},
|
||||
],
|
||||
@ -497,6 +529,7 @@ export const radioEtcData: Record<RadioEtcKeys, { id: number; label: string }[]>
|
||||
{
|
||||
/** 목재 */
|
||||
id: 1,
|
||||
code: null,
|
||||
label: '木製',
|
||||
},
|
||||
],
|
||||
@ -504,11 +537,13 @@ export const radioEtcData: Record<RadioEtcKeys, { id: number; label: string }[]>
|
||||
{
|
||||
/** 목재 */
|
||||
id: 1,
|
||||
code: null,
|
||||
label: '木製',
|
||||
},
|
||||
{
|
||||
/** 강재 */
|
||||
id: 2,
|
||||
code: null,
|
||||
label: '強制',
|
||||
},
|
||||
],
|
||||
@ -516,6 +551,7 @@ export const radioEtcData: Record<RadioEtcKeys, { id: number; label: string }[]>
|
||||
{
|
||||
/** 아스팔트 지붕 940(22kg 이상) */
|
||||
id: 1,
|
||||
code: null,
|
||||
label: 'アスファルト屋根940(22kg以上)',
|
||||
},
|
||||
],
|
||||
@ -523,11 +559,13 @@ export const radioEtcData: Record<RadioEtcKeys, { id: number; label: string }[]>
|
||||
{
|
||||
/** 없음 */
|
||||
id: 1,
|
||||
code: null,
|
||||
label: 'なし',
|
||||
},
|
||||
{
|
||||
/** 있음 */
|
||||
id: 2,
|
||||
code: null,
|
||||
label: 'あり',
|
||||
},
|
||||
],
|
||||
@ -535,11 +573,13 @@ export const radioEtcData: Record<RadioEtcKeys, { id: number; label: string }[]>
|
||||
{
|
||||
/** 수직 */
|
||||
id: 1,
|
||||
code: null,
|
||||
label: '垂直垂木',
|
||||
},
|
||||
{
|
||||
/** 수평 */
|
||||
id: 2,
|
||||
code: null,
|
||||
label: '水平垂木',
|
||||
},
|
||||
],
|
||||
@ -547,12 +587,14 @@ export const radioEtcData: Record<RadioEtcKeys, { id: number; label: string }[]>
|
||||
{
|
||||
/** 있음 */
|
||||
id: 1,
|
||||
code: null,
|
||||
label: 'あり',
|
||||
},
|
||||
{
|
||||
/** 없음 */
|
||||
id: 2,
|
||||
code: null,
|
||||
label: 'なし',
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user