onsitesurvey/src/hooks/useSurvey.ts
keyy1315 35b1002908 feat: add submit popup page
- 제출 팝업 페이지 추가
- 조사매물 작성 시 숫자 입력 항목 모바일에서 숫자 키패드만 나오도록 설정
- 제출 필수값 validation 구현
2025-05-27 09:08:45 +09:00

243 lines
7.6 KiB
TypeScript

import type { SurveyBasicInfo, SurveyDetailRequest, SurveyRegistRequest } from '@/types/Survey'
import { useMemo } from 'react'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { useSurveyFilterStore } from '@/store/surveyFilterStore'
import { useSessionStore } from '@/store/session'
import { useAxios } from './useAxios'
import { queryStringFormatter } from '@/utils/common-utils'
export const requiredFields = [
{
field: 'installationSystem',
name: '設置希望システム',
},
{
field: 'constructionYear',
name: '建築年数',
},
{
field: 'rafterSize',
name: '垂木サイズ',
},
{
field: 'rafterPitch',
name: '垂木傾斜',
},
{
field: 'waterproofMaterial',
name: '防水材',
},
{
field: 'insulationPresence',
name: '断熱材有無',
},
{
field: 'structureOrder',
name: '屋根構造の順序',
},
]
interface ZipCodeResponse {
status: number
message: string | null
results: ZipCode[] | null
}
type ZipCode = {
zipcode: string
prefcode: string
address1: string
address2: string
address3: string
kana1: string
kana2: string
kana3: string
}
export function useServey(id?: number): {
surveyList: { data: SurveyBasicInfo[]; count: number } | {}
surveyDetail: SurveyBasicInfo | null
isLoadingSurveyList: boolean
isLoadingSurveyDetail: boolean
isCreatingSurvey: boolean
isUpdatingSurvey: boolean
isDeletingSurvey: boolean
isSubmittingSurvey: boolean
createSurvey: (survey: SurveyRegistRequest) => Promise<number>
updateSurvey: ({ survey, isTemporary, storeId }: { survey: SurveyRegistRequest; isTemporary: boolean; storeId?: string }) => void
deleteSurvey: () => Promise<boolean>
submitSurvey: (params: { saveId?: number; targetId?: string; storeId?: string; srlNo?: string }) => void
validateSurveyDetail: (surveyDetail: SurveyDetailRequest) => string
getZipCode: (zipCode: string) => Promise<ZipCode[] | null>
refetchSurveyList: () => void
} {
const queryClient = useQueryClient()
const { keyword, searchOption, isMySurvey, sort, offset } = useSurveyFilterStore()
const { session } = useSessionStore()
const { axiosInstance } = useAxios()
const {
data: surveyListData,
isLoading: isLoadingSurveyList,
refetch: refetchSurveyList,
} = useQuery({
queryKey: ['survey', 'list', keyword, searchOption, isMySurvey, sort, offset, session?.storeNm, session?.builderNo, session?.role],
queryFn: async () => {
const resp = await axiosInstance(null).get<{ data: SurveyBasicInfo[]; count: number }>('/api/survey-sales', {
params: {
keyword,
searchOption,
isMySurvey,
sort,
offset,
store: session?.storeId,
builderNo: session?.builderNo,
role: session?.role,
},
})
return resp.data
},
enabled: session?.isLoggedIn,
})
const surveyData = useMemo(() => {
if (!surveyListData) return { count: 0, data: [] }
return {
...surveyListData,
}
}, [surveyListData])
const { data: surveyDetail, isLoading: isLoadingSurveyDetail } = useQuery({
queryKey: ['survey', id],
queryFn: async () => {
if (id === undefined) throw new Error('id is required')
if (id === null || isNaN(id)) return null
const resp = await axiosInstance(null).get<SurveyBasicInfo>(`/api/survey-sales/${id}`)
return resp.data
},
enabled: id !== undefined,
})
const { mutateAsync: createSurvey, isPending: isCreatingSurvey } = useMutation({
mutationFn: async (survey: SurveyRegistRequest) => {
const resp = await axiosInstance(null).post<SurveyBasicInfo>('/api/survey-sales', {
survey: survey,
storeId: session?.storeId ?? null,
role: session?.role ?? null,
})
return resp.data.id ?? 0
},
onSuccess: (data) => {
queryClient.invalidateQueries({ queryKey: ['survey', 'list'] })
queryClient.invalidateQueries({ queryKey: ['survey', id] })
return data
},
})
const { mutate: updateSurvey, isPending: isUpdatingSurvey } = useMutation({
mutationFn: async ({ survey, isTemporary, storeId }: { survey: SurveyRegistRequest; isTemporary: boolean; storeId?: string }) => {
if (id === undefined) throw new Error('id is required')
const resp = await axiosInstance(null).put<SurveyRegistRequest>(`/api/survey-sales/${id}`, {
survey: survey,
isTemporary: isTemporary,
storeId: storeId,
role: session?.role ?? null,
})
return resp.data
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['survey', id] })
queryClient.invalidateQueries({ queryKey: ['survey', 'list'] })
},
})
const { mutateAsync: deleteSurvey, isPending: isDeletingSurvey } = useMutation({
mutationFn: async () => {
if (id === null) throw new Error('id is required')
const resp = await axiosInstance(null).delete<boolean>(`/api/survey-sales/${id}`)
return resp.data
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['survey', 'list'] })
queryClient.invalidateQueries({ queryKey: ['survey', id] })
},
})
const { mutateAsync: submitSurvey, isPending: isSubmittingSurvey } = useMutation({
mutationFn: async ({ targetId, storeId, srlNo }: { targetId?: string; storeId?: string; srlNo?: string }) => {
if (!id) throw new Error('id is required')
const resp = await axiosInstance(null).patch<boolean>(`/api/survey-sales/${id}`, {
targetId,
storeId,
srlNo,
role: session?.role ?? null,
})
return resp.data
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['survey', 'list'] })
queryClient.invalidateQueries({ queryKey: ['survey', id] })
},
})
const validateSurveyDetail = (surveyDetail: SurveyDetailRequest) => {
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] === null ||
surveyDetail[`${field.field}Etc` as keyof SurveyDetailRequest]?.toString().trim() === '')
)
} else {
return surveyDetail[field.field as keyof SurveyDetailRequest] === null
}
})
const contractCapacity = surveyDetail.contractCapacity
if (contractCapacity && contractCapacity.trim() !== '' && contractCapacity.split(' ')?.length === 1) {
return 'contractCapacityUnit'
}
return emptyField?.field || ''
}
const getZipCode = async (zipCode: string): Promise<ZipCode[] | null> => {
try {
const { data } = await axiosInstance(null).get<ZipCodeResponse>(
`https://zipcloud.ibsnet.co.jp/api/search?${queryStringFormatter({ zipcode: zipCode.trim() })}`,
)
return data.results
} catch (e) {
console.error('Failed to fetch zipcode data:', e)
throw new Error('Failed to fetch zipcode data')
}
}
return {
surveyList: surveyData.data,
surveyDetail: surveyDetail as SurveyBasicInfo | null,
isLoadingSurveyList,
isLoadingSurveyDetail,
isCreatingSurvey,
isUpdatingSurvey,
isDeletingSurvey,
isSubmittingSurvey,
createSurvey,
updateSurvey,
deleteSurvey,
submitSurvey,
validateSurveyDetail,
getZipCode,
refetchSurveyList,
}
}