835 lines
27 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useState } from 'react'
import type { Mode, SurveyDetailInfo, SurveyDetailRequest } from '@/types/Survey'
import { useAlertMsg, WARNING_MESSAGE } from '@/hooks/useAlertMsg'
type RadioEtcKeys =
| 'structureOrder'
| 'houseStructure'
| 'rafterMaterial'
| 'waterproofMaterial'
| 'insulationPresence'
| 'rafterDirection'
| 'leakTrace'
type SelectBoxKeys =
| 'installationSystem'
| 'constructionYear'
| 'roofShape'
| 'rafterPitch'
| 'rafterSize'
| 'openFieldPlateKind'
| 'installationAvailability'
export const supplementaryFacilities = [
/** 에코큐트 */
{ id: 1, name: 'エコキュート' },
/** 에네팜 */
{ id: 2, name: 'エネパーム' },
/** 축전지시스템 */
{ id: 3, name: '蓄電池システム' },
/** 태양광발전 */
{ id: 4, name: '太陽光発電' },
]
export const roofMaterial = [
/** 슬레이트 */
{ id: 1, name: 'スレート' },
/** 아스팔트 싱글 */
{ id: 2, name: 'アスファルトシングル' },
/** 기와 */
{ id: 3, name: '瓦' },
/** 금속지붕 */
{ id: 4, name: '金属屋根' },
]
export const selectBoxOptions: Record<SelectBoxKeys, { id: number; name: string }[]> = {
installationSystem: [
{
/** 태양광발전 */
id: 1,
name: '太陽光発電',
},
{
/** 하이브리드축전지시스템 */
id: 2,
name: 'ハイブリッド蓄電システム',
},
{
/** 축전지시스템 */
id: 3,
name: '蓄電池システム',
},
],
constructionYear: [
{
/** 신축 */
id: 1,
name: '新築',
},
{
/** 기축 */
id: 2,
name: '既築',
},
],
roofShape: [
{
/** 박공지붕 */
id: 1,
name: '切妻',
},
{
/** 기동 */
id: 2,
name: '寄棟',
},
{
/** 한쪽흐름 */
id: 3,
name: '片流れ',
},
],
rafterSize: [
{
/** 35mm 이상×48mm 이상 */
id: 1,
name: '幅35mm以上×高さ48mm以上',
},
{
/** 36mm 이상×46mm 이상 */
id: 2,
name: '幅36mm以上×高さ46mm以上',
},
{
/** 37mm 이상×43mm 이상 */
id: 3,
name: '幅37mm以上×高さ43mm以上',
},
{
/** 38mm 이상×40mm 이상 */
id: 4,
name: '幅38mm以上×高さ40mm以上',
},
],
rafterPitch: [
{
/** 455mm 이하 */
id: 1,
name: '455mm以下',
},
{
/** 500mm 이하 */
id: 2,
name: '500mm以下',
},
{
/** 606mm 이하 */
id: 3,
name: '606mm以下',
},
],
openFieldPlateKind: [
{
/** 구조용합판 */
id: 1,
name: '構造用合板',
},
{
/** OSB */
id: 2,
name: 'OSB',
},
{
/** 파티클보드 */
id: 3,
name: 'パーティクルボード',
},
{
/** 소판 */
id: 4,
name: '小幅板',
},
],
installationAvailability: [
{
/** 확인완료 */
id: 1,
name: '確認済み',
},
{
/** 미확인 */
id: 2,
name: '未確認',
},
],
}
export const radioEtcData: Record<RadioEtcKeys, { id: number; label: string }[]> = {
structureOrder: [
{
/** 지붕재 - 방수재 - 지붕의기초 - 서까래 */
id: 1,
label: '屋根材 > 防水材 > 屋根の基礎 > 垂木',
},
],
houseStructure: [
{
/** 목재 */
id: 1,
label: '木製',
},
],
rafterMaterial: [
{
/** 목재 */
id: 1,
label: '木製',
},
{
/** 강재 */
id: 2,
label: '強制',
},
],
waterproofMaterial: [
{
/** 아스팔트 지붕 940(22kg 이상) */
id: 1,
label: 'アスファルト屋根94022kg以上',
},
],
insulationPresence: [
{
/** 없음 */
id: 1,
label: 'なし',
},
{
/** 있음 */
id: 2,
label: 'あり',
},
],
rafterDirection: [
{
/** 수직 */
id: 1,
label: '垂直垂木',
},
{
/** 수평 */
id: 2,
label: '水平垂木',
},
],
leakTrace: [
{
/** 있음 */
id: 1,
label: 'あり',
},
{
/** 없음 */
id: 2,
label: 'なし',
},
],
}
const makeNumArr = (value: string) => {
return value
.split(',')
.map((v) => v.trim())
.filter((v) => v.length > 0)
}
export default function RoofForm(props: {
roofInfo: SurveyDetailRequest | SurveyDetailInfo
setRoofInfo: (roofInfo: SurveyDetailRequest) => void
mode: Mode
}) {
const { roofInfo, setRoofInfo, mode } = props
const { showErrorAlert } = useAlertMsg()
const [isFlip, setIsFlip] = useState<boolean>(true)
const handleNumberInput = (key: keyof SurveyDetailRequest, value: number | string) => {
/** 지붕 경사도, 노지판 두께 처리 - 최대 5자리, 소수점 1자리 처리 */
if (key === 'roofSlope' || key === 'openFieldPlateThickness') {
const stringValue = value.toString()
if (stringValue.length > 5) {
showErrorAlert(WARNING_MESSAGE.SAVE_SIZE_OVERFLOW)
return
}
if (stringValue.includes('.')) {
const decimalPlaces = stringValue.split('.')[1].length
if (decimalPlaces > 1) {
showErrorAlert(WARNING_MESSAGE.DECIMAL_POINT_CANNOT_EXCEED)
return
}
}
}
/** 전기 계약 용량 처리 - 단위 붙여서 저장*/
if (key === 'contractCapacity') {
const remainValue = roofInfo.contractCapacity?.split(' ')[1] ?? roofInfo.contractCapacity
if (Number.isNaN(Number(remainValue))) {
setRoofInfo({ ...roofInfo, [key]: value + ' ' + remainValue })
return
}
setRoofInfo({ ...roofInfo, [key]: value.toString() })
}
setRoofInfo({ ...roofInfo, [key]: value.toString() })
}
/** 전기 계약 용량 단위 처리 */
const handleUnitInput = (value: string) => {
const numericValue = roofInfo.contractCapacity?.replace(/[^0-9.]/g, '') || ''
setRoofInfo({
...roofInfo,
contractCapacity: numericValue ? `${numericValue} ${value}` : '0 ' + value,
})
}
return (
<div className={`sale-detail-toggle-bx ${isFlip ? 'act' : ''}`}>
<div className="sale-detail-toggle-head" onClick={() => setIsFlip(!isFlip)}>
<div className="sale-detail-toggle-name"> / </div>
<div className="sale-detail-toggle-btn-wrap">
<button className="sale-detail-toggle-btn"></button>
</div>
</div>
<div className="sale-detail-toggle-cont">
<div className="sale-frame">
{/* 전기 관계 */}
<div className="sale-roof-title"></div>
<div className="data-form-wrap">
<div className="data-input-form-bx">
{/* 전기 계약 용량 */}
<div className="data-input-form-tit"></div>
{mode === 'READ' && <input type="text" className="input-frame" value={roofInfo?.contractCapacity ?? ''} readOnly={mode === 'READ'} />}
{mode !== 'READ' && (
<div className="data-input mb5">
<input
type="number"
inputMode="numeric"
id="contractCapacity"
className="input-frame"
value={roofInfo?.contractCapacity?.split(' ')[0] ?? ''}
onChange={(e) => handleNumberInput('contractCapacity', e.target.value)}
/>
<div className="data-input">
<select
className="select-form"
name="contractCapacityUnit"
id="contractCapacityUnit"
value={roofInfo?.contractCapacity?.split(' ')[1] ?? ''}
onChange={(e) => handleUnitInput(e.target.value)}
>
<option value="" hidden>
</option>
<option value="A">A</option>
<option value="kVA">kVA</option>
</select>
</div>
</div>
)}
</div>
<div className="data-input-form-bx">
{/* 전기 소매 회사사 */}
<div className="data-input-form-tit"></div>
<input
type="text"
className="input-frame"
value={roofInfo?.retailCompany ?? ''}
disabled={mode === 'READ'}
onChange={(e) => setRoofInfo({ ...roofInfo, retailCompany: e.target.value })}
/>
</div>
<div className="data-input-form-bx">
{/* 전기 부대 설비 */}
<div className="data-input-form-tit">
<span></span>
</div>
<MultiCheck mode={mode} column="supplementaryFacilities" roofInfo={roofInfo as SurveyDetailInfo} setRoofInfo={setRoofInfo} />
</div>
{/* 설치 희망 시스템 */}
<div className="data-input-form-bx">
<div className="data-input-form-tit red-f"></div>
<SelectedBox mode={mode} column="installationSystem" detailInfoData={roofInfo as SurveyDetailInfo} setRoofInfo={setRoofInfo} />
</div>
</div>
</div>
<div className="sale-frame">
{/* 지붕 관계 */}
<div className="sale-roof-title"></div>
<div className="data-form-wrap">
<div className="data-input-form-bx">
{/* 건축 연수 */}
<div className="data-input-form-tit red-f"></div>
<div className="data-input mb5">
<SelectedBox mode={mode} column="constructionYear" detailInfoData={roofInfo as SurveyDetailInfo} setRoofInfo={setRoofInfo} />
</div>
</div>
<div className="data-input-form-bx">
{/* 지붕재 */}
<div className="data-input-form-tit">
<span>2</span>
</div>
<MultiCheck mode={mode} column="roofMaterial" roofInfo={roofInfo as SurveyDetailInfo} setRoofInfo={setRoofInfo} />
</div>
<div className="data-input-form-bx">
{/* 지붕 모양 */}
<div className="data-input-form-tit"></div>
<div className="data-input mb5">
<SelectedBox mode={mode} column="roofShape" detailInfoData={roofInfo as SurveyDetailInfo} setRoofInfo={setRoofInfo} />
</div>
</div>
<div className="data-input-form-bx">
{/* 지붕 경사도 */}
<div className="data-input-form-tit"></div>
<div className="data-input flex">
<input
type="number"
inputMode="numeric"
id="roofSlope"
className="input-frame"
value={roofInfo?.roofSlope ?? ''}
disabled={mode === 'READ'}
onChange={(e) => handleNumberInput('roofSlope', e.target.value)}
/>
<span></span>
</div>
</div>
<div className="data-input-form-bx">
{/* 주택구조조 */}
<div className="data-input-form-tit"></div>
<RadioSelected mode={mode} column="houseStructure" detailInfoData={roofInfo as SurveyDetailInfo} setRoofInfo={setRoofInfo} />
</div>
<div className="data-input-form-bx">
{/* 서까래 재질 */}
<div className="data-input-form-tit"></div>
<RadioSelected mode={mode} column="rafterMaterial" detailInfoData={roofInfo as SurveyDetailInfo} setRoofInfo={setRoofInfo} />
</div>
<div className="data-input-form-bx">
{/* 서까래 크기 */}
<div className="data-input-form-tit red-f"></div>
<div className="data-input mb5">
<SelectedBox mode={mode} column="rafterSize" detailInfoData={roofInfo as SurveyDetailInfo} setRoofInfo={setRoofInfo} />
</div>
</div>
<div className="data-input-form-bx">
{/* 서까래 피치 */}
<div className="data-input-form-tit red-f"></div>
<div className="data-input mb5">
<SelectedBox mode={mode} column="rafterPitch" detailInfoData={roofInfo as SurveyDetailInfo} setRoofInfo={setRoofInfo} />
</div>
</div>
<div className="data-input-form-bx">
{/* 서까래 방향 */}
<div className="data-input-form-tit red-f"></div>
<div className="data-check-wrap mb0">
<RadioSelected mode={mode} column="rafterDirection" detailInfoData={roofInfo as SurveyDetailInfo} setRoofInfo={setRoofInfo} />
</div>
</div>
<div className="data-input-form-bx">
{/* 노지판 종류 */}
<div className="data-input-form-tit"></div>
<div className="data-input mb5">
<SelectedBox mode={mode} column="openFieldPlateKind" detailInfoData={roofInfo as SurveyDetailInfo} setRoofInfo={setRoofInfo} />
</div>
</div>
{roofInfo.openFieldPlateKind === '4' && (
<div className="data-input-form-bx">
{/* 노지판 두께 */}
<div className="data-input-form-tit">
<span>, . </span>
</div>
<div className="data-input flex">
<input
type="number"
inputMode="numeric"
id="openFieldPlateThickness"
className="input-frame"
value={roofInfo?.openFieldPlateThickness ?? ''}
disabled={mode === 'READ'}
onChange={(e) => handleNumberInput('openFieldPlateThickness', e.target.value)}
/>
<span>mm</span>
</div>
</div>
)}
<div className="data-input-form-bx">
{/* 누수 흔적 */}
<div className="data-input-form-tit "></div>
<div className="data-check-wrap mb0">
<RadioSelected mode={mode} column="leakTrace" detailInfoData={roofInfo as SurveyDetailInfo} setRoofInfo={setRoofInfo} />
</div>
</div>
<div className="data-input-form-bx">
{/* 방수재 종류 */}
<div className="data-input-form-tit red-f"></div>
<RadioSelected mode={mode} column="waterproofMaterial" detailInfoData={roofInfo as SurveyDetailInfo} setRoofInfo={setRoofInfo} />
</div>
<div className="data-input-form-bx">
{/* 단열재 유무 */}
<div className="data-input-form-tit red-f"></div>
<RadioSelected mode={mode} column="insulationPresence" detailInfoData={roofInfo as SurveyDetailInfo} setRoofInfo={setRoofInfo} />
</div>
<div className="data-input-form-bx">
{/* 지붕 구조의 순서 */}
<div className="data-input-form-tit red-f"></div>
<RadioSelected mode={mode} column="structureOrder" detailInfoData={roofInfo as SurveyDetailInfo} setRoofInfo={setRoofInfo} />
</div>
<div className="data-input-form-bx">
{/* 지붕 제품명 설치 가능 여부 확인 */}
<div className="data-input-form-tit"> </div>
<SelectedBox mode={mode} column="installationAvailability" detailInfoData={roofInfo as SurveyDetailInfo} setRoofInfo={setRoofInfo} />
</div>
<div className="data-input-form-bx">
{/* 메모 */}
<div className="data-input-form-tit"></div>
<div className="data-input">
<textarea
className="textarea-form"
name="memo"
id="memo"
placeholder="TextArea Filed"
value={roofInfo?.memo ?? ''}
disabled={mode === 'READ'}
onChange={(e) => setRoofInfo({ ...roofInfo, memo: e.target.value })}
></textarea>
</div>
</div>
</div>
</div>
</div>
</div>
)
}
/** SelectBox 처리 */
const SelectedBox = ({
mode,
column,
detailInfoData,
setRoofInfo,
}: {
mode: Mode
column: string
detailInfoData: SurveyDetailInfo
setRoofInfo: (roofInfo: SurveyDetailRequest) => void
}) => {
const selectedId = detailInfoData?.[column as keyof SurveyDetailInfo]
const etcValue = detailInfoData?.[`${column}Etc` as keyof SurveyDetailInfo]
const [isEtcSelected, setIsEtcSelected] = useState<boolean>(Boolean(etcValue))
const isSpecialCase = column === 'constructionYear' || column === 'installationAvailability'
const showEtcOption = !isSpecialCase
/** SelectBox 값 변경 처리 */
const handleSelectChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
const value = e.target.value
const isEtc = value === 'etc'
const isSpecialEtc = isSpecialCase && value === '2'
const updatedData = {
...detailInfoData,
[column]: isEtc ? null : value,
[`${column}Etc`]: isEtc ? '' : null,
}
if (isSpecialEtc) {
updatedData[column] = value
}
setIsEtcSelected(isEtc || isSpecialEtc)
setRoofInfo(updatedData)
}
/** 기타 입력 처리 */
const handleEtcInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setRoofInfo({ ...detailInfoData, [`${column}Etc`]: e.target.value })
}
/** Input box 비활성화 처리
* - 읽기 모드 : 비활성화
* - 설치 가능 여부 : 기타 입력 창 항상 활성화
* - 건축 연수 : 신축(1) 체크 시 비활성화
* */
const isInputDisabled = () => {
if (mode === 'READ') return true
if (column === 'installationAvailability') return false
if (column === 'constructionYear') {
return detailInfoData.constructionYear === '1' || detailInfoData.constructionYear === null
}
return !isEtcSelected && !etcValue
}
return (
<>
<select
className="select-form mb10"
name={column}
id={column}
disabled={mode === 'READ'}
value={selectedId ? Number(selectedId) : etcValue || isEtcSelected ? 'etc' : ''}
onChange={handleSelectChange}
>
{selectBoxOptions[column as keyof typeof selectBoxOptions].map((item) => (
<option key={item.id} value={item.id}>
{item.name}
</option>
))}
{showEtcOption && (
<option key="etc" value="etc">
()
</option>
)}
<option key="" value="" hidden>
</option>
</select>
<div className={`data-input ${column === 'constructionYear' ? 'flex' : ''}`}>
<input
id={`${column}Etc`}
type={column === 'constructionYear' ? 'number' : 'text'}
inputMode={column === 'constructionYear' ? 'numeric' : 'text'}
className="input-frame"
placeholder="-"
value={detailInfoData[`${column}Etc` as keyof SurveyDetailInfo]?.toString() ?? ''}
onChange={handleEtcInputChange}
readOnly={isInputDisabled()}
/>
{column === 'constructionYear' && <span></span>}
</div>
</>
)
}
/** RadioBox 선택 처리 */
const RadioSelected = ({
mode,
column,
detailInfoData,
setRoofInfo,
}: {
mode: Mode
column: string
detailInfoData: SurveyDetailInfo
setRoofInfo: (roofInfo: SurveyDetailRequest) => void
}) => {
const etcValue = detailInfoData?.[`${column}Etc` as keyof SurveyDetailInfo]
const [etcChecked, setEtcChecked] = useState<boolean>(Boolean(etcValue))
const selectedId =
column === 'leakTrace' ? Number(detailInfoData?.[column as keyof SurveyDetailInfo]) || 2 : detailInfoData?.[column as keyof SurveyDetailInfo]
const isSpecialColumn = column === 'rafterDirection' || column === 'leakTrace' || column === 'insulationPresence'
const showEtcOption = !isSpecialColumn
/** RadioBox 값 변경 처리 */
const handleRadioChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value
/** 누수 흔적 처리 - boolean 타입이므로 별도 처리 */
if (column === 'leakTrace') {
setRoofInfo({ ...detailInfoData, leakTrace: value === '1' })
return
}
/** 기타 체크 처리 */
if (value === 'etc') {
setEtcChecked(true)
setRoofInfo({ ...detailInfoData, [column]: null, [`${column}Etc`]: '' })
return
}
/** 단열재 유무 - 있음(1) 선택 시 기타 체크 처리
* 서까래 방향 - 기타 입력 칸 없음
* */
const isInsulationPresence = column === 'insulationPresence'
const isRafterDirection = column === 'rafterDirection'
setEtcChecked(isInsulationPresence && value === '2')
setRoofInfo({
...detailInfoData,
[column]: value,
[`${column}Etc`]: isRafterDirection ? detailInfoData[`${column}Etc` as keyof SurveyDetailInfo] : null,
})
}
/** 기타 입력 처리 */
const handleEtcInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setRoofInfo({ ...detailInfoData, [`${column}Etc`]: e.target.value })
}
/** Input box 비활성화 처리
* - 읽기 모드 : 비활성화
* - 단열재 유무 : 단열재 없음(1) 체크 시 비활성화
* */
const isInputDisabled = () => {
if (mode === 'READ') return true
if (column === 'insulationPresence') {
return detailInfoData.insulationPresence !== '2'
}
return !etcChecked && !etcValue
}
return (
<>
{radioEtcData[column as keyof typeof radioEtcData].map((item) => (
<div className="radio-form-box mb10" key={item.id}>
<input
type="radio"
name={column}
id={`${column}_${item.id}`}
disabled={mode === 'READ'}
checked={Number(selectedId) === item.id}
onChange={handleRadioChange}
value={item.id}
/>
<label htmlFor={`${column}_${item.id}`}>{item.label}</label>
</div>
))}
{showEtcOption && (
<div className="radio-form-box mb10">
<input
type="radio"
name={column}
id={`${column}Etc`}
value="etc"
disabled={mode === 'READ'}
checked={etcChecked || Boolean(etcValue)}
onChange={handleRadioChange}
/>
<label htmlFor={`${column}Etc`}> ()</label>
</div>
)}
{(showEtcOption || column === 'insulationPresence') && (
<div className="data-input">
<input
id={`${column}Etc`}
type="text"
className="input-frame"
placeholder="-"
value={detailInfoData[`${column}Etc` as keyof SurveyDetailInfo]?.toString() ?? ''}
onChange={handleEtcInputChange}
readOnly={isInputDisabled()}
/>
</div>
)}
</>
)
}
/** 다중 선택 처리 */
const MultiCheck = ({
mode,
column,
roofInfo,
setRoofInfo,
}: {
mode: Mode
column: string
roofInfo: SurveyDetailInfo
setRoofInfo: (roofInfo: SurveyDetailRequest) => void
}) => {
const { showErrorAlert } = useAlertMsg()
const multiCheckData = column === 'supplementaryFacilities' ? supplementaryFacilities : roofMaterial
const etcValue = roofInfo?.[`${column}Etc` as keyof SurveyDetailInfo]
const [isOtherCheck, setIsOtherCheck] = useState<boolean>(Boolean(etcValue))
const isRoofMaterial = column === 'roofMaterial'
const selectedValues = makeNumArr(String(roofInfo[column as keyof SurveyDetailInfo] ?? ''))
/** 다중 선택 처리 */
const handleCheckbox = (id: number) => {
const isOtherSelected = Boolean(etcValue)
let newValue: string[]
if (selectedValues.includes(String(id))) {
newValue = selectedValues.filter((v) => v !== String(id))
} else {
/** 지붕 재료 처리 - 최대 2개 선택 처리 */
if (isRoofMaterial) {
const totalSelected = selectedValues.length + (isOtherSelected || isOtherCheck ? 1 : 0)
if (totalSelected >= 2) {
showErrorAlert(WARNING_MESSAGE.ROOF_MATERIAL_MAX_SELECT)
return
}
}
newValue = [...selectedValues, String(id)]
}
setRoofInfo({ ...roofInfo, [column]: newValue.join(',') })
}
/** 기타 선택 처리 */
const handleOtherCheckbox = () => {
if (isRoofMaterial) {
const currentSelected = selectedValues.length
if (!isOtherCheck && currentSelected >= 2) {
showErrorAlert(WARNING_MESSAGE.ROOF_MATERIAL_MAX_SELECT)
return
}
}
const newIsOtherCheck = !isOtherCheck
setIsOtherCheck(newIsOtherCheck)
/** 기타 선택 해제 시 값도 null로 설정 */
setRoofInfo({
...roofInfo,
[`${column}Etc`]: newIsOtherCheck ? '' : null,
})
}
/** 기타 입력 처리 */
const handleOtherInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setRoofInfo({ ...roofInfo, [`${column}Etc`]: e.target.value })
}
/** Input box 비활성화 처리 */
const isInputDisabled = () => {
return mode === 'READ' || (!isOtherCheck && !etcValue)
}
return (
<>
<div className="data-check-wrap">
{multiCheckData.map((item) => (
<div className="check-form-box" key={item.id}>
<input
type="checkbox"
id={`${column}_${item.id}`}
checked={selectedValues.includes(String(item.id))}
disabled={mode === 'READ'}
onChange={() => handleCheckbox(item.id)}
/>
<label htmlFor={`${column}_${item.id}`}>{item.name}</label>
</div>
))}
<div className="check-form-box">
<input
type="checkbox"
id={`${column}Etc`}
checked={isOtherCheck || Boolean(etcValue)}
disabled={mode === 'READ'}
onChange={handleOtherCheckbox}
/>
<label htmlFor={`${column}Etc`}> ()</label>
</div>
</div>
<div className="data-input">
<input
type="text"
className="input-frame"
placeholder="-"
value={roofInfo[`${column}Etc` as keyof SurveyDetailInfo]?.toString() ?? ''}
onChange={handleOtherInputChange}
readOnly={isInputDisabled()}
/>
</div>
</>
)
}