Merge pull request 'feat: seporate save/submit/update process for reuse component' (#39) from feature/survey into dev
Reviewed-on: #39
This commit is contained in:
commit
e2e5a484ca
@ -1,9 +1,10 @@
|
||||
import { NextResponse } from 'next/server'
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { prisma } from '@/libs/prisma'
|
||||
import { convertToSnakeCase } from '../route'
|
||||
|
||||
export async function GET(request: Request, context: { params: { id: string } }) {
|
||||
export async function GET(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||
try {
|
||||
const { id } = await context.params
|
||||
const { id } = await params
|
||||
// @ts-ignore
|
||||
const survey = await prisma.SD_SURVEY_SALES_BASIC_INFO.findUnique({
|
||||
where: { ID: Number(id) },
|
||||
@ -18,34 +19,34 @@ export async function GET(request: Request, context: { params: { id: string } })
|
||||
}
|
||||
}
|
||||
|
||||
export async function PUT(request: Request, context: { params: { id: string } }) {
|
||||
export async function PUT(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||
try {
|
||||
const { id } = await context.params
|
||||
const { id } = await params
|
||||
const body = await request.json()
|
||||
console.log('body:: ', body)
|
||||
|
||||
// DETAIL_INFO를 분리
|
||||
const { DETAIL_INFO, ...basicInfo } = body
|
||||
|
||||
console.log('body:: ', body)
|
||||
// @ts-ignore
|
||||
const survey = await prisma.SD_SURVEY_SALES_BASIC_INFO.update({
|
||||
where: { ID: Number(id) },
|
||||
data: {
|
||||
...basicInfo,
|
||||
...convertToSnakeCase(basicInfo),
|
||||
UPT_DT: new Date(),
|
||||
DETAIL_INFO: DETAIL_INFO
|
||||
? {
|
||||
upsert: {
|
||||
create: DETAIL_INFO,
|
||||
update: DETAIL_INFO,
|
||||
},
|
||||
DETAIL_INFO: DETAIL_INFO ? {
|
||||
upsert: {
|
||||
create: convertToSnakeCase(DETAIL_INFO),
|
||||
update: convertToSnakeCase(DETAIL_INFO),
|
||||
where: {
|
||||
BASIC_INFO_ID: Number(id)
|
||||
}
|
||||
: undefined,
|
||||
}
|
||||
} : undefined
|
||||
},
|
||||
include: {
|
||||
DETAIL_INFO: true,
|
||||
},
|
||||
DETAIL_INFO: true
|
||||
}
|
||||
})
|
||||
console.log('survey:: ', survey)
|
||||
return NextResponse.json(survey)
|
||||
} catch (error) {
|
||||
console.error('Error updating survey:', error)
|
||||
@ -53,9 +54,9 @@ export async function PUT(request: Request, context: { params: { id: string } })
|
||||
}
|
||||
}
|
||||
|
||||
export async function DELETE(request: Request, context: { params: { id: string } }) {
|
||||
export async function DELETE(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||
try {
|
||||
const { id } = await context.params
|
||||
const { id } = await params
|
||||
|
||||
await prisma.$transaction(async (tx) => {
|
||||
// @ts-ignore
|
||||
@ -86,9 +87,9 @@ export async function DELETE(request: Request, context: { params: { id: string }
|
||||
}
|
||||
}
|
||||
|
||||
export async function PATCH(request: Request, context: { params: { id: string } }) {
|
||||
export async function PATCH(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||
try {
|
||||
const { id } = await context.params
|
||||
const { id } = await params
|
||||
const body = await request.json()
|
||||
|
||||
if (body.submit) {
|
||||
@ -98,40 +99,42 @@ export async function PATCH(request: Request, context: { params: { id: string }
|
||||
data: {
|
||||
SUBMISSION_STATUS: true,
|
||||
SUBMISSION_DATE: new Date(),
|
||||
UPT_DT: new Date(),
|
||||
},
|
||||
})
|
||||
return NextResponse.json({ message: 'Survey confirmed successfully' })
|
||||
} else {
|
||||
// @ts-ignore
|
||||
const hasDetails = await prisma.SD_SURVEY_SALES_DETAIL_INFO.findUnique({
|
||||
where: { BASIC_INFO_ID: Number(id) },
|
||||
})
|
||||
|
||||
if (hasDetails) {
|
||||
//@ts-ignore
|
||||
const result = await prisma.SD_SURVEY_SALES_BASIC_INFO.update({
|
||||
where: { ID: Number(id) },
|
||||
data: {
|
||||
UPT_DT: new Date(),
|
||||
DETAIL_INFO: {
|
||||
update: body.DETAIL_INFO,
|
||||
},
|
||||
},
|
||||
})
|
||||
return NextResponse.json(result)
|
||||
} else {
|
||||
// @ts-ignore
|
||||
const survey = await prisma.SD_SURVEY_SALES_BASIC_INFO.update({
|
||||
where: { ID: Number(id) },
|
||||
data: {
|
||||
DETAIL_INFO: {
|
||||
create: body.DETAIL_INFO,
|
||||
},
|
||||
},
|
||||
})
|
||||
return NextResponse.json({ message: 'Survey detail created successfully' })
|
||||
}
|
||||
}
|
||||
// } else {
|
||||
// // @ts-ignore
|
||||
// const hasDetails = await prisma.SD_SURVEY_SALES_DETAIL_INFO.findUnique({
|
||||
// where: { BASIC_INFO_ID: Number(id) },
|
||||
// })
|
||||
|
||||
// if (hasDetails) {
|
||||
// //@ts-ignore
|
||||
// const result = await prisma.SD_SURVEY_SALES_BASIC_INFO.update({
|
||||
// where: { ID: Number(id) },
|
||||
// data: {
|
||||
// UPT_DT: new Date(),
|
||||
// DETAIL_INFO: {
|
||||
// update: convertToSnakeCase(body.DETAIL_INFO),
|
||||
// },
|
||||
// },
|
||||
// })
|
||||
// return NextResponse.json(result)
|
||||
// } else {
|
||||
// // @ts-ignore
|
||||
// const survey = await prisma.SD_SURVEY_SALES_BASIC_INFO.update({
|
||||
// where: { ID: Number(id) },
|
||||
// data: {
|
||||
// DETAIL_INFO: {
|
||||
// create: convertToSnakeCase(body.DETAIL_INFO),
|
||||
// },
|
||||
// },
|
||||
// })
|
||||
// return NextResponse.json({ message: 'Survey detail created successfully' })
|
||||
// }
|
||||
// }
|
||||
} catch (error) {
|
||||
console.error('Error updating survey:', error)
|
||||
return NextResponse.json({ error: 'Failed to update survey' }, { status: 500 })
|
||||
|
||||
@ -219,19 +219,46 @@ export async function PUT(request: Request) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(request: Request) {
|
||||
// 카멜케이스를 스네이크케이스로 변환하는 함수
|
||||
export const toSnakeCase = (str: string) => {
|
||||
return str.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`);
|
||||
}
|
||||
|
||||
// 객체의 키를 스네이크케이스로 변환하는 함수
|
||||
export const convertToSnakeCase = (obj: any): Record<string, any> => {
|
||||
if (obj === null || obj === undefined) return obj;
|
||||
|
||||
if (Array.isArray(obj)) {
|
||||
return obj.map((item: any) => convertToSnakeCase(item))
|
||||
}
|
||||
|
||||
if (typeof obj === 'object') {
|
||||
return Object.keys(obj).reduce((acc, key) => {
|
||||
const snakeKey = toSnakeCase(key).toUpperCase();
|
||||
acc[snakeKey] = convertToSnakeCase(obj[key]);
|
||||
return acc;
|
||||
}, {} as Record<string, any>);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
export async function POST(request: Request) {
|
||||
try {
|
||||
const body = await request.json()
|
||||
const { DETAIL_INFO, ...basicInfo } = body
|
||||
console.log('body:: ', body)
|
||||
|
||||
const { detailInfo, ...basicInfo } = body
|
||||
|
||||
// 기본 정보 생성
|
||||
//@ts-ignore
|
||||
const result = await prisma.SD_SURVEY_SALES_BASIC_INFO.create({
|
||||
data: {
|
||||
...basicInfo,
|
||||
...convertToSnakeCase(basicInfo),
|
||||
DETAIL_INFO: {
|
||||
create: DETAIL_INFO,
|
||||
},
|
||||
},
|
||||
create: convertToSnakeCase(detailInfo)
|
||||
}
|
||||
}
|
||||
})
|
||||
return NextResponse.json(result)
|
||||
} catch (error) {
|
||||
|
||||
@ -4,7 +4,6 @@ export default function page() {
|
||||
return (
|
||||
<>
|
||||
<DataTable />
|
||||
{/* <DetailForm surveyInfo={surveyInfo} mode="READ" /> */}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import RegistForm from '@/components/survey-sale/detail/RegistForm'
|
||||
import DetailForm from "@/components/survey-sale/detail/DetailForm";
|
||||
|
||||
export default function RegistPage() {
|
||||
return (
|
||||
<>
|
||||
<RegistForm/>
|
||||
<DetailForm />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@ -2,18 +2,45 @@
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useSurveySaleTabState } from '@/store/surveySaleTabState'
|
||||
import { SurveyBasicRequest } from '@/types/Survey'
|
||||
import { Mode } from 'fs'
|
||||
import type { SurveyBasicRequest } from '@/types/Survey'
|
||||
import type { Mode } from 'fs'
|
||||
import { useSessionStore } from '@/store/session'
|
||||
import { usePopupController } from '@/store/popupController'
|
||||
import { useAddressStore } from '@/store/addressStore'
|
||||
|
||||
export default function BasicForm(props: { basicInfo: SurveyBasicRequest; setBasicInfo: (basicInfo: SurveyBasicRequest) => void; mode: Mode }) {
|
||||
const { basicInfo, setBasicInfo, mode } = props
|
||||
const { setBasicInfoSelected } = useSurveySaleTabState()
|
||||
const [isFlip, setIsFlip] = useState<boolean>(true)
|
||||
|
||||
const { session } = useSessionStore()
|
||||
const { addressData } = useAddressStore()
|
||||
|
||||
useEffect(() => {
|
||||
setBasicInfoSelected()
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (session?.isLoggedIn) {
|
||||
setBasicInfo({
|
||||
...basicInfo,
|
||||
representative: session.userNm ?? '',
|
||||
store: session.storeNm ?? null,
|
||||
constructionPoint: session.builderNo ?? null,
|
||||
})
|
||||
}
|
||||
if (addressData) {
|
||||
setBasicInfo({
|
||||
...basicInfo,
|
||||
postCode: addressData.post_code,
|
||||
address: addressData.address,
|
||||
addressDetail: addressData.address_detail,
|
||||
})
|
||||
}
|
||||
}, [session, addressData])
|
||||
|
||||
const popupController = usePopupController()
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={`sale-detail-toggle-bx ${isFlip ? 'act' : ''}`}>
|
||||
@ -31,31 +58,35 @@ export default function BasicForm(props: { basicInfo: SurveyBasicRequest; setBas
|
||||
<input
|
||||
type="text"
|
||||
className="input-frame"
|
||||
readOnly={mode === 'READ'}
|
||||
readOnly
|
||||
value={basicInfo?.representative ?? ''}
|
||||
onChange={(e) => setBasicInfo({ ...basicInfo, representative: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
<div className="data-input-form-bx">
|
||||
<div className="data-input-form-tit">販売店</div>
|
||||
<input
|
||||
type="text"
|
||||
className="input-frame"
|
||||
readOnly={mode === 'READ'}
|
||||
value={basicInfo?.store ?? ''}
|
||||
onChange={(e) => setBasicInfo({ ...basicInfo, store: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
<div className="data-input-form-bx">
|
||||
<div className="data-input-form-tit">施工店</div>
|
||||
<input
|
||||
type="text"
|
||||
className="input-frame"
|
||||
readOnly={mode === 'READ'}
|
||||
value={basicInfo?.constructionPoint ?? ''}
|
||||
onChange={(e) => setBasicInfo({ ...basicInfo, constructionPoint: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
{(session?.role === 'Builder' || session?.role?.includes('Admin')) && (
|
||||
<div className="data-input-form-bx">
|
||||
<div className="data-input-form-tit">販売店</div>
|
||||
<input
|
||||
type="text"
|
||||
className="input-frame"
|
||||
readOnly
|
||||
value={basicInfo?.store ?? ''}
|
||||
onChange={(e) => setBasicInfo({ ...basicInfo, store: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{(session?.role === 'Builder' || session?.role === 'Partner') && (
|
||||
<div className="data-input-form-bx">
|
||||
<div className="data-input-form-tit">施工店</div>
|
||||
<input
|
||||
type="text"
|
||||
className="input-frame"
|
||||
readOnly
|
||||
value={basicInfo?.constructionPoint ?? ''}
|
||||
onChange={(e) => setBasicInfo({ ...basicInfo, constructionPoint: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="sale-frame">
|
||||
@ -67,7 +98,13 @@ export default function BasicForm(props: { basicInfo: SurveyBasicRequest; setBas
|
||||
<button className="date-btn">
|
||||
<i className="date-icon"></i>
|
||||
</button>
|
||||
<input type="date" className="date-frame" readOnly defaultValue={basicInfo?.investigationDate?.toString()} />
|
||||
<input
|
||||
id="investigationDate"
|
||||
type="date"
|
||||
className="date-frame"
|
||||
defaultValue={basicInfo?.investigationDate?.toString()}
|
||||
onChange={(e) => setBasicInfo({ ...basicInfo, investigationDate: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<input type="date" className="input-frame" disabled defaultValue={basicInfo?.investigationDate?.toString()} />
|
||||
@ -76,12 +113,24 @@ export default function BasicForm(props: { basicInfo: SurveyBasicRequest; setBas
|
||||
<div className="data-input-form-bx">
|
||||
{/* 건물명 */}
|
||||
<div className="data-input-form-tit">建物名</div>
|
||||
<input type="text" className="input-frame" readOnly={mode === 'READ'} defaultValue={basicInfo?.buildingName ?? ''} />
|
||||
<input
|
||||
type="text"
|
||||
className="input-frame"
|
||||
readOnly={mode === 'READ'}
|
||||
defaultValue={basicInfo?.buildingName ?? ''}
|
||||
onChange={(e) => setBasicInfo({ ...basicInfo, buildingName: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
<div className="data-input-form-bx">
|
||||
{/* 고객명 */}
|
||||
<div className="data-input-form-tit">建物名</div>
|
||||
<input type="text" className="input-frame" readOnly={mode === 'READ'} defaultValue={basicInfo?.customerName ?? ''} />
|
||||
<div className="data-input-form-tit">お客様名</div>
|
||||
<input
|
||||
type="text"
|
||||
className="input-frame"
|
||||
readOnly={mode === 'READ'}
|
||||
defaultValue={basicInfo?.customerName ?? ''}
|
||||
onChange={(e) => setBasicInfo({ ...basicInfo, customerName: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
<div className="data-input-form-bx">
|
||||
<div className="data-input-form-tit">郵便番号/都道府県</div>
|
||||
@ -92,12 +141,12 @@ export default function BasicForm(props: { basicInfo: SurveyBasicRequest; setBas
|
||||
</div>
|
||||
{/* 도도부현 */}
|
||||
<div className="form-bx">
|
||||
<input type="text" className="input-frame" readOnly={mode === 'READ'} defaultValue={basicInfo?.address ?? ''} disabled />
|
||||
<input type="text" className="input-frame" readOnly={mode === 'READ'} defaultValue={basicInfo?.address ?? ''} />
|
||||
</div>
|
||||
</div>
|
||||
{/* 주소 */}
|
||||
<div className="form-btn">
|
||||
<button className="btn-frame n-blue icon">
|
||||
<button className="btn-frame n-blue icon" onClick={() => popupController.setZipCodePopup(true)}>
|
||||
郵便番号<i className="btn-arr"></i>
|
||||
</button>
|
||||
</div>
|
||||
@ -105,7 +154,7 @@ export default function BasicForm(props: { basicInfo: SurveyBasicRequest; setBas
|
||||
|
||||
<div className="data-input-form-bx">
|
||||
<div className="data-input-form-tit">市区町村名, 以後の住所</div>
|
||||
<input type="text" className="input-frame" defaultValue={'浜松 浜松町'} readOnly={mode === 'READ'} />
|
||||
<input type="text" className="input-frame" defaultValue={basicInfo?.addressDetail ?? ''} readOnly={mode === 'READ'} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,81 +1,267 @@
|
||||
import { Mode, SurveyBasicRequest, SurveyDetailRequest } from '@/types/Survey'
|
||||
'use client'
|
||||
|
||||
export default function ButtonForm(props: { mode: Mode; setMode: (mode: Mode) => void; data: { basic: SurveyBasicRequest; roof: SurveyDetailRequest } }) {
|
||||
import type { Mode, SurveyBasicRequest, SurveyDetailInfo, SurveyDetailRequest } from '@/types/Survey'
|
||||
import { useSessionStore } from '@/store/session'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useParams, useRouter, useSearchParams } from 'next/navigation'
|
||||
import { requiredFields, useServey } from '@/hooks/useSurvey'
|
||||
|
||||
export default function ButtonForm(props: {
|
||||
mode: Mode
|
||||
setMode: (mode: Mode) => void
|
||||
data: { basic: SurveyBasicRequest; roof: SurveyDetailRequest }
|
||||
}) {
|
||||
// 라우터
|
||||
const router = useRouter()
|
||||
const { mode, setMode } = props
|
||||
const { session } = useSessionStore()
|
||||
|
||||
const searchParams = useSearchParams()
|
||||
const idParam = searchParams.get('id')
|
||||
|
||||
const params = useParams()
|
||||
const routeId = params.id
|
||||
|
||||
const [isSubmitProcess, setIsSubmitProcess] = useState(false)
|
||||
// ------------------------------------------------------------
|
||||
// 권한
|
||||
|
||||
// 제출권한 ㅇ
|
||||
const [isSubmiter, setIsSubmiter] = useState(false)
|
||||
// 작성자
|
||||
const [isWriter, setIsWriter] = useState(false)
|
||||
const isSubmit = props.data.basic.submissionStatus
|
||||
|
||||
useEffect(() => {
|
||||
if (session?.isLoggedIn) {
|
||||
setIsSubmiter(session.storeNm === props.data.basic.store && session.builderNo === props.data.basic.constructionPoint)
|
||||
setIsWriter(session.userNm === props.data.basic.representative)
|
||||
}
|
||||
}, [session, props.data])
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// 저장/임시저장/수정
|
||||
|
||||
const id = routeId ? Number(routeId) : Number(idParam)
|
||||
const { deleteSurvey, submitSurvey, updateSurvey } = useServey(Number(id))
|
||||
const { validateSurveyDetail, createSurvey } = useServey()
|
||||
let saveData = {
|
||||
...props.data.basic,
|
||||
detailInfo: props.data.roof,
|
||||
}
|
||||
|
||||
const handleSave = (isTemporary: boolean) => {
|
||||
const emptyField = validateSurveyDetail(props.data.roof)
|
||||
console.log('handleSave, emptyField:: ', emptyField)
|
||||
if (isTemporary) {
|
||||
tempSaveProcess()
|
||||
} else {
|
||||
saveProcess(emptyField)
|
||||
}
|
||||
}
|
||||
|
||||
const tempSaveProcess = async () => {
|
||||
if (idParam) {
|
||||
await updateSurvey(saveData)
|
||||
router.push(`/survey-sale/detail?id=${idParam}&isTemporary=true`)
|
||||
} else {
|
||||
const id = await createSurvey(saveData)
|
||||
router.push(`/survey-sale/detail?id=${id}&isTemporary=true`)
|
||||
}
|
||||
alert('一時保存されました。')
|
||||
}
|
||||
|
||||
const focusInput = (field: keyof SurveyDetailInfo) => {
|
||||
const input = document.getElementById(field)
|
||||
if (input) {
|
||||
input.focus()
|
||||
}
|
||||
}
|
||||
|
||||
const saveProcess = async (emptyField: string) => {
|
||||
if (emptyField.trim() === '') {
|
||||
if (idParam) {
|
||||
// 수정 페이지에서 작성 후 제출
|
||||
if (isSubmitProcess) {
|
||||
saveData = {
|
||||
...saveData,
|
||||
submissionStatus: true,
|
||||
submissionDate: new Date().toISOString(),
|
||||
}
|
||||
}
|
||||
await updateSurvey(saveData)
|
||||
router.push(`/survey-sale/${idParam}`)
|
||||
} else {
|
||||
const id = await createSurvey(saveData)
|
||||
if (isSubmitProcess) {
|
||||
submitProcess(id)
|
||||
return
|
||||
}
|
||||
router.push(`/survey-sale/${id}`)
|
||||
}
|
||||
alert('保存されました。')
|
||||
} else {
|
||||
if (emptyField.includes('Unit')) {
|
||||
alert('電気契約容量の単位を入力してください。')
|
||||
focusInput(emptyField as keyof SurveyDetailInfo)
|
||||
} else {
|
||||
alert(requiredFields.find((field) => field.field === emptyField)?.name + ' 項目が空です。')
|
||||
focusInput(emptyField as keyof SurveyDetailInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------
|
||||
// 삭제/제출
|
||||
|
||||
const handleDelete = async () => {
|
||||
if (routeId) {
|
||||
window.neoConfirm('削除しますか?', async () => {
|
||||
await deleteSurvey()
|
||||
router.push('/survey-sale')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const handleSubmit = async () => {
|
||||
window.neoConfirm('提出しますか?', async () => {
|
||||
setIsSubmitProcess(true)
|
||||
if (routeId) {
|
||||
submitProcess()
|
||||
} else {
|
||||
handleSave(false)
|
||||
}
|
||||
})
|
||||
}
|
||||
const submitProcess = async (saveId?: number) => {
|
||||
await submitSurvey(saveId)
|
||||
alert('提出されました。')
|
||||
router.push('/survey-sale')
|
||||
}
|
||||
// ------------------------------------------------------------
|
||||
|
||||
if (mode === 'READ' && isSubmit && isSubmiter) {
|
||||
return (
|
||||
<>
|
||||
<div className="sale-form-btn-wrap">
|
||||
<div className="btn-flex-wrap">
|
||||
<ListButton />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{mode === 'CREATE' && (
|
||||
{mode === 'READ' && (
|
||||
<div className="sale-form-btn-wrap">
|
||||
<div className="btn-flex-wrap">
|
||||
<div className="btn-bx">
|
||||
{/* 임시저장 */}
|
||||
<button className="btn-frame n-blue icon" onClick={() => setMode('TEMP')}>
|
||||
一時保存<i className="btn-arr"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div className="btn-bx">
|
||||
{/* 저장 */}
|
||||
<button className="btn-frame red icon">
|
||||
保存<i className="btn-arr"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div className="btn-bx">
|
||||
{/* 목록 */}
|
||||
<button className="btn-frame n-blue icon">
|
||||
リスト<i className="btn-arr"></i>
|
||||
</button>
|
||||
</div>
|
||||
<ListButton />
|
||||
<EditButton setMode={setMode} id={id.toString()} mode={mode} />
|
||||
{(isWriter || !isSubmiter) && <DeleteButton handleDelete={handleDelete} />}
|
||||
{!isSubmit && isSubmiter && <SubmitButton handleSubmit={handleSubmit} />}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{mode === 'TEMP' && (
|
||||
|
||||
{(mode === 'CREATE' || mode === 'EDIT') && (
|
||||
<div className="sale-form-btn-wrap">
|
||||
<div className="btn-flex-wrap">
|
||||
<div className="btn-bx">
|
||||
{/* 수정 */}
|
||||
<button className="btn-frame n-blue icon" onClick={() => setMode('EDIT')}>
|
||||
修正<i className="btn-arr"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div className="btn-bx">
|
||||
{/* 삭제 */}
|
||||
<button className="btn-frame n-blue icon">
|
||||
削除<i className="btn-arr"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{mode === 'EDIT' && (
|
||||
<div className="sale-form-btn-wrap">
|
||||
<div className="btn-flex-wrap">
|
||||
<div className="btn-bx">
|
||||
{/* 목록 */}
|
||||
<button className="btn-frame n-blue icon">
|
||||
リスト<i className="btn-arr"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div className="btn-bx">
|
||||
{/* 제출 */}
|
||||
<button className="btn-frame red icon">
|
||||
提出<i className="btn-arr"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div className="btn-bx">
|
||||
{/* 수정 */}
|
||||
<button className="btn-frame n-blue icon" onClick={() => setMode('EDIT')}>
|
||||
修正<i className="btn-arr"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div className="btn-bx">
|
||||
{/* 삭제 */}
|
||||
<button className="btn-frame n-blue icon">
|
||||
削除<i className="btn-arr"></i>
|
||||
</button>
|
||||
</div>
|
||||
<ListButton />
|
||||
<TempButton setMode={setMode} handleSave={handleSave} />
|
||||
<SaveButton handleSave={handleSave} />
|
||||
<SubmitButton handleSubmit={handleSubmit} />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
// 목록 버튼
|
||||
function ListButton() {
|
||||
const router = useRouter()
|
||||
return (
|
||||
<div className="btn-bx">
|
||||
{/* 목록 */}
|
||||
<button className="btn-frame n-blue icon" onClick={() => router.push('/survey-sale')}>
|
||||
リスト<i className="btn-arr"></i>
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function EditButton(props: { setMode: (mode: Mode) => void; id: string; mode: Mode }) {
|
||||
const { setMode, id, mode } = props
|
||||
const router = useRouter()
|
||||
return (
|
||||
<div className="btn-bx">
|
||||
{/* 수정 */}
|
||||
<button
|
||||
className="btn-frame n-blue icon"
|
||||
onClick={() => {
|
||||
router.push(`/survey-sale/regist?id=${id}`)
|
||||
setMode('EDIT')
|
||||
}}
|
||||
>
|
||||
修正<i className="btn-arr"></i>
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function SubmitButton(props: { handleSubmit: () => void }) {
|
||||
const { handleSubmit } = props
|
||||
return (
|
||||
<div className="btn-bx">
|
||||
{/* 제출 */}
|
||||
<button className="btn-frame red icon" onClick={handleSubmit}>
|
||||
提出<i className="btn-arr"></i>
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function DeleteButton(props: { handleDelete: () => void }) {
|
||||
const { handleDelete } = props
|
||||
return (
|
||||
<div className="btn-bx">
|
||||
{/* 삭제 */}
|
||||
<button className="btn-frame n-blue icon" onClick={handleDelete}>
|
||||
削除<i className="btn-arr"></i>
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function SaveButton(props: { handleSave: (isTemporary: boolean) => void }) {
|
||||
const { handleSave } = props
|
||||
return (
|
||||
<div className="btn-bx">
|
||||
{/* 저장 */}
|
||||
<button className="btn-frame n-blue icon" onClick={() => handleSave(false)}>
|
||||
保存<i className="btn-arr"></i>
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function TempButton(props: { setMode: (mode: Mode) => void; handleSave: (isTemporary: boolean) => void }) {
|
||||
const { setMode, handleSave } = props
|
||||
const router = useRouter()
|
||||
|
||||
return (
|
||||
<div className="btn-bx">
|
||||
{/* 임시저장 */}
|
||||
<button
|
||||
className="btn-frame n-blue icon"
|
||||
onClick={() => {
|
||||
setMode('TEMP')
|
||||
handleSave(true)
|
||||
}}
|
||||
>
|
||||
一時保存<i className="btn-arr"></i>
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ import { useServey } from '@/hooks/useSurvey'
|
||||
import { useParams, useSearchParams } from 'next/navigation'
|
||||
import { useEffect, useState } from 'react'
|
||||
import DetailForm from './DetailForm'
|
||||
import { SurveyBasicInfo } from '@/types/Survey'
|
||||
import type { SurveyBasicInfo } from '@/types/Survey'
|
||||
|
||||
export default function DataTable() {
|
||||
const params = useParams()
|
||||
@ -83,7 +83,7 @@ export default function DataTable() {
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<DetailForm surveyInfo={surveyDetail as SurveyBasicInfo} mode="READ" />
|
||||
<DetailForm />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,10 +1,13 @@
|
||||
'use client'
|
||||
|
||||
import { Mode, SurveyBasicInfo, SurveyBasicRequest, SurveyDetailRequest } from '@/types/Survey'
|
||||
import type { Mode, SurveyBasicInfo, SurveyBasicRequest, SurveyDetailRequest } from '@/types/Survey'
|
||||
import { useEffect, useState } from 'react'
|
||||
import ButtonForm from './ButtonForm'
|
||||
import BasicForm from './BasicForm'
|
||||
import RoofForm from './RoofForm'
|
||||
import { useParams, useSearchParams } from 'next/navigation'
|
||||
import { useServey } from '@/hooks/useSurvey'
|
||||
|
||||
const roofInfoForm: SurveyDetailRequest = {
|
||||
contractCapacity: null,
|
||||
retailCompany: null,
|
||||
@ -57,21 +60,32 @@ const basicInfoForm: SurveyBasicRequest = {
|
||||
submissionDate: null,
|
||||
}
|
||||
|
||||
export default function DetailForm(props: { surveyInfo?: SurveyBasicInfo; mode?: Mode }) {
|
||||
const [mode, setMode] = useState<Mode>(props.mode ?? 'CREATE')
|
||||
export default function DetailForm() {
|
||||
const idParam = useSearchParams().get('id')
|
||||
const routeId = useParams().id
|
||||
|
||||
const id = idParam ?? routeId
|
||||
|
||||
const { surveyDetail } = useServey(Number(id))
|
||||
|
||||
const [mode, setMode] = useState<Mode>(idParam ? 'EDIT' : routeId ? 'READ' : 'CREATE')
|
||||
const [basicInfoData, setBasicInfoData] = useState<SurveyBasicRequest>(basicInfoForm)
|
||||
const [roofInfoData, setRoofInfoData] = useState<SurveyDetailRequest>(roofInfoForm)
|
||||
|
||||
useEffect(() => {
|
||||
if (props.surveyInfo && (mode === 'EDIT' || mode === 'READ')) {
|
||||
const { id, uptDt, regDt, detailInfo, ...rest } = props.surveyInfo
|
||||
if (surveyDetail && (mode === 'EDIT' || mode === 'READ')) {
|
||||
const { id, uptDt, regDt, detailInfo, ...rest } = surveyDetail
|
||||
setBasicInfoData(rest)
|
||||
if (detailInfo) {
|
||||
const { id, uptDt, regDt, basicInfoId, ...rest } = detailInfo
|
||||
setRoofInfoData(rest)
|
||||
}
|
||||
}
|
||||
}, [props.surveyInfo, mode])
|
||||
}, [surveyDetail, mode])
|
||||
|
||||
// console.log('mode:: ', mode)
|
||||
// console.log('surveyDetail:: ', surveyDetail)
|
||||
// console.log('roofInfoData:: ', roofInfoData)
|
||||
|
||||
const data = {
|
||||
basic: basicInfoData,
|
||||
|
||||
@ -1,29 +0,0 @@
|
||||
import { Mode } from '@/types/Survey'
|
||||
import { useSearchParams } from 'next/navigation'
|
||||
import DetailForm from './DetailForm'
|
||||
import { useServey } from '@/hooks/useSurvey'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { SurveyBasicInfo } from '@/types/Survey'
|
||||
import { useSessionStore } from '@/store/session'
|
||||
|
||||
export default function RegistForm() {
|
||||
const searchParams = useSearchParams()
|
||||
const id = searchParams.get('id')
|
||||
|
||||
const { surveyDetail } = useServey(Number(id))
|
||||
const { session } = useSessionStore()
|
||||
|
||||
const [mode, setMode] = useState<Mode>('CREATE')
|
||||
|
||||
useEffect(() => {
|
||||
if (id) {
|
||||
setMode('EDIT')
|
||||
}
|
||||
}, [id])
|
||||
|
||||
return (
|
||||
<>
|
||||
<DetailForm mode={mode} surveyInfo={surveyDetail as SurveyBasicInfo} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
import { useState } from 'react'
|
||||
import { Mode, SurveyDetailInfo, SurveyDetailRequest } from '@/types/Survey'
|
||||
import type { Mode, SurveyDetailInfo, SurveyDetailRequest } from '@/types/Survey'
|
||||
|
||||
type RadioEtcKeys = 'houseStructure' | 'rafterMaterial' | 'waterproofMaterial' | 'insulationPresence' | 'rafterDirection' | 'leakTrace'
|
||||
type SelectBoxKeys =
|
||||
@ -12,14 +12,14 @@ type SelectBoxKeys =
|
||||
| 'structureOrder'
|
||||
| 'installationAvailability'
|
||||
|
||||
export const supplementary_facilities = [
|
||||
export const supplementaryFacilities = [
|
||||
{ id: 1, name: 'エコキュート' }, //에코큐트
|
||||
{ id: 2, name: 'エネパーム' }, //에네팜
|
||||
{ id: 3, name: '蓄電池システム' }, //축전지시스템
|
||||
{ id: 4, name: '太陽光発電' }, //태양광발전
|
||||
]
|
||||
|
||||
export const roof_material = [
|
||||
export const roofMaterial = [
|
||||
{ id: 1, name: 'スレート' }, //슬레이트
|
||||
{ id: 2, name: 'アスファルトシングル' }, //아스팔트 싱글
|
||||
{ id: 3, name: '瓦' }, //기와
|
||||
@ -200,19 +200,47 @@ export const radioEtcData: Record<RadioEtcKeys, { id: number; label: string }[]>
|
||||
],
|
||||
}
|
||||
|
||||
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 makeNumArr = (value: string) => {
|
||||
return value
|
||||
.split(',')
|
||||
.map((v) => v.trim())
|
||||
.filter((v) => v.length > 0)
|
||||
}
|
||||
const { roofInfo, setRoofInfo, mode } = props
|
||||
const [isFlip, setIsFlip] = useState<boolean>(true)
|
||||
|
||||
const handleNumberInput = (key: keyof SurveyDetailRequest, value: number | string) => {
|
||||
if (key === 'roofSlope' || key === 'openFieldPlateThickness') {
|
||||
const stringValue = value.toString()
|
||||
if (stringValue.length > 5) {
|
||||
alert('保存できるサイズを超えました。')
|
||||
return
|
||||
}
|
||||
if (stringValue.includes('.')) {
|
||||
const decimalPlaces = stringValue.split('.')[1].length
|
||||
if (decimalPlaces > 1) {
|
||||
alert('小数点以下1桁までしか許されません。')
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
setRoofInfo({ ...roofInfo, [key]: value.toString() })
|
||||
}
|
||||
|
||||
const handleUnitInput = (value: string) => {
|
||||
const numericValue = roofInfo.contractCapacity?.replace(/[^0-9.]/g, '') || ''
|
||||
setRoofInfo({
|
||||
...roofInfo,
|
||||
contractCapacity: numericValue ? `${numericValue} ${value}` : value,
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`sale-detail-toggle-bx ${isFlip ? 'act' : ''}`}>
|
||||
<div className="sale-detail-toggle-head" onClick={() => setIsFlip(!isFlip)}>
|
||||
@ -229,78 +257,55 @@ export default function RoofForm(props: {
|
||||
<div className="data-input-form-bx">
|
||||
{/* 전기 계약 용량 */}
|
||||
<div className="data-input-form-tit">電気契約容量</div>
|
||||
<div className="data-input mb5">
|
||||
<input type="text" className="input-frame" value={roofInfo?.contractCapacity ?? ''} readOnly={mode === 'READ'} />
|
||||
</div>
|
||||
{mode === 'READ' && <input type="text" className="input-frame" defaultValue={'10'} readOnly={mode === 'READ'} />}
|
||||
{mode === 'READ' && <input type="text" className="input-frame" value={roofInfo?.contractCapacity ?? ''} disabled={mode === 'READ'} />}
|
||||
{mode !== 'READ' && (
|
||||
<div className="data-input">
|
||||
<select className="select-form" name="" id="">
|
||||
<option value="">kVA</option>
|
||||
<option value="">kVA</option>
|
||||
<option value="">kVA</option>
|
||||
<option value="">kVA</option>
|
||||
<option value="">kVA</option>
|
||||
</select>
|
||||
<div className="data-input mb5">
|
||||
<input
|
||||
type="text"
|
||||
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 ?? ''} readOnly={mode === 'READ'} />
|
||||
<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>
|
||||
<div className="data-check-wrap">
|
||||
{/* <div className="check-form-box">
|
||||
<input type="checkbox" id="ch01" readOnly={mode === 'READ'} />
|
||||
<label htmlFor="ch01">エコキュート</label>
|
||||
</div> */}
|
||||
{supplementary_facilities.map((item) => (
|
||||
<div className="check-form-box" key={item.id}>
|
||||
<input
|
||||
type="checkbox"
|
||||
id={`${item.id}`}
|
||||
checked={makeNumArr(roofInfo?.supplementaryFacilities ?? '').includes(String(item.id))}
|
||||
readOnly={mode === 'READ'}
|
||||
/>
|
||||
<label htmlFor={`${item.id}`}>{item.name}</label>
|
||||
</div>
|
||||
))}
|
||||
<div className="check-form-box">
|
||||
<input type="checkbox" id={`supplementaryFacilitiesEtc`} checked={roofInfo?.supplementaryFacilitiesEtc !== null} readOnly />
|
||||
<label htmlFor={`supplementaryFacilitiesEtc`}>その他 (直接入力)</label>
|
||||
</div>
|
||||
</div>
|
||||
<div className="data-input">
|
||||
<input type="text" className="input-frame" placeholder="-" readOnly value={roofInfo?.supplementaryFacilitiesEtc ?? ''} />
|
||||
</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>
|
||||
{mode === 'READ' && (
|
||||
<div className="data-input">
|
||||
<input type="text" className="input-frame" defaultValue={''} disabled />
|
||||
</div>
|
||||
)}
|
||||
{mode !== 'READ' && (
|
||||
<div className="data-input mb5">
|
||||
<select className="select-form" name="" id="">
|
||||
<option value="">太陽光発電</option>
|
||||
<option value="">太陽光発電</option>
|
||||
<option value="">太陽光発電</option>
|
||||
<option value="">太陽光発電</option>
|
||||
<option value="">太陽光発電</option>
|
||||
</select>
|
||||
</div>
|
||||
)} */}
|
||||
<div className="data-input-form-tit">設置希望システム</div>
|
||||
<SelectedBox column="installationSystem" detailInfoData={roofInfo as SurveyDetailInfo} />
|
||||
<div className="data-input-form-tit red-f">設置希望システム</div>
|
||||
<SelectedBox mode={mode} column="installationSystem" detailInfoData={roofInfo as SurveyDetailInfo} setRoofInfo={setRoofInfo} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -312,108 +317,73 @@ export default function RoofForm(props: {
|
||||
{/* 건축 연수 */}
|
||||
<div className="data-input-form-tit red-f">建築研修</div>
|
||||
<div className="data-input mb5">
|
||||
{/* {mode === 'READ' && <input type="text" className="input-frame" defaultValue={''} disabled />}
|
||||
{mode !== 'READ' && (
|
||||
<select className="select-form" name="" id="">
|
||||
<option value="">新築</option>
|
||||
<option value="">新築</option>
|
||||
<option value="">新築</option>
|
||||
<option value="">新築</option>
|
||||
<option value="">新築</option>
|
||||
</select>
|
||||
)} */}
|
||||
<SelectedBox column="constructionYear" detailInfoData={roofInfo as SurveyDetailInfo} />
|
||||
<SelectedBox mode={mode} column="constructionYear" detailInfoData={roofInfo as SurveyDetailInfo} setRoofInfo={setRoofInfo} />
|
||||
</div>
|
||||
{/* <div className="data-input flex">
|
||||
<input type="text" className="input-frame" defaultValue={''} disabled />
|
||||
<span>年</span>
|
||||
</div> */}
|
||||
</div>
|
||||
<div className="data-input-form-bx">
|
||||
{/* 지붕재 */}
|
||||
<div className="data-input-form-tit">
|
||||
屋根材<span>※最大2個まで選択可能</span>
|
||||
</div>
|
||||
<div className="data-check-wrap">
|
||||
{roof_material.map((item) => (
|
||||
<div className="check-form-box" key={item.id}>
|
||||
<input type="checkbox" id={`${item.id}`} checked={makeNumArr(roofInfo?.roofMaterial ?? '').includes(String(item.id))} readOnly />
|
||||
<label htmlFor={`${item.id}`}>{item.name}</label>
|
||||
</div>
|
||||
))}
|
||||
<div className="check-form-box">
|
||||
<input type="checkbox" id={`roofMaterialEtc`} checked={roofInfo?.roofMaterialEtc !== null} readOnly />
|
||||
<label htmlFor={`roofMaterialEtc`}>その他 (直接入力)</label>
|
||||
</div>
|
||||
</div>
|
||||
<div className="data-input">
|
||||
<input type="text" className="input-frame" placeholder="-" readOnly value={roofInfo?.roofMaterialEtc ?? ''} />
|
||||
</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-form-tit">屋根の形状</div>
|
||||
<div className="data-input mb5">
|
||||
{/* {mode === 'READ' && <input type="text" className="input-frame" defaultValue={''} disabled />}
|
||||
{mode !== 'READ' && (
|
||||
<select className="select-form" name="" id="">
|
||||
<option value="">太陽光発電</option>
|
||||
<option value="">太陽光発電</option>
|
||||
<option value="">太陽光発電</option>
|
||||
<option value="">太陽光発電</option>
|
||||
<option value="">太陽光発電</option>
|
||||
</select>
|
||||
)} */}
|
||||
<SelectedBox column="roofShape" detailInfoData={roofInfo as SurveyDetailInfo} />
|
||||
</div>
|
||||
<div className="data-input">
|
||||
<input type="text" className="input-frame" defaultValue={''} disabled />
|
||||
<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="text" className="input-frame" value={roofInfo?.roofSlope ?? ''} readOnly={mode === 'READ'} />
|
||||
<input
|
||||
type="number"
|
||||
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 column="houseStructure" detailInfoData={roofInfo as SurveyDetailInfo} />
|
||||
<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 column="rafterMaterial" detailInfoData={roofInfo as SurveyDetailInfo} />
|
||||
<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 column="rafterSize" detailInfoData={roofInfo as SurveyDetailInfo} />
|
||||
<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 column="rafterPitch" detailInfoData={roofInfo as SurveyDetailInfo} />
|
||||
<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 column="rafterDirection" detailInfoData={roofInfo as SurveyDetailInfo} />
|
||||
<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 column="openFieldPlateKind" detailInfoData={roofInfo as SurveyDetailInfo} />
|
||||
<SelectedBox mode={mode} column="openFieldPlateKind" detailInfoData={roofInfo as SurveyDetailInfo} setRoofInfo={setRoofInfo} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="data-input-form-bx">
|
||||
@ -422,7 +392,13 @@ export default function RoofForm(props: {
|
||||
路地板厚<span>※小幅板を選択した場合, 厚さ. 小幅板間の間隔寸法を記載</span>
|
||||
</div>
|
||||
<div className="data-input flex">
|
||||
<input type="text" className="input-frame" value={roofInfo?.openFieldPlateThickness ?? ''} readOnly={mode === 'READ'} />
|
||||
<input
|
||||
type="text"
|
||||
className="input-frame"
|
||||
value={roofInfo?.openFieldPlateThickness ?? ''}
|
||||
disabled={mode === 'READ'}
|
||||
onChange={(e) => handleNumberInput('openFieldPlateThickness', e.target.value)}
|
||||
/>
|
||||
<span>mm</span>
|
||||
</div>
|
||||
</div>
|
||||
@ -430,28 +406,28 @@ export default function RoofForm(props: {
|
||||
{/* 누수 흔적 */}
|
||||
<div className="data-input-form-tit ">水漏れの痕跡</div>
|
||||
<div className="data-check-wrap mb0">
|
||||
<RadioSelected column="leakTrace" detailInfoData={roofInfo as SurveyDetailInfo} />
|
||||
<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 column="waterproofMaterial" detailInfoData={roofInfo as SurveyDetailInfo} />
|
||||
<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 column="insulationPresence" detailInfoData={roofInfo as SurveyDetailInfo} />
|
||||
<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>
|
||||
<SelectedBox column="structureOrder" detailInfoData={roofInfo as SurveyDetailInfo} />
|
||||
<SelectedBox 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 column="installationAvailability" detailInfoData={roofInfo as SurveyDetailInfo} />
|
||||
<SelectedBox mode={mode} column="installationAvailability" detailInfoData={roofInfo as SurveyDetailInfo} setRoofInfo={setRoofInfo} />
|
||||
</div>
|
||||
<div className="data-input-form-bx">
|
||||
{/* 메모 */}
|
||||
@ -459,11 +435,12 @@ export default function RoofForm(props: {
|
||||
<div className="data-input">
|
||||
<textarea
|
||||
className="textarea-form"
|
||||
name=""
|
||||
id=""
|
||||
name="memo"
|
||||
id="memo"
|
||||
placeholder="TextArea Filed"
|
||||
value={roofInfo?.memo ?? ''}
|
||||
readOnly={mode === 'READ'}
|
||||
disabled={mode === 'READ'}
|
||||
onChange={(e) => setRoofInfo({ ...roofInfo, memo: e.target.value })}
|
||||
></textarea>
|
||||
</div>
|
||||
</div>
|
||||
@ -474,23 +451,107 @@ export default function RoofForm(props: {
|
||||
)
|
||||
}
|
||||
|
||||
const SelectedBox = ({ column, detailInfoData }: { column: string; detailInfoData: SurveyDetailInfo }) => {
|
||||
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>(etcValue !== null && etcValue !== undefined && etcValue !== '')
|
||||
const [etcVal, setEtcVal] = useState<string>(etcValue?.toString() ?? '')
|
||||
|
||||
const handleSelectChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
|
||||
const value = e.target.value
|
||||
const isSpecialCase = column === 'constructionYear' || column === 'installationAvailability'
|
||||
const isEtc = value === 'etc'
|
||||
const isSpecialEtc = isSpecialCase && value === '2'
|
||||
|
||||
const updatedData: typeof detailInfoData = {
|
||||
...detailInfoData,
|
||||
[column]: isEtc ? null : value,
|
||||
[`${column}Etc`]: isEtc ? '' : null,
|
||||
}
|
||||
|
||||
if (isSpecialEtc) {
|
||||
updatedData[column] = value
|
||||
}
|
||||
|
||||
setIsEtcSelected(isEtc || isSpecialEtc)
|
||||
if (!isEtc) setEtcVal('')
|
||||
setRoofInfo(updatedData)
|
||||
}
|
||||
|
||||
const handleEtcInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = e.target.value
|
||||
setEtcVal(value)
|
||||
setRoofInfo({ ...detailInfoData, [`${column}Etc`]: value })
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<select className="select-form mb10" name={column} id={column} disabled value={selectedId ? 'selected' : etcValue ? 'etc' : ''}>
|
||||
<option value="">-</option>
|
||||
<option value="etc">その他 (直接入力)</option>
|
||||
<option value="selected">{selectBoxOptions[column as keyof typeof selectBoxOptions][Number(selectedId)]?.name}</option>
|
||||
<select
|
||||
className="select-form mb10"
|
||||
name={column}
|
||||
id={column}
|
||||
disabled={mode === 'READ'}
|
||||
value={selectedId ? Number(selectedId) : etcValue !== null ? 'etc' : ''}
|
||||
onChange={handleSelectChange}
|
||||
>
|
||||
{selectBoxOptions[column as keyof typeof selectBoxOptions].map((item) => (
|
||||
<option key={item.id} value={item.id}>
|
||||
{item.name}
|
||||
</option>
|
||||
))}
|
||||
{column !== 'installationAvailability' && column !== 'constructionYear' && (
|
||||
<option key="etc" value="etc">
|
||||
その他 (直接入力)
|
||||
</option>
|
||||
)}
|
||||
<option key="" value="" hidden>
|
||||
選択してください
|
||||
</option>
|
||||
</select>
|
||||
{etcValue && <input type="text" className="input-frame" readOnly value={etcValue.toString()} />}
|
||||
<div className="data-input">
|
||||
<input
|
||||
type="text"
|
||||
className="input-frame"
|
||||
placeholder="-"
|
||||
value={etcVal}
|
||||
onChange={handleEtcInputChange}
|
||||
disabled={
|
||||
mode === 'READ'
|
||||
? true
|
||||
: column === 'installationAvailability'
|
||||
? false
|
||||
: column === 'constructionYear'
|
||||
? detailInfoData.constructionYear === '1' || detailInfoData.constructionYear === null
|
||||
: !isEtcSelected
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const RadioSelected = ({ column, detailInfoData }: { column: string; detailInfoData: SurveyDetailInfo | null }) => {
|
||||
const RadioSelected = ({
|
||||
mode,
|
||||
column,
|
||||
detailInfoData,
|
||||
setRoofInfo,
|
||||
}: {
|
||||
mode: Mode
|
||||
column: string
|
||||
detailInfoData: SurveyDetailInfo
|
||||
setRoofInfo: (roofInfo: SurveyDetailRequest) => void
|
||||
}) => {
|
||||
let selectedId = detailInfoData?.[column as keyof SurveyDetailInfo]
|
||||
if (column === 'leakTrace') {
|
||||
selectedId = Number(selectedId)
|
||||
@ -501,28 +562,182 @@ const RadioSelected = ({ column, detailInfoData }: { column: string; detailInfoD
|
||||
if (column !== 'rafterDirection') {
|
||||
etcValue = detailInfoData?.[`${column}Etc` as keyof SurveyDetailInfo]
|
||||
}
|
||||
const etcChecked = etcValue !== null && etcValue !== undefined && etcValue !== ''
|
||||
const [etcChecked, setEtcChecked] = useState<boolean>(etcValue !== null && etcValue !== undefined && etcValue !== '')
|
||||
const [etcVal, setEtcVal] = useState<string>(etcValue?.toString() ?? '')
|
||||
|
||||
const handleRadioChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = e.target.value
|
||||
if (column === 'leakTrace') {
|
||||
handleBooleanRadioChange(value)
|
||||
}
|
||||
if (value === 'etc') {
|
||||
setEtcChecked(true)
|
||||
setRoofInfo({ ...detailInfoData, [column]: null, [`${column}Etc`]: '' })
|
||||
} else {
|
||||
if (column === 'insulationPresence' && value === '2') {
|
||||
setEtcChecked(true)
|
||||
} else {
|
||||
setEtcChecked(false)
|
||||
}
|
||||
setRoofInfo({ ...detailInfoData, [column]: value, [`${column}Etc`]: null })
|
||||
}
|
||||
}
|
||||
|
||||
const handleBooleanRadioChange = (value: string) => {
|
||||
if (value === '1') {
|
||||
setRoofInfo({ ...detailInfoData, leakTrace: true })
|
||||
} else {
|
||||
setRoofInfo({ ...detailInfoData, leakTrace: false })
|
||||
}
|
||||
}
|
||||
|
||||
const handleEtcInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = e.target.value
|
||||
setEtcVal(value)
|
||||
setRoofInfo({ ...detailInfoData, [`${column}Etc`]: value })
|
||||
}
|
||||
|
||||
// console.log('column: selectedId', column, selectedId)
|
||||
return (
|
||||
<>
|
||||
{radioEtcData[column as keyof typeof radioEtcData].map((item) => (
|
||||
<div className="radio-form-box mb10" key={item.id}>
|
||||
<input type="radio" name={column} id={`${item.id}`} disabled checked={Number(selectedId) === item.id} />
|
||||
<label htmlFor={`${item.id}`}>{item.label}</label>
|
||||
<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>
|
||||
))}
|
||||
{column !== 'rafterDirection' && column !== 'leakTrace' && column !== 'insulationPresence' && (
|
||||
<div className="radio-form-box mb10">
|
||||
<input type="radio" name={column} id={`${column}Etc`} value="etc" disabled checked={etcChecked} />
|
||||
<input
|
||||
type="radio"
|
||||
name={column}
|
||||
id={`${column}Etc`}
|
||||
value="etc"
|
||||
disabled={mode === 'READ'}
|
||||
checked={etcChecked}
|
||||
onChange={handleRadioChange}
|
||||
/>
|
||||
<label htmlFor={`${column}Etc`}>その他 (直接入力)</label>
|
||||
</div>
|
||||
)}
|
||||
{etcChecked && (
|
||||
{column !== 'leakTrace' && column !== 'rafterDirection' && (
|
||||
<div className="data-input">
|
||||
<input type="text" className="input-frame" placeholder="-" readOnly value={etcValue?.toString() ?? ''} />
|
||||
<input
|
||||
type="text"
|
||||
className="input-frame"
|
||||
placeholder="-"
|
||||
value={etcVal}
|
||||
onChange={handleEtcInputChange}
|
||||
disabled={mode === 'READ' || !etcChecked}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const MultiCheck = ({
|
||||
mode,
|
||||
column,
|
||||
roofInfo,
|
||||
setRoofInfo,
|
||||
}: {
|
||||
mode: Mode
|
||||
column: string
|
||||
roofInfo: SurveyDetailInfo
|
||||
setRoofInfo: (roofInfo: SurveyDetailRequest) => void
|
||||
}) => {
|
||||
const multiCheckData = column === 'supplementaryFacilities' ? supplementaryFacilities : roofMaterial
|
||||
|
||||
const [isOtherCheck, setIsOtherCheck] = useState<boolean>(false)
|
||||
const [otherValue, setOtherValue] = useState<string>(roofInfo?.[`${column}Etc` as keyof SurveyDetailInfo]?.toString() ?? '')
|
||||
|
||||
const handleCheckbox = (id: number) => {
|
||||
const value = makeNumArr(String(roofInfo[column as keyof SurveyDetailInfo] ?? ''))
|
||||
const isOtherSelected = roofInfo?.[`${column}Etc` as keyof SurveyDetailInfo] !== null
|
||||
|
||||
let newValue: string[]
|
||||
if (value.includes(String(id))) {
|
||||
newValue = value.filter((v) => v !== String(id))
|
||||
} else {
|
||||
if (column === 'roofMaterial') {
|
||||
const totalSelected = value.length + (isOtherSelected ? 1 : 0)
|
||||
|
||||
if (totalSelected >= 2) {
|
||||
alert('屋根材は最大2個まで選択できます。')
|
||||
return
|
||||
}
|
||||
}
|
||||
newValue = [...value, String(id)]
|
||||
}
|
||||
setRoofInfo({ ...roofInfo, [column]: newValue.join(',') })
|
||||
}
|
||||
|
||||
const handleOtherCheckbox = () => {
|
||||
if (column === 'roofMaterial') {
|
||||
const value = makeNumArr(String(roofInfo[column as keyof SurveyDetailInfo] ?? ''))
|
||||
const currentSelected = value.length
|
||||
if (!isOtherCheck && currentSelected >= 2) {
|
||||
alert('屋根材は最大2個まで選択できます。')
|
||||
return
|
||||
}
|
||||
}
|
||||
const newIsOtherCheck = !isOtherCheck
|
||||
setIsOtherCheck(newIsOtherCheck)
|
||||
setOtherValue('')
|
||||
|
||||
setRoofInfo({ ...roofInfo, [`${column}Etc`]: newIsOtherCheck ? '' : null })
|
||||
}
|
||||
|
||||
const handleOtherInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = e.target.value
|
||||
setOtherValue(value)
|
||||
setRoofInfo({ ...roofInfo, [`${column}Etc`]: value })
|
||||
}
|
||||
|
||||
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={makeNumArr(String(roofInfo[column as keyof SurveyDetailInfo] ?? '')).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={roofInfo?.[`${column}Etc` as keyof SurveyDetailInfo] !== null}
|
||||
disabled={mode === 'READ'}
|
||||
onChange={handleOtherCheckbox}
|
||||
/>
|
||||
<label htmlFor={`${column}Etc`}>その他 (直接入力)</label>
|
||||
</div>
|
||||
</div>
|
||||
<div className="data-input">
|
||||
<input
|
||||
type="text"
|
||||
className="input-frame"
|
||||
placeholder="-"
|
||||
value={otherValue}
|
||||
onChange={handleOtherInputChange}
|
||||
disabled={mode === 'READ' || !isOtherCheck}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ import { useRouter } from 'next/navigation'
|
||||
import SearchForm from './SearchForm'
|
||||
import { useSurveyFilterStore } from '@/store/surveyFilterStore'
|
||||
import { useSessionStore } from '@/store/session'
|
||||
import { SurveyBasicInfo } from '@/types/Survey'
|
||||
import type { SurveyBasicInfo } from '@/types/Survey'
|
||||
|
||||
export default function ListTable() {
|
||||
const router = useRouter()
|
||||
|
||||
@ -17,7 +17,6 @@ export default function SearchForm({ memberRole, userId }: { memberRole: string;
|
||||
}
|
||||
setKeyword(searchKeyword)
|
||||
setSearchOption(option)
|
||||
// onItemsInit()
|
||||
}
|
||||
const searchOptions = memberRole === 'Partner' ? SEARCH_OPTIONS_PARTNERS : SEARCH_OPTIONS
|
||||
|
||||
@ -38,7 +37,6 @@ export default function SearchForm({ memberRole, userId }: { memberRole: string;
|
||||
if (e.target.value === 'all') {
|
||||
setKeyword('')
|
||||
setSearchKeyword('')
|
||||
// onItemsInit()
|
||||
setSearchOption('all')
|
||||
setOption('all')
|
||||
} else {
|
||||
@ -80,7 +78,6 @@ export default function SearchForm({ memberRole, userId }: { memberRole: string;
|
||||
checked={isMySurvey === userId}
|
||||
onChange={() => {
|
||||
setIsMySurvey(isMySurvey === userId ? null : userId)
|
||||
// onItemsInit()
|
||||
}}
|
||||
/>
|
||||
<label htmlFor="ch01">私が書いた物件</label>
|
||||
@ -94,7 +91,6 @@ export default function SearchForm({ memberRole, userId }: { memberRole: string;
|
||||
value={sort}
|
||||
onChange={(e) => {
|
||||
setSort(e.target.value as 'created' | 'updated')
|
||||
// onItemsInit()
|
||||
}}
|
||||
>
|
||||
<option value="created">最近の登録日</option>
|
||||
|
||||
@ -7,7 +7,7 @@ import { useSessionStore } from '@/store/session'
|
||||
import { useMemo } from 'react'
|
||||
import { AxiosResponse } from 'axios'
|
||||
|
||||
const requiredFields = [
|
||||
export const requiredFields = [
|
||||
{
|
||||
field: 'installationSystem',
|
||||
name: '設置希望システム',
|
||||
@ -67,7 +67,7 @@ export function useServey(id?: number): {
|
||||
createSurveyDetail: (params: { surveyId: number; surveyDetail: SurveyDetailCoverRequest }) => void
|
||||
updateSurvey: (survey: SurveyRegistRequest) => void
|
||||
deleteSurvey: () => Promise<boolean>
|
||||
submitSurvey: () => void
|
||||
submitSurvey: (saveId?: number) => void
|
||||
validateSurveyDetail: (surveyDetail: SurveyDetailRequest) => string
|
||||
getZipCode: (zipCode: string) => Promise<ZipCode[] | null>
|
||||
refetchSurveyList: () => void
|
||||
@ -77,7 +77,7 @@ export function useServey(id?: number): {
|
||||
const { session } = useSessionStore()
|
||||
|
||||
const {
|
||||
data,
|
||||
data: surveyListData,
|
||||
isLoading: isLoadingSurveyList,
|
||||
refetch: refetchSurveyList,
|
||||
} = useQuery({
|
||||
@ -100,18 +100,17 @@ export function useServey(id?: number): {
|
||||
enabled: session?.isLoggedIn,
|
||||
})
|
||||
const surveyData = useMemo(() => {
|
||||
if (!data) return {}
|
||||
if (!surveyListData) return { count: 0, data: [] }
|
||||
return {
|
||||
data: data.data,
|
||||
count: data.count,
|
||||
...surveyListData,
|
||||
}
|
||||
}, [data])
|
||||
}, [surveyListData])
|
||||
|
||||
const { data: surveyDetail, isLoading: isLoadingSurveyDetail } = useQuery({
|
||||
queryKey: ['survey', id],
|
||||
queryFn: async () => {
|
||||
if (id === undefined) throw new Error('id is required')
|
||||
if (id === null) return null
|
||||
if (id === null || isNaN(id)) return null
|
||||
const resp = await axiosInstance(null).get<SurveyBasicInfo>(`/api/survey-sales/${id}`)
|
||||
return resp.data
|
||||
},
|
||||
@ -132,6 +131,7 @@ export function useServey(id?: number): {
|
||||
|
||||
const { mutate: updateSurvey, isPending: isUpdatingSurvey } = useMutation({
|
||||
mutationFn: async (survey: SurveyRegistRequest) => {
|
||||
console.log('updateSurvey, survey:: ', survey)
|
||||
if (id === undefined) throw new Error('id is required')
|
||||
const resp = await axiosInstance(null).put<SurveyRegistRequest>(`/api/survey-sales/${id}`, survey)
|
||||
return resp.data
|
||||
@ -166,9 +166,10 @@ export function useServey(id?: number): {
|
||||
})
|
||||
|
||||
const { mutateAsync: submitSurvey } = useMutation({
|
||||
mutationFn: async () => {
|
||||
if (id === undefined) throw new Error('id is required')
|
||||
const resp = await axiosInstance(null).patch<boolean>(`/api/survey-sales/${id}`, {
|
||||
mutationFn: async (saveId?: number) => {
|
||||
const submitId = saveId ?? id
|
||||
if (!submitId) throw new Error('id is required')
|
||||
const resp = await axiosInstance(null).patch<boolean>(`/api/survey-sales/${submitId}`, {
|
||||
submit: true,
|
||||
})
|
||||
return resp.data
|
||||
@ -180,12 +181,22 @@ export function useServey(id?: number): {
|
||||
})
|
||||
|
||||
const validateSurveyDetail = (surveyDetail: SurveyDetailRequest) => {
|
||||
const etcFields = ['installationSystem', 'constructionYear', 'rafterSize', 'rafterPitch', 'waterproofMaterial', 'structureOrder'] as const
|
||||
const etcFields = [
|
||||
'installationSystem',
|
||||
'constructionYear',
|
||||
'rafterSize',
|
||||
'rafterPitch',
|
||||
'waterproofMaterial',
|
||||
'structureOrder',
|
||||
'insulationPresence',
|
||||
] as const
|
||||
|
||||
const emptyField = requiredFields.find((field) => {
|
||||
if (etcFields.includes(field.field as (typeof etcFields)[number])) {
|
||||
return (
|
||||
surveyDetail[field.field as keyof SurveyDetailRequest] === null && surveyDetail[`${field.field}_ETC` as keyof SurveyDetailRequest] === ''
|
||||
surveyDetail[field.field as keyof SurveyDetailRequest] === null &&
|
||||
(surveyDetail[`${field.field}Etc` as keyof SurveyDetailRequest] === null ||
|
||||
surveyDetail[`${field.field}Etc` as keyof SurveyDetailRequest]?.toString().trim() === '')
|
||||
)
|
||||
} else {
|
||||
return surveyDetail[field.field as keyof SurveyDetailRequest] === null
|
||||
@ -197,7 +208,7 @@ export function useServey(id?: number): {
|
||||
return 'contractCapacityUnit'
|
||||
}
|
||||
|
||||
return emptyField?.name || ''
|
||||
return emptyField?.field || ''
|
||||
}
|
||||
|
||||
const getZipCode = async (zipCode: string): Promise<ZipCode[] | null> => {
|
||||
@ -213,7 +224,7 @@ export function useServey(id?: number): {
|
||||
}
|
||||
|
||||
return {
|
||||
surveyList: surveyData,
|
||||
surveyList: surveyData.data,
|
||||
surveyDetail: surveyDetail as SurveyBasicInfo | null,
|
||||
isLoadingSurveyList,
|
||||
isLoadingSurveyDetail,
|
||||
|
||||
@ -84,10 +84,6 @@ const transformObjectKeys = (obj: any): any => {
|
||||
return obj
|
||||
}
|
||||
|
||||
export const camelToSnake = (str: string): string => {
|
||||
return str.replace(/([A-Z])/g, (group) => `_${group.toLowerCase()}`)
|
||||
}
|
||||
|
||||
const snakeToCamel = (str: string): string => {
|
||||
return str.toLowerCase().replace(/([-_][a-z])/g, (group) => group.toUpperCase().replace('-', '').replace('_', ''))
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user