Merge branch 'main' of https://gitea.bpsoft.co.kr/nicepayments/nice-app-web
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
import axios from 'axios';
|
||||
import { API_URL_ADDITIONAL_SERVICE } from '@/shared/api/api-url-additional-service';
|
||||
import { resultify } from '@/shared/lib/resultify';
|
||||
import { CBDCAxiosError } from '@/shared/@types/error';
|
||||
import {
|
||||
ExtensionCheckParams,
|
||||
ExtensionCheckResponse,
|
||||
ExtensionListParams,
|
||||
ExtensionListResponse
|
||||
} from '../model/types';
|
||||
import {
|
||||
useMutation,
|
||||
UseMutationOptions
|
||||
} from '@tanstack/react-query';
|
||||
|
||||
export const extensionCheck = (params: ExtensionCheckParams) => {
|
||||
return resultify(
|
||||
axios.post<ExtensionCheckResponse>(API_URL_ADDITIONAL_SERVICE.extensionCheck(), params),
|
||||
);
|
||||
};
|
||||
|
||||
export const useExtensionCheckMutation = (options?: UseMutationOptions<ExtensionCheckResponse, CBDCAxiosError, ExtensionCheckParams>) => {
|
||||
const mutation = useMutation<ExtensionCheckResponse, CBDCAxiosError, ExtensionCheckParams>({
|
||||
...options,
|
||||
mutationFn: (params: ExtensionCheckParams) => extensionCheck(params),
|
||||
});
|
||||
|
||||
return {
|
||||
...mutation,
|
||||
};
|
||||
};
|
||||
@@ -81,10 +81,10 @@ export const getAlimtalkServiceCodeText = (status?: string): string => {
|
||||
if (!status) return '';
|
||||
|
||||
const serviceCodeMap: Record<string, string> = {
|
||||
'01': '카드',
|
||||
'02': '신용카드',
|
||||
'03': '가상계좌',
|
||||
'05': '휴대폰'
|
||||
'CARD': '신용카드',
|
||||
'BANK': '계좌이체',
|
||||
'VBANK': '가상계좌',
|
||||
'PHONE': '휴대폰'
|
||||
}
|
||||
|
||||
return serviceCodeMap[status] || status;
|
||||
|
||||
@@ -126,14 +126,14 @@ export interface ExtensionAlimtalkDetailParams {
|
||||
|
||||
export interface ExtensionAlimtalkDetailResponse {
|
||||
receiverName: string;
|
||||
merchantName: string;
|
||||
companyName: string;
|
||||
sendDate: string;
|
||||
mid: string;
|
||||
tid: string;
|
||||
extensionServiceName: string;
|
||||
sendType: AlimtalkSendType;
|
||||
senderName: string;
|
||||
paymentMethod: string;
|
||||
serviceCode: string;
|
||||
alimCl: AlimtalkAlimCl;
|
||||
sendCl: AlimTalkSendCl;
|
||||
};
|
||||
|
||||
@@ -10,3 +10,15 @@ export const PayoutDisbursementStatusBtnGroup = [
|
||||
{name: '성공', value: PayoutDisbursementStatus.SUCCESS},
|
||||
{name: '실패', value: PayoutDisbursementStatus.FAIL},
|
||||
];
|
||||
|
||||
export const getPayoutStatusText = (status?: string): string => {
|
||||
if (!status) return '';
|
||||
|
||||
const statusMap: Record<string, string> = {
|
||||
"REQUEST" : "요청",
|
||||
"SUCCESS" : "성공",
|
||||
"FAIL" : "실패"
|
||||
}
|
||||
|
||||
return statusMap[status] || status;
|
||||
}
|
||||
@@ -6,7 +6,9 @@ export interface ExtensionPayoutRequestParams {
|
||||
disbursementAmount: number;
|
||||
settlementDate: string;
|
||||
};
|
||||
export interface ExtensionPayoutRequestResponse {};
|
||||
export interface ExtensionPayoutRequestResponse {
|
||||
status: boolean;
|
||||
};
|
||||
export enum PayoutSearchDateType {
|
||||
REQUEST_DATE = 'REQUEST_DATE',
|
||||
SETTLEMENT_DATE = 'SETTLEMENT_DATE',
|
||||
@@ -36,10 +38,15 @@ export interface PayoutContent {
|
||||
requestDate?: string;
|
||||
settlementDate?: string;
|
||||
companyName?: string;
|
||||
disbursementStatus?: PayoutDisbursementStatus;
|
||||
disbursementAmount?: number;
|
||||
status?: PayoutDisbursementStatus;
|
||||
amount?: number;
|
||||
};
|
||||
export interface ExtensionPayoutExcelParams {
|
||||
mid: string;
|
||||
email: string;
|
||||
fromDate: string;
|
||||
toDate: string;
|
||||
};
|
||||
export interface ExtensionPayoutExcelParams extends ExtensionPayoutListParams {};
|
||||
|
||||
export interface ExtensionPayoutExcelResponse {}
|
||||
|
||||
|
||||
@@ -117,6 +117,7 @@ export interface ExtensionSmsDownloadExcelParams extends ExtensionRequestParams
|
||||
fromDate: string;
|
||||
toDate: string;
|
||||
smsCl: string;
|
||||
|
||||
}
|
||||
|
||||
export interface ExtensionSmsDownloadExcelResponse {
|
||||
|
||||
@@ -10,6 +10,8 @@ import { AccountHolderSearchListItem } from './account-holder-search/types';
|
||||
import { KeyInPaymentListItem } from './key-in/types';
|
||||
import { AccountHolderAuthListItem, AccountHolderAuthStatus } from './account-holder-auth/types';
|
||||
import { LinkContentType, LinkPaymentHistoryListItem, LinkPaymentSendMethod, LinkPaymentWaitListItem } from './link-pay/types';
|
||||
import { IMAGE_ROOT } from '@/shared/constants/common';
|
||||
import { PATHS } from '@/shared/constants/paths';
|
||||
|
||||
// ========================================
|
||||
// 공통 Enums 및 타입들
|
||||
@@ -47,6 +49,20 @@ export enum Language {
|
||||
EN = "EN"
|
||||
}
|
||||
|
||||
export const SERVICE_MAP = [
|
||||
{ code: 'SMS', serviceName: 'SMS 결제 통보', serviceDesc: '입금 요청부터 완료까지 SMS 자동 전송', icon: IMAGE_ROOT + '/icon_ing03.svg', path: PATHS.additionalService.smsPaymentNotification },
|
||||
{ code: 'ARS', serviceName: '신용카드 ARS 결제', serviceDesc: '전화 한 통으로 결제 성공 편리하고 안전한 서비스', icon: IMAGE_ROOT + '/icon_ing01.svg', path: PATHS.additionalService.ars.list },
|
||||
{ code: 'KEYIN', serviceName: 'KEY-IN 결제', serviceDesc: '상담 중 카드정보 입력으로 간편한 결제 지원', icon: IMAGE_ROOT + '/icon_ing02.svg', path: PATHS.additionalService.keyInPayment.list },
|
||||
{ code: 'SEARCH_ACCOUNT_NAME', serviceName: '계좌성명조회', serviceDesc: '예금주 정보 입력으로 즉시 예금주 확인', icon: IMAGE_ROOT + '/icon_ing04.svg', path: PATHS.additionalService.accountHolderSearch.list },
|
||||
{ code: 'PAYOUT', serviceName: '지급대행', serviceDesc: '하위 가맹점에 빠른 정산금 지급 지급대행 서비스', icon: IMAGE_ROOT + '/icon_ing05.svg', path: PATHS.additionalService.payout.list },
|
||||
{ code: 'SETTLEMENT', serviceName: '정산대행', serviceDesc: '하위 가맹점 정산금 계산부터 지급까지 자동 해결 서비스', icon: IMAGE_ROOT + '/icon_ing06.svg', path: PATHS.additionalService.settlementAgency.manage },
|
||||
{ code: 'LINKPAY', serviceName: '링크 결제', serviceDesc: '결제 링크 전송만으로 어디서든 결제 가능 서비스', icon: IMAGE_ROOT + '/icon_ing07.svg', path: PATHS.additionalService.linkPayment.shippingHistory },
|
||||
{ code: 'FUND_ACCOUNT', serviceName: '자금이체', serviceDesc: '예치금으로 즉시 송금, 파일 등록만으로 다중 송금 가능', icon: IMAGE_ROOT + '/icon_ing08.svg', path: PATHS.additionalService.fundAccount.transferList },
|
||||
{ code: 'ACCOUNT_AUTH', serviceName: '계좌점유인증', serviceDesc: '1원 송금으로 실제 계좌 점유 확인 여부', icon: IMAGE_ROOT + '/icon_ing09.svg', path: PATHS.additionalService.accountHolderAuth.list },
|
||||
{ code: 'ALIMTALK', serviceName: '알림톡 결제통보', serviceDesc: '결제 상태를 알림톡으로 쉽고 빠른 안내', icon: IMAGE_ROOT + '/icon_ing10.svg', path: PATHS.additionalService.alimtalk.list },
|
||||
{ code: 'FACE_AUTH', serviceName: '얼굴인증', serviceDesc: '얼굴 인식으로 간편 본인확인과 결제 가능한 안전 결제 서비스', icon: IMAGE_ROOT + '/icon_ing11.svg', path: PATHS.additionalService.faceAuth.list },
|
||||
];
|
||||
|
||||
// ========================================
|
||||
// 상세정보 Interface
|
||||
// ========================================
|
||||
@@ -223,8 +239,17 @@ export interface ExtensionListItemProps {
|
||||
availableExtensionList: Array<availableExtensionListItem>;
|
||||
}
|
||||
|
||||
export interface ExtensionListResponse extends DefaulResponsePagination {
|
||||
content: Array<ExtensionListItemProps>
|
||||
export interface ExtensionListResponse {
|
||||
activeExtensionList: string[];
|
||||
availableExtensionList: string[];
|
||||
}
|
||||
|
||||
export interface ExtensionCheckParams {
|
||||
extensionCode: string;
|
||||
}
|
||||
|
||||
export interface ExtensionCheckResponse {
|
||||
checkResult: boolean;
|
||||
}
|
||||
|
||||
// ========================================
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import moment from 'moment';
|
||||
import { IMAGE_ROOT } from '@/shared/constants/common';
|
||||
import { motion } from 'framer-motion';
|
||||
import { useState } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { FilterSelect } from '@/shared/ui/filter/select';
|
||||
import { FilterCalendar } from '@/shared/ui/filter/calendar';
|
||||
import { FilterButtonGroups } from '@/shared/ui/filter/button-groups';
|
||||
@@ -42,6 +42,9 @@ export const AccountHolderAuthFilter = ({
|
||||
onClickToClose();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setFilterAuthStatus(authStatus);
|
||||
}, [authStatus]);
|
||||
return (
|
||||
<>
|
||||
<motion.div
|
||||
|
||||
@@ -49,8 +49,7 @@ export const ListDateGroup = ({
|
||||
submallId={ items[i]?.submallId }
|
||||
settlementDate={ items[i]?.settlementDate }
|
||||
companyName={ items[i]?. companyName }
|
||||
disbursementStatus={ items[i]?.disbursementStatus }
|
||||
disbursementAmount={ items[i]?.disbursementAmount }
|
||||
status={ items[i]?.status }
|
||||
|
||||
orderStatus={ items[i]?.orderStatus }
|
||||
arsPaymentMethod={ items[i]?.arsPaymentMethod }
|
||||
|
||||
@@ -12,30 +12,31 @@ import { getArsPaymentStatusName, getArsOrderStatusName } from '../model/ars/con
|
||||
import { ServiceCode } from '../model/alimtalk/types';
|
||||
import { getAlimtalkAlimClText, getAlimtalkSendClTypeText, getAlimtalkSendTypeText, getAlimtalkServiceCodeText } from '../model/alimtalk/constant';
|
||||
import { getAuthResultStatusText, getTransTypeText } from '../model/face-auth/constant';
|
||||
import { getPayoutStatusText } from '../model/payout/constant';
|
||||
|
||||
export const ListItem = ({
|
||||
additionalServiceCategory,
|
||||
mid, tid, paymentDate, paymentStatus,
|
||||
|
||||
applicationDate, requestDate, bankName, accountNo, resultStatus, resultMessage,
|
||||
amount, sendMethod, processStatus,registDate,
|
||||
amount, sendMethod, processStatus, registDate,
|
||||
|
||||
accountName,
|
||||
|
||||
submallId, settlementDate, companyName,
|
||||
disbursementStatus, disbursementAmount,
|
||||
status: disbursementStatus, amount: disbursementAmount,
|
||||
|
||||
orderStatus, arsPaymentMethod,
|
||||
|
||||
alimCl, sendType, sendCl,
|
||||
paymentMethod, receiverName,
|
||||
requestId,subReqId,
|
||||
buyerName,receiverInfo,
|
||||
seq,serviceCode,sendDate,
|
||||
authStatus,
|
||||
requestId, subReqId,
|
||||
buyerName, receiverInfo,
|
||||
seq, serviceCode, sendDate,
|
||||
authStatus, status,
|
||||
|
||||
smsCl,groupId,userMallId,transType,
|
||||
authResult,failReason,requestTime,
|
||||
smsCl, groupId, userMallId, transType,
|
||||
authResult, failReason, requestTime,
|
||||
onResendClick
|
||||
}: ListItemProps) => {
|
||||
const { navigate } = useNavigate();
|
||||
@@ -89,7 +90,7 @@ export const ListItem = ({
|
||||
}
|
||||
}
|
||||
else if (additionalServiceCategory === AdditionalServiceCategory.Alimtalk) {
|
||||
if (sendCl === "SUCCESS" || "REQUEST") {
|
||||
if (sendCl === "SUCCESS" || sendCl === "REQUEST") {
|
||||
rs = 'blue';
|
||||
} else {
|
||||
rs = 'gray';
|
||||
@@ -104,20 +105,13 @@ export const ListItem = ({
|
||||
}
|
||||
}
|
||||
else if (additionalServiceCategory === AdditionalServiceCategory.LinkPaymentHistory) {
|
||||
if (paymentStatus === "PAYMENT_COMPLETE") {
|
||||
if (paymentStatus === "0" || paymentStatus === "1" || paymentStatus === "2") {
|
||||
rs = 'blue';
|
||||
}
|
||||
|
||||
else if (paymentStatus === "ACTIVE") {
|
||||
rs = 'blue';
|
||||
else if (paymentStatus === "3") {
|
||||
rs = 'gray';
|
||||
}
|
||||
else if (paymentStatus === "DEPOSIT_REQUEST") {
|
||||
rs = 'blue';
|
||||
}
|
||||
else if (paymentStatus === "PAYMENT_FAIL") {
|
||||
rs = 'blue';
|
||||
}
|
||||
else if (paymentStatus === "INACTIVE") {
|
||||
else if (paymentStatus === '4') {
|
||||
rs = 'gray';
|
||||
}
|
||||
} else if (additionalServiceCategory === AdditionalServiceCategory.LinkPaymentWait) {
|
||||
@@ -144,6 +138,12 @@ export const ListItem = ({
|
||||
} else if (resultStatus === "FAIL") {
|
||||
rs = 'gray';
|
||||
}
|
||||
} else if (additionalServiceCategory === AdditionalServiceCategory.Payout) {
|
||||
if (status === "SUCCESS" || status === "REQUEST") {
|
||||
rs = 'blue';
|
||||
} else if (status === "FAIL") {
|
||||
rs = 'gray';
|
||||
}
|
||||
}
|
||||
return rs;
|
||||
|
||||
@@ -286,7 +286,7 @@ export const ListItem = ({
|
||||
if (applicationDate && applicationDate.length >= 12) {
|
||||
timeStr = applicationDate.substring(8, 10) + ':' + applicationDate.substring(10, 12);
|
||||
} else {
|
||||
timeStr = requestDate?.substring(8,10) + ':' + requestDate?.substring(10, 12);
|
||||
timeStr = requestDate?.substring(8, 10) + ':' + requestDate?.substring(10, 12);
|
||||
}
|
||||
}
|
||||
else if (additionalServiceCategory === AdditionalServiceCategory.Ars) {
|
||||
@@ -349,9 +349,10 @@ export const ListItem = ({
|
||||
else if (additionalServiceCategory === AdditionalServiceCategory.FaceAuth) {
|
||||
str = `${userMallId}(${mid})`;
|
||||
}
|
||||
else if (additionalServiceCategory === AdditionalServiceCategory.LinkPaymentHistory ||
|
||||
additionalServiceCategory === AdditionalServiceCategory.LinkPaymentWait
|
||||
else if (additionalServiceCategory === AdditionalServiceCategory.LinkPaymentHistory
|
||||
) {
|
||||
str = `${buyerName}`;
|
||||
} else if (additionalServiceCategory === AdditionalServiceCategory.LinkPaymentWait) {
|
||||
str = `${buyerName}(${receiverInfo})`;
|
||||
}
|
||||
else if (additionalServiceCategory === AdditionalServiceCategory.Payout) {
|
||||
@@ -451,7 +452,7 @@ export const ListItem = ({
|
||||
else if (additionalServiceCategory === AdditionalServiceCategory.Payout) {
|
||||
rs.push(
|
||||
<div className="transaction-details">
|
||||
<span>{disbursementStatus}</span>
|
||||
<span>{getPayoutStatusText(disbursementStatus)}</span>
|
||||
<span className="separator">|</span>
|
||||
<span>{submallId}</span>
|
||||
</div>
|
||||
@@ -498,7 +499,7 @@ export const ListItem = ({
|
||||
);
|
||||
}
|
||||
else if (additionalServiceCategory === AdditionalServiceCategory.Alimtalk) {
|
||||
console.log(serviceCode)
|
||||
console.log(serviceCode)
|
||||
rs.push(
|
||||
<div className="transaction-details">
|
||||
<span>{getTime()}</span>
|
||||
|
||||
90
src/entities/common/ui/download-type-bottom-sheet.tsx
Normal file
90
src/entities/common/ui/download-type-bottom-sheet.tsx
Normal file
@@ -0,0 +1,90 @@
|
||||
import { BottomSheetMotionDuration, BottomSheetMotionVaiants } from '@/entities/common/model/constant';
|
||||
import { IMAGE_ROOT } from '@/shared/constants/common';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
export interface DownloadTypeBottomSheetProps {
|
||||
bottomSheetOn: boolean;
|
||||
setBottomSheetOn: (bottomSheetOn: boolean) => void;
|
||||
onSelectType: (type: 'IMAGE' | 'EMAIL') => void;
|
||||
}
|
||||
|
||||
export const DownloadTypeBottomSheet = ({
|
||||
bottomSheetOn,
|
||||
setBottomSheetOn,
|
||||
onSelectType
|
||||
}: DownloadTypeBottomSheetProps) => {
|
||||
|
||||
const onClickToClose = () => {
|
||||
setBottomSheetOn(false);
|
||||
};
|
||||
|
||||
const handleSelectType = (type: 'IMAGE' | 'EMAIL') => {
|
||||
onSelectType(type);
|
||||
setBottomSheetOn(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{ (bottomSheetOn) &&
|
||||
<div className="bg-dim"></div>
|
||||
}
|
||||
<motion.div
|
||||
className="bottomsheet"
|
||||
initial="hidden"
|
||||
animate={ (bottomSheetOn)? 'visible': 'hidden' }
|
||||
variants={ BottomSheetMotionVaiants }
|
||||
transition={ BottomSheetMotionDuration }
|
||||
>
|
||||
<div className="bottomsheet-header">
|
||||
<div className="bottomsheet-title">
|
||||
<h2>다운로드 방식을 선택하세요</h2>
|
||||
<button
|
||||
className="close-btn"
|
||||
type="button"
|
||||
>
|
||||
<img
|
||||
src={ IMAGE_ROOT + '/ico_close.svg' }
|
||||
alt="닫기"
|
||||
onClick={ () => onClickToClose() }
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bottomsheet-content">
|
||||
<div className="email-section">
|
||||
<div
|
||||
className="email-label mb-10"
|
||||
onClick={() => handleSelectType('IMAGE')}
|
||||
style={{ cursor: 'pointer' }}
|
||||
>
|
||||
<div className="mail-icon">
|
||||
<div className="mail-icon-bg"></div>
|
||||
<img
|
||||
src={ IMAGE_ROOT + '/ico_pic.svg' }
|
||||
alt="이미지"
|
||||
/>
|
||||
</div>
|
||||
<span className="label-text">이미지 저장</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="email-label"
|
||||
onClick={() => handleSelectType('EMAIL')}
|
||||
style={{ cursor: 'pointer' }}
|
||||
>
|
||||
<div className="mail-icon">
|
||||
<div className="mail-icon-bg"></div>
|
||||
<img
|
||||
src={ IMAGE_ROOT + '/ico_email.svg' }
|
||||
alt='메일'
|
||||
/>
|
||||
</div>
|
||||
<span className="label-text">메일로 받기</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -22,12 +22,18 @@ import { useStore } from '@/shared/model/store';
|
||||
import { AccountHolderAuthListItem, AccountHolderAuthStatus, ExtensionAccountHolderAuthContentItem, ExtensionAccountHolderAuthDownloadExcelParams, ExtensionAccountHolderAuthDownloadExcelResponse } from '@/entities/additional-service/model/account-holder-auth/types';
|
||||
import { AdditionalServiceCategory } from '@/entities/additional-service/model/types';
|
||||
import { EmailBottomSheet } from '@/entities/common/ui/email-bottom-sheet';
|
||||
import { useExtensionAccessCheck } from '@/shared/lib/hooks/use-extension-access-check';
|
||||
|
||||
export const AccountHolderAuthPage = () => {
|
||||
const { navigate } = useNavigate();
|
||||
|
||||
const userMid = useStore.getState().UserStore.mid;
|
||||
|
||||
// 권한 체크
|
||||
const { hasAccess, AccessDeniedDialog } = useExtensionAccessCheck({
|
||||
extensionCode: 'ACCOUNT_AUTH'
|
||||
});
|
||||
|
||||
const [sortType, setSortType] = useState<SortTypeKeys>(SortTypeKeys.LATEST);
|
||||
const [listItems, setListItems] = useState<Array<ExtensionAccountHolderAuthContentItem>>([]);
|
||||
const [filterOn, setFilterOn] = useState<boolean>(false);
|
||||
@@ -115,6 +121,10 @@ export const AccountHolderAuthPage = () => {
|
||||
authStatus
|
||||
]);
|
||||
|
||||
if (!hasAccess) {
|
||||
return <AccessDeniedDialog />;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<main>
|
||||
|
||||
@@ -83,7 +83,7 @@ export const AccountHolderAuthDetailPage = () => {
|
||||
</li>
|
||||
<li className="kv-row">
|
||||
<span className="k">계좌번호</span>
|
||||
<span className="v">{detail?.bankName}</span>
|
||||
<span className="v">{detail?.accountNo}</span>
|
||||
</li>
|
||||
<li className="kv-row">
|
||||
<span className="k">예금주</span>
|
||||
|
||||
@@ -22,12 +22,18 @@ import { useStore } from '@/shared/model/store';
|
||||
import { AccountHolderSearchListItem, AccountHolderSearchCl, AccountHolderResultStatus } from '@/entities/additional-service/model/account-holder-search/types';
|
||||
import { resultStatusBtnGroup } from '@/entities/additional-service/model/account-holder-search/constant';
|
||||
import { EmailBottomSheet } from '@/entities/common/ui/email-bottom-sheet';
|
||||
import { useExtensionAccessCheck } from '@/shared/lib/hooks/use-extension-access-check';
|
||||
|
||||
export const AccountHolderSearchPage = () => {
|
||||
const { navigate } = useNavigate();
|
||||
|
||||
const userMid = useStore.getState().UserStore.mid;
|
||||
|
||||
// 권한 체크
|
||||
const { hasAccess, AccessDeniedDialog } = useExtensionAccessCheck({
|
||||
extensionCode: 'SEARCH_ACCOUNT_NAME'
|
||||
});
|
||||
|
||||
const [sortType, setSortType] = useState<SortTypeKeys>(SortTypeKeys.LATEST);
|
||||
const [listItems, setListItems] = useState<Array<AccountHolderSearchListItem>>([]);
|
||||
const [pageParam, setPageParam] = useState<DefaultRequestPagination>(DEFAULT_PAGE_PARAM);
|
||||
@@ -125,6 +131,10 @@ export const AccountHolderSearchPage = () => {
|
||||
resultStatus
|
||||
]);
|
||||
|
||||
if (!hasAccess) {
|
||||
return <AccessDeniedDialog />;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<main>
|
||||
|
||||
@@ -18,7 +18,7 @@ export const AccountHolderSearchRequestPage = () => {
|
||||
const midOptions = useStore.getState().UserStore.selectOptionsMids
|
||||
const bankList = useStore.getState().CommonStore.bankList
|
||||
|
||||
useSetHeaderTitle('계좌성명조회_신청');
|
||||
useSetHeaderTitle('계좌성명조회 신청');
|
||||
useSetHeaderType(HeaderType.LeftArrow);
|
||||
useSetFooterMode(false);
|
||||
useSetOnBack(() => {
|
||||
|
||||
@@ -12,7 +12,7 @@ import { useEffect, useState } from 'react';
|
||||
import { ExtensionAlimtalkDetailParams, ExtensionAlimtalkDetailResponse } from '@/entities/additional-service/model/alimtalk/types';
|
||||
import { useExtensionAlimtalkDetailMutation } from '@/entities/additional-service/api/alimtalk/use-extansion-alimtalk-detail-mutation';
|
||||
import moment from 'moment';
|
||||
import { getAlimtalkAlimClText, getAlimtalkSendClTypeText, getAlimtalkSendTypeText } from '@/entities/additional-service/model/alimtalk/constant';
|
||||
import { getAlimtalkAlimClText, getAlimtalkSendClTypeText, getAlimtalkSendTypeText, getAlimtalkServiceCodeText } from '@/entities/additional-service/model/alimtalk/constant';
|
||||
|
||||
export const AlimtalkDetailPage = () => {
|
||||
const { navigate } = useNavigate();
|
||||
@@ -60,7 +60,7 @@ export const AlimtalkDetailPage = () => {
|
||||
<div className="num-amount">
|
||||
<span className="amount">{ detail?.receiverName }</span>
|
||||
</div>
|
||||
<div className="num-store">{ detail?.merchantName }</div>
|
||||
<div className="num-store">{ detail?.companyName }</div>
|
||||
<div className="num-day">{ getDate(detail?.sendDate) }</div>
|
||||
</div>
|
||||
<div className="detail-divider"></div>
|
||||
@@ -89,7 +89,7 @@ export const AlimtalkDetailPage = () => {
|
||||
</li>
|
||||
<li className="kv-row">
|
||||
<span className="k">결제서비스</span>
|
||||
<span className="v">{ detail?.paymentMethod }</span>
|
||||
<span className="v">{ getAlimtalkServiceCodeText(detail?.serviceCode) }</span>
|
||||
</li>
|
||||
<li className="kv-row">
|
||||
<span className="k">알림구분</span>
|
||||
|
||||
@@ -31,11 +31,17 @@ import { useStore } from '@/shared/model/store';
|
||||
import { snackBar } from '@/shared/lib';
|
||||
import { EmailBottomSheet } from '@/entities/common/ui/email-bottom-sheet';
|
||||
import { AlimtalkFilter } from '@/entities/additional-service/ui/filter/alimtalk-filter';
|
||||
import { useExtensionAccessCheck } from '@/shared/lib/hooks/use-extension-access-check';
|
||||
|
||||
export const AlimtalkListPage = () => {
|
||||
const { navigate } = useNavigate();
|
||||
const userMid = useStore.getState().UserStore.mid;
|
||||
|
||||
// 권한 체크
|
||||
const { hasAccess, AccessDeniedDialog } = useExtensionAccessCheck({
|
||||
extensionCode: 'ALIMTALK'
|
||||
});
|
||||
|
||||
const [sortType, setSortType] = useState<SortTypeKeys>(SortTypeKeys.LATEST);
|
||||
const [listItems, setListItems] = useState<Array<AlimtalkListContent>>([]);
|
||||
const [filterOn, setFilterOn] = useState<boolean>(false);
|
||||
@@ -182,6 +188,10 @@ export const AlimtalkListPage = () => {
|
||||
sendCl
|
||||
]);
|
||||
|
||||
if (!hasAccess) {
|
||||
return <AccessDeniedDialog />;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<main>
|
||||
|
||||
@@ -165,9 +165,9 @@ export const AlimtalkSettingPage = () => {
|
||||
></AlimTalkSettingServiceRow>
|
||||
<AlimTalkSettingServiceRow
|
||||
title='신용카드(취소)'
|
||||
merchantFlag={merchantBankApprovalFlag}
|
||||
merchantFlag={merchantCardCancelFlag}
|
||||
userFlag={userCardCancelFlag}
|
||||
setMerchantFlag={setMerchantBankApprovalFlag}
|
||||
setMerchantFlag={setMerchantCardCancelFlag}
|
||||
setUserFlag={setUserCardCancelFlag}
|
||||
></AlimTalkSettingServiceRow>
|
||||
<AlimTalkSettingServiceRow
|
||||
|
||||
@@ -21,12 +21,18 @@ import { ArsPaymentStatusBtnGroup } from '@/entities/additional-service/model/ar
|
||||
import { ArsFilter } from '@/entities/additional-service/ui/filter/ars-filter';
|
||||
import { useStore } from '@/shared/model/store';
|
||||
import { EmailBottomSheet } from '@/entities/common/ui/email-bottom-sheet';
|
||||
import { useExtensionAccessCheck } from '@/shared/lib/hooks/use-extension-access-check';
|
||||
|
||||
export const ArsListPage = () => {
|
||||
const { navigate } = useNavigate();
|
||||
|
||||
const userMid = useStore.getState().UserStore.mid;
|
||||
|
||||
// 권한 체크
|
||||
const { hasAccess, AccessDeniedDialog } = useExtensionAccessCheck({
|
||||
extensionCode: 'ARS'
|
||||
});
|
||||
|
||||
const [sortType, setSortType] = useState<SortTypeKeys>(SortTypeKeys.LATEST);
|
||||
const [listItems, setListItems] = useState<Array<ArsListContent>>([]);
|
||||
const [filterOn, setFilterOn] = useState<boolean>(false);
|
||||
@@ -119,9 +125,6 @@ export const ArsListPage = () => {
|
||||
setPaymentStatus(val);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
callList();
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
callList();
|
||||
}, [
|
||||
@@ -181,6 +184,10 @@ export const ArsListPage = () => {
|
||||
return rs;
|
||||
}
|
||||
|
||||
// if (!hasAccess) {
|
||||
// return <AccessDeniedDialog />;
|
||||
// }
|
||||
|
||||
return (
|
||||
<>
|
||||
<main>
|
||||
|
||||
@@ -22,11 +22,17 @@ import { EmailBottomSheet } from '@/entities/common/ui/email-bottom-sheet';
|
||||
import { useExtensionFaceAuthListtMutation } from '@/entities/additional-service/api/face-auth/use-extension-face-auth-list-mutation';
|
||||
import { useExtensionFaceAuthDownloadExcelMutation } from '@/entities/additional-service/api/face-auth/use-extension-face-auth-download-excel-mutation';
|
||||
import { ListDateGroup } from '@/entities/additional-service/ui/list-date-group';
|
||||
import { useExtensionAccessCheck } from '@/shared/lib/hooks/use-extension-access-check';
|
||||
|
||||
export const FaceAuthPage = () => {
|
||||
const { navigate } = useNavigate();
|
||||
const userMid = useStore.getState().UserStore.mid;
|
||||
|
||||
// 권한 체크
|
||||
const { hasAccess, AccessDeniedDialog } = useExtensionAccessCheck({
|
||||
extensionCode: 'FACE_AUTH'
|
||||
});
|
||||
|
||||
const [sortType, setSortType] = useState<SortTypeKeys>(SortTypeKeys.LATEST);
|
||||
const [listItems, setListItems] = useState<Array<FaceAuthListItem>>([]);
|
||||
const [filterOn, setFilterOn] = useState<boolean>(false);
|
||||
@@ -54,7 +60,7 @@ export const FaceAuthPage = () => {
|
||||
authResult?: FaceAuthResult
|
||||
}) => {
|
||||
let params: ExtensionFaceAuthListParams = {
|
||||
mid: mid,
|
||||
mid: "faceauth0m",
|
||||
userMallId: userMallId,
|
||||
fromDate: fromDate,
|
||||
toDate: toDate,
|
||||
@@ -80,7 +86,7 @@ export const FaceAuthPage = () => {
|
||||
const onSendRequest = (selectedEmail?: string) => {
|
||||
if (selectedEmail) {
|
||||
const params: ExtensionFaceAuthExcelDownlaodPrams = {
|
||||
mid: mid,
|
||||
mid: "faceauth0m",
|
||||
email: selectedEmail,
|
||||
fromDate: fromDate,
|
||||
toDate: toDate
|
||||
@@ -106,9 +112,9 @@ export const FaceAuthPage = () => {
|
||||
};
|
||||
|
||||
const getListDateGroup = () => {
|
||||
let rs= [];
|
||||
let rs = [];
|
||||
let date = '';
|
||||
let list= [];
|
||||
let list = [];
|
||||
for (let i = 0; i < listItems.length; i++) {
|
||||
let item = listItems[i];
|
||||
if (!!item) {
|
||||
@@ -155,6 +161,10 @@ export const FaceAuthPage = () => {
|
||||
callList();
|
||||
}, [mid, userMallId, fromDate, toDate, transType, authResult]);
|
||||
|
||||
// if (!hasAccess) {
|
||||
// return <AccessDeniedDialog />;
|
||||
// }
|
||||
|
||||
return (
|
||||
<>
|
||||
<main>
|
||||
|
||||
@@ -6,15 +6,19 @@ import { FundAccountTransferListWrap } from '@/entities/additional-service/ui/fu
|
||||
import { FundAccountTabKeys } from '@/entities/additional-service/model/fund-account/types';
|
||||
import { HeaderType } from '@/entities/common/model/types';
|
||||
import {
|
||||
useSetHeaderTitle,
|
||||
useSetHeaderType,
|
||||
useSetFooterMode,
|
||||
useSetHeaderTitle,
|
||||
useSetHeaderType,
|
||||
useSetFooterMode,
|
||||
useSetOnBack
|
||||
} from '@/widgets/sub-layout/use-sub-layout';
|
||||
import { useExtensionAccessCheck } from '@/shared/lib/hooks/use-extension-access-check';
|
||||
|
||||
export const FundAccountTransferListPage = () => {
|
||||
const { navigate } = useNavigate();
|
||||
|
||||
// 권한 체크
|
||||
const { hasAccess, AccessDeniedDialog } = useExtensionAccessCheck({
|
||||
extensionCode: 'FUND_ACCOUNT'
|
||||
});
|
||||
const [activeTab, setActiveTab] = useState<FundAccountTabKeys>(FundAccountTabKeys.TransferList);
|
||||
|
||||
useSetHeaderTitle('자금이체');
|
||||
@@ -24,12 +28,16 @@ export const FundAccountTransferListPage = () => {
|
||||
navigate(PATHS.home);
|
||||
});
|
||||
|
||||
if (!hasAccess) {
|
||||
return <AccessDeniedDialog />;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<main>
|
||||
<div className="tab-content">
|
||||
<div className="tab-pane pt-46 active">
|
||||
<FundAccountTab activeTab={ activeTab }></FundAccountTab>
|
||||
<FundAccountTab activeTab={activeTab}></FundAccountTab>
|
||||
<FundAccountTransferListWrap></FundAccountTransferListWrap>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -138,7 +138,7 @@ export const FundAccountTransferRequestPage = () => {
|
||||
<input
|
||||
type="text"
|
||||
value={accountName}
|
||||
onChange={(e) => setAccountName(e.target.value)}
|
||||
onChange={(e: ChangeEvent<HTMLInputElement>) => setAccountName(e.target.value) }
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -159,7 +159,7 @@ export const FundAccountTransferRequestPage = () => {
|
||||
<input
|
||||
type="text"
|
||||
value={moid}
|
||||
onChange={(e) => setMoid(e.target.value)}
|
||||
onChange={(e: ChangeEvent<HTMLInputElement>) => setMoid(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -22,11 +22,17 @@ import { useStore } from '@/shared/model/store';
|
||||
import { KeyInPaymentListItem, KeyInPaymentPaymentStatus } from '@/entities/additional-service/model/key-in/types';
|
||||
import { keyInPaymentPaymentStatusBtnGroup } from '@/entities/additional-service/model/key-in/constant';
|
||||
import { EmailBottomSheet } from '@/entities/common/ui/email-bottom-sheet';
|
||||
import { useExtensionAccessCheck } from '@/shared/lib/hooks/use-extension-access-check';
|
||||
|
||||
export const KeyInPaymentPage = () => {
|
||||
const { navigate } = useNavigate();
|
||||
const userMid = useStore.getState().UserStore.mid;
|
||||
|
||||
// 권한 체크
|
||||
const { hasAccess, AccessDeniedDialog } = useExtensionAccessCheck({
|
||||
extensionCode: 'KEYIN'
|
||||
});
|
||||
|
||||
const [sortType, setSortType] = useState<SortTypeKeys>(SortTypeKeys.LATEST);
|
||||
const [listItems, setListItems] = useState<Array<KeyInPaymentListItem>>([]);
|
||||
const [filterOn, setFilterOn] = useState<boolean>(false);
|
||||
@@ -136,6 +142,11 @@ export const KeyInPaymentPage = () => {
|
||||
maxAmount
|
||||
]);
|
||||
|
||||
// if (!hasAccess) {
|
||||
// return <AccessDeniedDialog />;
|
||||
// }
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<main>
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
useSetOnBack
|
||||
} from '@/widgets/sub-layout/use-sub-layout';
|
||||
import { LinkPaymentTabKeys } from '@/entities/additional-service/model/link-pay/types';
|
||||
import { useExtensionAccessCheck } from '@/shared/lib/hooks/use-extension-access-check';
|
||||
|
||||
/**
|
||||
* 발송내역 탭 화면
|
||||
@@ -20,6 +21,11 @@ import { LinkPaymentTabKeys } from '@/entities/additional-service/model/link-pay
|
||||
export const LinkPaymentHistoryPage = () => {
|
||||
const { navigate } = useNavigate();
|
||||
|
||||
// 권한 체크
|
||||
const { hasAccess, AccessDeniedDialog } = useExtensionAccessCheck({
|
||||
extensionCode: 'LINKPAY'
|
||||
});
|
||||
|
||||
const [activeTab, setActiveTab] = useState<LinkPaymentTabKeys>(LinkPaymentTabKeys.ShippingHistory)
|
||||
|
||||
useSetHeaderTitle('링크결제')
|
||||
@@ -29,6 +35,10 @@ export const LinkPaymentHistoryPage = () => {
|
||||
navigate(PATHS.home);
|
||||
});
|
||||
|
||||
if (!hasAccess) {
|
||||
return <AccessDeniedDialog />;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<main>
|
||||
|
||||
@@ -16,7 +16,8 @@ import { AdditionalServiceCategory, DetailResponse, PaymentInfo, TitleInfo } fro
|
||||
import { useExtensionLinkPayWaitDetailMutation, } from '@/entities/additional-service/api/link-payment/use-extension-link-pay-wait-detail-mutation';
|
||||
import { PaymentInfoWrap } from '@/entities/additional-service/ui/info-wrap/payment-info-wrap';
|
||||
import { useExtensionLinkPayWaitDeleteMutation } from '@/entities/additional-service/api/link-payment/use-extension-link-pay-wait-delete-mutation';
|
||||
import { ExtensionLinkPayWaitDeleteParams, ExtensionLinkPayWaitDetailParams } from '@/entities/additional-service/model/link-pay/types';
|
||||
import { ExtensionLinkPayWaitDeleteParams, ExtensionLinkPayWaitDetailParams, LinkPaymentProcessStatus } from '@/entities/additional-service/model/link-pay/types';
|
||||
import { snackBar } from '@/shared/lib';
|
||||
|
||||
export const LinkPaymentWaitDetailPage = () => {
|
||||
const { navigate } = useNavigate();
|
||||
@@ -54,13 +55,13 @@ export const LinkPaymentWaitDetailPage = () => {
|
||||
requestId: requestId
|
||||
}
|
||||
linkPayWaitDelete(deleteParam)
|
||||
.then((response) => {
|
||||
console.log("Delete 성공 응답: ", response)
|
||||
.then((rs) => {
|
||||
onClickToNavigate(PATHS.additionalService.linkPayment.pendingSend)
|
||||
snackBar("삭제를 성공하였습니다.")
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Resend 실패: ", error);
|
||||
|
||||
snackBar(`[실패] ${error?.response?.data?.message}`)
|
||||
});
|
||||
}
|
||||
|
||||
@@ -120,6 +121,7 @@ export const LinkPaymentWaitDetailPage = () => {
|
||||
<button
|
||||
className="btn-50 btn-blue flex-1"
|
||||
onClick={() => onClickToCancel()}
|
||||
disabled={paymentInfo?.processStatus !== LinkPaymentProcessStatus.SEND_REQUEST}
|
||||
>삭제</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,16 +2,16 @@ import { ChangeEvent, useEffect, useState } from 'react';
|
||||
import { PATHS } from '@/shared/constants/paths';
|
||||
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
|
||||
import { HeaderType } from '@/entities/common/model/types';
|
||||
import { IMAGE_ROOT } from '@/shared/constants/common';
|
||||
import {
|
||||
useSetHeaderTitle,
|
||||
useSetHeaderType,
|
||||
useSetFooterMode,
|
||||
useSetHeaderTitle,
|
||||
useSetHeaderType,
|
||||
useSetFooterMode,
|
||||
useSetOnBack
|
||||
} from '@/widgets/sub-layout/use-sub-layout';
|
||||
import { useExtensionListMutation } from '@/entities/additional-service/api/use-extension-list-mutation';
|
||||
import { ExtensionListParams, ExtensionListResponse } from '@/entities/additional-service/model/types';
|
||||
import { ExtensionListParams, ExtensionListResponse, SERVICE_MAP } from '@/entities/additional-service/model/types';
|
||||
import { useStore } from '@/shared/model/store';
|
||||
import { Dialog } from '@/shared/ui/dialogs/dialog';
|
||||
|
||||
export const ListPage = () => {
|
||||
const { navigate } = useNavigate();
|
||||
@@ -19,6 +19,9 @@ export const ListPage = () => {
|
||||
const userMid = useStore.getState().UserStore.mid;
|
||||
|
||||
const [mid, setMid] = useState<string>(userMid);
|
||||
const [activeServices, setActiveServices] = useState<string[]>([]);
|
||||
const [availableServices, setAvailableServices] = useState<string[]>([]);
|
||||
const [dialogOpen, setDialogOpen] = useState<boolean>(false);
|
||||
|
||||
const { mutateAsync: extensionList } = useExtensionListMutation();
|
||||
|
||||
@@ -34,108 +37,59 @@ export const ListPage = () => {
|
||||
mid: mid
|
||||
}
|
||||
extensionList(params).then((rs: ExtensionListResponse) => {
|
||||
console.log(rs)
|
||||
setActiveServices(rs.activeExtensionList || []);
|
||||
setAvailableServices(rs.availableExtensionList || []);
|
||||
});
|
||||
};
|
||||
|
||||
const activeExtensionList = [
|
||||
{
|
||||
className: 'list-wrap01', serviceName: 'SMS 결제 통보', serviceDesc: '입금 요청부터 완료까지 SMS 자동 전송',
|
||||
icon: IMAGE_ROOT + '/icon_ing03.svg', path: PATHS.additionalService.smsPaymentNotification
|
||||
},
|
||||
{
|
||||
className: 'list-wrap01', serviceName: '신용카드 ARS 결제', serviceDesc: '전화 한 통으로 결제 성공 편리하고 안전한 서비스',
|
||||
icon: IMAGE_ROOT + '/icon_ing01.svg', path: PATHS.additionalService.ars.list
|
||||
},
|
||||
{
|
||||
className: 'list-wrap01', serviceName: 'KEY-IN 결제', serviceDesc: '상담 중 카드정보 입력으로 간편한 결제 지원',
|
||||
icon: IMAGE_ROOT + '/icon_ing02.svg', path: PATHS.additionalService.keyInPayment.list
|
||||
},
|
||||
{
|
||||
className: 'list-wrap01', serviceName: '계좌성명조회', serviceDesc: '예금주 정보 입력으로 즉시 예금주 확인',
|
||||
icon: IMAGE_ROOT + '/icon_ing04.svg', path: PATHS.additionalService.accountHolderSearch.list
|
||||
},
|
||||
];
|
||||
const availableExtensionList = [
|
||||
{
|
||||
className: 'list-wrap02', serviceName: '지급대행', serviceDesc: '하위 가맹점에 빠른 정산금 지급 지급대행 서비스',
|
||||
icon: IMAGE_ROOT + '/icon_ing05.svg', path: PATHS.additionalService.payout.list
|
||||
},
|
||||
{
|
||||
className: 'list-wrap02', serviceName: '정산대행', serviceDesc: '하위 가맹점 정산금 계산부터 지급까지 자동 해결 서비스',
|
||||
icon: IMAGE_ROOT + '/icon_ing06.svg', path: PATHS.additionalService.settlementAgency.manage
|
||||
},
|
||||
{
|
||||
className: 'list-wrap02', serviceName: '링크 결제', serviceDesc: '결제 링크 전송만으로 어디서든 결제 가능 서비스',
|
||||
icon: IMAGE_ROOT + '/icon_ing07.svg', path: PATHS.additionalService.linkPayment.shippingHistory
|
||||
},
|
||||
{
|
||||
className: 'list-wrap02', serviceName: '자금이체', serviceDesc: '예치금으로 즉시 송금, 파일 등록만으로 다중 송금 가능',
|
||||
icon: IMAGE_ROOT + '/icon_ing08.svg', path: PATHS.additionalService.fundAccount.transferList
|
||||
},
|
||||
{
|
||||
className: 'list-wrap02', serviceName: '계좌점유인증', serviceDesc: '1원 송금으로 실제 계좌 점유 확인 여부',
|
||||
icon: IMAGE_ROOT + '/icon_ing09.svg', path: PATHS.additionalService.accountHolderAuth.list
|
||||
},
|
||||
{
|
||||
className: 'list-wrap02', serviceName: '알림톡 결제통보', serviceDesc: '결제 상태를 알림톡으로 쉽고 빠른 안내',
|
||||
icon: IMAGE_ROOT + '/icon_ing10.svg', path: PATHS.additionalService.alimtalk.list
|
||||
},
|
||||
];
|
||||
|
||||
const onClickToNavigate = (path?: string) => {
|
||||
if(!!path){
|
||||
navigate(path);
|
||||
}
|
||||
};
|
||||
|
||||
const getActiveExtensionList = () => {
|
||||
let rs = [];
|
||||
for(let i=0;i<activeExtensionList.length;i++){
|
||||
rs.push(
|
||||
<div
|
||||
key={ 'key-active-' + i }
|
||||
className={ activeExtensionList[i]?.className }
|
||||
onClick={ () => onClickToNavigate(activeExtensionList[i]?.path) }
|
||||
>
|
||||
<div>
|
||||
<div className="service-name">{ activeExtensionList[i]?.serviceName }</div>
|
||||
<p className="service-desc">{ activeExtensionList[i]?.serviceDesc }</p>
|
||||
</div>
|
||||
<img
|
||||
src={ activeExtensionList[i]?.icon }
|
||||
alt={ activeExtensionList[i]?.serviceName }
|
||||
/>
|
||||
const filteredServices = SERVICE_MAP.filter(service =>
|
||||
activeServices.includes(service.code)
|
||||
);
|
||||
|
||||
return filteredServices.map((service) => (
|
||||
<div
|
||||
key={'key-active-' + service.code}
|
||||
className="list-wrap01"
|
||||
onClick={() => service.path && navigate(service.path)}
|
||||
>
|
||||
<div>
|
||||
<div className="service-name">{service.serviceName}</div>
|
||||
<p className="service-desc">{service.serviceDesc}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return rs;
|
||||
<img
|
||||
src={service.icon}
|
||||
alt={service.serviceName}
|
||||
/>
|
||||
</div>
|
||||
));
|
||||
};
|
||||
|
||||
const getAvailableExtensionList = () => {
|
||||
let rs = [];
|
||||
for(let i=0;i<availableExtensionList.length;i++){
|
||||
rs.push(
|
||||
<div
|
||||
key={ 'key-available-' + i }
|
||||
className={ availableExtensionList[i]?.className }
|
||||
onClick={ () => onClickToNavigate(availableExtensionList[i]?.path) }
|
||||
>
|
||||
<div>
|
||||
<div className="service-name">{ availableExtensionList[i]?.serviceName }</div>
|
||||
<p className="service-desc">{ availableExtensionList[i]?.serviceDesc }</p>
|
||||
</div>
|
||||
<img
|
||||
src={ availableExtensionList[i]?.icon }
|
||||
alt={ availableExtensionList[i]?.serviceName }
|
||||
/>
|
||||
const filteredServices = SERVICE_MAP.filter(service =>
|
||||
availableServices.includes(service.code)
|
||||
);
|
||||
|
||||
return filteredServices.map((service) => (
|
||||
<div
|
||||
key={'key-available-' + service.code}
|
||||
className="list-wrap02"
|
||||
onClick={() => setDialogOpen(true)}
|
||||
>
|
||||
<div>
|
||||
<div className="service-name">{service.serviceName}</div>
|
||||
<p className="service-desc">{service.serviceDesc}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return rs;
|
||||
<img
|
||||
src={service.icon}
|
||||
alt={service.serviceName}
|
||||
/>
|
||||
</div>
|
||||
));
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if(!!mid){
|
||||
if (!!mid) {
|
||||
callExtensionList();
|
||||
}
|
||||
}, [mid]);
|
||||
@@ -147,28 +101,41 @@ export const ListPage = () => {
|
||||
<div className="tab-pane sub active">
|
||||
<div className="ing-list">
|
||||
<div className="input-wrapper top-select">
|
||||
<select
|
||||
value={ mid }
|
||||
onChange={ (e: ChangeEvent<HTMLSelectElement>) => setMid(e.target.value) }
|
||||
>
|
||||
{
|
||||
midOptions.map((value, index) => (
|
||||
<option
|
||||
key={ value.value }
|
||||
value={ value.value }
|
||||
>{ value.name }</option>
|
||||
))
|
||||
}
|
||||
</select>
|
||||
<select
|
||||
value={mid}
|
||||
onChange={(e: ChangeEvent<HTMLSelectElement>) => setMid(e.target.value)}
|
||||
>
|
||||
{
|
||||
midOptions.map((value) => (
|
||||
<option
|
||||
key={value.value}
|
||||
value={value.value}
|
||||
>{value.name}</option>
|
||||
))
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<h3 className="ing-title">사용중인 서비스</h3>
|
||||
{ getActiveExtensionList() }
|
||||
{getActiveExtensionList()}
|
||||
<h3 className="ing-title">신청 가능한 서비스</h3>
|
||||
{ getAvailableExtensionList() }
|
||||
{getAvailableExtensionList()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<Dialog
|
||||
open={dialogOpen}
|
||||
onClose={() => setDialogOpen(false)}
|
||||
message={
|
||||
<>
|
||||
이용 중이지 않은 서비스입니다.<br />
|
||||
가입 문의는 영업 담당자 또는 고객센터로 문의해 주세요.
|
||||
</>
|
||||
}
|
||||
buttonLabel={['확인']}
|
||||
onConfirmClick={() => setDialogOpen(false)}
|
||||
afterLeave={() => { }}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
};
|
||||
@@ -13,6 +13,9 @@ import { ExtensionPayoutDetailDownloadCertificateParams, ExtensionPayoutDetailDo
|
||||
import { useEffect, useState } from 'react';
|
||||
import { NumericFormat } from 'react-number-format';
|
||||
import { useExtensionPayoutDetailDownloadCertificateMutation } from '@/entities/additional-service/api/payout/use-extension-payout-detail-download-cetificate-mutation';
|
||||
import moment from 'moment';
|
||||
import { EmailBottomSheet } from '@/entities/common/ui/email-bottom-sheet';
|
||||
import { DownloadTypeBottomSheet } from '@/entities/common/ui/download-type-bottom-sheet';
|
||||
|
||||
export const PayoutDetailPage = () => {
|
||||
const { navigate } = useNavigate();
|
||||
@@ -21,9 +24,9 @@ export const PayoutDetailPage = () => {
|
||||
const tid = location.state.tid;
|
||||
const mid = location.state.mid;
|
||||
|
||||
const [requestType, setRequestType] = useState<string>('');
|
||||
const [email, setEmail] = useState<string>('');
|
||||
const [detail, setDetail] = useState<ExtensionPayoutDetailResponse>();
|
||||
const [downloadTypeBottomSheetOn, setDownloadTypeBottomSheetOn] = useState<boolean>(false);
|
||||
const [emailBottomSheetOn, setEmailBottomSheetOn] = useState<boolean>(false);
|
||||
|
||||
const { mutateAsync: extensionPayoutDetail } = useExtensionPayoutDetailMutation();
|
||||
const { mutateAsync: extensionPayoutDetailDownloadCertification } = useExtensionPayoutDetailDownloadCertificateMutation();
|
||||
@@ -47,15 +50,48 @@ export const PayoutDetailPage = () => {
|
||||
});
|
||||
|
||||
const onClickToDownload = () => {
|
||||
let params: ExtensionPayoutDetailDownloadCertificateParams = {
|
||||
tid: tid,
|
||||
mid: mid,
|
||||
requestType: requestType,
|
||||
email: email
|
||||
};
|
||||
extensionPayoutDetailDownloadCertification(params).then((rs: ExtensionPayoutDetailDownloadCertificateResponse) => {
|
||||
console.log(rs);
|
||||
});
|
||||
setDownloadTypeBottomSheetOn(true);
|
||||
};
|
||||
|
||||
const onSelectDownloadType = (type: 'IMAGE' | 'EMAIL') => {
|
||||
if (type === 'IMAGE') {
|
||||
// 이미지 저장은 바로 실행
|
||||
const params: ExtensionPayoutDetailDownloadCertificateParams = {
|
||||
mid: mid,
|
||||
tid: tid,
|
||||
requestType: 'IMAGE',
|
||||
email: ''
|
||||
};
|
||||
extensionPayoutDetailDownloadCertification(params)
|
||||
.then((rs: ExtensionPayoutDetailDownloadCertificateResponse) => {
|
||||
console.log('Certificate Download Status:', rs);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Certificate Download Failed:', error);
|
||||
});
|
||||
} else {
|
||||
// 이메일은 EmailBottomSheet 열기
|
||||
setEmailBottomSheetOn(true);
|
||||
}
|
||||
};
|
||||
|
||||
const onSendRequest = (selectedEmail?: string) => {
|
||||
if (selectedEmail) {
|
||||
const params: ExtensionPayoutDetailDownloadCertificateParams = {
|
||||
mid: mid,
|
||||
tid: tid,
|
||||
requestType: 'EMAIL',
|
||||
email: selectedEmail
|
||||
};
|
||||
extensionPayoutDetailDownloadCertification(params)
|
||||
.then((rs: ExtensionPayoutDetailDownloadCertificateResponse) => {
|
||||
console.log('Certificate Download Status:', rs);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Certificate Download Failed:', error);
|
||||
});
|
||||
}
|
||||
setEmailBottomSheetOn(false);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@@ -105,11 +141,11 @@ export const PayoutDetailPage = () => {
|
||||
</li>
|
||||
<li className="kv-row">
|
||||
<span className="k">요청일</span>
|
||||
<span className="v">{ detail?.requestDate }</span>
|
||||
<span className="v">{ moment(detail?.requestDate).format('YYYY.MM.DD') }</span>
|
||||
</li>
|
||||
<li className="kv-row">
|
||||
<span className="k">지급일시</span>
|
||||
<span className="v">{ detail?.settlementDateTime }</span>
|
||||
<span className="v">{moment(detail?.settlementDateTime,'YYYYMMDDHHmmss').format('YYYY.MM.DD HH:mm:ss')}</span>
|
||||
</li>
|
||||
<li className="kv-row">
|
||||
<span className="k">사업자번호</span>
|
||||
@@ -140,6 +176,18 @@ export const PayoutDetailPage = () => {
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<DownloadTypeBottomSheet
|
||||
bottomSheetOn={downloadTypeBottomSheetOn}
|
||||
setBottomSheetOn={setDownloadTypeBottomSheetOn}
|
||||
onSelectType={onSelectDownloadType}
|
||||
/>
|
||||
<EmailBottomSheet
|
||||
bottomSheetOn={emailBottomSheetOn}
|
||||
setBottomSheetOn={setEmailBottomSheetOn}
|
||||
imageSave={false}
|
||||
sendEmail={true}
|
||||
sendRequest={onSendRequest}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -15,9 +15,9 @@ import {
|
||||
import { JSX, useEffect, useState } from 'react';
|
||||
import { DEFAULT_PAGE_PARAM } from '@/entities/common/model/constant';
|
||||
import {
|
||||
useSetHeaderTitle,
|
||||
useSetHeaderType,
|
||||
useSetFooterMode,
|
||||
useSetHeaderTitle,
|
||||
useSetHeaderType,
|
||||
useSetFooterMode,
|
||||
useSetOnBack
|
||||
} from '@/widgets/sub-layout/use-sub-layout';
|
||||
import moment from 'moment';
|
||||
@@ -29,8 +29,13 @@ import { ListDateGroup } from '@/entities/additional-service/ui/list-date-group'
|
||||
import { AdditionalServiceCategory } from '@/entities/additional-service/model/types';
|
||||
import { useStore } from '@/shared/model/store';
|
||||
import { EmailBottomSheet } from '@/entities/common/ui/email-bottom-sheet';
|
||||
import { useExtensionAccessCheck } from '@/shared/lib/hooks/use-extension-access-check';
|
||||
|
||||
export const PayoutListPage = () => {
|
||||
// 권한 체크
|
||||
const { hasAccess, AccessDeniedDialog } = useExtensionAccessCheck({
|
||||
extensionCode: 'PAYOUT'
|
||||
});
|
||||
const { navigate } = useNavigate();
|
||||
const userMid = useStore.getState().UserStore.mid;
|
||||
|
||||
@@ -44,7 +49,7 @@ export const PayoutListPage = () => {
|
||||
const [toDate, setToDate] = useState<string>(moment().format('YYYYMMDD'));
|
||||
const [status, setStatus] = useState<PayoutDisbursementStatus>(PayoutDisbursementStatus.ALL);
|
||||
const [minAmount, setMinAmount] = useState<number>(0);
|
||||
const [maxAmount, setMaxAmount] = useState<number>(50000000);
|
||||
const [maxAmount, setMaxAmount] = useState<number>(50000000);
|
||||
const [emailBottomSheetOn, setEmailBottomSheetOn] = useState<boolean>(false);
|
||||
|
||||
const { mutateAsync: extensionPayoutList } = useExtensionPayoutListMutation();
|
||||
@@ -65,26 +70,19 @@ export const PayoutListPage = () => {
|
||||
sortType?: SortTypeKeys,
|
||||
status?: PayoutDisbursementStatus
|
||||
}) => {
|
||||
let newMinAmount = minAmount;
|
||||
if(!!minAmount && typeof(minAmount) === 'string'){
|
||||
newMinAmount = parseInt(minAmount);
|
||||
}
|
||||
let newMaxAmount = maxAmount;
|
||||
if(!!maxAmount && typeof(maxAmount) === 'string'){
|
||||
newMaxAmount = parseInt(maxAmount);
|
||||
}
|
||||
|
||||
let params: ExtensionPayoutListParams = {
|
||||
mid: mid,
|
||||
searchDateType: searchDateType,
|
||||
fromDate: fromDate,
|
||||
toDate: toDate,
|
||||
status: option?.status ?? status,
|
||||
minAmount: newMinAmount,
|
||||
maxAmount: newMaxAmount,
|
||||
minAmount: minAmount,
|
||||
maxAmount: maxAmount,
|
||||
page: pageParam
|
||||
};
|
||||
|
||||
if(params.page){
|
||||
if (params.page) {
|
||||
params.page.sortType = option?.sortType || sortType;
|
||||
setPageParam(params.page);
|
||||
}
|
||||
@@ -102,13 +100,9 @@ export const PayoutListPage = () => {
|
||||
if (selectedEmail) {
|
||||
const params: ExtensionPayoutExcelParams = {
|
||||
mid: mid,
|
||||
searchDateType: searchDateType,
|
||||
email: selectedEmail,
|
||||
fromDate: fromDate,
|
||||
toDate: toDate,
|
||||
status: status,
|
||||
minAmount: minAmount,
|
||||
maxAmount: maxAmount,
|
||||
//email: selectedEmail
|
||||
};
|
||||
extensionPayoutExcel(params).then((rs: ExtensionPayoutExcelResponse) => {
|
||||
console.log('Excel Download Status:', rs);
|
||||
@@ -127,9 +121,6 @@ export const PayoutListPage = () => {
|
||||
};
|
||||
const onClickToDisbursementStatus = (val: PayoutDisbursementStatus) => {
|
||||
setStatus(val);
|
||||
callExtensionPayoutList({
|
||||
status: val
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@@ -145,9 +136,9 @@ export const PayoutListPage = () => {
|
||||
]);
|
||||
|
||||
const getListDateGroup = () => {
|
||||
let rs= [];
|
||||
let rs = [];
|
||||
let date = '';
|
||||
let list= [];
|
||||
let list = [];
|
||||
for (let i = 0; i < listItems.length; i++) {
|
||||
let itemDateStr = '';
|
||||
if (searchDateType === PayoutSearchDateType.REQUEST_DATE) {
|
||||
@@ -190,6 +181,10 @@ export const PayoutListPage = () => {
|
||||
return rs;
|
||||
};
|
||||
|
||||
if (!hasAccess) {
|
||||
return <AccessDeniedDialog />;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<main>
|
||||
@@ -201,16 +196,16 @@ export const PayoutListPage = () => {
|
||||
<input
|
||||
className="credit-period"
|
||||
type="text"
|
||||
value={ moment(fromDate).format('YYYY.MM.DD') + '-' + moment(toDate).format('YYYY.MM.DD') }
|
||||
readOnly={ true }
|
||||
value={moment(fromDate).format('YYYY.MM.DD') + '-' + moment(toDate).format('YYYY.MM.DD')}
|
||||
readOnly={true}
|
||||
/>
|
||||
<button
|
||||
className="filter-btn"
|
||||
aria-label="필터"
|
||||
onClick={ () => onClickToOpenFilter() }
|
||||
onClick={() => onClickToOpenFilter()}
|
||||
>
|
||||
<img
|
||||
src={ IMAGE_ROOT + '/ico_setting.svg' }
|
||||
src={IMAGE_ROOT + '/ico_setting.svg'}
|
||||
alt="검색옵션"
|
||||
/>
|
||||
</button>
|
||||
@@ -218,10 +213,10 @@ export const PayoutListPage = () => {
|
||||
<button
|
||||
className="download-btn"
|
||||
aria-label="다운로드"
|
||||
onClick={ () => onClickToOpenEmailBottomSheet() }
|
||||
onClick={() => onClickToOpenEmailBottomSheet()}
|
||||
>
|
||||
<img
|
||||
src={ IMAGE_ROOT + '/ico_download.svg' }
|
||||
src={IMAGE_ROOT + '/ico_download.svg'}
|
||||
alt="다운로드"
|
||||
/>
|
||||
</button>
|
||||
@@ -240,52 +235,52 @@ export const PayoutListPage = () => {
|
||||
|
||||
<section className="filter-section">
|
||||
<SortTypeBox
|
||||
sortType={ sortType }
|
||||
onClickToSort={ onClickToSort }
|
||||
sortType={sortType}
|
||||
onClickToSort={onClickToSort}
|
||||
></SortTypeBox>
|
||||
<div className="excrow mr-0">
|
||||
<div className="full-menu-keywords no-padding">
|
||||
{
|
||||
PayoutDisbursementStatusBtnGroup.map((value, index) => (
|
||||
<span
|
||||
key={ `key-service-code=${ index }` }
|
||||
className={ `keyword-tag ${(status === value.value)? 'active': ''}` }
|
||||
onClick={ () => onClickToDisbursementStatus(value.value) }
|
||||
>{ value.name }</span>
|
||||
))
|
||||
}
|
||||
{
|
||||
PayoutDisbursementStatusBtnGroup.map((value, index) => (
|
||||
<span
|
||||
key={`key-service-code=${index}`}
|
||||
className={`keyword-tag ${(status === value.value) ? 'active' : ''}`}
|
||||
onClick={() => onClickToDisbursementStatus(value.value)}
|
||||
>{value.name}</span>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section className="transaction-list">
|
||||
{ getListDateGroup() }
|
||||
{getListDateGroup()}
|
||||
</section>
|
||||
<div className="apply-row">
|
||||
<button
|
||||
className="btn-50 btn-blue flex-1"
|
||||
onClick={ () => onClickToNavigation() }
|
||||
onClick={() => onClickToNavigation()}
|
||||
>지급대행 신청</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<PayoutFilter
|
||||
filterOn={ filterOn }
|
||||
setFilterOn={ setFilterOn }
|
||||
mid={ mid }
|
||||
searchDateType={ searchDateType }
|
||||
fromDate={ fromDate }
|
||||
toDate={ toDate }
|
||||
status= { status }
|
||||
minAmount={ minAmount }
|
||||
maxAmount={ maxAmount }
|
||||
setMid={ setMid }
|
||||
setSearchDateType={ setSearchDateType }
|
||||
setFromDate={ setFromDate }
|
||||
setToDate={ setToDate }
|
||||
setStatus={ setStatus }
|
||||
setMinAmount={ setMinAmount }
|
||||
setMaxAmount={ setMaxAmount }
|
||||
filterOn={filterOn}
|
||||
setFilterOn={setFilterOn}
|
||||
mid={mid}
|
||||
searchDateType={searchDateType}
|
||||
fromDate={fromDate}
|
||||
toDate={toDate}
|
||||
status={status}
|
||||
minAmount={minAmount}
|
||||
maxAmount={maxAmount}
|
||||
setMid={setMid}
|
||||
setSearchDateType={setSearchDateType}
|
||||
setFromDate={setFromDate}
|
||||
setToDate={setToDate}
|
||||
setStatus={setStatus}
|
||||
setMinAmount={setMinAmount}
|
||||
setMaxAmount={setMaxAmount}
|
||||
></PayoutFilter>
|
||||
<EmailBottomSheet
|
||||
bottomSheetOn={emailBottomSheetOn}
|
||||
|
||||
@@ -8,12 +8,14 @@ import {
|
||||
useSetFooterMode,
|
||||
useSetOnBack
|
||||
} from '@/widgets/sub-layout/use-sub-layout';
|
||||
import { useState } from "react";
|
||||
import { ChangeEvent, useState } from "react";
|
||||
import { useExtensionPayoutRequestMutation } from "@/entities/additional-service/api/payout/use-extension-payout-request-mutation";
|
||||
import { ExtensionPayoutRequestParams, ExtensionPayoutRequestResponse } from "@/entities/additional-service/model/payout/types";
|
||||
import NiceCalendar from "@/shared/ui/calendar/nice-calendar";
|
||||
import { useStore } from "@/shared/model/store";
|
||||
import moment from 'moment';
|
||||
import { NumericFormat } from "react-number-format";
|
||||
import { snackBar } from "@/shared/lib";
|
||||
|
||||
export const PayoutRequestPage = () => {
|
||||
const { navigate } = useNavigate();
|
||||
@@ -41,9 +43,14 @@ export const PayoutRequestPage = () => {
|
||||
disbursementAmount: disbursementAmount,
|
||||
settlementDate: settlementDate,
|
||||
};
|
||||
extensionPayoutRequest(params).then((rs: ExtensionPayoutRequestResponse) => {
|
||||
navigate(PATHS.additionalService.payout.list);
|
||||
});
|
||||
extensionPayoutRequest(params)
|
||||
.then((rs) => {
|
||||
snackBar("신청을 성공하였습니다.")
|
||||
})
|
||||
.catch((error) => {
|
||||
snackBar(`[실패] ${error?.response?.data?.message} `|| '[실패] 신청을 실패하였습니다.')
|
||||
})
|
||||
;
|
||||
};
|
||||
|
||||
const isFormValid = () => {
|
||||
@@ -58,9 +65,8 @@ export const PayoutRequestPage = () => {
|
||||
setSettlementDate(moment(date).format('YYYYMMDD'));
|
||||
setCalendarOpen(false);
|
||||
};
|
||||
const onClickToOpenCalendar = () => {
|
||||
setCalendarOpen(true);
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<main>
|
||||
@@ -69,44 +75,44 @@ export const PayoutRequestPage = () => {
|
||||
<div className="ing-list">
|
||||
<div className="billing-form gap-30">
|
||||
<div className="billing-row">
|
||||
<div className="billing-label">서브ID<span>*</span></div>
|
||||
<div className="billing-label">서브ID</div>
|
||||
<div className="billing-field">
|
||||
<input
|
||||
type="text"
|
||||
value={submallId}
|
||||
onChange={(e) => setSubmallId(e.target.value)}
|
||||
onChange={(e: ChangeEvent<HTMLInputElement>) => setSubmallId(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="billing-row">
|
||||
<div className="billing-label">지급액<span>*</span></div>
|
||||
<div className="billing-label">지급액</div>
|
||||
<div className="billing-field">
|
||||
<input
|
||||
type="text"
|
||||
<NumericFormat
|
||||
value={disbursementAmount}
|
||||
onChange={(e) => setDisbursementAmount(parseInt(e.target.value))}
|
||||
/>
|
||||
allowNegative={false}
|
||||
displayType="input"
|
||||
onChange={(e: ChangeEvent<HTMLInputElement>) => setDisbursementAmount(parseInt(e.target.value))}
|
||||
></NumericFormat>
|
||||
</div>
|
||||
</div>
|
||||
<div className="billing-row">
|
||||
<div className="billing-label">지급일<span>*</span></div>
|
||||
<div className="billing-label">지급일</div>
|
||||
<div className="billing-field">
|
||||
<div className="input-wrapper date">
|
||||
<div className="input-wrapper date wid-100">
|
||||
<input
|
||||
className="date-input"
|
||||
type="text"
|
||||
placeholder="날짜 선택"
|
||||
value={settlementDate}
|
||||
value={settlementDate ? moment(settlementDate).format('YYYY.MM.DD') : '' }
|
||||
readOnly={true}
|
||||
/>
|
||||
<button
|
||||
className="date-btn"
|
||||
type="button"
|
||||
onClick={() => onClickToOpenCalendar()}
|
||||
disabled={!isFormValid}
|
||||
onClick={() => setCalendarOpen(true)}
|
||||
>
|
||||
<img
|
||||
src={IMAGE_ROOT + '/ico_date.svg'}
|
||||
alt="날짜 선택"
|
||||
alt="clear"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
@@ -129,6 +135,7 @@ export const PayoutRequestPage = () => {
|
||||
setCalendarOpen={setCalendarOpen}
|
||||
calendarType={CalendarType.Single}
|
||||
setNewDate={setNewDate}
|
||||
minDate={new Date()}
|
||||
></NiceCalendar>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -21,12 +21,17 @@ import { useStore } from '@/shared/model/store';
|
||||
import { AdditionalServiceCategory } from '@/entities/additional-service/model/types';
|
||||
import { PATHS } from '@/shared/constants/paths';
|
||||
import { EmailBottomSheet } from '@/entities/common/ui/email-bottom-sheet';
|
||||
|
||||
import { useExtensionAccessCheck } from '@/shared/lib/hooks/use-extension-access-check';
|
||||
|
||||
export const SmsPaymentPage = () => {
|
||||
const { navigate } = useNavigate();
|
||||
const userMid = useStore.getState().UserStore.mid;
|
||||
|
||||
// 권한 체크
|
||||
const { hasAccess, AccessDeniedDialog } = useExtensionAccessCheck({
|
||||
extensionCode: 'SMS'
|
||||
});
|
||||
|
||||
const [bottomSmsPaymentDetailResendOn, setBottomSmsPaymentDetailResendOn] = useState<boolean>(false)
|
||||
|
||||
const [sortType, setSortType] = useState<SortTypeKeys>(SortTypeKeys.LATEST);
|
||||
@@ -131,6 +136,10 @@ export const SmsPaymentPage = () => {
|
||||
smsCl
|
||||
]);
|
||||
|
||||
// if (!hasAccess) {
|
||||
// return <AccessDeniedDialog />;
|
||||
// }
|
||||
|
||||
return (
|
||||
<>
|
||||
<main>
|
||||
|
||||
@@ -11,7 +11,7 @@ export const API_URL_ADDITIONAL_SERVICE = {
|
||||
},
|
||||
extensionAccountHolderAuthDownlaodExcel: () => {
|
||||
// POST: 계좌점유인증 엑셀 다운
|
||||
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/extension/account-auth/excel`;
|
||||
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/extension/account-auth/download/excel`;
|
||||
},
|
||||
extensionAccountHolderAuthDetail: () => {
|
||||
// POST: 계좌점유인증 상세 조회
|
||||
@@ -97,6 +97,10 @@ export const API_URL_ADDITIONAL_SERVICE = {
|
||||
// POST: 부가서비스 조회
|
||||
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/extension/list`;
|
||||
},
|
||||
extensionCheck: () => {
|
||||
// POST: 부가서비스 사용여부 체크
|
||||
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/extension/check`;
|
||||
},
|
||||
extensionKeyinList: () => {
|
||||
// POST: KEY-IN 결제 목록 조회
|
||||
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/extension/keyin/list`;
|
||||
|
||||
97
src/shared/lib/hooks/use-extension-access-check.tsx
Normal file
97
src/shared/lib/hooks/use-extension-access-check.tsx
Normal file
@@ -0,0 +1,97 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
|
||||
import { useExtensionCheckMutation } from '@/entities/additional-service/api/use-extension-check-mutation';
|
||||
import { Dialog } from '@/shared/ui/dialogs/dialog';
|
||||
import { PATHS } from '@/shared/constants/paths';
|
||||
|
||||
interface UseExtensionAccessCheckProps {
|
||||
extensionCode: string;
|
||||
enabled?: boolean;
|
||||
}
|
||||
|
||||
interface UseExtensionAccessCheckReturn {
|
||||
hasAccess: boolean | null;
|
||||
AccessDeniedDialog: () => React.ReactElement | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 부가서비스 접근 권한을 체크하는 훅
|
||||
* 페이지 마운트 시 extensionCheck API를 호출하여 권한을 확인하고,
|
||||
* 권한이 없으면 다이얼로그를 표시한 후 이전 페이지로 이동합니다.
|
||||
*/
|
||||
export const useExtensionAccessCheck = ({
|
||||
extensionCode,
|
||||
enabled = true
|
||||
}: UseExtensionAccessCheckProps): UseExtensionAccessCheckReturn => {
|
||||
const { navigate } = useNavigate();
|
||||
const { mutateAsync: extensionCheck } = useExtensionCheckMutation();
|
||||
|
||||
const [hasAccess, setHasAccess] = useState<boolean | null>(null);
|
||||
const [isChecking, setIsChecking] = useState<boolean>(true);
|
||||
const [dialogOpen, setDialogOpen] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!enabled) {
|
||||
setIsChecking(false);
|
||||
setHasAccess(true);
|
||||
return;
|
||||
}
|
||||
|
||||
const checkAccess = async () => {
|
||||
try {
|
||||
setIsChecking(true);
|
||||
const result = await extensionCheck({ extensionCode });
|
||||
|
||||
if (result.checkResult === true) {
|
||||
// 권한 체크 통과
|
||||
setHasAccess(true);
|
||||
} else {
|
||||
// 권한 체크 실패 - 다이얼로그 표시
|
||||
setHasAccess(false);
|
||||
setDialogOpen(true);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Extension access check error:', error);
|
||||
// 에러 발생 시에도 다이얼로그 표시
|
||||
setHasAccess(false);
|
||||
setDialogOpen(true);
|
||||
} finally {
|
||||
setIsChecking(false);
|
||||
}
|
||||
};
|
||||
|
||||
checkAccess();
|
||||
}, [extensionCode, enabled]);
|
||||
|
||||
const handleConfirm = () => {
|
||||
|
||||
setDialogOpen(false);
|
||||
|
||||
setTimeout(() => {
|
||||
navigate(PATHS.additionalService.list);
|
||||
}, 0);
|
||||
};
|
||||
|
||||
const AccessDeniedDialog = () => {
|
||||
return (
|
||||
<Dialog
|
||||
open={dialogOpen}
|
||||
onClose={() => {}}
|
||||
message={
|
||||
<>
|
||||
이용 중이지 않은 서비스입니다.<br />
|
||||
가입 문의는 영업 담당자 또는 고객센터로 문의해 주세요.
|
||||
</>
|
||||
}
|
||||
buttonLabel={['확인']}
|
||||
onConfirmClick={handleConfirm}
|
||||
afterLeave={() => {}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
return {
|
||||
hasAccess,
|
||||
AccessDeniedDialog,
|
||||
};
|
||||
};
|
||||
@@ -36,7 +36,7 @@ export const Dialog = ({
|
||||
const { nativeDialog, resetNativeDialog } = useBridge(bridge.store, (state) => state);
|
||||
|
||||
const whenToBlock = useCallback(() => open, [open]);
|
||||
// 다이얼로그가 열려있을때 뒤로가기 방지
|
||||
|
||||
const blocker = useBlocker(whenToBlock);
|
||||
const nativeMessage = nativeDialog?.message;
|
||||
const displayMessage = nativeMessage || message;
|
||||
@@ -68,7 +68,6 @@ export const Dialog = ({
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<_Dialog onClose={shouldCloseOnBackdropClick ? onClose : () => null} static={!shouldCloseOnBackdropClick}>
|
||||
{/* The backdrop, rendered as a fixed sibling to the panel container */}
|
||||
<div
|
||||
id="cancelConfirmPopup"
|
||||
className="popup-overlay"
|
||||
|
||||
Reference in New Issue
Block a user