feature/translation : 일본어 번역 수정 #126

Merged
seul merged 8 commits from feature/translation into dev 2025-08-07 09:48:18 +09:00
12 changed files with 195 additions and 91 deletions

View File

@ -17,9 +17,14 @@ export default function layout({ children }: SuitableLayoutProps) {
<div className="sale-contents">
<div className="border-frame">
<div className="pw-guide">
<div className="pw-guide-txt">使.</div>
<div className="pw-guide-txt">11.</div>
<div className="pw-guide-txt">or屋根材名を直接入力してください.</div>
<div className="pw-guide-txt">使</div>
<div className="pw-guide-txt"></div>
<div className="pw-guide-txt">
"屋根材の種類を選択""製品名を入力"
</div>
<div className="pw-guide-txt">
"全選択""選択ダウンロード"PDFのダウンロードが可能です
</div>
</div>
</div>
{children}

View File

@ -38,9 +38,7 @@ export default function Detail() {
</tr>
<tr>
<th></th>
<td>
{inquiryDetail?.regNm ? inquiryDetail?.regNm : '-'}
</td>
<td>{inquiryDetail?.regNm ? inquiryDetail?.regNm : '-'}</td>
</tr>
<tr>
<th></th>
@ -93,7 +91,7 @@ export default function Detail() {
<div className="sale-edit-btn">
<button className="btn-frame n-blue icon" onClick={() => router.push('/inquiry/list')}>
<i className="btn-arr"></i>
<i className="btn-arr"></i>
</button>
</div>
</div>

View File

@ -297,7 +297,7 @@ export default function RegistForm() {
<div className="inquiry-file-wrap">
<div className="filebox">
<label className="btn-frame l-blue icon" htmlFor="file">
<i className="btn-clip"></i>Attach
<i className="btn-clip"></i>
</label>
<input type="file" id="file" onChange={handleFileChange} multiple style={{ display: 'none' }} />
</div>
@ -324,10 +324,10 @@ export default function RegistForm() {
router.push('/inquiry/list')
}}
>
<i className="btn-arr"></i>
<i className="btn-arr"></i>
</button>
<button className="btn-frame n-blue icon" onClick={handleSubmit} disabled={isSavingInquiry}>
<i className="btn-arr"></i>
<i className="btn-arr"></i>
</button>
</div>
</div>

View File

@ -41,7 +41,7 @@ export default function Suitable() {
<div className="compliance-icon">
<Image src={'/assets/images/sub/compliance_quest_icon.svg'} width={22} height={22} alt=""></Image>
</div>
<span></span>
<span></span>
</div>
</li>
<li className="reference-item">

View File

@ -46,7 +46,7 @@ export default function SuitableSearch() {
<>
<div className="sale-form-bx">
<select className="select-form" name="" id="" value={searchCategory || ''} onChange={(e) => setSearchCategory(e.target.value)}>
<option value="">.</option>
<option value=""></option>
{suitableCommCode.get(SUITABLE_HEAD_CODE.ROOF_MATL_GRP_CD)?.map((category: CommCode, index: number) => (
<option key={index} value={category.code}>
{category.codeJp}
@ -59,7 +59,7 @@ export default function SuitableSearch() {
<input
type="text"
className="search-frame"
placeholder="屋根材 製品名を入力してください."
placeholder="製品名を入力"
value={searchValue}
onChange={(e) => handleInputChange(e.target.value)}
onKeyDown={(e) => {

View File

@ -1,8 +1,8 @@
import { useEffect, useState } from 'react'
import type { Mode, SurveyDetailInfo, SurveyDetailRequest } from '@/types/Survey'
import { useAlertMsg, WARNING_MESSAGE } from '@/hooks/useAlertMsg'
import { radioEtcData, supplementaryFacilities } from '@/types/Survey'
import { useSurveyOptionStore } from '@/store/surveyOptionStore'
import { radioEtcData, supplementaryFacilities } from '@/types/Survey'
const makeNumArr = (value: string) => {
return value
@ -20,6 +20,11 @@ export default function RoofForm(props: {
const { showErrorAlert } = useAlertMsg()
const [isFlip, setIsFlip] = useState<boolean>(true)
const { selectBoxOptions, initialized, loading, loadOptions } = useSurveyOptionStore()
useEffect(() => {
if (!initialized && !loading) loadOptions()
}, [initialized, loading])
const handleNumberInput = (key: keyof SurveyDetailRequest, value: number | string) => {
/** 지붕 경사도, 노지판 두께 처리 - 최대 5자리, 소수점 1자리 처리 */
if (key === 'roofSlope' || key === 'openFieldPlateThickness') {
@ -116,7 +121,7 @@ export default function RoofForm(props: {
<div className="data-input-form-bx">
{/* 전기 부대 설비 */}
<div className="data-input-form-tit">
<span></span>
<span></span>
</div>
<MultiCheck mode={mode} column="supplementaryFacilities" roofInfo={roofInfo as SurveyDetailInfo} setRoofInfo={setRoofInfo} />
</div>
@ -133,9 +138,44 @@ export default function RoofForm(props: {
<div className="data-form-wrap">
<div className="data-input-form-bx">
{/* 건축 연수 */}
<div className="data-input-form-tit red-f"></div>
<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} />
<select
className="select-form mb10"
disabled={mode === 'READ'}
name="constructionYear"
id="constructionYear"
value={roofInfo?.constructionYear ?? ''}
onChange={(e) =>
setRoofInfo({
...roofInfo,
constructionYear: e.target.value,
constructionYearEtc: e.target.value === selectBoxOptions.constructionYear[0].code ? null : roofInfo?.constructionYearEtc,
})
}
>
<option value="" hidden>
</option>
{selectBoxOptions.constructionYear.map((item) => (
<option key={item.code ?? String(item.id)} value={item.code ?? String(item.id)}>
{item.name}
</option>
))}
</select>
<div className="data-input flex">
<input
readOnly={mode === 'READ' || roofInfo?.constructionYear === selectBoxOptions.constructionYear[0].code}
type="number"
inputMode="numeric"
id="constructionYearEtc"
className="input-frame"
placeholder="-"
value={roofInfo?.constructionYearEtc ?? ''}
onChange={(e) => setRoofInfo({ ...roofInfo, constructionYearEtc: e.target.value })}
/>
<span></span>
</div>
</div>
</div>
<div className="data-input-form-bx">
@ -154,7 +194,7 @@ export default function RoofForm(props: {
</div>
<div className="data-input-form-bx">
{/* 지붕 경사도 */}
<div className="data-input-form-tit"></div>
<div className="data-input-form-tit"></div>
<div className="data-input flex">
<input
type="number"
@ -187,7 +227,7 @@ export default function RoofForm(props: {
</div>
<div className="data-input-form-bx">
{/* 서까래 피치 */}
<div className="data-input-form-tit red-f"></div>
<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>
@ -201,7 +241,7 @@ export default function RoofForm(props: {
</div>
<div className="data-input-form-bx">
{/* 노지판 종류 */}
<div className="data-input-form-tit"></div>
<div className="data-input-form-tit"></div>
<div className="data-input mb5">
<SelectedBox mode={mode} column="openFieldPlateKind" detailInfoData={roofInfo as SurveyDetailInfo} setRoofInfo={setRoofInfo} />
</div>
@ -228,14 +268,14 @@ export default function RoofForm(props: {
)}
<div className="data-input-form-bx">
{/* 누수 흔적 */}
<div className="data-input-form-tit "></div>
<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>
<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">
@ -251,7 +291,39 @@ export default function RoofForm(props: {
<div className="data-input-form-bx">
{/* 지붕 제품명 설치 가능 여부 확인 */}
<div className="data-input-form-tit"> </div>
<SelectedBox mode={mode} column="installationAvailability" detailInfoData={roofInfo as SurveyDetailInfo} setRoofInfo={setRoofInfo} />
<select
className="select-form mb10"
disabled={mode === 'READ'}
name="installationAvailability"
id="installationAvailability"
value={roofInfo?.installationAvailability ?? ''}
onChange={(e) =>
setRoofInfo({
...roofInfo,
installationAvailability: e.target.value,
installationAvailabilityEtc: null,
})
}
>
<option value="" hidden>
</option>
{selectBoxOptions.installationAvailability.map((item) => (
<option key={item.code ?? String(item.id)} value={item.code ?? String(item.id)}>
{item.name}
</option>
))}
</select>
<div className="data-input">
<input
type="text"
className="input-frame"
value={roofInfo?.installationAvailabilityEtc ?? ''}
onChange={(e) => setRoofInfo({ ...roofInfo, installationAvailabilityEtc: e.target.value })}
placeholder="屋根製品名が分かる場合は入力してください"
readOnly={mode === 'READ'}
/>
</div>
</div>
<div className="data-input-form-bx">
{/* 메모 */}
@ -297,14 +369,10 @@ const SelectedBox = ({
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
/** SelectBox 값 변경 처리 */
const handleSelectChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
const value = e.target.value
@ -327,18 +395,21 @@ const SelectedBox = ({
/** Input box
* - 모드 : 비활성화
* - 여부 : 기타
* - 연수 : 新築 (N)
* -
* */
const isInputDisabled = () => {
if (mode === 'READ') return true
if (column === 'installationAvailability') return false
if (column === 'constructionYear') {
return detailInfoData.constructionYear === selectBoxOptions.constructionYear[0].code || detailInfoData.constructionYear === null
}
return !isEtcSelected && !etcValue
}
/** placeholder 설정 처리 */
const setPlaceholder = (column: string) => {
switch (column) {
default:
return '-'
}
}
return (
<>
<select
@ -354,27 +425,24 @@ const SelectedBox = ({
{item.name}
</option>
))}
{showEtcOption && (
<option key="etc" value="etc">
()
</option>
)}
<option key="etc" value="etc">
()
</option>
<option key="" value="" hidden>
</option>
</select>
<div className={`data-input ${column === 'constructionYear' ? 'flex' : ''}`}>
<div className="data-input">
<input
id={`${column}Etc`}
type={column === 'constructionYear' ? 'number' : 'text'}
inputMode={column === 'constructionYear' ? 'numeric' : 'text'}
type="text"
inputMode="text"
className="input-frame"
placeholder="-"
placeholder={setPlaceholder(column)}
value={detailInfoData[`${column}Etc` as keyof SurveyDetailInfo]?.toString() ?? ''}
onChange={handleEtcInputChange}
readOnly={isInputDisabled()}
/>
{column === 'constructionYear' && <span></span>}
</div>
</>
)
@ -453,6 +521,13 @@ const RadioSelected = ({
return !etcChecked && !etcValue
}
const setPlaceholder = (column: string) => {
switch (column) {
default:
return '-'
}
}
return (
<>
{radioEtcData[column as keyof typeof radioEtcData].map((item) => (
@ -489,7 +564,7 @@ const RadioSelected = ({
id={`${column}Etc`}
type="text"
className="input-frame"
placeholder="-"
placeholder={setPlaceholder(column)}
value={detailInfoData[`${column}Etc` as keyof SurveyDetailInfo]?.toString() ?? ''}
onChange={handleEtcInputChange}
readOnly={isInputDisabled()}
@ -580,6 +655,13 @@ const MultiCheck = ({
return mode === 'READ' || etcValue === null
}
const setPlaceholder = (column: string) => {
switch (column) {
default:
return '-'
}
}
return (
<>
<div className="data-check-wrap">
@ -604,7 +686,7 @@ const MultiCheck = ({
<input
type="text"
className="input-frame"
placeholder="-"
placeholder={setPlaceholder(column)}
value={roofInfo[`${column}Etc` as keyof SurveyDetailInfo]?.toString() ?? ''}
onChange={handleOtherInputChange}
readOnly={isInputDisabled()}

View File

@ -41,7 +41,7 @@ export default function SearchForm({ memberRole, userId }: { memberRole: string;
router.push('/survey-sale/regist')
}}
>
<i className="btn-arr"></i>
調<i className="btn-arr"></i>
</button>
</div>
<div className="sale-form-bx">

View File

@ -8,11 +8,11 @@ export default function Main() {
<>
<div className="main-contens">
<div className="main-head-block">
<div className="head-block-tit"></div>
<div className="head-block-text">使</div>
<div className="head-block-tit"></div>
<div className="head-block-text"></div>
<div className="head-block-link-wrap">
<button className="head-block-link" onClick={() => router.push('/suitable')}>
<i className="block-arr"></i>
<i className="block-arr"></i>
</button>
</div>
</div>
@ -26,7 +26,7 @@ export default function Main() {
</div>
<div className="grid-bx-body">
<div className="grid-bx-body-tit">調</div>
<div className="grid-bx-body-txt"></div>
<div className="grid-bx-body-txt">調</div>
</div>
</div>
<div className="main-grid-bx bx02">
@ -38,7 +38,7 @@ export default function Main() {
</div>
<div className="grid-bx-body">
<div className="grid-bx-body-tit">調</div>
<div className="grid-bx-body-txt"></div>
<div className="grid-bx-body-txt">調</div>
</div>
</div>
<div className="main-grid-bx bx03">
@ -50,7 +50,7 @@ export default function Main() {
</div>
<div className="grid-bx-body">
<div className="grid-bx-body-tit"></div>
<div className="grid-bx-body-txt"></div>
<div className="grid-bx-body-txt"></div>
</div>
</div>
<div className="main-grid-bx bx04">

View File

@ -88,7 +88,7 @@ export default function Header() {
}}
>
<div className="side-swiper-icon icon01"></div>
<div className="side-swiper-infor"></div>
<div className="side-swiper-infor"></div>
</div>
</SwiperSlide>
<SwiperSlide>
@ -100,16 +100,19 @@ export default function Header() {
}}
>
<div className="side-swiper-icon icon02"></div>
<div className="side-swiper-infor"></div>
<div className="side-swiper-infor"></div>
</div>
</SwiperSlide>
<SwiperSlide>
<div className="side-swiper-card" onClick={() => {
router.push('/suitable')
setSideNavIsOpen(false)
}}>
<div
className="side-swiper-card"
onClick={() => {
router.push('/suitable')
setSideNavIsOpen(false)
}}
>
<div className="side-swiper-icon icon01"></div>
<div className="side-swiper-infor"></div>
<div className="side-swiper-infor"></div>
</div>
</SwiperSlide>
</Swiper>
@ -127,29 +130,45 @@ export default function Header() {
</button>
</li>
<li className="side-nav-item">
<button onClick={() => {
router.push('/survey-sale/regist')
setSideNavIsOpen(false)
}}>調</button>
<button
onClick={() => {
router.push('/survey-sale/regist')
setSideNavIsOpen(false)
}}
>
調
</button>
</li>
<li className="side-nav-item">
<button onClick={() => {
router.push('/inquiry/list?isMyInquiry=false')
setSideNavIsOpen(false)
}}></button>
<button
onClick={() => {
router.push('/inquiry/list?isMyInquiry=false')
setSideNavIsOpen(false)
}}
>
</button>
</li>
<li className="side-nav-item">
<button onClick={() => {
router.push('/inquiry/regist')
setSideNavIsOpen(false)
}}></button>
<button
onClick={() => {
router.push('/inquiry/regist')
setSideNavIsOpen(false)
}}
>
</button>
</li>
{session.role !== 'Partner' && (
<li className="side-nav-item">
<button onClick={() => {
router.push('/pw-reset')
setSideNavIsOpen(false)
}}></button>
<button
onClick={() => {
router.push('/pw-reset')
setSideNavIsOpen(false)
}}
>
</button>
</li>
)}
</ul>

View File

@ -15,7 +15,7 @@ export const requiredFields = [
},
{
field: 'constructionYear',
name: '築年数',
name: '築年数',
},
{
field: 'rafterSize',
@ -23,15 +23,15 @@ export const requiredFields = [
},
{
field: 'rafterPitch',
name: '垂木傾斜',
name: '垂木ピッチ',
},
{
field: 'waterproofMaterial',
name: '防水材',
name: 'ルーフィングの種類',
},
{
field: 'insulationPresence',
name: '断熱材有無',
name: '断熱材有無',
},
{
field: 'structureOrder',

View File

@ -14,13 +14,13 @@ export const useTitle = () => {
case '/':
return 'Hanasys 現地調査'
case '/suitable':
return '屋根材適合の確認'
return '屋根材適合の確認'
case '/survey-sale':
return '調査物件一覧'
case '/survey-sale/regist':
return '調査物件登録'
case '/inquiry/list':
return 'お問い合わせ'
return 'お問い合わせ一覧'
case '/inquiry/regist':
return 'お問い合わせ登録'
case '/pw-reset':

View File

@ -345,7 +345,7 @@ export const supplementaryFacilities: { id: number; code: string | null; name: s
/** 에코큐트 */
{ id: 1, code: null, name: 'エコキュート' },
/** 에네팜 */
{ id: 2, code: null, name: 'エネーム' },
{ id: 2, code: null, name: 'エネファーム' },
/** 축전지시스템 */
{ id: 3, code: null, name: '蓄電池システム' },
/** 태양광발전 */
@ -382,7 +382,7 @@ export const selectBoxOptions: Record<SelectBoxKeys, { id: number; code: string
/** 축전지시스템 */
id: 3,
code: null,
name: '蓄電池システム',
name: '単機能蓄電池システム',
},
],
@ -522,7 +522,7 @@ export const radioEtcData: Record<RadioEtcKeys, { id: number; code: string | nul
/** 지붕재 - 방수재 - 지붕의기초 - 서까래 */
id: 1,
code: null,
label: '屋根材 > 防水材 > 屋根の基礎 > 垂木',
label: '屋根材>ルーフィング>野地板>垂木',
},
],
houseStructure: [
@ -530,7 +530,7 @@ export const radioEtcData: Record<RadioEtcKeys, { id: number; code: string | nul
/** 목재 */
id: 1,
code: null,
label: '木',
label: '木',
},
],
rafterMaterial: [
@ -538,13 +538,13 @@ export const radioEtcData: Record<RadioEtcKeys, { id: number; code: string | nul
/** 목재 */
id: 1,
code: null,
label: '木',
label: '木',
},
{
/** 강재 */
id: 2,
code: null,
label: '強制',
label: '鉄骨材',
},
],
waterproofMaterial: [
@ -552,7 +552,7 @@ export const radioEtcData: Record<RadioEtcKeys, { id: number; code: string | nul
/** 아스팔트 지붕 940(22kg 이상) */
id: 1,
code: null,
label: 'アスファルト屋根94022kg以上',
label: 'アスファルトルーフィング94022kg以上',
},
],
insulationPresence: [
@ -566,7 +566,7 @@ export const radioEtcData: Record<RadioEtcKeys, { id: number; code: string | nul
/** 있음 */
id: 2,
code: null,
label: 'あり',
label: 'あり(断熱材の名称や厚さを直接入力)',
},
],
rafterDirection: [
@ -574,13 +574,13 @@ export const radioEtcData: Record<RadioEtcKeys, { id: number; code: string | nul
/** 수직 */
id: 1,
code: null,
label: '垂直垂木',
label: '垂木',
},
{
/** 수평 */
id: 2,
code: null,
label: '水平垂木',
label: '垂木',
},
],
leakTrace: [