keyy1315 25a061b981 fix: Builder 권한 매물 작성 폼 수정
- 시공ID 없는 Builder 계정 작성 매물과 Admin_Sub 작성 매물 구분하기 위한 폼 수정
2025-07-25 14:49:04 +09:00

338 lines
11 KiB
TypeScript

'use client'
import type { Mode, SurveyBasicRequest, SurveyDetailInfo, SurveyDetailRequest } from '@/types/Survey'
import { CONFIRM_MESSAGE, SUCCESS_MESSAGE, useAlertMsg, WARNING_MESSAGE } from '@/hooks/useAlertMsg'
import { useSessionStore } from '@/store/session'
import { useParams, useRouter } from 'next/navigation'
import { useEffect, useState } from 'react'
import { usePopupController } from '@/store/popupController'
import { requiredFields, useSurvey } from '@/hooks/useSurvey'
interface ButtonFormProps {
mode: Mode
setMode: (mode: Mode) => void
data: {
basic: SurveyBasicRequest
roof: SurveyDetailRequest
}
}
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 params = useParams()
const id = Number(params.id)
const popupController = usePopupController()
const [saveData, setSaveData] = useState<SaveData>({
...data.basic,
detailInfo: data.roof,
})
const [permissions, setPermissions] = useState<PermissionState>({
isSubmiter: false,
isWriter: false,
isReceiver: false,
})
const isSubmit = data.basic.submissionStatus
const { deleteSurvey, updateSurvey, isDeletingSurvey, isUpdatingSurvey, isSubmittingSurvey, isLoadingSurveyDetail } = useSurvey(id)
const { validateSurveyDetail, createSurvey, isCreatingSurvey } = useSurvey()
const { showErrorAlert, showSuccessAlert, showConfirm } = useAlertMsg()
const buttonDisabled = isLoadingSurveyDetail || isSubmittingSurvey || isCreatingSurvey || isUpdatingSurvey || isDeletingSurvey
useEffect(() => {
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.userId === basicData.representativeId
const isReceiver =
session?.storeId === basicData.submissionTargetId ||
session?.storeNm === basicData.submissionTargetNm ||
(session?.role === 'T01' && basicData.submissionStatus && basicData.submissionTargetId === null && basicData.submissionTargetNm !== null)
return { isSubmiter, isWriter, isReceiver }
}
/** 제출 권한 체크 */
const calculateSubmitPermission = (session: any, basicData: SurveyBasicRequest): boolean => {
switch (session?.role) {
case 'T01':
case 'Admin':
return session.storeId === basicData.storeId
case 'Admin_Sub':
return session.storeId === basicData.storeId && session.builderId === basicData.constructionPointId
case 'Builder':
return session.builderId ? session.builderId === basicData.constructionPointId : session.userId === basicData.representativeId
case 'Partner':
return session.builderId === basicData.constructionPointId
default:
return false
}
}
/** 저장 로직 */
const handleSave = (isTemporary: boolean) => {
const emptyField = validateSurveyDetail(data.roof)
if (isTemporary) {
tempSaveProcess()
} else {
saveProcess(emptyField)
}
}
/** 임시 저장 로직 */
const tempSaveProcess = async () => {
/**route 에 id 가 있는 경우 업데이트, 없는 경우 생성 */
if (!Number.isNaN(id)) {
await updateSurvey({ survey: saveData, isTemporary: true })
if (!isUpdatingSurvey) {
setMode('READ')
}
} else {
const updatedData = {
...saveData,
srlNo: '一時保存',
}
const savedId = await createSurvey(updatedData)
if (!isCreatingSurvey) {
router.push(`/survey-sale/${savedId}`)
}
}
showSuccessAlert(SUCCESS_MESSAGE.TEMP_SAVE_SUCCESS)
}
/** 입력 필드 포커스 처리 */
const focusInput = (field: keyof SurveyDetailInfo) => {
const input = document.getElementById(field)
input?.focus()
}
/** 저장 로직 */
const saveProcess = async (emptyField: string | null) => {
if (emptyField?.trim() === '') {
showConfirm(CONFIRM_MESSAGE.SAVE_CONFIRM, async () => {
await handleSuccessfulSave()
})
} else {
handleFailedSave(emptyField)
}
}
/** 저장 성공 로직 */
const handleSuccessfulSave = async (isSubmitProcess?: boolean) => {
/** route 에 id 가 있는 경우 업데이트, 없는 경우 생성 */
if (!Number.isNaN(id)) {
await updateSurvey({
survey: saveData,
isTemporary: false,
storeId: session?.role === 'Partner' ? session?.builderId ?? null : session?.storeId ?? null,
})
if (!isUpdatingSurvey) {
setMode('READ')
if (isSubmitProcess) {
popupController.setSurveySaleSubmitPopup(true)
} else {
showSuccessAlert(SUCCESS_MESSAGE.SAVE_SUCCESS)
}
}
} else {
/** 제출 로직인 경우 search param 추가 */
const savedId = await createSurvey(saveData)
if (isSubmitProcess) {
await router.push(`/survey-sale/${savedId}?show=true`)
} else {
await router.push(`/survey-sale/${savedId}`)
showSuccessAlert(SUCCESS_MESSAGE.SAVE_SUCCESS)
}
}
}
/** 필수값 미입력 처리 */
const handleFailedSave = (emptyField: string | null) => {
if (emptyField?.includes('Unit')) {
showErrorAlert(WARNING_MESSAGE.REQUIRED_UNIT_IS_EMPTY)
} else {
const fieldInfo = requiredFields.find((field) => field.field === emptyField)
showErrorAlert(WARNING_MESSAGE.REQUIRED_FIELD_IS_EMPTY, fieldInfo?.name || '')
}
focusInput(emptyField as keyof SurveyDetailInfo)
}
/** 삭제 로직 */
const handleDelete = async () => {
if (!Number.isNaN(id)) {
showConfirm(CONFIRM_MESSAGE.DELETE_CONFIRM, async () => {
await deleteSurvey()
if (!isDeletingSurvey) {
showSuccessAlert(SUCCESS_MESSAGE.DELETE_SUCCESS)
router.push('/survey-sale')
}
})
}
}
/** 제출 로직 */
const handleSubmit = async () => {
if (mode === 'READ') {
if (data.basic.srlNo?.includes('一時保存')) {
showErrorAlert(WARNING_MESSAGE.TEMP_CANNOT_SUBMIT)
return
}
popupController.setSurveySaleSubmitPopup(true)
}
}
/** 로그인 여부 체크 */
if (!session?.isLoggedIn) return null
/** 읽기 모드, 제출 된 데이터, 제출 권한자는 리스트 버튼만 표시, 작성자만 삭제 가능*/
if (mode === 'READ' && isSubmit && permissions.isSubmiter) {
return (
<div className="sale-form-btn-wrap">
<div className="btn-flex-wrap">
<ListButton mode={mode} setMode={setMode} />
</div>
</div>
)
}
return (
<>
{/* 읽기 모드 버튼 처리 */}
{/* 작성자 - 수정, 삭제, 제출(미제출인 매물) 버튼 표시 */}
{/* 제출권한자 - 수정, 제출(미제출인 매물) 버튼 표시 */}
{/* 제출수신자 - 수정, 삭제 버튼 표시 */}
{mode === 'READ' && (
<div className="sale-form-btn-wrap">
<div className="btn-flex-wrap">
<ListButton mode={mode} setMode={setMode} />
{(permissions.isWriter || permissions.isSubmiter || (permissions.isReceiver && isSubmit)) && (
<EditButton setMode={setMode} disabled={buttonDisabled} />
)}
{(permissions.isWriter || (permissions.isReceiver && isSubmit)) && <DeleteButton handleDelete={handleDelete} disabled={buttonDisabled} />}
{!isSubmit && permissions.isSubmiter && !data.basic.srlNo?.includes('一時保存') && (
<SubmitButton handleSubmit={handleSubmit} disabled={buttonDisabled} />
)}
</div>
</div>
)}
{/* 수정, 작성 모드 */}
{/* 작성자 - 임시저장, 저장, 제출(미제출인 매물) 버튼 표시 */}
{/* 제출권한자 - 임시저장, 저장, 제출(미제출인 매물) 버튼 표시 */}
{/* 제출수신자 - 임시저장, 저장 버튼 표시 */}
{/* 수정화면에서는 리스트 버튼 클릭 시 READ 모드로 이동 */}
{(mode === 'CREATE' || mode === 'EDIT') && (
<div className="sale-form-btn-wrap">
<div className="btn-flex-wrap">
<ListButton mode={mode} setMode={setMode} />
{(data.basic.srlNo?.includes('一時保存') || mode === 'CREATE') && (
<TempButton handleSave={() => handleSave(true)} disabled={buttonDisabled} />
)}
<SaveButton handleSave={() => handleSave(false)} disabled={buttonDisabled} />
</div>
</div>
)}
</>
)
}
/** Button Components */
const ListButton = ({ mode, setMode }: { mode: Mode; setMode: (mode: Mode) => void }) => {
const router = useRouter()
const { showConfirm } = useAlertMsg()
return (
<div className="btn-bx">
<button
className="btn-frame n-blue icon"
onClick={() => {
if (mode === 'READ' || mode === 'CREATE') {
router.push('/survey-sale')
} else {
showConfirm(CONFIRM_MESSAGE.EDIT_CANCEL_CONFIRM, () => {
setMode('READ')
})
}
}}
>
{mode === 'READ' || mode === 'CREATE' ? 'リスト' : '戻る'}
<i className="btn-arr"></i>
</button>
</div>
)
}
const EditButton = ({ setMode, disabled }: { setMode: (mode: Mode) => void; disabled: boolean }) => {
return (
<div className="btn-bx">
<button
className="btn-frame n-blue icon"
onClick={() => {
setMode('EDIT')
}}
disabled={disabled}
>
<i className="btn-arr"></i>
</button>
</div>
)
}
const SubmitButton = ({ handleSubmit, disabled }: { handleSubmit: () => void; disabled: boolean }) => (
<div className="btn-bx">
<button className="btn-frame red icon" onClick={handleSubmit} disabled={disabled}>
<i className="btn-arr"></i>
</button>
</div>
)
const DeleteButton = ({ handleDelete, disabled }: { handleDelete: () => void; disabled: boolean }) => (
<div className="btn-bx">
<button className="btn-frame n-blue icon" onClick={handleDelete} disabled={disabled}>
<i className="btn-arr"></i>
</button>
</div>
)
const SaveButton = ({ handleSave, disabled }: { handleSave: () => void; disabled: boolean }) => (
<div className="btn-bx">
<button className="btn-frame n-blue icon" onClick={handleSave} disabled={disabled}>
<i className="btn-arr"></i>
</button>
</div>
)
const TempButton = ({ handleSave, disabled }: { handleSave: () => void; disabled: boolean }) => (
<div className="btn-bx">
<button className="btn-frame n-blue icon" onClick={handleSave} disabled={disabled}>
<i className="btn-arr"></i>
</button>
</div>
)