- 부가서비스 각 요청 페이지 : SnackBar 추가, 양식 수정

This commit is contained in:
HyeonJongKim
2025-10-29 14:33:24 +09:00
parent 5888c2844b
commit 448cdcc9d2
17 changed files with 462 additions and 334 deletions

View File

@@ -5,7 +5,8 @@ import { useLocation } from 'react-router';
import { IMAGE_ROOT } from "@/shared/constants/common";
import { PATHS } from '@/shared/constants/paths';
import { useExtensionLinkPayRequestMutation } from '@/entities/additional-service/api/link-payment/use-extension-link-pay-request-mutation';
import { ExtensionLinkPayRequestParams, LinkPaymentFormData } from '@/entities/additional-service/model/link-pay/types';
import { ExtensionLinkPayRequestParams, ExtensionLinkPayRequestResponse, LinkPaymentFormData } from '@/entities/additional-service/model/link-pay/types';
import { snackBar } from '@/shared/lib';
export const LinkPaymentApplyConfirmPage = () => {
const { navigate } = useNavigate();
@@ -40,17 +41,30 @@ export const LinkPaymentApplyConfirmPage = () => {
language: formData.language,
linkContentType: formData.linkContentType
};
console.log("Link Payment 요청 파라미터: ", requestParams);
linkPayRequest(requestParams)
.then((response) => {
console.log("Link Payment 성공 응답: ", response);
navigate(PATHS.additionalService.linkPayment.confirmSuccess);
.then((rs: ExtensionLinkPayRequestResponse) => {
if (rs.status) {
navigate(PATHS.additionalService.linkPayment.confirmSuccess);
} else {
// 응답은 성공했지만 status가 false인 경우
const validationErrors = rs.error?.details?.validationErrors;
if (validationErrors) {
// validation 에러 메시지들을 수집
const errorMessages = Object.values(validationErrors).join('\n');
snackBar(`[실패] ${errorMessages}`);
} else {
// 일반 에러 메시지
const errorMessage = rs.error?.message || '요청을 처리할 수 없습니다.';
snackBar(`[실패] ${errorMessage}`);
}
}
})
.catch((error) => {
console.error("Link Payment 실패: ", error);
// 에러 처리 로직 추가 가능
// 네트워크 에러 등 예외 상황
const errorMessage = error?.response?.data?.error?.message ||
error?.message ||
'요청 중 오류가 발생했습니다';
snackBar(`[실패] ${errorMessage}`);
});
};
@@ -66,18 +80,18 @@ export const LinkPaymentApplyConfirmPage = () => {
<div className="attention-icon" aria-hidden="true">
<img src={IMAGE_ROOT + '/ico_alert.svg'} alt="주의" />
</div>
<h1 className="preview-title"> <br/> </h1>
<h1 className="preview-title"> <br /> </h1>
<div className="preview-result">
<p className="preview-text">
TEST , ?<br/>
<br/>
.<br/>
URL로 .<br/><br/>
!$&#123;pay_url&#125;<br/><br/>
{formData.buyerName} , ?<br />
<br />
.<br />
URL로 .<br /><br />
!$&#123;pay_url&#125;<br /><br />
<b>
상호 : 나이스페이먼츠 <br/>
: {formData.goodsName}<br/>
: {formData.amount}
상호 : 나이스페이먼츠 <br />
: {formData.goodsName}<br />
: {formData.amount.toLocaleString()}
</b>
</p>
</div>

View File

@@ -1,11 +1,11 @@
import {useState} from 'react';
import {LinkPaymentStep1} from '@/entities/additional-service/ui/link-payment/apply/link-payment-step1';
import {LinkPaymentStep2} from '@/entities/additional-service/ui/link-payment/apply/link-payment-step2';
import {HeaderType} from '@/entities/common/model/types';
import {ProcessStep} from '@/entities/transaction/model/types';
import {useSetFooterMode, useSetHeaderTitle, useSetHeaderType} from '@/widgets/sub-layout/use-sub-layout';
import {useNavigate} from '@/shared/lib/hooks/use-navigate';
import {PATHS} from "@/shared/constants/paths";
import { useState } from 'react';
import { LinkPaymentStep1 } from '@/entities/additional-service/ui/link-payment/apply/link-payment-step1';
import { LinkPaymentStep2 } from '@/entities/additional-service/ui/link-payment/apply/link-payment-step2';
import { HeaderType } from '@/entities/common/model/types';
import { ProcessStep } from '@/entities/transaction/model/types';
import { useSetFooterMode, useSetHeaderTitle, useSetHeaderType } from '@/widgets/sub-layout/use-sub-layout';
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { PATHS } from "@/shared/constants/paths";
import { IdentityType, Language } from '@/entities/additional-service/model/types';
import { LinkContentType, LinkPaymentFormData, LinkPaymentSendMethod } from '@/entities/additional-service/model/link-pay/types';
import { useStore } from '@/shared/model/store';
@@ -14,25 +14,25 @@ import moment from 'moment';
export const LinkPaymentApplyPage = () => {
const { navigate } = useNavigate();
const userMid = useStore.getState().UserStore.mid;
const [processStep, setProcessStep] = useState<ProcessStep>(ProcessStep.One);
const [formData, setFormData] = useState<LinkPaymentFormData>({
mid: userMid,
sendMethod: LinkPaymentSendMethod.SMS,
goodsName: '',
amount: 0,
moid: '',
paymentLimitDate: moment().format('YYYY.MM.DD'),
buyerName: '',
email: '',
phoneNumber: '',
isIdentity: false,
identityType: IdentityType.INDIVIDUAL,
identityValue: '',
language: Language.KR,
linkContentType: LinkContentType.BASIC
});
const { navigate } = useNavigate();
const userMid = useStore.getState().UserStore.mid;
const [processStep, setProcessStep] = useState<ProcessStep>(ProcessStep.One);
const [formData, setFormData] = useState<LinkPaymentFormData>({
mid: userMid,
sendMethod: LinkPaymentSendMethod.SMS,
goodsName: '',
amount: 0,
moid: '',
paymentLimitDate: moment().format('YYYY.MM.DD'),
buyerName: '',
email: '',
phoneNumber: '',
isIdentity: false,
identityType: IdentityType.INDIVIDUAL,
identityValue: '',
language: Language.KR,
linkContentType: LinkContentType.BASIC
});
useSetHeaderTitle('링크결제 신청');
useSetHeaderType(HeaderType.LeftArrow);
@@ -64,15 +64,11 @@ export const LinkPaymentApplyPage = () => {
// Step2 필수 필드 검증
const isStep2Valid = () => {
const basicFieldsValid = (
formData.buyerName.trim() !== '' &&
formData.email.trim() !== '' &&
isValidEmail(formData.email) &&
formData.phoneNumber.trim() !== '' &&
isValidPhoneNumber(formData.phoneNumber)
);
// isIdentity가 true면 identityValue도 필수
const basicFieldsValid = formData.sendMethod === 'EMAIL'
? formData.email.trim() !== '' && isValidEmail(formData.email)
: formData.buyerName.trim() !== '' && formData.phoneNumber.trim() !== '' && isValidPhoneNumber(formData.phoneNumber);
if (formData.isIdentity) {
return basicFieldsValid && formData.identityValue.trim() !== '';
}
@@ -85,14 +81,14 @@ export const LinkPaymentApplyPage = () => {
};
const onClickToChangeTab = () => {
if(processStep === ProcessStep.One) {
setProcessStep(ProcessStep.Two);
}
else if(processStep === ProcessStep.Two) {
navigate(PATHS.additionalService.linkPayment.requestConfirm, {
state: { formData }
});
}
if (processStep === ProcessStep.One) {
setProcessStep(ProcessStep.Two);
}
else if (processStep === ProcessStep.Two) {
navigate(PATHS.additionalService.linkPayment.requestConfirm, {
state: { formData }
});
}
};
return (
@@ -103,62 +99,62 @@ export const LinkPaymentApplyPage = () => {
<div className="option-list">
<div className="issue-progress">
<div className="bar">
{(processStep === ProcessStep.One) &&
<div
className="fill"
style={{ width: '50%' }}
></div>
}
{(processStep === ProcessStep.Two) &&
<div
className="fill"
style={{ width: '100%' }}
></div>
}
{(processStep === ProcessStep.One) &&
<div
className="fill"
style={{ width: '50%' }}
></div>
}
{(processStep === ProcessStep.Two) &&
<div
className="fill"
style={{ width: '100%' }}
></div>
}
</div>
</div>
{(processStep === ProcessStep.One) &&
<LinkPaymentStep1
formData={formData}
setFormData={setFormData}
></LinkPaymentStep1>
}
{ (processStep === ProcessStep.Two) &&
<LinkPaymentStep2
setProcessStep={ setProcessStep }
formData={formData}
setFormData={setFormData}
></LinkPaymentStep2>
}
</div>
{(processStep === ProcessStep.One) &&
<div className="apply-row">
<button
className="btn-50 btn-blue flex-1"
onClick={() => onClickToChangeTab()}
disabled={!isStep1Valid()}
></button>
</div>
<LinkPaymentStep1
formData={formData}
setFormData={setFormData}
></LinkPaymentStep1>
}
{(processStep === ProcessStep.Two) &&
<div className="apply-row two-button">
<button
className="btn-50 btn-darkgray flex-1"
onClick={() => onClickToBack()}
></button>
<button
className="btn-50 btn-blue flex-3"
onClick={() => onClickToChangeTab()}
disabled={!isStep2Valid()}
> </button>
</div>
<LinkPaymentStep2
setProcessStep={setProcessStep}
formData={formData}
setFormData={setFormData}
></LinkPaymentStep2>
}
</div>
{(processStep === ProcessStep.One) &&
<div className="apply-row">
<button
className="btn-50 btn-blue flex-1"
onClick={() => onClickToChangeTab()}
disabled={!isStep1Valid()}
></button>
</div>
}
{(processStep === ProcessStep.Two) &&
<div className="apply-row two-button">
<button
className="btn-50 btn-darkgray flex-1"
onClick={() => onClickToBack()}
></button>
<button
className="btn-50 btn-blue flex-3"
onClick={() => onClickToChangeTab()}
disabled={!isStep2Valid()}
> </button>
</div>
}
</div>
</div>
</main>
</>
);
};

View File

@@ -26,7 +26,7 @@ export const LinkPaymentWaitDetailPage = () => {
const [titleInfo, setTitleInfo] = useState<TitleInfo>();
const [paymentInfo, setPaymentInfo] = useState<PaymentInfo>();
useSetHeaderTitle('링크결제 상세_발송대기');
useSetHeaderTitle('링크결제 상세 발송대기');
useSetHeaderType(HeaderType.RightClose);
useSetOnBack(() => {
navigate(PATHS.additionalService.linkPayment.pendingSend);
@@ -56,23 +56,14 @@ export const LinkPaymentWaitDetailPage = () => {
}
linkPayWaitDelete(deleteParam)
.then((rs) => {
onClickToNavigate(PATHS.additionalService.linkPayment.pendingSend)
callDetail();
snackBar("삭제를 성공하였습니다.")
})
.catch((error) => {
console.error("Resend 실패: ", error);
snackBar(`[실패] ${error?.response?.data?.message}`)
});
}
const onClickToNavigate = (path: string) => {
let timeout = setTimeout(() => {
clearTimeout(timeout);
navigate(PATHS.additionalService.linkPayment.pendingSend, {
});
}, 10)
};
const onClickToCancel = () => {
let msg = '삭제 하시겠습니까?';