feature/survey #56
@ -2,20 +2,96 @@ import { NextRequest, NextResponse } from 'next/server'
|
|||||||
import { prisma } from '@/libs/prisma'
|
import { prisma } from '@/libs/prisma'
|
||||||
import { convertToSnakeCase } from '@/utils/common-utils'
|
import { convertToSnakeCase } from '@/utils/common-utils'
|
||||||
|
|
||||||
|
interface Survey {
|
||||||
|
SRL_NO: string
|
||||||
|
SUBMISSION_STATUS: boolean
|
||||||
|
SUBMISSION_TARGET_ID: string | null
|
||||||
|
STORE_ID: string | null
|
||||||
|
CONSTRUCTION_POINT_ID: string | null
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SessionParams {
|
||||||
|
role: string | null
|
||||||
|
storeId: string | null
|
||||||
|
builderNo: string | null
|
||||||
|
isLoggedIn: string | null
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkT01Role = (survey: Survey): boolean => survey.SRL_NO !== '一時保存'
|
||||||
|
|
||||||
|
const checkAdminRole = (survey: Survey, storeId: string | null): boolean => {
|
||||||
|
if (!storeId) return false
|
||||||
|
|
||||||
|
if (survey.SUBMISSION_STATUS) {
|
||||||
|
return survey.SUBMISSION_TARGET_ID === storeId || survey.STORE_ID === storeId
|
||||||
|
}
|
||||||
|
return survey.STORE_ID === storeId
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkAdminSubRole = (survey: Survey, storeId: string | null): boolean => {
|
||||||
|
if (!storeId) return false
|
||||||
|
|
||||||
|
if (survey.SUBMISSION_STATUS) {
|
||||||
|
return survey.SUBMISSION_TARGET_ID === storeId || (survey.STORE_ID === storeId && survey.CONSTRUCTION_POINT_ID === null)
|
||||||
|
}
|
||||||
|
return survey.STORE_ID === storeId && survey.CONSTRUCTION_POINT_ID === null
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkPartnerOrBuilderRole = (survey: Survey, builderNo: string | null): boolean => {
|
||||||
|
if (!builderNo) return false
|
||||||
|
return survey.CONSTRUCTION_POINT_ID === builderNo
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkRole = (survey: Survey, sessionParams: SessionParams): boolean => {
|
||||||
|
if (!survey || !sessionParams.role) return false
|
||||||
|
|
||||||
|
switch (sessionParams.role) {
|
||||||
|
case 'T01':
|
||||||
|
return checkT01Role(survey)
|
||||||
|
// T01 이외 1차점
|
||||||
|
case 'Admin':
|
||||||
|
return checkAdminRole(survey, sessionParams.storeId)
|
||||||
|
// 2차점
|
||||||
|
case 'Admin_Sub':
|
||||||
|
return checkAdminSubRole(survey, sessionParams.storeId)
|
||||||
|
// partner
|
||||||
|
case 'Partner':
|
||||||
|
// 2차점 시공권한 user
|
||||||
|
case 'Builder':
|
||||||
|
return checkPartnerOrBuilderRole(survey, sessionParams.builderNo)
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function GET(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
export async function GET(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||||
try {
|
try {
|
||||||
const { id } = await params
|
const { id } = await params
|
||||||
|
const { searchParams } = new URL(request.url)
|
||||||
|
|
||||||
|
const sessionParams: SessionParams = {
|
||||||
|
role: searchParams.get('role'),
|
||||||
|
storeId: searchParams.get('storeId'),
|
||||||
|
builderNo: searchParams.get('builderNo'),
|
||||||
|
isLoggedIn: searchParams.get('isLoggedIn'),
|
||||||
|
}
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const survey = await prisma.SD_SURVEY_SALES_BASIC_INFO.findUnique({
|
const survey = await prisma.SD_SURVEY_SALES_BASIC_INFO.findFirst({
|
||||||
where: { ID: Number(id) },
|
where: {
|
||||||
|
ID: Number(id),
|
||||||
|
},
|
||||||
include: {
|
include: {
|
||||||
DETAIL_INFO: true,
|
DETAIL_INFO: true,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
return NextResponse.json(survey)
|
if (checkRole(survey, sessionParams)) {
|
||||||
} catch (error) {
|
return NextResponse.json(survey)
|
||||||
|
} else {
|
||||||
|
return NextResponse.json({ error: '権限がありません。' }, { status: 403 })
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
console.error('Error fetching survey:', error)
|
console.error('Error fetching survey:', error)
|
||||||
return NextResponse.json({ error: 'Failed to fetch survey' }, { status: 500 })
|
return NextResponse.json({ error: 'データの取得に失敗しました。' }, { status: 500 })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,20 +191,18 @@ export async function PATCH(request: NextRequest, { params }: { params: Promise<
|
|||||||
try {
|
try {
|
||||||
const { id } = await params
|
const { id } = await params
|
||||||
const body = await request.json()
|
const body = await request.json()
|
||||||
|
// @ts-ignore
|
||||||
if (body.targetId) {
|
const survey = await prisma.SD_SURVEY_SALES_BASIC_INFO.update({
|
||||||
// @ts-ignore
|
where: { ID: Number(id) },
|
||||||
const survey = await prisma.SD_SURVEY_SALES_BASIC_INFO.update({
|
data: {
|
||||||
where: { ID: Number(id) },
|
SUBMISSION_STATUS: true,
|
||||||
data: {
|
SUBMISSION_DATE: new Date(),
|
||||||
SUBMISSION_STATUS: true,
|
SUBMISSION_TARGET_ID: body.targetId,
|
||||||
SUBMISSION_DATE: new Date(),
|
SUBMISSION_TARGET_NM: body.targetNm,
|
||||||
SUBMISSION_TARGET_ID: body.targetId,
|
UPT_DT: new Date(),
|
||||||
UPT_DT: new Date(),
|
},
|
||||||
},
|
})
|
||||||
})
|
return NextResponse.json({ message: 'Survey confirmed successfully', data: survey })
|
||||||
return NextResponse.json({ message: 'Survey confirmed successfully', data: survey })
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error updating survey:', error)
|
console.error('Error updating survey:', error)
|
||||||
return NextResponse.json({ error: 'Failed to update survey' }, { status: 500 })
|
return NextResponse.json({ error: 'Failed to update survey' }, { status: 500 })
|
||||||
|
|||||||
@ -11,7 +11,7 @@ type SearchParams = {
|
|||||||
sort?: string | null // 정렬 방식
|
sort?: string | null // 정렬 방식
|
||||||
offset?: string | null
|
offset?: string | null
|
||||||
role?: string | null // 회원권한한
|
role?: string | null // 회원권한한
|
||||||
store?: string | null // 판매점ID
|
storeId?: string | null // 판매점ID
|
||||||
builderNo?: string | null // 시공ID
|
builderNo?: string | null // 시공ID
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,8 +25,10 @@ type WhereCondition = {
|
|||||||
const SEARCH_OPTIONS = [
|
const SEARCH_OPTIONS = [
|
||||||
'BUILDING_NAME', // 건물명
|
'BUILDING_NAME', // 건물명
|
||||||
'REPRESENTATIVE', // 담당자
|
'REPRESENTATIVE', // 담당자
|
||||||
'STORE', // 판매점
|
'STORE', // 판매점명
|
||||||
'CONSTRUCTION_POINT', // 시공점
|
'STORE_ID', // 판매점ID
|
||||||
|
'CONSTRUCTION_POINT', // 시공점명
|
||||||
|
'CONSTRUCTION_POINT_ID', // 시공점ID
|
||||||
'CUSTOMER_NAME', // 고객명
|
'CUSTOMER_NAME', // 고객명
|
||||||
'POST_CODE', // 우편번호
|
'POST_CODE', // 우편번호
|
||||||
'ADDRESS', // 주소
|
'ADDRESS', // 주소
|
||||||
@ -75,11 +77,11 @@ const createMemberRoleCondition = (params: SearchParams): WhereCondition => {
|
|||||||
where.OR = [
|
where.OR = [
|
||||||
{
|
{
|
||||||
// 같은 판매점에서 작성한 제출/제출되지 않은 매물
|
// 같은 판매점에서 작성한 제출/제출되지 않은 매물
|
||||||
AND: [{ STORE_ID: { equals: params.store } }],
|
AND: [{ STORE_ID: { equals: params.storeId } }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// MUSUBI (시공권한 X) 가 ORDER 에 제출한 매물
|
// MUSUBI (시공권한 X) 가 ORDER 에 제출한 매물
|
||||||
AND: [{ SUBMISSION_TARGET_ID: { equals: params.store } }, { SUBMISSION_STATUS: { equals: true } }],
|
AND: [{ SUBMISSION_TARGET_ID: { equals: params.storeId } }, { SUBMISSION_STATUS: { equals: true } }],
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
break
|
break
|
||||||
@ -88,19 +90,14 @@ const createMemberRoleCondition = (params: SearchParams): WhereCondition => {
|
|||||||
where.OR = [
|
where.OR = [
|
||||||
{
|
{
|
||||||
// MUSUBI (시공권한 X) 같은 판매점에서 작성한 제출/제출되지 않은 매물
|
// MUSUBI (시공권한 X) 같은 판매점에서 작성한 제출/제출되지 않은 매물
|
||||||
AND: [
|
AND: [{ STORE_ID: { equals: params.storeId } }, { CONSTRUCTION_POINT_ID: { equals: params.builderNo } }],
|
||||||
{ STORE_ID: { equals: params.store } },
|
|
||||||
{
|
|
||||||
OR: [{ CONSTRUCTION_POINT: { equals: null } }, { CONSTRUCTION_POINT: { equals: '' } }],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// MUSUBI (시공권한 O) 가 MUSUBI 에 제출한 매물 + PARTNER 가 제출한 매물
|
// MUSUBI (시공권한 O) 가 MUSUBI 에 제출한 매물 + PARTNER 가 제출한 매물
|
||||||
AND: [
|
AND: [
|
||||||
{ SUBMISSION_TARGET_ID: { equals: params.store } },
|
{ SUBMISSION_TARGET_ID: { equals: params.storeId } },
|
||||||
{ CONSTRUCTION_POINT: { not: null } },
|
{ CONSTRUCTION_POINT_ID: { not: null } },
|
||||||
{ CONSTRUCTION_POINT: { not: '' } },
|
{ CONSTRUCTION_POINT_ID: { not: '' } },
|
||||||
{ SUBMISSION_STATUS: { equals: true } },
|
{ SUBMISSION_STATUS: { equals: true } },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -109,10 +106,9 @@ const createMemberRoleCondition = (params: SearchParams): WhereCondition => {
|
|||||||
|
|
||||||
case 'Builder': // MUSUBI (시공권한 O)
|
case 'Builder': // MUSUBI (시공권한 O)
|
||||||
case 'Partner': // PARTNER
|
case 'Partner': // PARTNER
|
||||||
// 시공점이 있고 STORE_ID가 시공ID와 같은 매물
|
// 시공ID 같은 매물
|
||||||
where.AND?.push({
|
where.AND?.push({
|
||||||
CONSTRUCTION_POINT: { not: null },
|
CONSTRUCTION_POINT_ID: { equals: params.builderNo },
|
||||||
STORE_ID: { equals: params.builderNo },
|
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
|
|
||||||
@ -127,7 +123,7 @@ const createMemberRoleCondition = (params: SearchParams): WhereCondition => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
STORE_ID: {
|
STORE_ID: {
|
||||||
equals: params.store,
|
equals: params.storeId,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@ -154,7 +150,7 @@ export async function GET(request: Request) {
|
|||||||
sort: searchParams.get('sort'),
|
sort: searchParams.get('sort'),
|
||||||
offset: searchParams.get('offset'),
|
offset: searchParams.get('offset'),
|
||||||
role: searchParams.get('role'),
|
role: searchParams.get('role'),
|
||||||
store: searchParams.get('store'), //storeId
|
storeId: searchParams.get('storeId'), //storeId
|
||||||
builderNo: searchParams.get('builderNo'),
|
builderNo: searchParams.get('builderNo'),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,6 @@ import { useSpinnerStore } from '@/store/spinnerStore'
|
|||||||
export default function SurveySaleDownloadPdf() {
|
export default function SurveySaleDownloadPdf() {
|
||||||
const params = useParams()
|
const params = useParams()
|
||||||
const id = params.id
|
const id = params.id
|
||||||
const router = useRouter()
|
|
||||||
|
|
||||||
const { surveyDetail, isLoadingSurveyDetail } = useSurvey(Number(id))
|
const { surveyDetail, isLoadingSurveyDetail } = useSurvey(Number(id))
|
||||||
const { setIsShow } = useSpinnerStore()
|
const { setIsShow } = useSpinnerStore()
|
||||||
@ -19,13 +18,13 @@ export default function SurveySaleDownloadPdf() {
|
|||||||
const isGeneratedRef = useRef(false)
|
const isGeneratedRef = useRef(false)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setIsShow(true)
|
|
||||||
if (isLoadingSurveyDetail || !surveyDetail || isGeneratedRef.current) return
|
if (isLoadingSurveyDetail || !surveyDetail || isGeneratedRef.current) return
|
||||||
isGeneratedRef.current = true
|
isGeneratedRef.current = true
|
||||||
handleDownPdf()
|
handleDownPdf()
|
||||||
}, [surveyDetail?.id, isLoadingSurveyDetail])
|
}, [surveyDetail?.id, isLoadingSurveyDetail])
|
||||||
|
|
||||||
const handleDownPdf = () => {
|
const handleDownPdf = () => {
|
||||||
|
setIsShow(true)
|
||||||
const options = {
|
const options = {
|
||||||
method: 'open' as const,
|
method: 'open' as const,
|
||||||
resolution: Resolution.HIGH,
|
resolution: Resolution.HIGH,
|
||||||
@ -50,12 +49,9 @@ export default function SurveySaleDownloadPdf() {
|
|||||||
|
|
||||||
generatePDF(targetRef, options).then(() => {
|
generatePDF(targetRef, options).then(() => {
|
||||||
setIsShow(false)
|
setIsShow(false)
|
||||||
router.push(`/survey-sale/${id}`)
|
alert('PDFの生成が完了しました。 ポップアップウィンドウからダウンロードしてください。')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const supplementList = supplementaryFacilities
|
|
||||||
.filter((facility) => surveyDetail?.detailInfo?.supplementaryFacilities?.includes(facility.id.toString()))
|
|
||||||
.map((facility) => facility.name)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -249,11 +245,15 @@ export default function SurveySaleDownloadPdf() {
|
|||||||
boxSizing: 'border-box',
|
boxSizing: 'border-box',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{supplementList === null && surveyDetail?.detailInfo?.supplementaryFacilitiesEtc === null
|
{surveyDetail?.detailInfo?.supplementaryFacilities
|
||||||
? '-'
|
? supplementaryFacilities
|
||||||
|
.filter((facility) => surveyDetail?.detailInfo?.supplementaryFacilities?.includes(facility.id.toString()))
|
||||||
|
.map((facility) => facility.name)
|
||||||
|
.join(', ') +
|
||||||
|
(surveyDetail?.detailInfo?.supplementaryFacilitiesEtc ? `, ${surveyDetail?.detailInfo?.supplementaryFacilitiesEtc}` : '')
|
||||||
: surveyDetail?.detailInfo?.supplementaryFacilitiesEtc
|
: surveyDetail?.detailInfo?.supplementaryFacilitiesEtc
|
||||||
? `${supplementList.join(', ')}, ${surveyDetail?.detailInfo?.supplementaryFacilitiesEtc}`
|
? `${surveyDetail?.detailInfo?.supplementaryFacilitiesEtc}`
|
||||||
: supplementList.join(', ')}
|
: '-'}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@ -330,7 +330,11 @@ export default function SurveySaleDownloadPdf() {
|
|||||||
boxSizing: 'border-box',
|
boxSizing: 'border-box',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{surveyDetail?.detailInfo?.constructionYear === '1' ? '新築' : `既築 (${surveyDetail?.detailInfo?.constructionYear}年)`}
|
{surveyDetail?.detailInfo?.constructionYear === '1'
|
||||||
|
? '新築'
|
||||||
|
: surveyDetail?.detailInfo?.constructionYearEtc
|
||||||
|
? `既築 (${surveyDetail?.detailInfo?.constructionYear}年)`
|
||||||
|
: '-'}
|
||||||
</td>
|
</td>
|
||||||
<th
|
<th
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import Image from 'next/image'
|
|||||||
import { usePopupController } from '@/store/popupController'
|
import { usePopupController } from '@/store/popupController'
|
||||||
import { useParams } from 'next/navigation'
|
import { useParams } from 'next/navigation'
|
||||||
import { useSurvey } from '@/hooks/useSurvey'
|
import { useSurvey } from '@/hooks/useSurvey'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useRef, useState } from 'react'
|
||||||
import { useSessionStore } from '@/store/session'
|
import { useSessionStore } from '@/store/session'
|
||||||
import { useCommCode } from '@/hooks/useCommCode'
|
import { useCommCode } from '@/hooks/useCommCode'
|
||||||
import { CommCode } from '@/types/CommCode'
|
import { CommCode } from '@/types/CommCode'
|
||||||
@ -11,12 +11,13 @@ import { useSpinnerStore } from '@/store/spinnerStore'
|
|||||||
|
|
||||||
interface SubmitFormData {
|
interface SubmitFormData {
|
||||||
saleBase: string | null
|
saleBase: string | null
|
||||||
store: string
|
targetId: string | null
|
||||||
|
targetNm: string | null
|
||||||
sender: string
|
sender: string
|
||||||
receiver: string[] | string
|
receiver: string[] | string
|
||||||
reference: string | null
|
reference: string | null
|
||||||
title: string
|
title: string
|
||||||
contents: string
|
contents: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
interface FormField {
|
interface FormField {
|
||||||
@ -32,38 +33,47 @@ export default function SurveySaleSubmitPopup() {
|
|||||||
const routeId = params.id
|
const routeId = params.id
|
||||||
|
|
||||||
const { setIsShow } = useSpinnerStore()
|
const { setIsShow } = useSpinnerStore()
|
||||||
const [commCodeList, setCommCodeList] = useState<CommCode[]>([])
|
|
||||||
|
|
||||||
const { getCommCode } = useCommCode()
|
const { getCommCode } = useCommCode()
|
||||||
|
const { surveyDetail } = useSurvey(Number(routeId))
|
||||||
|
|
||||||
|
const [submitData, setSubmitData] = useState<SubmitFormData>({
|
||||||
|
saleBase: null,
|
||||||
|
targetId: null,
|
||||||
|
targetNm: null,
|
||||||
|
sender: '',
|
||||||
|
receiver: [],
|
||||||
|
reference: null,
|
||||||
|
title: '',
|
||||||
|
contents: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
const [commCodeList, setCommCodeList] = useState<CommCode[]>([])
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (session?.isLoggedIn && session?.role === 'Admin') {
|
if (!session?.isLoggedIn || !surveyDetail?.id) return
|
||||||
|
if (session?.role === 'Admin') {
|
||||||
getCommCode('SALES_OFFICE_CD').then((codes) => {
|
getCommCode('SALES_OFFICE_CD').then((codes) => {
|
||||||
setCommCodeList(codes)
|
setCommCodeList(codes)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}, [session])
|
setSubmitData({
|
||||||
|
...submitData,
|
||||||
|
targetId: session?.role === 'Builder' ? surveyDetail?.storeId ?? null : null,
|
||||||
|
targetNm: session?.role === 'Builder' ? surveyDetail?.store ?? null : null,
|
||||||
|
sender: session?.email ?? '',
|
||||||
|
title: '[HANASYS現地調査] 調査物件が提出. (' + surveyDetail?.srlNo + ')',
|
||||||
|
})
|
||||||
|
}, [session, surveyDetail])
|
||||||
|
|
||||||
const FORM_FIELDS: FormField[] = [
|
const FORM_FIELDS: FormField[] = [
|
||||||
{ id: 'saleBase', name: '提出地点選択', required: session?.role === 'Admin' },
|
|
||||||
{ id: 'store', name: '提出販売店', required: true },
|
|
||||||
{ id: 'sender', name: '発送者', required: true },
|
{ id: 'sender', name: '発送者', required: true },
|
||||||
|
{ id: 'saleBase', name: '提出地点選択', required: session?.role === 'Admin' },
|
||||||
|
{ id: 'targetNm', name: '提出販売店', required: session?.role !== 'Admin' },
|
||||||
{ id: 'receiver', name: '受信者', required: true },
|
{ id: 'receiver', name: '受信者', required: true },
|
||||||
{ id: 'reference', name: '参考', required: false },
|
{ id: 'reference', name: '参考', required: false },
|
||||||
{ id: 'title', name: 'タイトル', required: true },
|
{ id: 'title', name: 'タイトル', required: true },
|
||||||
{ id: 'contents', name: '内容', required: true },
|
{ id: 'contents', name: '内容', required: false },
|
||||||
]
|
]
|
||||||
|
|
||||||
const [submitData, setSubmitData] = useState<SubmitFormData>({
|
|
||||||
saleBase: null,
|
|
||||||
store: '',
|
|
||||||
sender: session?.email ?? '',
|
|
||||||
receiver: [],
|
|
||||||
reference: null,
|
|
||||||
title: '[HANASYS現地調査] 調査物件が提出.',
|
|
||||||
contents: '',
|
|
||||||
})
|
|
||||||
|
|
||||||
const { submitSurvey, isSubmittingSurvey } = useSurvey(Number(routeId))
|
const { submitSurvey, isSubmittingSurvey } = useSurvey(Number(routeId))
|
||||||
|
|
||||||
const handleInputChange = (field: keyof SubmitFormData, value: string) => {
|
const handleInputChange = (field: keyof SubmitFormData, value: string) => {
|
||||||
@ -74,7 +84,7 @@ export default function SurveySaleSubmitPopup() {
|
|||||||
const requiredFields = FORM_FIELDS.filter((field) => field.required)
|
const requiredFields = FORM_FIELDS.filter((field) => field.required)
|
||||||
|
|
||||||
for (const field of requiredFields) {
|
for (const field of requiredFields) {
|
||||||
if (data[field.id]?.length === 0) {
|
if (data[field.id] === '' || data[field.id] === null || data[field.id]?.length === 0) {
|
||||||
alert(`${field.name}は必須入力項目です。`)
|
alert(`${field.name}は必須入力項目です。`)
|
||||||
const element = document.getElementById(field.id)
|
const element = document.getElementById(field.id)
|
||||||
if (element) {
|
if (element) {
|
||||||
@ -86,32 +96,38 @@ export default function SurveySaleSubmitPopup() {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Admin_Sub 계정 매핑된 submit target id 추가!!!! && 메일 테스트트
|
||||||
const handleSubmit = () => {
|
const handleSubmit = () => {
|
||||||
if (validateData(submitData)) {
|
if (validateData(submitData)) {
|
||||||
window.neoConfirm('送信しますか? 送信後は変更・修正することはできません。', () => {
|
window.neoConfirm('送信しますか? 送信後は変更・修正することはできません。', () => {
|
||||||
setIsShow(true)
|
setIsShow(true)
|
||||||
submitSurvey({ targetId: submitData.store })
|
|
||||||
sendEmail({
|
sendEmail({
|
||||||
to: submitData.receiver,
|
to: submitData.receiver,
|
||||||
subject: submitData.title,
|
subject: submitData.title,
|
||||||
content: submitData.contents,
|
content: contentsRef.current?.innerHTML ?? '',
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
if (!isSubmittingSurvey) {
|
if (!isSubmittingSurvey) {
|
||||||
popupController.setSurveySaleSubmitPopup(false)
|
alert('提出が完了しました。')
|
||||||
}
|
// submitSurvey({ targetId: submitData.targetId, targetNm: submitData.targetNm })
|
||||||
})
|
popupController.setSurveySaleSubmitPopup(false)
|
||||||
.catch((error) => {
|
}
|
||||||
console.error('Error sending email:', error)
|
})
|
||||||
alert('メール送信に失敗しました。')
|
.catch((error) => {
|
||||||
|
console.error('Error sending email:', error)
|
||||||
|
alert('メール送信に失敗しました。 再度送信してください。')
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
|
submitSurvey({ targetId: submitData.targetId, targetNm: submitData.targetNm })
|
||||||
setIsShow(false)
|
setIsShow(false)
|
||||||
|
popupController.setSurveySaleSubmitPopup(false)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const contentsRef = useRef<HTMLDivElement>(null)
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
popupController.setSurveySaleSubmitPopup(false)
|
popupController.setSurveySaleSubmitPopup(false)
|
||||||
}
|
}
|
||||||
@ -122,6 +138,9 @@ export default function SurveySaleSubmitPopup() {
|
|||||||
if (field.id === 'saleBase' && session?.role !== 'Admin') {
|
if (field.id === 'saleBase' && session?.role !== 'Admin') {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
if (field.id === 'targetNm' && session?.role === 'Admin') {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="data-input-form-bx" key={field.id}>
|
<div className="data-input-form-bx" key={field.id}>
|
||||||
@ -130,12 +149,38 @@ export default function SurveySaleSubmitPopup() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="data-input">
|
<div className="data-input">
|
||||||
{field.id === 'contents' ? (
|
{field.id === 'contents' ? (
|
||||||
<textarea
|
<div className="submit-content" id={field.id}>
|
||||||
className="textarea-form"
|
<div ref={contentsRef}>
|
||||||
id={field.id}
|
<p style={{ fontSize: '13px', fontWeight: '400', color: '#2e3a59', marginBottom: '15px' }}>
|
||||||
value={submitData[field.id] ?? ''}
|
HANASYS現地調査アプリを使用した現地調査結果が送信されました。
|
||||||
onChange={(e) => handleInputChange(field.id, e.target.value)}
|
</p>
|
||||||
/>
|
<p style={{ fontSize: '13px', fontWeight: '400', color: '#2e3a59', marginBottom: '3px' }}>
|
||||||
|
-担当者名: <span style={{ color: '#417DDC' }}>{surveyDetail?.representative}</span>
|
||||||
|
</p>
|
||||||
|
<p style={{ fontSize: '13px', fontWeight: '400', color: '#2e3a59', marginBottom: '3px' }}>
|
||||||
|
-販売店名:
|
||||||
|
<span style={{ color: '#417DDC' }}>
|
||||||
|
{surveyDetail?.store} ({surveyDetail?.storeId})
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
<p style={{ fontSize: '13px', fontWeight: '400', color: '#2e3a59', marginBottom: '15px' }}>
|
||||||
|
-施工店名:
|
||||||
|
<span style={{ color: '#417DDC' }}>{surveyDetail?.constructionPoint}</span>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a
|
||||||
|
style={{ fontSize: '13px', fontWeight: '400', color: '#1259CB', marginBottom: '5px', textDecoration: 'underline' }}
|
||||||
|
href={`${process.env.NEXT_PUBLIC_API_URL}/pdf/survey-sale/${surveyDetail?.id}`}
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
現地調査結果PDFダウンロード
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<p style={{ fontSize: '13px', fontWeight: '400', color: '#2e3a59' }}>
|
||||||
|
※リンクをクリックしてローカル調査結果PDFをダウンロードできます。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{field.id === 'saleBase' && session?.role === 'Admin' ? (
|
{field.id === 'saleBase' && session?.role === 'Admin' ? (
|
||||||
|
|||||||
@ -107,6 +107,13 @@ export default function ZipCodePopup() {
|
|||||||
<td>{item.address3}</td>
|
<td>{item.address3}</td>
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
|
{addressInfo?.length === 0 && (
|
||||||
|
<tr>
|
||||||
|
<td colSpan={3} className="al-c">
|
||||||
|
<div className="nodata">조회된 데이터가 없습니다.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
)}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -4,46 +4,38 @@ import { useEffect, useState } from 'react'
|
|||||||
import { useSurveySaleTabState } from '@/store/surveySaleTabState'
|
import { useSurveySaleTabState } from '@/store/surveySaleTabState'
|
||||||
import type { SurveyBasicRequest } from '@/types/Survey'
|
import type { SurveyBasicRequest } from '@/types/Survey'
|
||||||
import type { Mode } from 'fs'
|
import type { Mode } from 'fs'
|
||||||
import { useSessionStore } from '@/store/session'
|
|
||||||
import { usePopupController } from '@/store/popupController'
|
import { usePopupController } from '@/store/popupController'
|
||||||
import { useAddressStore } from '@/store/addressStore'
|
import { useAddressStore } from '@/store/addressStore'
|
||||||
|
import { SessionData } from '@/types/Auth'
|
||||||
|
|
||||||
export default function BasicForm(props: { basicInfo: SurveyBasicRequest; setBasicInfo: (basicInfo: SurveyBasicRequest) => void; mode: Mode }) {
|
interface BasicFormProps {
|
||||||
const { basicInfo, setBasicInfo, mode } = props
|
basicInfo: SurveyBasicRequest
|
||||||
|
setBasicInfo: (basicInfo: SurveyBasicRequest) => void
|
||||||
|
mode: Mode
|
||||||
|
session: SessionData
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function BasicForm({ basicInfo, setBasicInfo, mode, session }: BasicFormProps) {
|
||||||
const { setBasicInfoSelected } = useSurveySaleTabState()
|
const { setBasicInfoSelected } = useSurveySaleTabState()
|
||||||
const [isFlip, setIsFlip] = useState<boolean>(true)
|
const [isFlip, setIsFlip] = useState<boolean>(true)
|
||||||
|
|
||||||
const { session } = useSessionStore()
|
|
||||||
const { addressData } = useAddressStore()
|
const { addressData } = useAddressStore()
|
||||||
|
const popupController = usePopupController()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setBasicInfoSelected()
|
setBasicInfoSelected()
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
// 시공권한 user(Builder), Partner 계정은 조사매물 등록 할 때 STORE_ID에 시공점ID가 들어감
|
// 주소 데이터가 변경될 때만 업데이트
|
||||||
// 권한 별 목록 필터링 시 시공권한 user(Builder), Partner는 시공점ID가 같은 것들만 조회
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (session?.isLoggedIn) {
|
if (!addressData) return
|
||||||
setBasicInfo({
|
|
||||||
...basicInfo,
|
|
||||||
representative: session.userNm ?? '',
|
|
||||||
representativeId: session.userId ?? null,
|
|
||||||
store: session.role === 'Partner' ? null : session.storeNm ?? null,
|
|
||||||
storeId: session.role === 'Partner' || session.role === 'Builder' ? session.builderNo : session.storeId ?? 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()
|
setBasicInfo({
|
||||||
|
...basicInfo,
|
||||||
|
postCode: addressData.post_code,
|
||||||
|
address: addressData.address,
|
||||||
|
addressDetail: addressData.address_detail,
|
||||||
|
})
|
||||||
|
}, [addressData])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -67,29 +59,15 @@ export default function BasicForm(props: { basicInfo: SurveyBasicRequest; setBas
|
|||||||
onChange={(e) => setBasicInfo({ ...basicInfo, representative: e.target.value })}
|
onChange={(e) => setBasicInfo({ ...basicInfo, representative: e.target.value })}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{(session?.role === 'Builder' || session?.role?.includes('Admin')) && (
|
{mode === 'READ' || session?.role === 'Builder' ? (
|
||||||
<div className="data-input-form-bx">
|
<>
|
||||||
<div className="data-input-form-tit">販売店</div>
|
{storeInput(basicInfo, setBasicInfo, mode)}
|
||||||
<input
|
{builderInput(basicInfo, setBasicInfo, mode)}
|
||||||
type="text"
|
</>
|
||||||
className="input-frame"
|
) : session?.role === 'Partner' ? (
|
||||||
readOnly
|
<>{builderInput(basicInfo, setBasicInfo, mode)}</>
|
||||||
value={basicInfo?.store ?? ''}
|
) : (
|
||||||
onChange={(e) => setBasicInfo({ ...basicInfo, store: e.target.value })}
|
<>{storeInput(basicInfo, setBasicInfo, mode)}</>
|
||||||
/>
|
|
||||||
</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>
|
</div>
|
||||||
@ -169,3 +147,33 @@ export default function BasicForm(props: { basicInfo: SurveyBasicRequest; setBas
|
|||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const storeInput = (basicInfo: SurveyBasicRequest, setBasicInfo: (basicInfo: SurveyBasicRequest) => void, mode: Mode) => {
|
||||||
|
return (
|
||||||
|
<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>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const builderInput = (basicInfo: SurveyBasicRequest, setBasicInfo: (basicInfo: SurveyBasicRequest) => void, mode: Mode) => {
|
||||||
|
return (
|
||||||
|
<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>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
@ -7,76 +7,88 @@ import { useParams, useRouter, useSearchParams } from 'next/navigation'
|
|||||||
import { requiredFields, useSurvey } from '@/hooks/useSurvey'
|
import { requiredFields, useSurvey } from '@/hooks/useSurvey'
|
||||||
import { usePopupController } from '@/store/popupController'
|
import { usePopupController } from '@/store/popupController'
|
||||||
|
|
||||||
export default function ButtonForm(props: {
|
interface ButtonFormProps {
|
||||||
mode: Mode
|
mode: Mode
|
||||||
setMode: (mode: Mode) => void
|
setMode: (mode: Mode) => void
|
||||||
data: { basic: SurveyBasicRequest; roof: SurveyDetailRequest }
|
data: {
|
||||||
}) {
|
basic: SurveyBasicRequest
|
||||||
// 라우터
|
roof: SurveyDetailRequest
|
||||||
const router = useRouter()
|
}
|
||||||
const { mode, setMode } = props
|
}
|
||||||
const { session } = useSessionStore()
|
|
||||||
|
|
||||||
|
interface PermissionState {
|
||||||
|
isSubmiter: boolean
|
||||||
|
isWriter: boolean
|
||||||
|
isReceiver: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SaveData extends SurveyBasicRequest {
|
||||||
|
detailInfo: SurveyDetailRequest
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ButtonForm({ mode, setMode, data }: ButtonFormProps) {
|
||||||
|
const router = useRouter()
|
||||||
|
const { session } = useSessionStore()
|
||||||
const searchParams = useSearchParams()
|
const searchParams = useSearchParams()
|
||||||
const idParam = searchParams.get('id')
|
const idParam = searchParams.get('id')
|
||||||
|
|
||||||
const params = useParams()
|
const params = useParams()
|
||||||
const routeId = params.id
|
const routeId = params.id
|
||||||
|
|
||||||
const popupController = usePopupController()
|
const popupController = usePopupController()
|
||||||
// ------------------------------------------------------------
|
|
||||||
const [saveData, setSaveData] = useState({
|
const [saveData, setSaveData] = useState<SaveData>({
|
||||||
...props.data.basic,
|
...data.basic,
|
||||||
detailInfo: props.data.roof,
|
detailInfo: data.roof,
|
||||||
})
|
})
|
||||||
// --------------------------------------------------------------
|
|
||||||
// 권한
|
|
||||||
|
|
||||||
// 제출권한 ㅇ
|
const [permissions, setPermissions] = useState<PermissionState>({
|
||||||
const [isSubmiter, setIsSubmiter] = useState(false)
|
isSubmiter: false,
|
||||||
// 작성자
|
isWriter: false,
|
||||||
const [isWriter, setIsWriter] = useState(false)
|
isReceiver: false,
|
||||||
const isSubmit = props.data.basic.submissionStatus
|
})
|
||||||
|
|
||||||
useEffect(() => {
|
const isSubmit = data.basic.submissionStatus
|
||||||
if (session?.isLoggedIn) {
|
|
||||||
switch (session?.role) {
|
|
||||||
// T01 제출권한 없음
|
|
||||||
case 'T01':
|
|
||||||
setIsSubmiter(false)
|
|
||||||
break
|
|
||||||
// 1차 판매점(Order) + 2차 판매점(Musubi) => 같은 판매점 제출권한
|
|
||||||
case 'Admin':
|
|
||||||
case 'Admin_Sub':
|
|
||||||
setIsSubmiter(session.storeNm === props.data.basic.store && session.builderNo === props.data.basic.constructionPoint)
|
|
||||||
break
|
|
||||||
// 시공권한 User(Musubi) + Partner => 같은 시공ID 제출권한
|
|
||||||
case 'Builder':
|
|
||||||
case 'Partner':
|
|
||||||
setIsSubmiter(session.builderNo === props.data.basic.constructionPoint)
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
setIsSubmiter(false)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
setIsWriter(session.userNm === props.data.basic.representative)
|
|
||||||
}
|
|
||||||
setSaveData({
|
|
||||||
...props.data.basic,
|
|
||||||
detailInfo: props.data.roof,
|
|
||||||
})
|
|
||||||
}, [session, props.data])
|
|
||||||
|
|
||||||
// ------------------------------------------------------------
|
|
||||||
// 저장/임시저장/수정
|
|
||||||
const id = Number(routeId) ? Number(routeId) : Number(idParam)
|
const id = Number(routeId) ? Number(routeId) : Number(idParam)
|
||||||
|
|
||||||
const { deleteSurvey, updateSurvey, isDeletingSurvey, isUpdatingSurvey } = useSurvey(Number(id))
|
const { deleteSurvey, updateSurvey, isDeletingSurvey, isUpdatingSurvey } = useSurvey(id)
|
||||||
const { validateSurveyDetail, createSurvey, isCreatingSurvey } = useSurvey()
|
const { validateSurveyDetail, createSurvey, isCreatingSurvey } = useSurvey()
|
||||||
|
|
||||||
const handleSave = (isTemporary: boolean, isSubmitProcess = false) => {
|
useEffect(() => {
|
||||||
const emptyField = validateSurveyDetail(props.data.roof)
|
if (!session?.isLoggedIn) return
|
||||||
|
|
||||||
|
const newPermissions = calculatePermissions(session, data.basic)
|
||||||
|
setPermissions(newPermissions)
|
||||||
|
|
||||||
|
setSaveData({
|
||||||
|
...data.basic,
|
||||||
|
detailInfo: data.roof,
|
||||||
|
})
|
||||||
|
}, [session, data])
|
||||||
|
|
||||||
|
const calculatePermissions = (session: any, basicData: SurveyBasicRequest): PermissionState => {
|
||||||
|
const isSubmiter = calculateSubmitPermission(session, basicData)
|
||||||
|
const isWriter = session.userNm === basicData.representative
|
||||||
|
const isReceiver = session?.storeId === basicData.submissionTargetId
|
||||||
|
|
||||||
|
return { isSubmiter, isWriter, isReceiver }
|
||||||
|
}
|
||||||
|
|
||||||
|
const calculateSubmitPermission = (session: any, basicData: SurveyBasicRequest): boolean => {
|
||||||
|
switch (session?.role) {
|
||||||
|
case 'T01':
|
||||||
|
return false
|
||||||
|
case 'Admin':
|
||||||
|
case 'Admin_Sub':
|
||||||
|
return session.storeNm === basicData.store && session.builderNo === basicData.constructionPointId
|
||||||
|
case 'Builder':
|
||||||
|
case 'Partner':
|
||||||
|
return session.builderNo === basicData.constructionPointId
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSave = (isTemporary: boolean, isSubmitProcess: boolean) => {
|
||||||
|
const emptyField = validateSurveyDetail(data.roof)
|
||||||
const hasEmptyField = emptyField?.trim() !== ''
|
const hasEmptyField = emptyField?.trim() !== ''
|
||||||
|
|
||||||
if (isTemporary) {
|
if (isTemporary) {
|
||||||
@ -89,53 +101,65 @@ export default function ButtonForm(props: {
|
|||||||
const tempSaveProcess = async () => {
|
const tempSaveProcess = async () => {
|
||||||
if (idParam) {
|
if (idParam) {
|
||||||
await updateSurvey({ survey: saveData, isTemporary: true })
|
await updateSurvey({ survey: saveData, isTemporary: true })
|
||||||
router.push(`/survey-sale/${idParam}`)
|
if (!isUpdatingSurvey) {
|
||||||
|
router.push(`/survey-sale/${idParam}`)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const updatedData = {
|
const updatedData = {
|
||||||
...saveData,
|
...saveData,
|
||||||
srlNo: '一時保存',
|
srlNo: '一時保存',
|
||||||
}
|
}
|
||||||
const id = await createSurvey(updatedData)
|
const id = await createSurvey(updatedData)
|
||||||
router.push(`/survey-sale/${id}`)
|
if (!isCreatingSurvey) {
|
||||||
|
router.push(`/survey-sale/${id}`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
alert('一時保存されました。')
|
alert('一時保存されました。')
|
||||||
}
|
}
|
||||||
|
|
||||||
const focusInput = (field: keyof SurveyDetailInfo) => {
|
const focusInput = (field: keyof SurveyDetailInfo) => {
|
||||||
const input = document.getElementById(field)
|
const input = document.getElementById(field)
|
||||||
if (input) {
|
input?.focus()
|
||||||
input.focus()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const saveProcess = async (emptyField: string | null, isSubmitProcess?: boolean) => {
|
const saveProcess = async (emptyField: string | null, isSubmitProcess?: boolean) => {
|
||||||
if (emptyField?.trim() === '') {
|
if (emptyField?.trim() === '') {
|
||||||
if (idParam) {
|
await handleSuccessfulSave(isSubmitProcess)
|
||||||
await updateSurvey({ survey: saveData, isTemporary: false, storeId: session.storeId ?? '' })
|
|
||||||
router.push(`/survey-sale/${idParam}`)
|
|
||||||
} else {
|
|
||||||
const id = await createSurvey(saveData)
|
|
||||||
router.push(`/survey-sale/${id}`)
|
|
||||||
}
|
|
||||||
if (isSubmitProcess) {
|
|
||||||
if (!isCreatingSurvey && !isUpdatingSurvey) {
|
|
||||||
popupController.setSurveySaleSubmitPopup(true)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
alert('保存されました。')
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (emptyField?.includes('Unit')) {
|
handleFailedSave(emptyField)
|
||||||
alert('電気契約容量の単位を入力してください。')
|
|
||||||
focusInput(emptyField as keyof SurveyDetailInfo)
|
|
||||||
} else {
|
|
||||||
alert(requiredFields.find((field) => field.field === emptyField)?.name + ' 項目が空です。')
|
|
||||||
focusInput(emptyField as keyof SurveyDetailInfo)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------
|
|
||||||
// 삭제/제출
|
const handleSuccessfulSave = async (isSubmitProcess?: boolean) => {
|
||||||
|
if (idParam) {
|
||||||
|
await updateSurvey({ survey: saveData, isTemporary: false, storeId: session.storeId ?? '' })
|
||||||
|
if (!isUpdatingSurvey) {
|
||||||
|
router.push(`/survey-sale/${idParam}`)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const id = await createSurvey(saveData)
|
||||||
|
if (!isCreatingSurvey) {
|
||||||
|
router.push(`/survey-sale/${id}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isSubmitProcess) {
|
||||||
|
if (!isCreatingSurvey && !isUpdatingSurvey) {
|
||||||
|
await popupController.setSurveySaleSubmitPopup(true)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alert('保存されました。')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleFailedSave = (emptyField: string | null) => {
|
||||||
|
if (emptyField?.includes('Unit')) {
|
||||||
|
alert('電気契約容量の単位を入力してください。')
|
||||||
|
} else {
|
||||||
|
alert(requiredFields.find((field) => field.field === emptyField)?.name + ' 項目が空です。')
|
||||||
|
}
|
||||||
|
focusInput(emptyField as keyof SurveyDetailInfo)
|
||||||
|
}
|
||||||
|
|
||||||
const handleDelete = async () => {
|
const handleDelete = async () => {
|
||||||
if (routeId) {
|
if (routeId) {
|
||||||
@ -150,10 +174,11 @@ export default function ButtonForm(props: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
if (props.data.basic.srlNo?.startsWith('一時保存') && Number(routeId)) {
|
if (data.basic.srlNo?.startsWith('一時保存') && Number(routeId)) {
|
||||||
alert('一時保存されたデータは提出できません。')
|
alert('一時保存されたデータは提出できません。')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Number(routeId)) {
|
if (Number(routeId)) {
|
||||||
window.neoConfirm('提出しますか?', async () => {
|
window.neoConfirm('提出しますか?', async () => {
|
||||||
popupController.setSurveySaleSubmitPopup(true)
|
popupController.setSurveySaleSubmitPopup(true)
|
||||||
@ -165,17 +190,15 @@ export default function ButtonForm(props: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------
|
if (!session?.isLoggedIn) return null
|
||||||
|
|
||||||
if (mode === 'READ' && isSubmit && isSubmiter) {
|
if (mode === 'READ' && isSubmit && permissions.isSubmiter) {
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="sale-form-btn-wrap">
|
||||||
<div className="sale-form-btn-wrap">
|
<div className="btn-flex-wrap">
|
||||||
<div className="btn-flex-wrap">
|
<ListButton />
|
||||||
<ListButton />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,9 +208,11 @@ export default function ButtonForm(props: {
|
|||||||
<div className="sale-form-btn-wrap">
|
<div className="sale-form-btn-wrap">
|
||||||
<div className="btn-flex-wrap">
|
<div className="btn-flex-wrap">
|
||||||
<ListButton />
|
<ListButton />
|
||||||
<EditButton setMode={setMode} id={id.toString()} mode={mode} />
|
{(permissions.isWriter || permissions.isSubmiter || (permissions.isReceiver && isSubmit)) && (
|
||||||
{(isWriter || !isSubmiter) && <DeleteButton handleDelete={handleDelete} />}
|
<EditButton setMode={setMode} id={id.toString()} />
|
||||||
{!isSubmit && isSubmiter && <SubmitButton handleSubmit={handleSubmit} />}
|
)}
|
||||||
|
{(permissions.isWriter || (permissions.isReceiver && isSubmit)) && <DeleteButton handleDelete={handleDelete} />}
|
||||||
|
{!isSubmit && permissions.isSubmiter && <SubmitButton handleSubmit={handleSubmit} />}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -196,9 +221,9 @@ export default function ButtonForm(props: {
|
|||||||
<div className="sale-form-btn-wrap">
|
<div className="sale-form-btn-wrap">
|
||||||
<div className="btn-flex-wrap">
|
<div className="btn-flex-wrap">
|
||||||
<ListButton />
|
<ListButton />
|
||||||
<TempButton setMode={setMode} handleSave={handleSave} />
|
<TempButton handleSave={() => handleSave(true, false)} />
|
||||||
<SaveButton handleSave={handleSave} />
|
<SaveButton handleSave={() => handleSave(false, false)} />
|
||||||
{session?.role !== 'T01' && <SubmitButton handleSubmit={handleSubmit} />}
|
{session?.role === 'T01' || isSubmit ? null : <SubmitButton handleSubmit={handleSubmit} />}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -206,12 +231,11 @@ export default function ButtonForm(props: {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 목록 버튼
|
// Button Components
|
||||||
function ListButton() {
|
const ListButton = () => {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
return (
|
return (
|
||||||
<div className="btn-bx">
|
<div className="btn-bx">
|
||||||
{/* 목록 */}
|
|
||||||
<button className="btn-frame n-blue icon" onClick={() => router.push('/survey-sale')}>
|
<button className="btn-frame n-blue icon" onClick={() => router.push('/survey-sale')}>
|
||||||
リスト<i className="btn-arr"></i>
|
リスト<i className="btn-arr"></i>
|
||||||
</button>
|
</button>
|
||||||
@ -219,12 +243,10 @@ function ListButton() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function EditButton(props: { setMode: (mode: Mode) => void; id: string; mode: Mode }) {
|
const EditButton = ({ setMode, id }: { setMode: (mode: Mode) => void; id: string }) => {
|
||||||
const { setMode, id, mode } = props
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
return (
|
return (
|
||||||
<div className="btn-bx">
|
<div className="btn-bx">
|
||||||
{/* 수정 */}
|
|
||||||
<button
|
<button
|
||||||
className="btn-frame n-blue icon"
|
className="btn-frame n-blue icon"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@ -238,59 +260,34 @@ function EditButton(props: { setMode: (mode: Mode) => void; id: string; mode: Mo
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function SubmitButton(props: { handleSubmit: () => void }) {
|
const SubmitButton = ({ handleSubmit }: { handleSubmit: () => void }) => (
|
||||||
const { handleSubmit } = props
|
<div className="btn-bx">
|
||||||
return (
|
<button className="btn-frame red icon" onClick={handleSubmit}>
|
||||||
<>
|
提出<i className="btn-arr"></i>
|
||||||
<div className="btn-bx">
|
</button>
|
||||||
{/* 제출 */}
|
</div>
|
||||||
<button className="btn-frame red icon" onClick={handleSubmit}>
|
)
|
||||||
提出<i className="btn-arr"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function DeleteButton(props: { handleDelete: () => void }) {
|
const DeleteButton = ({ handleDelete }: { handleDelete: () => void }) => (
|
||||||
const { handleDelete } = props
|
<div className="btn-bx">
|
||||||
return (
|
<button className="btn-frame n-blue icon" onClick={handleDelete}>
|
||||||
<div className="btn-bx">
|
削除<i className="btn-arr"></i>
|
||||||
{/* 삭제 */}
|
</button>
|
||||||
<button className="btn-frame n-blue icon" onClick={handleDelete}>
|
</div>
|
||||||
削除<i className="btn-arr"></i>
|
)
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function SaveButton(props: { handleSave: (isTemporary: boolean) => void }) {
|
const SaveButton = ({ handleSave }: { handleSave: () => void }) => (
|
||||||
const { handleSave } = props
|
<div className="btn-bx">
|
||||||
return (
|
<button className="btn-frame n-blue icon" onClick={handleSave}>
|
||||||
<div className="btn-bx">
|
保存<i className="btn-arr"></i>
|
||||||
{/* 저장 */}
|
</button>
|
||||||
<button className="btn-frame n-blue icon" onClick={() => handleSave(false)}>
|
</div>
|
||||||
保存<i className="btn-arr"></i>
|
)
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function TempButton(props: { setMode: (mode: Mode) => void; handleSave: (isTemporary: boolean) => void }) {
|
const TempButton = ({ handleSave }: { handleSave: () => void }) => (
|
||||||
const { setMode, handleSave } = props
|
<div className="btn-bx">
|
||||||
const router = useRouter()
|
<button className="btn-frame n-blue icon" onClick={handleSave}>
|
||||||
|
一時保存<i className="btn-arr"></i>
|
||||||
return (
|
</button>
|
||||||
<div className="btn-bx">
|
</div>
|
||||||
{/* 임시저장 */}
|
)
|
||||||
<button
|
|
||||||
className="btn-frame n-blue icon"
|
|
||||||
onClick={() => {
|
|
||||||
handleSave(true)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
一時保存<i className="btn-arr"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|||||||
@ -4,12 +4,15 @@ import { useSurvey } from '@/hooks/useSurvey'
|
|||||||
import { useParams, useRouter } from 'next/navigation'
|
import { useParams, useRouter } from 'next/navigation'
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
import DetailForm from './DetailForm'
|
import DetailForm from './DetailForm'
|
||||||
|
import { useSessionStore } from '@/store/session'
|
||||||
|
|
||||||
export default function DataTable() {
|
export default function DataTable() {
|
||||||
const params = useParams()
|
const params = useParams()
|
||||||
const id = params.id
|
const id = params.id
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
|
const { session } = useSessionStore()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (Number.isNaN(Number(id))) {
|
if (Number.isNaN(Number(id))) {
|
||||||
alert('間違ったアプローチです。')
|
alert('間違ったアプローチです。')
|
||||||
@ -20,7 +23,25 @@ export default function DataTable() {
|
|||||||
const { surveyDetail, isLoadingSurveyDetail } = useSurvey(Number(id))
|
const { surveyDetail, isLoadingSurveyDetail } = useSurvey(Number(id))
|
||||||
|
|
||||||
if (isLoadingSurveyDetail) {
|
if (isLoadingSurveyDetail) {
|
||||||
return <div>Loading...</div>
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const submitStatus = () => {
|
||||||
|
const { submissionTargetNm, submissionTargetId } = surveyDetail ?? {}
|
||||||
|
|
||||||
|
if (!submissionTargetNm) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!submissionTargetId) {
|
||||||
|
return <div>{submissionTargetNm}</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
({submissionTargetNm} - {submissionTargetId})
|
||||||
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -56,9 +77,7 @@ export default function DataTable() {
|
|||||||
{surveyDetail?.submissionStatus && surveyDetail?.submissionDate ? (
|
{surveyDetail?.submissionStatus && surveyDetail?.submissionDate ? (
|
||||||
<>
|
<>
|
||||||
<div>{new Date(surveyDetail.submissionDate).toLocaleString()}</div>
|
<div>{new Date(surveyDetail.submissionDate).toLocaleString()}</div>
|
||||||
<div>
|
{submitStatus()}
|
||||||
({surveyDetail.store} - {surveyDetail.storeId})
|
|
||||||
</div>
|
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
'-'
|
'-'
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import BasicForm from './BasicForm'
|
|||||||
import RoofForm from './RoofForm'
|
import RoofForm from './RoofForm'
|
||||||
import { useParams, useSearchParams } from 'next/navigation'
|
import { useParams, useSearchParams } from 'next/navigation'
|
||||||
import { useSurvey } from '@/hooks/useSurvey'
|
import { useSurvey } from '@/hooks/useSurvey'
|
||||||
|
import { useSessionStore } from '@/store/session'
|
||||||
|
|
||||||
const roofInfoForm: SurveyDetailRequest = {
|
const roofInfoForm: SurveyDetailRequest = {
|
||||||
contractCapacity: null,
|
contractCapacity: null,
|
||||||
@ -52,6 +53,7 @@ const basicInfoForm: SurveyBasicRequest = {
|
|||||||
store: null,
|
store: null,
|
||||||
storeId: null,
|
storeId: null,
|
||||||
constructionPoint: null,
|
constructionPoint: null,
|
||||||
|
constructionPointId: null,
|
||||||
investigationDate: new Date().toLocaleDateString('en-CA'),
|
investigationDate: new Date().toLocaleDateString('en-CA'),
|
||||||
buildingName: null,
|
buildingName: null,
|
||||||
customerName: null,
|
customerName: null,
|
||||||
@ -61,6 +63,7 @@ const basicInfoForm: SurveyBasicRequest = {
|
|||||||
submissionStatus: false,
|
submissionStatus: false,
|
||||||
submissionDate: null,
|
submissionDate: null,
|
||||||
submissionTargetId: null,
|
submissionTargetId: null,
|
||||||
|
submissionTargetNm: null,
|
||||||
srlNo: null,
|
srlNo: null,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,29 +74,54 @@ export default function DetailForm() {
|
|||||||
const modeset = Number(routeId) ? 'READ' : idParam ? 'EDIT' : 'CREATE'
|
const modeset = Number(routeId) ? 'READ' : idParam ? 'EDIT' : 'CREATE'
|
||||||
const id = Number(routeId) ? Number(routeId) : Number(idParam)
|
const id = Number(routeId) ? Number(routeId) : Number(idParam)
|
||||||
|
|
||||||
const { surveyDetail, validateSurveyDetail } = useSurvey(Number(id))
|
const { surveyDetail, isLoadingSurveyDetail, validateSurveyDetail } = useSurvey(Number(id))
|
||||||
|
const { session } = useSessionStore()
|
||||||
|
|
||||||
const [mode, setMode] = useState<Mode>(modeset)
|
const [mode, setMode] = useState<Mode>(modeset)
|
||||||
const [basicInfoData, setBasicInfoData] = useState<SurveyBasicRequest>(basicInfoForm)
|
const [basicInfoData, setBasicInfoData] = useState<SurveyBasicRequest>(() => ({
|
||||||
|
...basicInfoForm,
|
||||||
|
representative: session?.userNm ?? '',
|
||||||
|
representativeId: session?.userId ?? null,
|
||||||
|
store: session?.storeNm ?? null,
|
||||||
|
storeId: session?.storeId ?? null,
|
||||||
|
constructionPoint: session?.builderNm ?? null,
|
||||||
|
constructionPointId: session?.builderNo ?? null,
|
||||||
|
}))
|
||||||
const [roofInfoData, setRoofInfoData] = useState<SurveyDetailRequest>(roofInfoForm)
|
const [roofInfoData, setRoofInfoData] = useState<SurveyDetailRequest>(roofInfoForm)
|
||||||
|
|
||||||
|
// 세션 데이터가 변경될 때 기본 정보 업데이트
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (Number(idParam) !== 0 && surveyDetail === null) {
|
if (!session?.isLoggedIn) return
|
||||||
alert('データが見つかりません。')
|
setBasicInfoData((prev) => ({
|
||||||
window.location.href = '/survey-sale'
|
...prev,
|
||||||
}
|
representative: session.userNm ?? '',
|
||||||
|
representativeId: session.userId ?? null,
|
||||||
|
store: session.storeNm ?? null,
|
||||||
|
storeId: session.storeId ?? null,
|
||||||
|
constructionPoint: session.builderNm ?? null,
|
||||||
|
constructionPointId: session.builderNo ?? null,
|
||||||
|
}))
|
||||||
|
}, [session?.isLoggedIn])
|
||||||
|
|
||||||
|
// 설문 데이터 로딩 및 업데이트
|
||||||
|
useEffect(() => {
|
||||||
|
if (isLoadingSurveyDetail || !session?.isLoggedIn) return
|
||||||
if (surveyDetail && (mode === 'EDIT' || mode === 'READ')) {
|
if (surveyDetail && (mode === 'EDIT' || mode === 'READ')) {
|
||||||
const { id, uptDt, regDt, detailInfo, ...rest } = surveyDetail
|
const { id, uptDt, regDt, detailInfo, ...rest } = surveyDetail
|
||||||
setBasicInfoData(rest)
|
setBasicInfoData((prev) => ({
|
||||||
|
...prev,
|
||||||
|
...rest,
|
||||||
|
}))
|
||||||
|
|
||||||
if (detailInfo) {
|
if (detailInfo) {
|
||||||
const { id, uptDt, regDt, basicInfoId, ...rest } = detailInfo
|
const { id, uptDt, regDt, basicInfoId, ...rest } = detailInfo
|
||||||
setRoofInfoData(rest)
|
setRoofInfoData(rest)
|
||||||
if (validateSurveyDetail(rest).trim() !== '') {
|
if (validateSurveyDetail(rest).trim() !== '') {
|
||||||
|
// validation logic here if needed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [surveyDetail, id])
|
}, [mode, session?.isLoggedIn, isLoadingSurveyDetail])
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
basic: basicInfoData,
|
basic: basicInfoData,
|
||||||
@ -105,9 +133,7 @@ export default function DetailForm() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="sale-detail-toggle-wrap">
|
<div className="sale-detail-toggle-wrap">
|
||||||
{/* 기본정보 */}
|
<BasicForm basicInfo={basicInfoData} setBasicInfo={setBasicInfoData} mode={mode} session={session} />
|
||||||
<BasicForm basicInfo={basicInfoData} setBasicInfo={setBasicInfoData} mode={mode} />
|
|
||||||
{/* 전기/지붕정보 */}
|
|
||||||
<RoofForm roofInfo={roofInfoData} setRoofInfo={setRoofInfoData} mode={mode} />
|
<RoofForm roofInfo={roofInfoData} setRoofInfo={setRoofInfoData} mode={mode} />
|
||||||
<ButtonForm {...buttonFormProps} />
|
<ButtonForm {...buttonFormProps} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -137,7 +137,7 @@ export const radioEtcData: Record<RadioEtcKeys, { id: number; label: string }[]>
|
|||||||
structureOrder: [
|
structureOrder: [
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
label: '屋根材 - 防水材 - 屋根の基礎 - 垂木', //지붕재 방수재 지붕의기초 서까래
|
label: '屋根材 > 防水材 > 屋根の基礎 > 垂木', //지붕재 방수재 지붕의기초 서까래
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
houseStructure: [
|
houseStructure: [
|
||||||
@ -537,6 +537,7 @@ const SelectedBox = ({
|
|||||||
</select>
|
</select>
|
||||||
<div className={`data-input ${column === 'constructionYear' ? 'flex' : ''}`}>
|
<div className={`data-input ${column === 'constructionYear' ? 'flex' : ''}`}>
|
||||||
<input
|
<input
|
||||||
|
id={`${column}Etc`}
|
||||||
type={column === 'constructionYear' ? 'number' : 'text'}
|
type={column === 'constructionYear' ? 'number' : 'text'}
|
||||||
inputMode={column === 'constructionYear' ? 'numeric' : 'text'}
|
inputMode={column === 'constructionYear' ? 'numeric' : 'text'}
|
||||||
className="input-frame"
|
className="input-frame"
|
||||||
@ -642,6 +643,7 @@ const RadioSelected = ({
|
|||||||
{(showEtcOption || column === 'insulationPresence') && (
|
{(showEtcOption || column === 'insulationPresence') && (
|
||||||
<div className="data-input">
|
<div className="data-input">
|
||||||
<input
|
<input
|
||||||
|
id={`${column}Etc`}
|
||||||
type="text"
|
type="text"
|
||||||
className="input-frame"
|
className="input-frame"
|
||||||
placeholder="-"
|
placeholder="-"
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
import type { SurveyBasicInfo, SurveyDetailRequest, SurveyRegistRequest } from '@/types/Survey'
|
import type { SurveyBasicInfo, SurveyDetailRequest, SurveyRegistRequest } from '@/types/Survey'
|
||||||
import { useMemo } from 'react'
|
import { useMemo, useEffect } from 'react'
|
||||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
||||||
import { useSurveyFilterStore } from '@/store/surveyFilterStore'
|
import { useSurveyFilterStore } from '@/store/surveyFilterStore'
|
||||||
import { useSessionStore } from '@/store/session'
|
import { useSessionStore } from '@/store/session'
|
||||||
import { useAxios } from './useAxios'
|
import { useAxios } from './useAxios'
|
||||||
import { queryStringFormatter } from '@/utils/common-utils'
|
import { queryStringFormatter } from '@/utils/common-utils'
|
||||||
|
import { useRouter } from 'next/navigation'
|
||||||
|
|
||||||
export const requiredFields = [
|
export const requiredFields = [
|
||||||
{
|
{
|
||||||
@ -66,7 +67,7 @@ export function useSurvey(id?: number): {
|
|||||||
createSurvey: (survey: SurveyRegistRequest) => Promise<number>
|
createSurvey: (survey: SurveyRegistRequest) => Promise<number>
|
||||||
updateSurvey: ({ survey, isTemporary, storeId }: { survey: SurveyRegistRequest; isTemporary: boolean; storeId?: string }) => void
|
updateSurvey: ({ survey, isTemporary, storeId }: { survey: SurveyRegistRequest; isTemporary: boolean; storeId?: string }) => void
|
||||||
deleteSurvey: () => Promise<boolean>
|
deleteSurvey: () => Promise<boolean>
|
||||||
submitSurvey: (params: { saveId?: number; targetId?: string; storeId?: string; srlNo?: string }) => void
|
submitSurvey: (params: { targetId?: string | null; targetNm?: string | null }) => void
|
||||||
validateSurveyDetail: (surveyDetail: SurveyDetailRequest) => string
|
validateSurveyDetail: (surveyDetail: SurveyDetailRequest) => string
|
||||||
getZipCode: (zipCode: string) => Promise<ZipCode[] | null>
|
getZipCode: (zipCode: string) => Promise<ZipCode[] | null>
|
||||||
refetchSurveyList: () => void
|
refetchSurveyList: () => void
|
||||||
@ -75,6 +76,7 @@ export function useSurvey(id?: number): {
|
|||||||
const { keyword, searchOption, isMySurvey, sort, offset } = useSurveyFilterStore()
|
const { keyword, searchOption, isMySurvey, sort, offset } = useSurveyFilterStore()
|
||||||
const { session } = useSessionStore()
|
const { session } = useSessionStore()
|
||||||
const { axiosInstance } = useAxios()
|
const { axiosInstance } = useAxios()
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: surveyListData,
|
data: surveyListData,
|
||||||
@ -90,7 +92,7 @@ export function useSurvey(id?: number): {
|
|||||||
isMySurvey,
|
isMySurvey,
|
||||||
sort,
|
sort,
|
||||||
offset,
|
offset,
|
||||||
store: session?.storeId,
|
storeId: session?.storeId,
|
||||||
builderNo: session?.builderNo,
|
builderNo: session?.builderNo,
|
||||||
role: session?.role,
|
role: session?.role,
|
||||||
},
|
},
|
||||||
@ -109,12 +111,24 @@ export function useSurvey(id?: number): {
|
|||||||
const { data: surveyDetail, isLoading: isLoadingSurveyDetail } = useQuery({
|
const { data: surveyDetail, isLoading: isLoadingSurveyDetail } = useQuery({
|
||||||
queryKey: ['survey', id],
|
queryKey: ['survey', id],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
if (id === undefined) throw new Error('id is required')
|
if (!session?.isLoggedIn || id === 0 || id === undefined) return null
|
||||||
if (id === null || isNaN(id)) return null
|
try {
|
||||||
const resp = await axiosInstance(null).get<SurveyBasicInfo>(`/api/survey-sales/${id}`)
|
const resp = await axiosInstance(null).get<SurveyBasicInfo>(`/api/survey-sales/${id}`, {
|
||||||
return resp.data
|
params: {
|
||||||
|
role: session?.role,
|
||||||
|
storeId: session?.storeId,
|
||||||
|
builderNo: session?.builderNo,
|
||||||
|
isLoggedIn: session?.isLoggedIn,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return resp.data
|
||||||
|
} catch (error: any) {
|
||||||
|
alert(error.response?.data.error)
|
||||||
|
router.replace('/survey-sale')
|
||||||
|
return null
|
||||||
|
}
|
||||||
},
|
},
|
||||||
enabled: id !== undefined,
|
enabled: id !== 0 && id !== undefined && session?.isLoggedIn,
|
||||||
})
|
})
|
||||||
|
|
||||||
const { mutateAsync: createSurvey, isPending: isCreatingSurvey } = useMutation({
|
const { mutateAsync: createSurvey, isPending: isCreatingSurvey } = useMutation({
|
||||||
@ -163,13 +177,11 @@ export function useSurvey(id?: number): {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const { mutateAsync: submitSurvey, isPending: isSubmittingSurvey } = useMutation({
|
const { mutateAsync: submitSurvey, isPending: isSubmittingSurvey } = useMutation({
|
||||||
mutationFn: async ({ targetId, storeId, srlNo }: { targetId?: string; storeId?: string; srlNo?: string }) => {
|
mutationFn: async ({ targetId, targetNm }: { targetId?: string | null; targetNm?: string | null }) => {
|
||||||
if (!id) throw new Error('id is required')
|
if (!id) throw new Error('id is required')
|
||||||
const resp = await axiosInstance(null).patch<boolean>(`/api/survey-sales/${id}`, {
|
const resp = await axiosInstance(null).patch<boolean>(`/api/survey-sales/${id}`, {
|
||||||
targetId,
|
targetId,
|
||||||
storeId,
|
targetNm,
|
||||||
srlNo,
|
|
||||||
role: session?.role ?? null,
|
|
||||||
})
|
})
|
||||||
return resp.data
|
return resp.data
|
||||||
},
|
},
|
||||||
@ -180,34 +192,44 @@ export function useSurvey(id?: number): {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const validateSurveyDetail = (surveyDetail: SurveyDetailRequest) => {
|
const validateSurveyDetail = (surveyDetail: SurveyDetailRequest) => {
|
||||||
const etcFields = [
|
// 상수 정의
|
||||||
'installationSystem',
|
const ETC_FIELDS = ['installationSystem', 'rafterSize', 'rafterPitch', 'waterproofMaterial', 'structureOrder'] as const
|
||||||
'constructionYear',
|
|
||||||
'rafterSize',
|
|
||||||
'rafterPitch',
|
|
||||||
'waterproofMaterial',
|
|
||||||
'structureOrder',
|
|
||||||
'insulationPresence',
|
|
||||||
] as const
|
|
||||||
|
|
||||||
const emptyField = requiredFields.find((field) => {
|
const SPECIAL_CONDITIONS = ['constructionYear', 'insulationPresence'] as const
|
||||||
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) {
|
const isEmptyValue = (value: any): boolean => {
|
||||||
return 'contractCapacityUnit'
|
return value === null || value?.toString().trim() === ''
|
||||||
}
|
}
|
||||||
|
|
||||||
return emptyField?.field || ''
|
const checkRequiredField = (field: string): string => {
|
||||||
|
if (ETC_FIELDS.includes(field as (typeof ETC_FIELDS)[number])) {
|
||||||
|
if (
|
||||||
|
isEmptyValue(surveyDetail[field as keyof SurveyDetailRequest]) &&
|
||||||
|
isEmptyValue(surveyDetail[`${field}Etc` as keyof SurveyDetailRequest])
|
||||||
|
) {
|
||||||
|
return field
|
||||||
|
}
|
||||||
|
} else if (SPECIAL_CONDITIONS.includes(field as (typeof SPECIAL_CONDITIONS)[number])) {
|
||||||
|
if (surveyDetail[field as keyof SurveyDetailRequest] === '2' && isEmptyValue(surveyDetail[`${field}Etc` as keyof SurveyDetailRequest])) {
|
||||||
|
return `${field}Etc`
|
||||||
|
} else if (isEmptyValue(surveyDetail[field as keyof SurveyDetailRequest])) {
|
||||||
|
return field
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
|
// 필수 필드 체크
|
||||||
|
const emptyField = requiredFields.find((field) => checkRequiredField(field.field))
|
||||||
|
if (emptyField) return emptyField.field
|
||||||
|
|
||||||
|
// 계약 용량 단위 체크
|
||||||
|
const contractCapacity = surveyDetail.contractCapacity
|
||||||
|
if (contractCapacity?.trim() && contractCapacity.split(' ').length === 1) {
|
||||||
|
return 'contractCapacityUnit'
|
||||||
|
}
|
||||||
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
const getZipCode = async (zipCode: string): Promise<ZipCode[] | null> => {
|
const getZipCode = async (zipCode: string): Promise<ZipCode[] | null> => {
|
||||||
|
|||||||
@ -21,18 +21,18 @@ export const SEARCH_OPTIONS = [
|
|||||||
id: 'store',
|
id: 'store',
|
||||||
label: '販売店名',
|
label: '販売店名',
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// id: 'store_id',
|
id: 'store_id',
|
||||||
// label: '販売店ID',
|
label: '販売店ID',
|
||||||
// },
|
},
|
||||||
{
|
{
|
||||||
id: 'construction_point',
|
id: 'construction_point',
|
||||||
label: '施工店名',
|
label: '施工店名',
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// id: 'construction_id',
|
id: 'construction_point_id',
|
||||||
// label: '施工店ID',
|
label: '施工店ID',
|
||||||
// },
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
export const SEARCH_OPTIONS_PARTNERS = [
|
export const SEARCH_OPTIONS_PARTNERS = [
|
||||||
|
|||||||
@ -5,6 +5,7 @@ export type SurveyBasicInfo = {
|
|||||||
store: string | null
|
store: string | null
|
||||||
storeId: string | null
|
storeId: string | null
|
||||||
constructionPoint: string | null
|
constructionPoint: string | null
|
||||||
|
constructionPointId: string | null
|
||||||
investigationDate: string | null
|
investigationDate: string | null
|
||||||
buildingName: string | null
|
buildingName: string | null
|
||||||
customerName: string | null
|
customerName: string | null
|
||||||
@ -17,6 +18,7 @@ export type SurveyBasicInfo = {
|
|||||||
regDt: Date
|
regDt: Date
|
||||||
uptDt: Date
|
uptDt: Date
|
||||||
submissionTargetId: string | null
|
submissionTargetId: string | null
|
||||||
|
submissionTargetNm: string | null
|
||||||
srlNo: string | null //판매점IDyyMMdd000
|
srlNo: string | null //판매점IDyyMMdd000
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,6 +70,7 @@ export type SurveyBasicRequest = {
|
|||||||
store: string | null
|
store: string | null
|
||||||
storeId: string | null
|
storeId: string | null
|
||||||
constructionPoint: string | null
|
constructionPoint: string | null
|
||||||
|
constructionPointId: string | null
|
||||||
investigationDate: string | null
|
investigationDate: string | null
|
||||||
buildingName: string | null
|
buildingName: string | null
|
||||||
customerName: string | null
|
customerName: string | null
|
||||||
@ -77,6 +80,7 @@ export type SurveyBasicRequest = {
|
|||||||
submissionStatus: boolean
|
submissionStatus: boolean
|
||||||
submissionDate: string | null
|
submissionDate: string | null
|
||||||
submissionTargetId: string | null
|
submissionTargetId: string | null
|
||||||
|
submissionTargetNm: string | null
|
||||||
srlNo: string | null //판매점IDyyMMdd000
|
srlNo: string | null //판매점IDyyMMdd000
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user