294 lines
10 KiB
TypeScript
294 lines
10 KiB
TypeScript
import Image from 'next/image'
|
|
import { usePopupController } from '@/store/popupController'
|
|
import { useParams } from 'next/navigation'
|
|
import { useSurvey } from '@/hooks/useSurvey'
|
|
import { useEffect, useState } from 'react'
|
|
import { useSessionStore } from '@/store/session'
|
|
import { useCommCode } from '@/hooks/useCommCode'
|
|
import { CommCode } from '@/types/CommCode'
|
|
import { sendEmail } from '@/libs/mailer'
|
|
import { useSpinnerStore } from '@/store/spinnerStore'
|
|
import { CONFIRM_MESSAGE, SUCCESS_MESSAGE, ERROR_MESSAGE, useAlertMsg, WARNING_MESSAGE } from '@/hooks/useAlertMsg'
|
|
|
|
interface SubmitFormData {
|
|
saleBase: string | null
|
|
targetId: string | null
|
|
targetNm: string | null
|
|
sender: string
|
|
receiver: string[] | string
|
|
reference: string[] | null
|
|
title: string
|
|
contents: string | null
|
|
srlNo: string | null
|
|
}
|
|
|
|
interface FormField {
|
|
id: keyof SubmitFormData
|
|
name: string
|
|
required: boolean
|
|
}
|
|
|
|
export default function SurveySaleSubmitPopup() {
|
|
const popupController = usePopupController()
|
|
const { session } = useSessionStore()
|
|
const params = useParams()
|
|
const routeId = params.id
|
|
|
|
const { setIsShow } = useSpinnerStore()
|
|
const { getCommCode } = useCommCode()
|
|
const { surveyDetail, getSubmitTarget, isSubmittingSurvey, submitSurvey } = useSurvey(Number(routeId))
|
|
const { showErrorAlert, showSuccessAlert, showConfirm } = useAlertMsg()
|
|
|
|
const [submitData, setSubmitData] = useState<SubmitFormData>({
|
|
saleBase: null,
|
|
targetId: null,
|
|
targetNm: null,
|
|
sender: '',
|
|
receiver: [],
|
|
reference: null,
|
|
title: '',
|
|
contents: '',
|
|
srlNo: null,
|
|
})
|
|
|
|
const [commCodeList, setCommCodeList] = useState<CommCode[]>([])
|
|
/** 제출 타겟 데이터 조회 및 제출 폼 데이터 삽입 */
|
|
useEffect(() => {
|
|
if (!session?.isLoggedIn || !surveyDetail?.id) return
|
|
const baseUpdate = {
|
|
sender: session?.email ?? '',
|
|
title: '[HANASYS現地調査] 調査物件が提出. (' + surveyDetail?.srlNo + ')',
|
|
srlNo: surveyDetail?.srlNo ?? null,
|
|
}
|
|
/** Admin 제출 폼 데이터 삽입 - 1차 판매점*/
|
|
if (session?.role === 'Admin') {
|
|
getCommCode('SALES_OFFICE_CD').then((codes) => {
|
|
setCommCodeList(codes)
|
|
})
|
|
setSubmitData((prev) => ({
|
|
...prev,
|
|
...baseUpdate,
|
|
}))
|
|
/** Builder, Admin_Sub 제출 폼 데이터 삽입 - 2차 판매점, 2차 판매점 시공권한*/
|
|
} else if (session?.role === 'Builder' || session?.role === 'Admin_Sub') {
|
|
getSubmitTarget({ storeId: surveyDetail?.storeId ?? '', role: session?.role ?? '' }).then((data) => {
|
|
if (!data) return
|
|
if (data && data.length > 0) {
|
|
const updateData: Partial<SubmitFormData> = {
|
|
sender: session?.email ?? '',
|
|
title: '[HANASYS現地調査] 調査物件が提出. (' + surveyDetail?.srlNo + ')',
|
|
targetId: data[0]?.targetStoreId ?? '',
|
|
targetNm: data[0]?.targetStoreNm ?? '',
|
|
receiver: data.filter((item) => item.auth === 'S').map((item) => item.repUserEmail),
|
|
reference: data.filter((item) => item.auth === 'N').map((item) => item.repUserEmail),
|
|
saleBase: null,
|
|
contents: '',
|
|
}
|
|
setSubmitData((prev) => ({
|
|
...prev,
|
|
...updateData,
|
|
}))
|
|
}
|
|
})
|
|
/** Partner 제출 폼 데이터 삽입 - (T01은 제출 불가) */
|
|
} else {
|
|
setSubmitData((prev) => ({
|
|
...prev,
|
|
...baseUpdate,
|
|
}))
|
|
}
|
|
}, [session, surveyDetail])
|
|
|
|
const FORM_FIELDS: FormField[] = [
|
|
{ id: 'sender', name: '発送者', required: true },
|
|
{ id: 'saleBase', name: '提出地点選択', required: session?.role === 'Admin' },
|
|
{ id: 'targetNm', name: '提出販売店', required: session?.role !== 'Admin' && session?.role !== 'T01' },
|
|
{ id: 'receiver', name: '受信者', required: true },
|
|
{ id: 'reference', name: '参考', required: false },
|
|
{ id: 'title', name: 'タイトル', required: true },
|
|
{ id: 'contents', name: '内容', required: false },
|
|
]
|
|
|
|
const handleInputChange = (field: keyof SubmitFormData, value: string) => {
|
|
setSubmitData((prev) => ({ ...prev, [field]: value }))
|
|
}
|
|
|
|
/** 필수값 검증 */
|
|
const validateData = (data: SubmitFormData): boolean => {
|
|
const requiredFields = FORM_FIELDS.filter((field) => field.required)
|
|
|
|
for (const field of requiredFields) {
|
|
if (data[field.id] === '' || data[field.id] === null || data[field.id]?.length === 0) {
|
|
showErrorAlert(WARNING_MESSAGE.REQUIRED_FIELD_IS_EMPTY, field.name)
|
|
const element = document.getElementById(field.id)
|
|
if (element) {
|
|
element.focus()
|
|
}
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
/** 제출 처리 - 데이터 검증 이후 메일 전송 완료되면 데이터 저장 */
|
|
const handleSubmit = () => {
|
|
if (validateData(submitData)) {
|
|
showConfirm(CONFIRM_MESSAGE.SUBMIT_CONFIRM, () => {
|
|
setIsShow(true)
|
|
sendEmail({
|
|
from: submitData.sender,
|
|
to: submitData.receiver,
|
|
cc: submitData.reference ?? '',
|
|
subject: submitData.title,
|
|
content: generateEmailContent(),
|
|
surveyPdf: {
|
|
id: surveyDetail?.id ?? 0,
|
|
filename: surveyDetail?.srlNo ?? 'hanasys_survey',
|
|
},
|
|
})
|
|
.then(() => {
|
|
submitSurvey({ targetId: submitData.targetId, targetNm: submitData.targetNm })
|
|
if (!isSubmittingSurvey) {
|
|
showSuccessAlert(SUCCESS_MESSAGE.SUBMIT_SUCCESS)
|
|
popupController.setSurveySaleSubmitPopup(false)
|
|
}
|
|
})
|
|
.catch((error) => {
|
|
console.error('❌ SEND EMAIL ERROR : ', error)
|
|
showErrorAlert(ERROR_MESSAGE.EMAIL_SEND_ERROR)
|
|
})
|
|
.finally(() => {
|
|
setIsShow(false)
|
|
popupController.setSurveySaleSubmitPopup(false)
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
const generateEmailContent = () => `
|
|
<div>
|
|
<p style="font-size: 13px; font-weight: 400; color: #2e3a59; margin-bottom: 15px;">
|
|
HANASYS現地調査アプリを使用した現地調査結果が送信されました。
|
|
</p>
|
|
<p style="font-size: 13px; font-weight: 400; color: #2e3a59; margin-bottom: 3px;">
|
|
-担当者名: <span style="color: #417DDC;">${surveyDetail?.representative}</span>
|
|
</p>
|
|
<p style="font-size: 13px; font-weight: 400; color: #2e3a59; margin-bottom: 3px;">
|
|
-販売店名:
|
|
<span style="color: #417DDC;">
|
|
${surveyDetail?.store ? `${surveyDetail?.store} (${surveyDetail?.storeId ?? ' - '})` : ' - '}
|
|
</span>
|
|
</p>
|
|
<p style="font-size: 13px; font-weight: 400; color: #2e3a59; margin-bottom: 15px;">
|
|
-施工店名:
|
|
<span style="color: #417DDC;">${surveyDetail?.constructionPoint ?? ' - '}</span>
|
|
</p>
|
|
</div>
|
|
`
|
|
|
|
const handleClose = () => {
|
|
popupController.setSurveySaleSubmitPopup(false)
|
|
}
|
|
|
|
/** 권한 별 폼 필드 렌더링 */
|
|
const renderFormField = (field: FormField) => {
|
|
const isReadOnly = false
|
|
|
|
if (field.id === 'saleBase' && session?.role !== 'Admin') {
|
|
return null
|
|
}
|
|
if (field.id === 'targetNm' && session?.role === 'Admin') {
|
|
return null
|
|
}
|
|
|
|
return (
|
|
<div className="data-input-form-bx" key={field.id}>
|
|
<div className="data-input-form-tit">
|
|
{field.name} {field.required && <i className="import">*</i>}
|
|
</div>
|
|
<div className="data-input">
|
|
{field.id === 'contents' ? (
|
|
<div className="submit-content" id={field.id}>
|
|
<div dangerouslySetInnerHTML={{ __html: generateEmailContent() }} />
|
|
</div>
|
|
) : (
|
|
<>
|
|
{field.id === 'saleBase' && session?.role === 'Admin' ? (
|
|
<select
|
|
className="select-form"
|
|
id={field.id}
|
|
value={submitData[field.id] ?? ''}
|
|
onChange={(e) => {
|
|
const selectedOffice = commCodeList.find((item) => item.code === e.target.value)
|
|
if (selectedOffice) {
|
|
//@ts-ignore
|
|
const receiver = selectedOffice.REF_CHR1.split(';')
|
|
setSubmitData((prev) => ({
|
|
...prev,
|
|
receiver: receiver,
|
|
saleBase: e.target.value,
|
|
targetNm: selectedOffice.codeJp ?? '',
|
|
}))
|
|
}
|
|
}}
|
|
>
|
|
<option value="">選択してください</option>
|
|
{commCodeList.map((item) => (
|
|
<option key={item.code} value={item.code}>
|
|
{item.codeJp}
|
|
</option>
|
|
))}
|
|
</select>
|
|
) : (
|
|
<input
|
|
className="input-frame"
|
|
type="text"
|
|
id={field.id}
|
|
value={submitData[field.id] ?? ''}
|
|
onChange={(e) => handleInputChange(field.id, e.target.value)}
|
|
readOnly={isReadOnly}
|
|
/>
|
|
)}
|
|
</>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<div className="modal-popup">
|
|
<div className="modal-dialog">
|
|
<div className="modal-content">
|
|
<div className="modal-header">
|
|
<div className="modal-header-inner">
|
|
<div className="modal-name-wrap">
|
|
<div className="modal-img">
|
|
<Image src="/assets/images/layout/modal_header_icon04.svg" width={19} height={22} alt="" />
|
|
</div>
|
|
<div className="modal-name">調査物件の提出</div>
|
|
</div>
|
|
<button className="modal-close" onClick={handleClose}></button>
|
|
</div>
|
|
</div>
|
|
<div className="modal-body">
|
|
<div className="data-form-wrap">{FORM_FIELDS.map(renderFormField)}</div>
|
|
<div className="btn-flex-wrap">
|
|
<div className="btn-bx">
|
|
<button className="btn-frame n-blue icon" onClick={handleClose}>
|
|
閉じる<i className="btn-arr"></i>
|
|
</button>
|
|
</div>
|
|
<div className="btn-bx">
|
|
<button className="btn-frame red icon" onClick={handleSubmit} disabled={isSubmittingSurvey}>
|
|
転送<i className="btn-arr"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|