Merge pull request 'feature/survey : 조사매물 PDF 번역 수정 및 컴포넌트 랜더링 이슈 해결' (#124) from feature/survey into dev

Reviewed-on: #124
This commit is contained in:
seul 2025-08-06 13:56:52 +09:00
commit 1c91622119
2 changed files with 39 additions and 44 deletions

View File

@ -137,7 +137,7 @@ export default function SurveySalePdf({ survey }: { survey: SurveyBasicInfo }) {
<Text style={styles.title}>HWJ 調</Text> <Text style={styles.title}>HWJ 調</Text>
<View style={styles.headerRight}> <View style={styles.headerRight}>
<View style={styles.headerLeft}> <View style={styles.headerLeft}>
<Text style={styles.headerLabel}>調</Text> <Text style={styles.headerLabel}>調</Text>
<Text style={styles.headerValue}>{survey?.store ?? '-'}</Text> <Text style={styles.headerValue}>{survey?.store ?? '-'}</Text>
</View> </View>
{survey?.constructionPoint && ( {survey?.constructionPoint && (
@ -147,7 +147,7 @@ export default function SurveySalePdf({ survey }: { survey: SurveyBasicInfo }) {
</View> </View>
)} )}
<View> <View>
<Text style={styles.headerLabel}></Text> <Text style={styles.headerLabel}>調</Text>
<Text style={styles.headerValue}>{survey?.investigationDate ?? '-'}</Text> <Text style={styles.headerValue}>{survey?.investigationDate ?? '-'}</Text>
</View> </View>
</View> </View>
@ -171,16 +171,16 @@ export default function SurveySalePdf({ survey }: { survey: SurveyBasicInfo }) {
{/* Electric Info */} {/* Electric Info */}
<View style={styles.section}> <View style={styles.section}>
<Text style={styles.sectionTitle}></Text> <Text style={styles.sectionTitle}></Text>
<View style={styles.table}> <View style={styles.table}>
<View style={styles.tableRow}> <View style={styles.tableRow}>
<Text style={[styles.tableHeader, styles.tableHeaderMedium]}></Text> <Text style={[styles.tableHeader, styles.tableHeaderMedium]}></Text>
<Text style={[styles.tableCell, styles.tableCellFlex1, styles.marginL]}>{survey?.detailInfo?.contractCapacity ?? '-'}</Text> <Text style={[styles.tableCell, styles.tableCellFlex1, styles.marginL]}>{survey?.detailInfo?.contractCapacity ?? '-'}</Text>
<Text style={[styles.tableHeader, styles.tableHeaderMedium, styles.marginL]}></Text> <Text style={[styles.tableHeader, styles.tableHeaderMedium, styles.marginL]}></Text>
<Text style={[styles.tableCell, styles.tableCellFlex1, styles.marginL]}>{survey?.detailInfo?.retailCompany ?? '-'}</Text> <Text style={[styles.tableCell, styles.tableCellFlex1, styles.marginL]}>{survey?.detailInfo?.retailCompany ?? '-'}</Text>
</View> </View>
<View style={styles.tableRow}> <View style={styles.tableRow}>
<Text style={[styles.tableHeader, styles.tableHeaderMedium, styles.marginT]}></Text> <Text style={[styles.tableHeader, styles.tableHeaderMedium, styles.marginT]}></Text>
<Text style={[styles.tableCell, styles.tableCellFlex1, styles.marginL, styles.marginT]}> <Text style={[styles.tableCell, styles.tableCellFlex1, styles.marginL, styles.marginT]}>
{survey?.detailInfo?.supplementaryFacilities {survey?.detailInfo?.supplementaryFacilities
? supplementaryFacilities ? supplementaryFacilities
@ -207,7 +207,7 @@ export default function SurveySalePdf({ survey }: { survey: SurveyBasicInfo }) {
{/* Roof Info */} {/* Roof Info */}
<View style={styles.section}> <View style={styles.section}>
<Text style={styles.sectionTitle}></Text> <Text style={styles.sectionTitle}></Text>
<View style={styles.table}> <View style={styles.table}>
<View style={styles.tableRow}> <View style={styles.tableRow}>
<Text style={[styles.tableHeader, styles.tableHeaderMedium]}></Text> <Text style={[styles.tableHeader, styles.tableHeaderMedium]}></Text>
@ -218,7 +218,7 @@ export default function SurveySalePdf({ survey }: { survey: SurveyBasicInfo }) {
? `既築 (${survey?.detailInfo?.constructionYear}年)` ? `既築 (${survey?.detailInfo?.constructionYear}年)`
: '-'} : '-'}
</Text> </Text>
<Text style={[styles.tableHeader, styles.tableHeaderMedium, styles.marginL]}></Text> <Text style={[styles.tableHeader, styles.tableHeaderMedium, styles.marginL]}></Text>
<Text style={[styles.tableCell, styles.tableCellFlex07, styles.marginL, styles.marginL]}> <Text style={[styles.tableCell, styles.tableCellFlex07, styles.marginL, styles.marginL]}>
{survey?.detailInfo?.roofMaterial === null && survey?.detailInfo?.roofMaterialEtc === null {survey?.detailInfo?.roofMaterial === null && survey?.detailInfo?.roofMaterialEtc === null
? '-' ? '-'
@ -228,25 +228,25 @@ export default function SurveySalePdf({ survey }: { survey: SurveyBasicInfo }) {
.join(', ')} .join(', ')}
{survey?.detailInfo?.roofMaterialEtc ? `, ${survey?.detailInfo?.roofMaterialEtc}` : ''} {survey?.detailInfo?.roofMaterialEtc ? `, ${survey?.detailInfo?.roofMaterialEtc}` : ''}
</Text> </Text>
<Text style={[styles.tableHeader, styles.tableHeaderMedium, styles.marginL]}></Text> <Text style={[styles.tableHeader, styles.tableHeaderMedium, styles.marginL]}></Text>
<Text style={[styles.tableCell, styles.tableCellFlex07, styles.marginL]}> <Text style={[styles.tableCell, styles.tableCellFlex07, styles.marginL]}>
{selectBoxOptions.roofShape.find((shape) => shape.id.toString() === survey?.detailInfo?.roofShape)?.name ?? {selectBoxOptions.roofShape.find((shape) => shape.id.toString() === survey?.detailInfo?.roofShape)?.name ??
(survey?.detailInfo?.roofShapeEtc ? ` ${survey?.detailInfo?.roofShapeEtc}` : '-')} (survey?.detailInfo?.roofShapeEtc ? ` ${survey?.detailInfo?.roofShapeEtc}` : '-')}
</Text> </Text>
</View> </View>
<View style={styles.tableRow}> <View style={styles.tableRow}>
<Text style={[styles.tableHeader, styles.tableHeaderMedium, styles.marginT]}></Text> <Text style={[styles.tableHeader, styles.tableHeaderMedium, styles.marginT]}></Text>
<Text style={[styles.tableCell, styles.tableCellFlex1, styles.marginL, styles.marginT, styles.marginL]}> <Text style={[styles.tableCell, styles.tableCellFlex1, styles.marginL, styles.marginT, styles.marginL]}>
{survey?.detailInfo?.roofSlope ? `${survey?.detailInfo?.roofSlope}` : '-'} {survey?.detailInfo?.roofSlope ? `${survey?.detailInfo?.roofSlope}` : '-'}
</Text> </Text>
<Text style={[styles.tableHeader, styles.tableHeaderMedium, styles.marginL, styles.marginT]}></Text> <Text style={[styles.tableHeader, styles.tableHeaderMedium, styles.marginL, styles.marginT]}></Text>
<Text style={[styles.tableCell, styles.tableCellFlex2, styles.marginL, styles.marginL, styles.marginT]}> <Text style={[styles.tableCell, styles.tableCellFlex2, styles.marginL, styles.marginL, styles.marginT]}>
{radioEtcData.houseStructure.find((structure) => structure.id.toString() === survey?.detailInfo?.houseStructure)?.label ?? {radioEtcData.houseStructure.find((structure) => structure.id.toString() === survey?.detailInfo?.houseStructure)?.label ??
(survey?.detailInfo?.houseStructureEtc ? ` ${survey?.detailInfo?.houseStructureEtc}` : '-')} (survey?.detailInfo?.houseStructureEtc ? ` ${survey?.detailInfo?.houseStructureEtc}` : '-')}
</Text> </Text>
</View> </View>
<View style={styles.tableRow}> <View style={styles.tableRow}>
<Text style={[styles.tableHeader, styles.tableHeaderMedium, styles.marginT]}></Text> <Text style={[styles.tableHeader, styles.tableHeaderMedium, styles.marginT]}></Text>
<Text style={[styles.tableCell, styles.tableCellFlex1, styles.marginL, styles.marginT]}> <Text style={[styles.tableCell, styles.tableCellFlex1, styles.marginL, styles.marginT]}>
{radioEtcData.rafterMaterial.find((material) => material.id.toString() === survey?.detailInfo?.rafterMaterial)?.label ?? {radioEtcData.rafterMaterial.find((material) => material.id.toString() === survey?.detailInfo?.rafterMaterial)?.label ??
(survey?.detailInfo?.rafterMaterialEtc ? ` ${survey?.detailInfo?.rafterMaterialEtc}` : '-')} (survey?.detailInfo?.rafterMaterialEtc ? ` ${survey?.detailInfo?.rafterMaterialEtc}` : '-')}
@ -280,7 +280,7 @@ export default function SurveySalePdf({ survey }: { survey: SurveyBasicInfo }) {
</Text> </Text>
</View> </View>
<View style={styles.tableRow}> <View style={styles.tableRow}>
<Text style={[styles.tableHeader, styles.tableHeaderMedium, styles.marginT]}></Text> <Text style={[styles.tableHeader, styles.tableHeaderMedium, styles.marginT]}></Text>
<Text style={[styles.tableCell, styles.tableCellFlex1, styles.marginL, styles.marginT]}> <Text style={[styles.tableCell, styles.tableCellFlex1, styles.marginL, styles.marginT]}>
{survey?.detailInfo?.leakTrace ? 'あり' : 'なし'} {survey?.detailInfo?.leakTrace ? 'あり' : 'なし'}
</Text> </Text>
@ -313,7 +313,7 @@ export default function SurveySalePdf({ survey }: { survey: SurveyBasicInfo }) {
<View style={styles.sectionNoPadding}> <View style={styles.sectionNoPadding}>
<View style={styles.table}> <View style={styles.table}>
<View style={styles.tableRow}> <View style={styles.tableRow}>
<Text style={[styles.tableHeader, styles.tableHeaderLarge]}></Text> <Text style={[styles.tableHeader, styles.tableHeaderLarge]}></Text>
<Text style={[styles.tableCell, styles.tableCellFlex1, styles.marginL]}> <Text style={[styles.tableCell, styles.tableCellFlex1, styles.marginL]}>
{survey?.detailInfo?.installationAvailability === null && survey.detailInfo?.installationAvailabilityEtc === null {survey?.detailInfo?.installationAvailability === null && survey.detailInfo?.installationAvailabilityEtc === null
? '-' ? '-'

View File

@ -309,7 +309,6 @@ const SelectedBox = ({
const handleSelectChange = (e: React.ChangeEvent<HTMLSelectElement>) => { const handleSelectChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
const value = e.target.value const value = e.target.value
const isEtc = value === 'etc' const isEtc = value === 'etc'
const isSpecialEtc = isSpecialCase && value === 'O'
const updatedData = { const updatedData = {
...detailInfoData, ...detailInfoData,
@ -317,11 +316,7 @@ const SelectedBox = ({
[`${column}Etc`]: isEtc ? '' : null, [`${column}Etc`]: isEtc ? '' : null,
} }
if (isSpecialEtc) { setIsEtcSelected(isEtc)
updatedData[column] = value
}
setIsEtcSelected(isEtc || isSpecialEtc)
setRoofInfo(updatedData) setRoofInfo(updatedData)
} }
@ -333,13 +328,13 @@ const SelectedBox = ({
/** Input box /** Input box
* - 모드 : 비활성화 * - 모드 : 비활성화
* - 여부 : 기타 * - 여부 : 기타
* - 연수 : 신축(1) * - 연수 : 新築 (N)
* */ * */
const isInputDisabled = () => { const isInputDisabled = () => {
if (mode === 'READ') return true if (mode === 'READ') return true
if (column === 'installationAvailability') return false if (column === 'installationAvailability') return false
if (column === 'constructionYear') { if (column === 'constructionYear') {
return detailInfoData.constructionYear === 'N' || detailInfoData.constructionYear === null return detailInfoData.constructionYear === selectBoxOptions.constructionYear[0].code || detailInfoData.constructionYear === null
} }
return !isEtcSelected && !etcValue return !isEtcSelected && !etcValue
} }
@ -401,8 +396,10 @@ const RadioSelected = ({
const [etcChecked, setEtcChecked] = useState<boolean>(Boolean(etcValue)) const [etcChecked, setEtcChecked] = useState<boolean>(Boolean(etcValue))
const selectedId = const selectedId =
/** 누수 흔적 boolean 타입이므로 number 타입으로 변환 - 값이 없을 경우 2(없음) 으로 초기화*/ /** 누수 흔적 boolean 타입이므로 number 타입으로 변환 - 값이 없을 경우 2(없음) 으로 초기화*/
column === 'leakTrace' ? Number(detailInfoData?.[column as keyof SurveyDetailInfo]) || 2 : detailInfoData?.[column as keyof SurveyDetailInfo] column === 'leakTrace'
? Number(detailInfoData?.[column as keyof SurveyDetailInfo]) || radioEtcData.leakTrace[1].id
: detailInfoData?.[column as keyof SurveyDetailInfo]
const isSpecialColumn = column === 'rafterDirection' || column === 'leakTrace' || column === 'insulationPresence' const isSpecialColumn = column === 'rafterDirection' || column === 'leakTrace' || column === 'insulationPresence'
const showEtcOption = !isSpecialColumn const showEtcOption = !isSpecialColumn
@ -413,7 +410,7 @@ const RadioSelected = ({
/** 누수 흔적 처리 - boolean 타입이므로 별도 처리 */ /** 누수 흔적 처리 - boolean 타입이므로 별도 처리 */
if (column === 'leakTrace') { if (column === 'leakTrace') {
setRoofInfo({ ...detailInfoData, leakTrace: value === '1' }) setRoofInfo({ ...detailInfoData, leakTrace: value === String(radioEtcData.leakTrace[0].id) })
return return
} }
@ -430,7 +427,7 @@ const RadioSelected = ({
const isInsulationPresence = column === 'insulationPresence' const isInsulationPresence = column === 'insulationPresence'
const isRafterDirection = column === 'rafterDirection' const isRafterDirection = column === 'rafterDirection'
setEtcChecked(isInsulationPresence && value === '2') setEtcChecked(isInsulationPresence && value === String(radioEtcData.insulationPresence[1].id))
setRoofInfo({ setRoofInfo({
...detailInfoData, ...detailInfoData,
@ -451,7 +448,7 @@ const RadioSelected = ({
const isInputDisabled = () => { const isInputDisabled = () => {
if (mode === 'READ') return true if (mode === 'READ') return true
if (column === 'insulationPresence') { if (column === 'insulationPresence') {
return detailInfoData.insulationPresence !== '2' return detailInfoData.insulationPresence === String(radioEtcData.insulationPresence[0].id)
} }
return !etcChecked && !etcValue return !etcChecked && !etcValue
} }
@ -518,8 +515,11 @@ const MultiCheck = ({
const { showErrorAlert } = useAlertMsg() const { showErrorAlert } = useAlertMsg()
const { roofMaterial, initialized, loading, loadOptions } = useSurveyOptionStore() const { roofMaterial, initialized, loading, loadOptions } = useSurveyOptionStore()
const multiCheckData = column === 'supplementaryFacilities' ? supplementaryFacilities : roofMaterial const multiCheckData = column === 'supplementaryFacilities' ? supplementaryFacilities : roofMaterial
const etcValue = roofInfo?.[`${column}Etc` as keyof SurveyDetailInfo] const [etcValue, setEtcValue] = useState<string | null>(roofInfo?.[`${column}Etc` as keyof SurveyDetailInfo]?.toString() ?? null)
const [isOtherCheck, setIsOtherCheck] = useState<boolean>(Boolean(etcValue)) useEffect(() => {
const newValue = roofInfo?.[`${column}Etc` as keyof SurveyDetailInfo]?.toString() ?? null
setEtcValue(newValue)
}, [roofInfo, column])
useEffect(() => { useEffect(() => {
if (!initialized && !loading) loadOptions() if (!initialized && !loading) loadOptions()
@ -530,7 +530,7 @@ const MultiCheck = ({
/** 다중 선택 처리 */ /** 다중 선택 처리 */
const handleCheckbox = (item: { id: number; code: string | null; name: string }) => { const handleCheckbox = (item: { id: number; code: string | null; name: string }) => {
const isOtherSelected = Boolean(etcValue) const isOtherSelected = etcValue !== null
let newValue: string[] let newValue: string[]
if (selectedValues.includes(item.code ?? String(item.id))) { if (selectedValues.includes(item.code ?? String(item.id))) {
@ -538,7 +538,7 @@ const MultiCheck = ({
} else { } else {
/** 지붕 재료 처리 - 최대 2개 선택 처리 */ /** 지붕 재료 처리 - 최대 2개 선택 처리 */
if (isRoofMaterial) { if (isRoofMaterial) {
const totalSelected = selectedValues.length + (isOtherSelected || isOtherCheck ? 1 : 0) const totalSelected = selectedValues.length + (isOtherSelected ? 1 : 0)
if (totalSelected >= 2) { if (totalSelected >= 2) {
showErrorAlert(WARNING_MESSAGE.ROOF_MATERIAL_MAX_SELECT) showErrorAlert(WARNING_MESSAGE.ROOF_MATERIAL_MAX_SELECT)
return return
@ -551,21 +551,22 @@ const MultiCheck = ({
/** 기타 선택 처리 */ /** 기타 선택 처리 */
const handleOtherCheckbox = () => { const handleOtherCheckbox = () => {
setEtcValue(etcValue !== null ? null : '')
const isOtherSelected = etcValue !== null
if (isRoofMaterial) { if (isRoofMaterial) {
const currentSelected = selectedValues.length /** 지붕 재료 기타 선택 포함 최대 2개 선택 처리 */
if (!isOtherCheck && currentSelected >= 2) { if (!isOtherSelected && selectedValues.length >= 2) {
showErrorAlert(WARNING_MESSAGE.ROOF_MATERIAL_MAX_SELECT) showErrorAlert(WARNING_MESSAGE.ROOF_MATERIAL_MAX_SELECT)
setEtcValue(null)
return return
} }
} }
const newIsOtherCheck = !isOtherCheck
setIsOtherCheck(newIsOtherCheck)
/** 기타 선택 해제 시 값도 null로 설정 */ /** 기타 선택 해제 시 값도 null로 설정 */
setRoofInfo({ setRoofInfo({
...roofInfo, ...roofInfo,
[`${column}Etc`]: newIsOtherCheck ? '' : null, [`${column}Etc`]: isOtherSelected ? null : '',
}) })
} }
@ -576,7 +577,7 @@ const MultiCheck = ({
/** Input box 비활성화 처리 */ /** Input box 비활성화 처리 */
const isInputDisabled = () => { const isInputDisabled = () => {
return mode === 'READ' || (!isOtherCheck && !etcValue) return mode === 'READ' || etcValue === null
} }
return ( return (
@ -595,13 +596,7 @@ const MultiCheck = ({
</div> </div>
))} ))}
<div className="check-form-box"> <div className="check-form-box">
<input <input type="checkbox" id={`${column}Etc`} checked={etcValue !== null} disabled={mode === 'READ'} onChange={handleOtherCheckbox} />
type="checkbox"
id={`${column}Etc`}
checked={isOtherCheck || Boolean(etcValue)}
disabled={mode === 'READ'}
onChange={handleOtherCheckbox}
/>
<label htmlFor={`${column}Etc`}> ()</label> <label htmlFor={`${column}Etc`}> ()</label>
</div> </div>
</div> </div>