- 링크결제_분리승인 상세 추가
This commit is contained in:
@@ -0,0 +1,23 @@
|
|||||||
|
import { resultify } from "@/shared/lib/resultify";
|
||||||
|
import { ExtensionLInkPaySeparateActionParams, ExtensionLinkPaySeparateActionResponse } from "../../model/link-pay/types";
|
||||||
|
import axios from "axios";
|
||||||
|
import { API_URL_ADDITIONAL_SERVICE } from "@/shared/api/api-url-additional-service";
|
||||||
|
import { useMutation, UseMutationOptions } from "@tanstack/react-query";
|
||||||
|
import { CBDCAxiosError } from "@/shared/@types/error";
|
||||||
|
|
||||||
|
export const extensionLinkPaySeparateAction = (params: ExtensionLInkPaySeparateActionParams) => {
|
||||||
|
return resultify(
|
||||||
|
axios.post<ExtensionLinkPaySeparateActionResponse>(API_URL_ADDITIONAL_SERVICE.extensionLinkPaymentSeparateAction(), params)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useExtensionLinkPaySeparateAction = (options?: UseMutationOptions<ExtensionLinkPaySeparateActionResponse, CBDCAxiosError, ExtensionLInkPaySeparateActionParams>) => {
|
||||||
|
const mutation = useMutation<ExtensionLinkPaySeparateActionResponse, CBDCAxiosError, ExtensionLInkPaySeparateActionParams>({
|
||||||
|
...options,
|
||||||
|
mutationFn: (params: ExtensionLInkPaySeparateActionParams) => extensionLinkPaySeparateAction(params),
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
...mutation,
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { resultify } from "@/shared/lib/resultify";
|
||||||
|
import { ExtensionLinkPaySeparateDetailParams, ExtensionLinkPaySeparateDetailResponse } from "../../model/link-pay/types";
|
||||||
|
import axios from "axios";
|
||||||
|
import { API_URL_ADDITIONAL_SERVICE } from "@/shared/api/api-url-additional-service";
|
||||||
|
import { useMutation, UseMutationOptions } from "@tanstack/react-query";
|
||||||
|
import { CBDCAxiosError } from "@/shared/@types/error";
|
||||||
|
|
||||||
|
export const extensionLinkPaySeparateDetail = (params: ExtensionLinkPaySeparateDetailParams) => {
|
||||||
|
return resultify(
|
||||||
|
axios.post<ExtensionLinkPaySeparateDetailResponse>(API_URL_ADDITIONAL_SERVICE.extensionLinkPaymentSeparateDetail(), params)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useExtensionLinkPaySeparateDetail = (options?: UseMutationOptions<ExtensionLinkPaySeparateDetailResponse,CBDCAxiosError, ExtensionLinkPaySeparateDetailParams>) => {
|
||||||
|
const mutation = useMutation<ExtensionLinkPaySeparateDetailResponse, CBDCAxiosError, ExtensionLinkPaySeparateDetailParams>({
|
||||||
|
...options,
|
||||||
|
mutationFn: (params: ExtensionLinkPaySeparateDetailParams) => extensionLinkPaySeparateDetail(params),
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
...mutation,
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -64,6 +64,16 @@ export enum LinkContentType {
|
|||||||
ADDITIONAL = "ADDITIONAL"
|
ADDITIONAL = "ADDITIONAL"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum LinkPaymentSeparateType {
|
||||||
|
MAIN = "MAIN",
|
||||||
|
SUB = "SUB"
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum LinkPaymentSeparateAction {
|
||||||
|
EXTEND = "EXTEND",
|
||||||
|
DEACTIVATE = "DEACTIVATE"
|
||||||
|
}
|
||||||
|
|
||||||
export interface LinkPaymentHistoryListItem {
|
export interface LinkPaymentHistoryListItem {
|
||||||
requestId?: string;
|
requestId?: string;
|
||||||
cursorId?: string;
|
cursorId?: string;
|
||||||
@@ -301,3 +311,43 @@ export interface ExtensionLinkPayWaitDeleteParams extends ExtensionRequestParams
|
|||||||
export interface ExtensionLinkPayWaitDeleteRespone {
|
export interface ExtensionLinkPayWaitDeleteRespone {
|
||||||
status: boolean
|
status: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 분리승인 상세 조회 Request
|
||||||
|
export interface ExtensionLinkPaySeparateDetailParams {
|
||||||
|
reqId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 분리승인 상세 조회 Response Item
|
||||||
|
export interface ExtensionLinkPaySeparateDetailItem {
|
||||||
|
type: string;
|
||||||
|
moid: string;
|
||||||
|
amount: number;
|
||||||
|
paymentStatus: string;
|
||||||
|
paymentStatusName: string;
|
||||||
|
paymentLimitDate: string;
|
||||||
|
paymentLimitCount: number;
|
||||||
|
requestId: string;
|
||||||
|
subRequestId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 분리승인 상세 조회 Response
|
||||||
|
export interface ExtensionLinkPaySeparateDetailResponse {
|
||||||
|
details: Array<ExtensionLinkPaySeparateDetailItem>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ExtensionLInkPaySeparateActionParams extends ExtensionRequestParams {
|
||||||
|
action: string;
|
||||||
|
reqId: string;
|
||||||
|
selectedItems: Array<{
|
||||||
|
type: string;
|
||||||
|
subRequestId: string;
|
||||||
|
}>;
|
||||||
|
extendDate?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ExtensionLinkPaySeparateActionResponse {
|
||||||
|
success : boolean;
|
||||||
|
totalCount: number;
|
||||||
|
successCount: number;
|
||||||
|
failCount: number;
|
||||||
|
}
|
||||||
@@ -117,6 +117,7 @@ export interface DetailResponse {
|
|||||||
titleInfo?: TitleInfo //최상단 섹션
|
titleInfo?: TitleInfo //최상단 섹션
|
||||||
detailInfo?: DetailInfo // '상세 정보' 섹션
|
detailInfo?: DetailInfo // '상세 정보' 섹션
|
||||||
paymentInfo?: PaymentInfo // '결제 정보' 섹션
|
paymentInfo?: PaymentInfo // '결제 정보' 섹션
|
||||||
|
detailExposure?: boolean // 분리승인 상세 노출 여부
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DetailInfoSectionProps extends DetailResponse {
|
export interface DetailInfoSectionProps extends DetailResponse {
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ export const LinkPaymentHistoryList = ({
|
|||||||
let date = '';
|
let date = '';
|
||||||
let list: LinkPaymentHistoryListItem[] = [];
|
let list: LinkPaymentHistoryListItem[] = [];
|
||||||
for (let i = 0; i < listItems.length; i++) {
|
for (let i = 0; i < listItems.length; i++) {
|
||||||
// paymentDate format: "20211018140420" (YYYYMMDDHHmmss)
|
|
||||||
|
// sendDate(발송일자) 기준
|
||||||
let sendDate = listItems[i]?.sendDate || '';
|
let sendDate = listItems[i]?.sendDate || '';
|
||||||
let itemDate = sendDate.substring(0, 8);
|
let itemDate = sendDate.substring(0, 8);
|
||||||
if (i === 0) {
|
if (i === 0) {
|
||||||
|
|||||||
@@ -395,7 +395,7 @@ export const ListItem = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
else if (additionalServiceCategory === AdditionalServiceCategory.LinkPaymentHistory) {
|
else if (additionalServiceCategory === AdditionalServiceCategory.LinkPaymentHistory) {
|
||||||
if (paymentStatus === "3" || paymentStatus === "4") {
|
if (paymentStatus === "0" || paymentStatus === "3" || paymentStatus === "4") {
|
||||||
rs.push(
|
rs.push(
|
||||||
<div key="link-payment-history" className="transaction-details">
|
<div key="link-payment-history" className="transaction-details">
|
||||||
<span>{getPaymentStatusText(paymentStatus)}</span>
|
<span>{getPaymentStatusText(paymentStatus)}</span>
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export const LinkPaymentDetailPage = () => {
|
|||||||
const [titleInfo, setTitleInfo] = useState<TitleInfo>();
|
const [titleInfo, setTitleInfo] = useState<TitleInfo>();
|
||||||
const [detailInfo, setDetailInfo] = useState<DetailInfo>();
|
const [detailInfo, setDetailInfo] = useState<DetailInfo>();
|
||||||
const [paymentInfo, setPaymentInfo] = useState<PaymentInfo>();
|
const [paymentInfo, setPaymentInfo] = useState<PaymentInfo>();
|
||||||
|
const [detailExposure, setDetailExposure] = useState<boolean>(false);
|
||||||
const [showPayment, setShowPayment] = useState<boolean>(false);
|
const [showPayment, setShowPayment] = useState<boolean>(false);
|
||||||
|
|
||||||
useSetHeaderTitle('링크결제 상세');
|
useSetHeaderTitle('링크결제 상세');
|
||||||
@@ -54,10 +54,11 @@ export const LinkPaymentDetailPage = () => {
|
|||||||
setTitleInfo(rs.titleInfo)
|
setTitleInfo(rs.titleInfo)
|
||||||
setDetailInfo(rs.detailInfo)
|
setDetailInfo(rs.detailInfo)
|
||||||
setPaymentInfo(rs.paymentInfo)
|
setPaymentInfo(rs.paymentInfo)
|
||||||
|
setDetailExposure(rs.detailExposure ?? false)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//제발송 API
|
//재발송 API
|
||||||
const resendPayment = () => {
|
const resendPayment = () => {
|
||||||
let resendParam: ExtensionLinkPayHistoryResendParams = {
|
let resendParam: ExtensionLinkPayHistoryResendParams = {
|
||||||
mid: mid,
|
mid: mid,
|
||||||
@@ -107,7 +108,7 @@ export const LinkPaymentDetailPage = () => {
|
|||||||
|
|
||||||
const onClickToSeparateApproval = () => {
|
const onClickToSeparateApproval = () => {
|
||||||
navigate(PATHS.additionalService.linkPayment.separateApproval, {
|
navigate(PATHS.additionalService.linkPayment.separateApproval, {
|
||||||
state: { mid, tid }
|
state: { mid, requestId }
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -154,19 +155,20 @@ export const LinkPaymentDetailPage = () => {
|
|||||||
detailInfo={detailInfo}
|
detailInfo={detailInfo}
|
||||||
></DetailInfoWrap>
|
></DetailInfoWrap>
|
||||||
</div>
|
</div>
|
||||||
{/* <div className="apply-row">
|
<div className="apply-row">
|
||||||
<button
|
<button
|
||||||
className="btn-50 btn-blue flex-1"
|
className="btn-50 btn-blue flex-1"
|
||||||
onClick={() => onClickToSeparateApproval()}
|
onClick={() => onClickToSeparateApproval()}
|
||||||
|
disabled={false}
|
||||||
>분리승인 상세</button>
|
>분리승인 상세</button>
|
||||||
</div> */}
|
</div>
|
||||||
<div className="apply-row">
|
{/* <div className="apply-row">
|
||||||
<button
|
<button
|
||||||
className="btn-50 btn-blue flex-1"
|
className="btn-50 btn-blue flex-1"
|
||||||
onClick={() => onClickToResend()}
|
onClick={() => onClickToResend()}
|
||||||
disabled={!isResendEnabled()}
|
disabled={!isResendEnabled()}
|
||||||
>재발송</button>
|
>재발송</button>
|
||||||
</div>
|
</div> */}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main >
|
</main >
|
||||||
|
|||||||
@@ -10,19 +10,27 @@ import {
|
|||||||
export interface LinkPaymentApplyFailPageProps {
|
export interface LinkPaymentApplyFailPageProps {
|
||||||
pageOn: boolean;
|
pageOn: boolean;
|
||||||
setPageOn: (pageOn: boolean) => void;
|
setPageOn: (pageOn: boolean) => void;
|
||||||
|
resultMessage?: string;
|
||||||
errorMessage?: string;
|
errorMessage?: string;
|
||||||
|
successCount?: number;
|
||||||
|
failCount?: number;
|
||||||
|
totalCount?: number;
|
||||||
|
onClose?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const LinkPaymentApplyFailPage = ({
|
export const LinkPaymentApplyFailPage = ({
|
||||||
pageOn,
|
pageOn,
|
||||||
setPageOn,
|
setPageOn,
|
||||||
errorMessage
|
resultMessage,
|
||||||
|
errorMessage,
|
||||||
|
onClose
|
||||||
}: LinkPaymentApplyFailPageProps) => {
|
}: LinkPaymentApplyFailPageProps) => {
|
||||||
const { navigate } = useNavigate();
|
|
||||||
|
|
||||||
const onClickToClose = () => {
|
const onClickToClose = () => {
|
||||||
setPageOn(false);
|
setPageOn(false);
|
||||||
navigate(PATHS.additionalService.linkPayment.shippingHistory);
|
if (onClose) {
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -44,10 +52,14 @@ export const LinkPaymentApplyFailPage = ({
|
|||||||
></div>
|
></div>
|
||||||
<h1 className="success-title">
|
<h1 className="success-title">
|
||||||
<span>링크결제_분리승인</span>
|
<span>링크결제_분리승인</span>
|
||||||
<br />
|
|
||||||
<span>처리에 실패했습니다</span>
|
|
||||||
|
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
|
{resultMessage && (
|
||||||
|
<p className="result-text" style={{ textAlign: 'center', marginBottom: '20px' }}>
|
||||||
|
{resultMessage}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="success-result">
|
<div className="success-result">
|
||||||
<p className="result-text align-left position_label">
|
<p className="result-text align-left position_label">
|
||||||
<span>결과 :</span>
|
<span>결과 :</span>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState, useCallback } from 'react';
|
||||||
import { PATHS } from '@/shared/constants/paths';
|
import { PATHS } from '@/shared/constants/paths';
|
||||||
|
import { useLocation } from 'react-router';
|
||||||
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
|
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
|
||||||
import { HeaderType } from '@/entities/common/model/types';
|
import { HeaderType } from '@/entities/common/model/types';
|
||||||
import {
|
import {
|
||||||
@@ -12,46 +13,35 @@ import { ExtendedPeriodBottomSheet } from '@/entities/additional-service/ui/link
|
|||||||
import { LinkBreakBottomSheet } from '@/entities/additional-service/ui/link-payment/bottom-sheet/link-break-bottom-sheet';
|
import { LinkBreakBottomSheet } from '@/entities/additional-service/ui/link-payment/bottom-sheet/link-break-bottom-sheet';
|
||||||
import { LinkPaymentApplySuccessPage } from './link-payment-separate-approval-success-page';
|
import { LinkPaymentApplySuccessPage } from './link-payment-separate-approval-success-page';
|
||||||
import { LinkPaymentApplyFailPage } from './link-payment-separate-approval-fail';
|
import { LinkPaymentApplyFailPage } from './link-payment-separate-approval-fail';
|
||||||
|
import { useExtensionLinkPaySeparateAction } from '@/entities/additional-service/api/link-payment/use-extension-link-pay-separate-action-mutaion';
|
||||||
interface SeparateApprovalItem {
|
import { useExtensionLinkPaySeparateDetail } from '@/entities/additional-service/api/link-payment/use-extension-link-pay-separate-detail-mutation';
|
||||||
tid: string;
|
import { ExtensionLinkPaySeparateDetailItem, LinkPaymentSeparateAction, LinkPaymentSeparateType } from '@/entities/additional-service/model/link-pay/types';
|
||||||
merchantId: string;
|
import { useStore } from '@/shared/model/store';
|
||||||
amount: number;
|
import moment from 'moment';
|
||||||
status: string;
|
|
||||||
validityPeriod: string;
|
|
||||||
approvalCount: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const LinkPaymentSeparateApprovalPage = () => {
|
export const LinkPaymentSeparateApprovalPage = () => {
|
||||||
const { navigate } = useNavigate();
|
const { navigate } = useNavigate();
|
||||||
|
const location = useLocation();
|
||||||
|
const userMid = useStore.getState().UserStore.mid;
|
||||||
|
|
||||||
|
const { mid: stateMid, requestId } = location.state || {};
|
||||||
|
const mid = stateMid || userMid;
|
||||||
|
|
||||||
|
const [items, setItems] = useState<ExtensionLinkPaySeparateDetailItem[]>([]);
|
||||||
const [selectedItems, setSelectedItems] = useState<string[]>([]);
|
const [selectedItems, setSelectedItems] = useState<string[]>([]);
|
||||||
|
const [extendPeriods, setExtendPeriods] = useState<{ [key: string]: string }>({});
|
||||||
const [extendedPeriodBottomSheetOn, setExtendedPeriodBottomSheetOn] = useState<boolean>(false);
|
const [extendedPeriodBottomSheetOn, setExtendedPeriodBottomSheetOn] = useState<boolean>(false);
|
||||||
const [linkBreakBottomSheetOn, setLinkBreakBottomSheetOn] = useState<boolean>(false);
|
const [linkBreakBottomSheetOn, setLinkBreakBottomSheetOn] = useState<boolean>(false);
|
||||||
const [successPageOn, setSuccessPageOn] = useState<boolean>(false);
|
const [successPageOn, setSuccessPageOn] = useState<boolean>(false);
|
||||||
const [failPageOn, setFailPageOn] = useState<boolean>(false);
|
const [failPageOn, setFailPageOn] = useState<boolean>(false);
|
||||||
const [resultMessage, setResultMessage] = useState<string>('');
|
const [resultMessage, setResultMessage] = useState<string>('');
|
||||||
const [errorMessage, setErrorMessage] = useState<string>('');
|
const [errorMessage, setErrorMessage] = useState<string>('');
|
||||||
|
const [successCount, setSuccessCount] = useState<number>(0);
|
||||||
|
const [failCount, setFailCount] = useState<number>(0);
|
||||||
|
const [totalCount, setTotalCount] = useState<number>(0);
|
||||||
|
|
||||||
const [mainItem] = useState<SeparateApprovalItem>({
|
const { mutateAsync: callItems } = useExtensionLinkPaySeparateDetail();
|
||||||
tid: 'NLPDAR2025101315330',
|
const { mutateAsync: linkPaySeparateAction } = useExtensionLinkPaySeparateAction();
|
||||||
merchantId: '100,000',
|
|
||||||
amount: 100000,
|
|
||||||
status: '활성화',
|
|
||||||
validityPeriod: '2025/10/13',
|
|
||||||
approvalCount: 0
|
|
||||||
});
|
|
||||||
|
|
||||||
const [additionalItems] = useState<SeparateApprovalItem[]>([
|
|
||||||
{
|
|
||||||
tid: '',
|
|
||||||
merchantId: '(NNN,NNN)',
|
|
||||||
amount: 0,
|
|
||||||
status: '(결제상태)',
|
|
||||||
validityPeriod: 'YYYY/MM/DD',
|
|
||||||
approvalCount: 0
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
useSetHeaderTitle('분리승인 상세');
|
useSetHeaderTitle('분리승인 상세');
|
||||||
useSetHeaderType(HeaderType.RightClose);
|
useSetHeaderType(HeaderType.RightClose);
|
||||||
@@ -60,30 +50,27 @@ export const LinkPaymentSeparateApprovalPage = () => {
|
|||||||
});
|
});
|
||||||
useSetFooterMode(false);
|
useSetFooterMode(false);
|
||||||
|
|
||||||
const handleCheckboxChange = (tid: string) => {
|
const handleCheckboxChange = (subRequestId: string) => {
|
||||||
setSelectedItems(prev => {
|
setSelectedItems(prev => {
|
||||||
if (prev.includes(tid)) {
|
if (prev.includes(subRequestId)) {
|
||||||
return prev.filter(id => id !== tid);
|
return prev.filter(id => id !== subRequestId);
|
||||||
} else {
|
} else {
|
||||||
return [...prev, tid];
|
return [...prev, subRequestId];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMainCheckboxChange = () => {
|
const handleExtendPeriodChange = (itemId: string, days: string) => {
|
||||||
const mainTid = mainItem.tid;
|
setExtendPeriods(prev => ({
|
||||||
setSelectedItems(prev => {
|
...prev,
|
||||||
if (prev.includes(mainTid)) {
|
[itemId]: days
|
||||||
return prev.filter(id => id !== mainTid);
|
}));
|
||||||
} else {
|
|
||||||
return [...prev, mainTid];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAdditionalCheckboxChange = (index: number) => {
|
// 기간연장 버튼 활성화 조건: 선택된 항목이 있고, 모든 선택된 항목의 연장기간이 설정됨
|
||||||
const itemTid = `additional-${index}`;
|
const isExtendButtonEnabled = () => {
|
||||||
handleCheckboxChange(itemTid);
|
if (selectedItems.length === 0) return false;
|
||||||
|
return selectedItems.every(id => extendPeriods[id] && extendPeriods[id] !== '');
|
||||||
};
|
};
|
||||||
|
|
||||||
const onClickToValidityPeriod = () => {
|
const onClickToValidityPeriod = () => {
|
||||||
@@ -100,42 +87,134 @@ export const LinkPaymentSeparateApprovalPage = () => {
|
|||||||
// 바텀시트 닫기
|
// 바텀시트 닫기
|
||||||
setExtendedPeriodBottomSheetOn(false);
|
setExtendedPeriodBottomSheetOn(false);
|
||||||
|
|
||||||
// 기간연장 API 호출 로직
|
// 선택된 항목이 없으면 리턴
|
||||||
console.log('기간연장 실행', selectedItems);
|
if (selectedItems.length === 0) {
|
||||||
// TODO: 실제 API 호출
|
setErrorMessage('선택된 항목이 없습니다.');
|
||||||
const apiCallSuccess = true; // 임시로 성공으로 설정
|
setFailPageOn(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (apiCallSuccess) {
|
// 모든 선택된 항목들의 연장 기간이 설정되었는지 확인
|
||||||
setResultMessage('기간이 성공적으로 연장되었습니다');
|
const allHaveExtendPeriod = selectedItems.every(id => extendPeriods[id]);
|
||||||
|
|
||||||
|
if (!allHaveExtendPeriod) {
|
||||||
|
setErrorMessage('모든 선택된 항목의 연장 기간을 선택해주세요.');
|
||||||
|
setFailPageOn(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 첫 번째 선택된 항목의 연장 기간 사용 (모든 항목이 같은 기간으로 연장)
|
||||||
|
const firstSelectedId = selectedItems[0] as string;
|
||||||
|
const extendDays = extendPeriods[firstSelectedId] as string;
|
||||||
|
|
||||||
|
// 연장 날짜 계산 (오늘 날짜 + 연장일수)
|
||||||
|
const extendDate = moment().add(parseInt(extendDays), 'days').format('YYYYMMDD');
|
||||||
|
|
||||||
|
// selectedItems를 API 형식으로 변환
|
||||||
|
const selectedItemsData = selectedItems.map(itemId => {
|
||||||
|
const item = items.find(i => (i.subRequestId || `item-${items.indexOf(i)}`) === itemId);
|
||||||
|
return {
|
||||||
|
type: item?.type || '',
|
||||||
|
subRequestId: item?.subRequestId || itemId
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// 기간연장 API 호출
|
||||||
|
linkPaySeparateAction({
|
||||||
|
mid: mid,
|
||||||
|
action: LinkPaymentSeparateAction.EXTEND,
|
||||||
|
reqId: requestId,
|
||||||
|
selectedItems: selectedItemsData,
|
||||||
|
extendDate: extendDate
|
||||||
|
}).then((response) => {
|
||||||
|
setSuccessCount(response.successCount);
|
||||||
|
setFailCount(response.failCount);
|
||||||
|
setTotalCount(response.totalCount);
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
setResultMessage(`전체요청 성공했습니다.`);
|
||||||
setSuccessPageOn(true);
|
setSuccessPageOn(true);
|
||||||
} else {
|
} else {
|
||||||
setErrorMessage('기간 연장에 실패했습니다');
|
setResultMessage(`유효기간 연장에 실패했습니다. 개별 상태를 확인해주세요.`);
|
||||||
|
setErrorMessage('');
|
||||||
setFailPageOn(true);
|
setFailPageOn(true);
|
||||||
}
|
}
|
||||||
|
}).catch((error) => {
|
||||||
|
console.error('기간연장 실패:', error);
|
||||||
|
setResultMessage('유효기간 연장에 실패했습니다.');
|
||||||
|
setFailPageOn(true);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleLinkBreak = () => {
|
const handleLinkBreak = () => {
|
||||||
// 바텀시트 닫기
|
// 바텀시트 닫기
|
||||||
setLinkBreakBottomSheetOn(false);
|
setLinkBreakBottomSheetOn(false);
|
||||||
|
|
||||||
// 링크중단 API 호출 로직
|
// 선택된 항목이 없으면 리턴
|
||||||
console.log('링크중단 실행', selectedItems);
|
if (selectedItems.length === 0) {
|
||||||
// TODO: 실제 API 호출
|
setErrorMessage('선택된 항목이 없습니다.');
|
||||||
const apiCallSuccess = true; // 임시로 성공으로 설정
|
setFailPageOn(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (apiCallSuccess) {
|
const selectedItemsData = selectedItems.map(itemId => {
|
||||||
setResultMessage('링크가 성공적으로 중단되었습니다');
|
const item = items.find(i => (i.subRequestId || `item-${items.indexOf(i)}`) === itemId);
|
||||||
|
return {
|
||||||
|
type: item?.type || '',
|
||||||
|
subRequestId: item?.subRequestId || itemId
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// 링크중단 API 호출
|
||||||
|
linkPaySeparateAction({
|
||||||
|
mid: mid,
|
||||||
|
action: LinkPaymentSeparateAction.DEACTIVATE,
|
||||||
|
reqId: requestId,
|
||||||
|
selectedItems: selectedItemsData
|
||||||
|
}).then((response) => {
|
||||||
|
setSuccessCount(response.successCount);
|
||||||
|
setFailCount(response.failCount);
|
||||||
|
setTotalCount(response.totalCount);
|
||||||
|
if (response.success) {
|
||||||
|
setResultMessage(`전체요청 성공했습니다.`);
|
||||||
setSuccessPageOn(true);
|
setSuccessPageOn(true);
|
||||||
} else {
|
} else {
|
||||||
setErrorMessage('링크 중단에 실패했습니다');
|
setResultMessage('링크중단 요청에 실패했습니다. 개별 상태를 확인해주세요.');
|
||||||
|
setErrorMessage('');
|
||||||
setFailPageOn(true);
|
setFailPageOn(true);
|
||||||
}
|
}
|
||||||
|
}).catch((error) => {
|
||||||
|
console.error('링크중단 실패:', error);
|
||||||
|
setResultMessage('링크중단 요청에 실패했습니다.');
|
||||||
|
setFailPageOn(true);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 데이터 새로고침 함수
|
||||||
|
const refreshItems = useCallback(() => {
|
||||||
|
if (requestId) {
|
||||||
|
callItems({ reqId: requestId }).then((response) => {
|
||||||
|
console.log('Separate Detail Response:', response);
|
||||||
|
// type이 MAIN인 항목을 최상위로 정렬
|
||||||
|
const sortedItems = [...(response.details || [])].sort((a, b) => {
|
||||||
|
if (a.type === LinkPaymentSeparateType.MAIN) return -1;
|
||||||
|
if (b.type === LinkPaymentSeparateType.MAIN) return 1;
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
setItems(sortedItems);
|
||||||
|
// 선택 항목과 연장 기간 초기화
|
||||||
|
setSelectedItems([]);
|
||||||
|
setExtendPeriods({});
|
||||||
|
}).catch((error) => {
|
||||||
|
console.error('Failed to load separate detail:', error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [requestId, callItems]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// API 호출하여 데이터 로드
|
// API 호출하여 데이터 로드
|
||||||
// const { mid, tid } = location.state || {};
|
refreshItems();
|
||||||
}, []);
|
}, [refreshItems]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -149,44 +228,49 @@ export const LinkPaymentSeparateApprovalPage = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="approval-cards-wrapper">
|
<div className="approval-cards-wrapper">
|
||||||
{/* Main Item */}
|
{items.map((item, index) => {
|
||||||
<div className={`approval-card ${selectedItems.includes(mainItem.tid) ? 'selected' : ''}`}>
|
const itemId = item.subRequestId || `item-${index}`;
|
||||||
|
return (
|
||||||
|
<div key={itemId} className={`approval-card ${selectedItems.includes(itemId) ? 'selected' : ''}`}>
|
||||||
<div className="card-header">
|
<div className="card-header">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
id={`checkbox-${mainItem.tid}`}
|
id={`checkbox-${itemId}`}
|
||||||
name={`checkbox-${mainItem.tid}`}
|
name={`checkbox-${itemId}`}
|
||||||
checked={selectedItems.includes(mainItem.tid)}
|
checked={selectedItems.includes(itemId)}
|
||||||
onChange={handleMainCheckboxChange}
|
onChange={() => handleCheckboxChange(itemId)}
|
||||||
className="card-checkbox"
|
className="card-checkbox"
|
||||||
/>
|
/>
|
||||||
<span className="card-tag">[MAIN]</span>
|
<span className="card-tag">[{item.type}]</span>
|
||||||
<span className="card-tid">{mainItem.tid}</span>
|
<span className="card-tid">{item.moid}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
<ul className="info-list">
|
<ul className="info-list">
|
||||||
<li>
|
<li>
|
||||||
<span className="label">• 거래금액:</span>
|
<span className="label">• 거래금액:</span>
|
||||||
<span className="value">{mainItem.merchantId}</span>
|
<span className="value">{item.amount.toLocaleString()}</span>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<span className="label">• 결제상태:</span>
|
<span className="label">• 결제상태:</span>
|
||||||
<span className="value">{mainItem.status}</span>
|
<span className="value">{item.paymentStatusName}</span>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<span className="label">• 유효기간:</span>
|
<span className="label">• 유효기간:</span>
|
||||||
<span className="value">{mainItem.validityPeriod}</span>
|
<span className="value">{item.paymentLimitDate}</span>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<span className="label">• 연장횟수:</span>
|
<span className="label">• 연장횟수:</span>
|
||||||
<span className="value">{mainItem.approvalCount}</span>
|
<span className="value">{item.paymentLimitCount}</span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div className="card-footer">
|
<div className="card-footer">
|
||||||
<div className="period-selector">
|
<div className="period-selector">
|
||||||
<label>연장기간</label>
|
<label>연장기간</label>
|
||||||
<select>
|
<select
|
||||||
|
value={extendPeriods[itemId] || ''}
|
||||||
|
onChange={(e) => handleExtendPeriodChange(itemId, e.target.value)}
|
||||||
|
>
|
||||||
<option value="">미설정</option>
|
<option value="">미설정</option>
|
||||||
<option value="1">1일</option>
|
<option value="1">1일</option>
|
||||||
<option value="2">2일</option>
|
<option value="2">2일</option>
|
||||||
@@ -199,57 +283,8 @@ export const LinkPaymentSeparateApprovalPage = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
);
|
||||||
{/* Additional Items */}
|
})}
|
||||||
{additionalItems.map((item, index) => (
|
|
||||||
<div key={index} className={`approval-card ${selectedItems.includes(`additional-${index}`) ? 'selected' : ''}`}>
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
checked={selectedItems.includes(`additional-${index}`)}
|
|
||||||
onChange={() => handleAdditionalCheckboxChange(index)}
|
|
||||||
className="card-checkbox"
|
|
||||||
/>
|
|
||||||
<div className="card-header">
|
|
||||||
<span className="card-tag">(유형)</span>
|
|
||||||
<span className="card-tig">주문번호</span>
|
|
||||||
</div>
|
|
||||||
<div className="card-body">
|
|
||||||
<ul className="info-list">
|
|
||||||
<li>
|
|
||||||
<span className="label">• 거래금액:</span>
|
|
||||||
<span className="value">{item.merchantId}</span>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<span className="label">• 결제상태:</span>
|
|
||||||
<span className="value">{item.status}</span>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<span className="label">• 유효기간:</span>
|
|
||||||
<span className="value">{item.validityPeriod}</span>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<span className="label">• 연장횟수:</span>
|
|
||||||
<span className="value">(N)</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div className="card-footer">
|
|
||||||
<div className="period-selector">
|
|
||||||
<label>연장기간</label>
|
|
||||||
<select>
|
|
||||||
<option value="">미설정</option>
|
|
||||||
<option value="1">1일</option>
|
|
||||||
<option value="2">2일</option>
|
|
||||||
<option value="3">3일</option>
|
|
||||||
<option value="4">4일</option>
|
|
||||||
<option value="5">5일</option>
|
|
||||||
<option value="6">6일</option>
|
|
||||||
<option value="7">7일</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -257,11 +292,13 @@ export const LinkPaymentSeparateApprovalPage = () => {
|
|||||||
<button
|
<button
|
||||||
className="btn-50 btn-blue flex-1"
|
className="btn-50 btn-blue flex-1"
|
||||||
onClick={onClickToValidityPeriod}
|
onClick={onClickToValidityPeriod}
|
||||||
|
disabled={!isExtendButtonEnabled()}
|
||||||
>기간연장
|
>기간연장
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="btn-50 btn-blue flex-1"
|
className="btn-50 btn-blue flex-1"
|
||||||
onClick={onClickToSendLink}
|
onClick={onClickToSendLink}
|
||||||
|
disabled={selectedItems.length === 0}
|
||||||
>링크중단
|
>링크중단
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -285,12 +322,15 @@ export const LinkPaymentSeparateApprovalPage = () => {
|
|||||||
pageOn={successPageOn}
|
pageOn={successPageOn}
|
||||||
setPageOn={setSuccessPageOn}
|
setPageOn={setSuccessPageOn}
|
||||||
resultMessage={resultMessage}
|
resultMessage={resultMessage}
|
||||||
|
onClose={refreshItems}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<LinkPaymentApplyFailPage
|
<LinkPaymentApplyFailPage
|
||||||
pageOn={failPageOn}
|
pageOn={failPageOn}
|
||||||
setPageOn={setFailPageOn}
|
setPageOn={setFailPageOn}
|
||||||
|
resultMessage={resultMessage}
|
||||||
errorMessage={errorMessage}
|
errorMessage={errorMessage}
|
||||||
|
onClose={refreshItems}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -11,18 +11,27 @@ export interface LinkPaymentApplySuccessPageProps {
|
|||||||
pageOn: boolean;
|
pageOn: boolean;
|
||||||
setPageOn: (pageOn: boolean) => void;
|
setPageOn: (pageOn: boolean) => void;
|
||||||
resultMessage?: string;
|
resultMessage?: string;
|
||||||
|
successCount?: number;
|
||||||
|
failCount?: number;
|
||||||
|
totalCount?: number;
|
||||||
|
onClose?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const LinkPaymentApplySuccessPage = ({
|
export const LinkPaymentApplySuccessPage = ({
|
||||||
pageOn,
|
pageOn,
|
||||||
setPageOn,
|
setPageOn,
|
||||||
resultMessage
|
resultMessage,
|
||||||
|
successCount,
|
||||||
|
failCount,
|
||||||
|
totalCount,
|
||||||
|
onClose
|
||||||
}: LinkPaymentApplySuccessPageProps) => {
|
}: LinkPaymentApplySuccessPageProps) => {
|
||||||
const { navigate } = useNavigate();
|
|
||||||
|
|
||||||
const onClickToClose = () => {
|
const onClickToClose = () => {
|
||||||
setPageOn(false);
|
setPageOn(false);
|
||||||
navigate(PATHS.additionalService.linkPayment.shippingHistory);
|
if (onClose) {
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -45,10 +54,11 @@ export const LinkPaymentApplySuccessPage = ({
|
|||||||
<h1 className="success-title">
|
<h1 className="success-title">
|
||||||
<span>링크결제_분리승인</span>
|
<span>링크결제_분리승인</span>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<div className="success-result">
|
<div className="success-result">
|
||||||
<p className="result-text align-left position_label">
|
<p className="result-text align-left position_label">
|
||||||
<span>결과 :</span>
|
<span>결과 :</span>
|
||||||
<span>{resultMessage || '성공적으로 처리되었습니다'}</span>
|
<span>{resultMessage || '전체요청 성공했습니다.'}</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -69,6 +69,14 @@ export const API_URL_ADDITIONAL_SERVICE = {
|
|||||||
// POST: 링크결제 - 발송대기 삭제
|
// POST: 링크결제 - 발송대기 삭제
|
||||||
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/extension/linkpay/wait/delete`;
|
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/extension/linkpay/wait/delete`;
|
||||||
},
|
},
|
||||||
|
extensionLinkPaymentSeparateDetail: () => {
|
||||||
|
// POST: 링크결제 - 분리승인 상세 조회
|
||||||
|
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/extension/linkpay/separate/detail`
|
||||||
|
},
|
||||||
|
extensionLinkPaymentSeparateAction: () => {
|
||||||
|
// POST: 링크결제 - 분리승인 액션
|
||||||
|
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/extension/linkpay/separate/action`
|
||||||
|
},
|
||||||
extensionSmsResend: () => {
|
extensionSmsResend: () => {
|
||||||
// POST: SMS 결제 통보 > SMS 재발송
|
// POST: SMS 결제 통보 > SMS 재발송
|
||||||
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/extension/sms/resend`;
|
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/extension/sms/resend`;
|
||||||
|
|||||||
Reference in New Issue
Block a user