243 lines
7.6 KiB
TypeScript
243 lines
7.6 KiB
TypeScript
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
|
import type {
|
|
SurveyBasicInfo,
|
|
SurveyDetailInfo,
|
|
SurveyDetailRequest,
|
|
SurveyDetailCoverRequest,
|
|
SurveyRegistRequest,
|
|
} from '@/types/Survey'
|
|
import { axiosInstance } from '@/libs/axios'
|
|
import { useSurveyFilterStore } from '@/store/surveyFilterStore'
|
|
import { queryStringFormatter } from '@/utils/common-utils'
|
|
import { useSessionStore } from '@/store/session'
|
|
|
|
const requiredFields = [
|
|
{
|
|
field: 'INSTALLATION_SYSTEM',
|
|
name: '設置希望システム',
|
|
},
|
|
{
|
|
field: 'CONSTRUCTION_YEAR',
|
|
name: '建築年数',
|
|
},
|
|
{
|
|
field: 'RAFTER_SIZE',
|
|
name: '垂木サイズ',
|
|
},
|
|
{
|
|
field: 'RAFTER_PITCH',
|
|
name: '垂木傾斜',
|
|
},
|
|
{
|
|
field: 'WATERPROOF_MATERIAL',
|
|
name: '防水材',
|
|
},
|
|
{
|
|
field: 'INSULATION_PRESENCE',
|
|
name: '断熱材有無',
|
|
},
|
|
{
|
|
field: 'STRUCTURE_ORDER',
|
|
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: SurveyBasicInfo[] | []
|
|
surveyDetail: SurveyBasicInfo | null
|
|
surveyListCount: number
|
|
isLoadingSurveyList: boolean
|
|
isLoadingSurveyDetail: boolean
|
|
isCreatingSurvey: boolean
|
|
isUpdatingSurvey: boolean
|
|
isDeletingSurvey: boolean
|
|
createSurvey: (survey: SurveyRegistRequest) => Promise<number>
|
|
createSurveyDetail: (params: { surveyId: number; surveyDetail: SurveyDetailCoverRequest }) => void
|
|
updateSurvey: (survey: SurveyRegistRequest) => void
|
|
deleteSurvey: () => Promise<boolean>
|
|
submitSurvey: () => void
|
|
validateSurveyDetail: (surveyDetail: SurveyDetailRequest) => string
|
|
getZipCode: (zipCode: string) => Promise<ZipCode[] | null>
|
|
} {
|
|
const queryClient = useQueryClient()
|
|
const { keyword, searchOption, isMySurvey, sort, offset } = useSurveyFilterStore()
|
|
const { session } = useSessionStore()
|
|
|
|
const { data: surveyList, isLoading: isLoadingSurveyList } = useQuery({
|
|
queryKey: ['survey', 'list', keyword, searchOption, isMySurvey, sort, offset, session?.storeNm, session?.builderNo, session?.role],
|
|
queryFn: async () => {
|
|
const resp = await axiosInstance(null).get<SurveyBasicInfo[]>('/api/survey-sales', {
|
|
params: {
|
|
keyword,
|
|
searchOption,
|
|
isMySurvey,
|
|
sort,
|
|
offset,
|
|
store: session?.storeNm,
|
|
builderNo: session?.builderNo,
|
|
role: session?.role,
|
|
},
|
|
})
|
|
return resp.data
|
|
},
|
|
})
|
|
|
|
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
|
|
const resp = await axiosInstance(null).get<SurveyBasicInfo>(`/api/survey-sales/${id}`)
|
|
return resp.data
|
|
},
|
|
enabled: id !== undefined,
|
|
})
|
|
|
|
const { data: surveyListCount } = useQuery({
|
|
queryKey: ['survey', 'list', keyword, searchOption, isMySurvey, sort, session?.builderNo, session?.storeNm, session?.role],
|
|
queryFn: async () => {
|
|
const resp = await axiosInstance(null).get<number>('/api/survey-sales', {
|
|
params: {
|
|
keyword,
|
|
searchOption,
|
|
isMySurvey,
|
|
sort,
|
|
builderNo: session?.builderNo,
|
|
store: session?.storeNm,
|
|
role: session?.role,
|
|
},
|
|
})
|
|
return resp.data
|
|
},
|
|
})
|
|
|
|
const { mutateAsync: createSurvey, isPending: isCreatingSurvey } = useMutation({
|
|
mutationFn: async (survey: SurveyRegistRequest) => {
|
|
const resp = await axiosInstance(null).post<SurveyBasicInfo>('/api/survey-sales', survey)
|
|
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: SurveyRegistRequest) => {
|
|
if (id === undefined) throw new Error('id is required')
|
|
const resp = await axiosInstance(null).put<SurveyRegistRequest>(`/api/survey-sales/${id}`, survey)
|
|
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: createSurveyDetail } = useMutation({
|
|
mutationFn: async ({ surveyId, surveyDetail }: { surveyId: number; surveyDetail: SurveyDetailCoverRequest }) => {
|
|
const resp = await axiosInstance(null).patch<SurveyDetailInfo>(`/api/survey-sales/${surveyId}`, surveyDetail)
|
|
return resp.data
|
|
},
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: ['survey', 'list'] })
|
|
queryClient.invalidateQueries({ queryKey: ['survey', id] })
|
|
},
|
|
})
|
|
|
|
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}`, {
|
|
submit: true,
|
|
})
|
|
return resp.data
|
|
},
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: ['survey', 'list'] })
|
|
queryClient.invalidateQueries({ queryKey: ['survey', id] })
|
|
},
|
|
})
|
|
|
|
const validateSurveyDetail = (surveyDetail: SurveyDetailRequest) => {
|
|
const etcFields = ['INSTALLATION_SYSTEM', 'CONSTRUCTION_YEAR', 'RAFTER_SIZE', 'RAFTER_PITCH', 'WATERPROOF_MATERIAL', 'STRUCTURE_ORDER'] 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] === ''
|
|
)
|
|
} else {
|
|
return surveyDetail[field.field as keyof SurveyDetailRequest] === null
|
|
}
|
|
})
|
|
|
|
const contractCapacity = surveyDetail.CONTRACT_CAPACITY
|
|
if (contractCapacity && contractCapacity.trim() !== '' && contractCapacity.split(' ')?.length === 1) {
|
|
return 'CONTRACT_CAPACITY_UNIT'
|
|
}
|
|
|
|
return emptyField?.name || ''
|
|
}
|
|
|
|
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: surveyList || [],
|
|
surveyDetail: surveyDetail || null,
|
|
surveyListCount: surveyListCount || 0,
|
|
isLoadingSurveyList,
|
|
isLoadingSurveyDetail,
|
|
isCreatingSurvey,
|
|
isUpdatingSurvey,
|
|
isDeletingSurvey,
|
|
createSurvey,
|
|
updateSurvey,
|
|
deleteSurvey,
|
|
createSurveyDetail,
|
|
submitSurvey,
|
|
validateSurveyDetail,
|
|
getZipCode,
|
|
}
|
|
}
|