This commit is contained in:
focp212@naver.com
2025-10-23 11:08:11 +09:00
48 changed files with 1070 additions and 1310 deletions

View File

@@ -111,7 +111,7 @@ export const UserAccountAuthWrap = ({
]
return (
<>
<div className="ing-list pdtop">
<div className="ing-list pdtop pb-86">
<div className="perm-form">
<div className="perm-field">
<div className="perm-label"> </div>
@@ -144,7 +144,7 @@ export const UserAccountAuthWrap = ({
menuGrants={ permissions }
></UserAccountAuthPermList>
<div className="apply-row bottom-padding">
<div className="apply-row">
<button
className="btn-50 btn-blue flex-1"
type="button"

View File

@@ -5,6 +5,7 @@ import { useEffect, useState } from 'react';
import { useUserModifyAuthMethodMutation } from '@/entities/user/api/use-user-modify-authmethod-mutation';
import { PATHS } from '@/shared/constants/paths';
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { snackBar } from '@/shared/lib/toast';
export const UserLoginAuthInfoWrap = ({
mid,
@@ -25,7 +26,7 @@ export const UserLoginAuthInfoWrap = ({
const { mutateAsync: userFindAuthMethod } = useUserFindAuthMethodMutation();
const { mutateAsync: userModifyAuthMethod } = useUserModifyAuthMethodMutation({
onSuccess: () => {
// snackBar('사용자 정보가 성공적으로 저장되었습니다.');
snackBar('사용자 정보가 성공적으로 저장되었습니다.');
navigate(PATHS.account.user.manage, {
state: {
mid: mid,
@@ -33,7 +34,7 @@ export const UserLoginAuthInfoWrap = ({
});
},
onError: (error) => {
// snackBar(error?.response?.data?.message || '사용자 정보 저장에 실패했습니다.');
snackBar(error?.response?.data?.message || '사용자 정보 저장에 실패했습니다.');
}
});
@@ -391,7 +392,7 @@ export const UserLoginAuthInfoWrap = ({
return (
<>
<div className="ing-list pdtop">
<div className="settings-login-auth">
<div className="settings-login-auth pb-86">
<div className="group">
<div className="group-header">
<div className="title"> </div>
@@ -489,7 +490,7 @@ export const UserLoginAuthInfoWrap = ({
<div className="notice-bar"> .</div>
</div>
</div>
<div className="apply-row bottom-padding">
<div className="apply-row">
<button
className="btn-50 btn-blue flex-1"
disabled={!isSaveButtonEnabled()}

View File

@@ -41,7 +41,8 @@ export const UserManageWrap = () => {
return (
<>
<div className="ing-list" style={{ display: 'flex', flexDirection: 'column', height: 'calc(100vh - 200px)' }}>
{/* <div className="ing-list" style={{ display: 'flex', flexDirection: 'column', height: 'calc(100vh - 86px)' }}> */}
<div className="ing-list pb-86">
<div style={{ flexShrink: 0 }}>
<div className="input-wrapper top-select mt-16">
<select

View File

@@ -0,0 +1,29 @@
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 {
ExtensionFundAccountDownloadReceiptParams as ExtensionFundAccountDownloadReceiptParams,
ExtensionFundAccountDownloadReceiptResponse as ExtensionFundAccountDownloadReceiptResponse
} from '../../model/fund-account/types';
import {
useMutation,
UseMutationOptions
} from '@tanstack/react-query';
export const extensionFundAccountDownloadReceipt = (params: ExtensionFundAccountDownloadReceiptParams) => {
return resultify(
axios.post<ExtensionFundAccountDownloadReceiptResponse>(API_URL_ADDITIONAL_SERVICE.extensionFundAccountDownloadReceipt(), params),
);
};
export const useExtensionFundAccountDownloadReceiptMutation = (options?: UseMutationOptions<ExtensionFundAccountDownloadReceiptResponse, CBDCAxiosError, ExtensionFundAccountDownloadReceiptParams>) => {
const mutation = useMutation<ExtensionFundAccountDownloadReceiptResponse, CBDCAxiosError, ExtensionFundAccountDownloadReceiptParams>({
...options,
mutationFn: (params: ExtensionFundAccountDownloadReceiptParams) => extensionFundAccountDownloadReceipt(params),
});
return {
...mutation,
};
};

View File

@@ -0,0 +1,29 @@
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 {
ExtensionFundAccountTransferRegistParams,
ExtensionFundAccountTransferRegistResponse
} from '../../model/fund-account/types';
import {
useMutation,
UseMutationOptions
} from '@tanstack/react-query';
export const extensionFundAccountTransferRegist = (params: ExtensionFundAccountTransferRegistParams) => {
return resultify(
axios.post<ExtensionFundAccountTransferRegistResponse>(API_URL_ADDITIONAL_SERVICE.extensionFundAccountTransferRegist(), params),
);
};
export const useExtensionFundAccountTransferRegistMutation = (options?: UseMutationOptions<ExtensionFundAccountTransferRegistResponse, CBDCAxiosError, ExtensionFundAccountTransferRegistParams>) => {
const mutation = useMutation<ExtensionFundAccountTransferRegistResponse, CBDCAxiosError, ExtensionFundAccountTransferRegistParams>({
...options,
mutationFn: (params: ExtensionFundAccountTransferRegistParams) => extensionFundAccountTransferRegist(params),
});
return {
...mutation,
};
};

View File

@@ -1,29 +0,0 @@
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 {
ExtensionFundAccountTransferRequestParams,
ExtensionFundAccountTransferRequestResponse
} from '../../model/fund-account/types';
import {
useMutation,
UseMutationOptions
} from '@tanstack/react-query';
export const extensionFundAccountTransferRequest = (params: ExtensionFundAccountTransferRequestParams) => {
return resultify(
axios.post<ExtensionFundAccountTransferRequestResponse>(API_URL_ADDITIONAL_SERVICE.extensionFundAccountTransferRequest(), params),
);
};
export const useExtensionFundAccountTransferRequestMutation = (options?: UseMutationOptions<ExtensionFundAccountTransferRequestResponse, CBDCAxiosError, ExtensionFundAccountTransferRequestParams>) => {
const mutation = useMutation<ExtensionFundAccountTransferRequestResponse, CBDCAxiosError, ExtensionFundAccountTransferRequestParams>({
...options,
mutationFn: (params: ExtensionFundAccountTransferRequestParams) => extensionFundAccountTransferRequest(params),
});
return {
...mutation,
};
};

View File

@@ -1,5 +1,5 @@
import { DefaulResponsePagination, DefaultRequestPagination } from "@/entities/common/model/types";
import { ExtensionRequestParams, FilterProps, ListItemProps } from "../types";
import { AdditionalServiceCategory, ExtensionRequestParams, FilterProps, ListItemProps } from "../types";
// 계좌 점유 조회 관련 타입들
export enum AuthAndTransferStatus {
@@ -18,7 +18,8 @@ export interface AccountHolderAuthListItem {
transferStatus?: AuthAndTransferStatus;
}
export interface AccountHolderAuthListProps {
listItems: Record<string, Array<ListItemProps>>;
additionalServiceCategory: AdditionalServiceCategory;
listItems: Array<ExtensionAccountHolderAuthContentItem>;
mid: string;
}
export interface AccountHolderAuthFilterProps extends FilterProps {
@@ -34,7 +35,8 @@ export interface AccountHolderAuthFilterProps extends FilterProps {
// 계좌 점유 인증 확장 서비스
// ========================================
export interface ExtensionAccountHolderAuthListParams extends ExtensionRequestParams {
export interface ExtensionAccountHolderAuthListParams {
mid: string;
fromDate: string;
toDate: string;
authStatus: string;
@@ -42,7 +44,16 @@ export interface ExtensionAccountHolderAuthListParams extends ExtensionRequestPa
}
export interface ExtensionAccountHolderAuthListResponse extends DefaulResponsePagination {
content: Array<ListItemProps>
content: Array<ExtensionAccountHolderAuthContentItem>
}
export interface ExtensionAccountHolderAuthContentItem {
tid?: string;
accountName?: string;
accountNo?: string;
requestDate?: string;
bankName?: string;
authStatus?: AuthAndTransferStatus;
}
export interface ExtensionAccountHolderAuthDownloadExcelParams extends ExtensionRequestParams {

View File

@@ -24,7 +24,6 @@ export interface AccountHolderSearchListItem {
export interface AccountHolderSearchListProps {
listItems: Array<AccountHolderSearchListItem>;
mid: string;
setTarget: (element: HTMLElement | null) => void;
}
export interface AccountHolderSearchFilterProps extends FilterProps {

View File

@@ -0,0 +1,42 @@
import { AlimtalkAlimCl, AlimtalkSearchCl, AlimTalkSendCl, AlimtalkSendType, ServiceCode } from "./types";
export const AlimtalkSearchClOptionGroup = [
{name: '주문자', value: AlimtalkSearchCl.BUYER_NAME },
{name: 'TID', value: AlimtalkSearchCl.TID },
];
export const AlimtalkServiceCodeOptionGroup = [
{name: '전체', value: ''},
{name: '카드', value: ServiceCode.CARD },
{name: '계좌이체', value: ServiceCode.BANK },
{name: '가상계좌', value: ServiceCode.VBANK },
{name: '휴대폰', value: ServiceCode.PHONE }
]
// 알림구분 - 카드/계좌이체/휴대폰용
export const AlimtalkAlimClBtnGroupForGeneral = [
{name: '전체', value: '' },
{name: '승인', value: AlimtalkAlimCl.APPROVAL },
{name: '취소', value: AlimtalkAlimCl.CANCEL }
]
// 알림구분 - 가상계좌용
export const AlimtalkAlimClBtnGroupForVBank = [
{name: '전체', value: '' },
{name: '입금요청', value: AlimtalkAlimCl.DEPOSIT_REQUEST },
{name: '입금완료', value: AlimtalkAlimCl.DEPOSIT_COMPLETE },
{name: '환불', value: AlimtalkAlimCl.REFUND }
]
export const AlimtalkSendTypeBtnGroup = [
{name: '전체', value: AlimtalkSendType.ALL },
{name: '카카오톡', value: AlimtalkSendType.KAKAOTALK },
{name: 'FB SMS', value: AlimtalkSendType.FB_SMS }
]
export const AlimtalkSendClBtnGroup = [
{name: '전체', value: AlimTalkSendCl.ALL },
{name: '요청', value: AlimTalkSendCl.REQUEST },
{name: '성공', value: AlimTalkSendCl.SUCCESS },
{name: '실패', value: AlimTalkSendCl.FAIL }
]

View File

@@ -31,6 +31,14 @@ export enum AlimTalkSendCl {
SUCCESS = 'SUCCESS',
FAIL = 'FAIL'
};
export enum ServiceCode {
CARD = 'CARD',
BANK = 'BANK',
VBANK = 'VBANK',
PHONE = 'PHONE'
}
export interface ExtensionAlimtalkSettingSaveParams {
mid: string;
sendMerchantInfo?: SendMerchantInfo;
@@ -97,7 +105,7 @@ export interface ExtensionAlimtalkDownloadExcelParams {
mid?: string;
searchCl?: AlimtalkSearchCl;
searchValue?: string;
paymentMethod?: string;
serviceCode?: string;
alimCl?: AlimtalkAlimCl;
fromDate?: string;
toDate?: string;
@@ -105,7 +113,9 @@ export interface ExtensionAlimtalkDownloadExcelParams {
sendCl?: AlimTalkSendCl;
};
export interface ExtensionAlimtalkDownloadExcelResponse {};
export interface ExtensionAlimtalkDownloadExcelResponse {
status : boolean
};
export interface ExtensionAlimtalkDetailParams {
mid: string;

View File

@@ -20,8 +20,7 @@ export enum FundAccountReceiveAccountNameNo {
ReceiveAccountName = 'ReceiveAccountName'
};
export interface ExtensionFundAccountTransferRequestParams {
export interface ExtensionFundAccountTransferRegistParams {
mid?: string;
bankCode: string;
accountNo: string;
@@ -30,10 +29,19 @@ export interface ExtensionFundAccountTransferRequestParams {
moid: string;
depositParameter?: string;
};
export interface ExtensionFundAccountTransferRequestResponse {
export interface ExtensionFundAccountTransferRegistResponse {
status: boolean;
};
export interface ExtensionFundAccountTransferRequestParams {
}
export interface ExtensionFundAccountTransferRequestResponse {
}
export enum FundAccountSearchCl {
ACCOUNT_NAME = 'ACCOUNT_NAME',
ACCOUNT_NO = 'ACCOUNT_NO'
@@ -94,8 +102,7 @@ export interface ExtensionFundAccountTransferExcelResponse {
status: boolean;
};
export interface ExtensionFundAccountTransferDetailParams {
mid: string;
tid: string;
seq: string;
};
export interface ExtensionFundAccountTransferDetailResponse {
tid: string;
@@ -177,7 +184,7 @@ export interface ExtensionFundAccountResultDetailResponse {
requsetDate: string;
resultMessage: string;
failReason: string;
bankCode: string;
bankName: string;
};
export interface ExtensionFundAccountBalanceParams {
mid: string;
@@ -187,11 +194,11 @@ export interface ExtensionFundAccountBalanceResponse {
};
// 입금확인증 다운로드
export interface ExtensionFundAccountDownloadCertificateParams {
export interface ExtensionFundAccountDownloadReceiptParams {
mid: string;
tid: string;
email: string;
};
export interface ExtensionFundAccountDownloadCertificateResponse {
export interface ExtensionFundAccountDownloadReceiptResponse {
status: boolean;
};

View File

@@ -22,7 +22,6 @@ export interface KeyInPaymentListProps {
additionalServiceCategory: AdditionalServiceCategory;
listItems: Array<KeyInPaymentListItem>;
mid?: string;
setTarget: (element: HTMLElement | null) => void;
}
export interface KeyInPaymentFilterProps extends FilterProps {

View File

@@ -103,14 +103,12 @@ export interface LinkPaymentWaitListItem {
export interface LinkPaymentHistoryListProps {
additionalServiceCategory: AdditionalServiceCategory;
listItems: Array<LinkPaymentHistoryListItem>;
setTarget: (element: HTMLElement | null) => void;
mid: string;
}
export interface LinkPaymentWaitListProps {
additionalServiceCategory: AdditionalServiceCategory;
listItems: Array<LinkPaymentWaitListItem>;
setTarget: (element: HTMLElement | null) => void;
mid: string;
}

View File

@@ -25,7 +25,6 @@ export interface SmsPaymentListProps {
additionalServiceCategory: AdditionalServiceCategory;
mid: string;
onResendClick?: (mid: string, tid: string) => void;
setTarget: (element: HTMLElement | null) => void;
}
export interface SmsPaymentFilterProps extends FilterProps {

View File

@@ -167,6 +167,7 @@ export interface ListItemProps extends
ArsListContent, AlimtalkListContent, FaceAuthListItem {
additionalServiceCategory?: AdditionalServiceCategory;
mid?: string;
seq?: string;
onResendClick?: (mid: string, tid: string) => void;
}

View File

@@ -1,24 +1,53 @@
import { ListDateGroup } from '../list-date-group';
import { AdditionalServiceCategory } from '../../model/types';
import { AccountHolderAuthListProps } from '../../model/account-holder-auth/types';
import { AccountHolderAuthListProps, ExtensionAccountHolderAuthContentItem } from '../../model/account-holder-auth/types';
import { JSX } from 'react';
export const AccountHolderAuthList = ({
additionalServiceCategory,
listItems,
mid
}: AccountHolderAuthListProps) => {
const getListDateGroup = () => {
let rs = [];
for (const [key, value] of Object.entries(listItems)) {
let rs: JSX.Element[] = [];
let date = '';
let list: ExtensionAccountHolderAuthContentItem[] = [];
for (let i = 0; i < listItems.length; i++) {
// sendDate(발송일자) 기준
let requestDate = listItems[i]?.requestDate || '';
let itemDate = requestDate.substring(0, 8);
if (i === 0) {
date = itemDate;
}
if (date !== itemDate) {
if (list.length > 0) {
rs.push(
<ListDateGroup
additionalServiceCategory={AdditionalServiceCategory.AccountHolderAuth}
key={key}
date={key}
items={value}
additionalServiceCategory={additionalServiceCategory}
key={date + '-' + i}
date={date}
items={list as any}
mid={mid}
></ListDateGroup>
)
);
}
date = itemDate;
list = [];
}
list.push(listItems[i] as any);
}
if (list.length > 0) {
rs.push(
<ListDateGroup
additionalServiceCategory={additionalServiceCategory}
key={date + '-last'}
date={date}
items={list as any}
mid={mid}
></ListDateGroup>
);
}
return rs;
};

View File

@@ -7,8 +7,7 @@ import { JSX } from 'react';
export const AccountHolderSearchList = ({
listItems,
mid,
setTarget
mid
}: AccountHolderSearchListProps) => {
const { navigate } = useNavigate();
@@ -63,7 +62,6 @@ export const AccountHolderSearchList = ({
<>
<section className="transaction-list">
{getListDateGroup()}
<div ref={setTarget}></div>
</section>
<div className="apply-row">
<button

View File

@@ -1,4 +1,4 @@
import { useEffect, useState } from 'react';
import { useEffect, useState, useMemo } from 'react';
import { motion } from 'framer-motion';
import { IMAGE_ROOT } from '@/shared/constants/common';
import { FilterSelect } from '@/shared/ui/filter/select';
@@ -11,93 +11,112 @@ import {
FilterMotionVariants
} from '@/entities/common/model/constant';
import moment from 'moment';
import { FilterInput } from '@/shared/ui/filter/input';
import { OrderStatus, PaymentStatus } from '../../model/ars/types';
import { ArsOrderStatusBtnGroup, ArsPaymentStatusBtnGroup } from '../../model/ars/constant';
import { useStore } from '@/shared/model/store';
import { AlimtalkAlimCl, AlimtalkSearchCl, AlimTalkSendCl, AlimtalkSendType, ServiceCode } from '../../model/alimtalk/types';
import { FilterSelectInput } from '@/shared/ui/filter/select-input';
import { AlimtalkAlimClBtnGroupForGeneral, AlimtalkAlimClBtnGroupForVBank, AlimtalkSearchClOptionGroup, AlimtalkSendClBtnGroup, AlimtalkSendTypeBtnGroup, AlimtalkServiceCodeOptionGroup } from '../../model/alimtalk/constant';
export interface AlimtalkFilterProps {
filterOn: boolean;
setFilterOn: (filterOn: boolean) => void;
mid: string;
moid: string;
searchCl: AlimtalkSearchCl;
searchValue: string;
fromDate: string;
toDate: string;
paymentStatus: PaymentStatus;
orderStatus: OrderStatus;
minAmount?: number;
maxAmount?: number;
serviceCode: ServiceCode;
alimCl: AlimtalkAlimCl;
sendType: AlimtalkSendType;
sendCl: AlimTalkSendCl;
setMid: (mid: string) => void;
setMoid: (moid: string) => void;
setSearchCl: (searchCl: AlimtalkSearchCl) => void;
setSearchValue: (searchValue: string) => void;
setFromDate: (fromDate: string) => void;
setToDate: (toDate: string) => void;
setPaymentStatus: (paymentStatus: PaymentStatus) => void;
setOrderStatus: (orderStatus: OrderStatus) => void;
setMinAmount: (minAmount?: number) => void;
setMaxAmount: (maxAmount?: number) => void;
setServiceCode: (serviceCode: ServiceCode) => void;
setAlimCl: (alimCl: AlimtalkAlimCl) => void;
setSendType: (sendType: AlimtalkSendType) => void;
setSendCl: (sendCl: AlimTalkSendCl) => void;
};
export const AlimtalkFilter = ({
filterOn,
setFilterOn,
mid,
moid,
searchCl,
searchValue,
fromDate,
toDate,
paymentStatus,
orderStatus,
minAmount,
maxAmount,
serviceCode,
alimCl,
sendType,
sendCl,
setMid,
setMoid,
setSearchCl,
setSearchValue,
setFromDate,
setToDate,
setPaymentStatus,
setOrderStatus,
setMinAmount,
setMaxAmount
setServiceCode,
setAlimCl,
setSendType,
setSendCl
}: AlimtalkFilterProps) => {
const [filterMid, setFilterMid] = useState<string>(mid);
const [filterMoid, setFilterMoid] = useState<string>(moid);
const [filterFromDate, setFilterFromDate] = useState<string>(moment(fromDate).format('YYYY.MM.DD'));
const [filterToDate, setFilterToDate] = useState<string>(moment(toDate).format('YYYY.MM.DD'));
const [filterPaymentStatus, setFilterPaymentStatus] = useState<PaymentStatus>(paymentStatus);
const [filterOrderStatus, setFilterOrderStatus] = useState<OrderStatus>(orderStatus);
const [filterMinAmount, setFilterMinAmount] = useState<number | undefined>(minAmount);
const [filterMaxAmount, setFilterMaxAmount] = useState<number | undefined>(maxAmount);
const [filterSearchCl, setFilterSearchCl] = useState<AlimtalkSearchCl>(searchCl);
const [filterSearchValue, setFilterSearchValue] = useState<string>(searchValue);
const [filterFromDate, setFilterFromDate] = useState<string>(moment(fromDate).format('YYYYMMDD'));
const [filterToDate, setFilterToDate] = useState<string>(moment(toDate).format('YYYYMMDD'));
const [filterServiceCode, setFilterServiceCode] = useState<ServiceCode>(serviceCode);
const [filterAlimCl, setFilterAlimCl] = useState<AlimtalkAlimCl>(alimCl);
const [filterSendType, setFilterSendType] = useState<AlimtalkSendType>(sendType);
const [filterSendCl, setFilterSendCl] = useState<AlimTalkSendCl>(sendCl);
const midOptions = useStore.getState().UserStore.selectOptionsMids;
// 결제수단에 따라 알림구분 버튼 그룹 선택
const alimClBtnGroup = useMemo(() => {
if (filterServiceCode === ServiceCode.VBANK) {
return AlimtalkAlimClBtnGroupForVBank;
}
return AlimtalkAlimClBtnGroupForGeneral;
}, [filterServiceCode]);
const onClickToClose = () => {
setFilterOn(false);
};
const onClickToSetFilter = () => {
setMid(filterMid);
setFilterMoid(filterMoid);
setSearchCl(filterSearchCl);
setSearchValue(filterSearchValue);
setFromDate(filterFromDate);
setToDate(filterToDate);
setPaymentStatus(filterPaymentStatus);
setOrderStatus(filterOrderStatus);
setMinAmount(filterMinAmount);
setMaxAmount(filterMaxAmount);
setServiceCode(filterServiceCode);
setAlimCl(filterAlimCl);
setSendType(filterSendType);
setSendCl(filterSendCl);
onClickToClose();
};
useEffect(() => {
setFilterPaymentStatus(paymentStatus);
}, [paymentStatus]);
setFilterSendCl(sendCl);
}, [searchCl]);
// 결제수단이 변경되면 알림구분을 초기화
useEffect(() => {
setFilterAlimCl('' as AlimtalkAlimCl);
}, [filterServiceCode]);
return (
<>
<motion.div
className="full-menu-modal"
initial="hidden"
animate={ (filterOn)? 'visible': 'hidden' }
variants={ FilterMotionVariants }
transition={ FilterMotionDuration }
style={ FilterMotionStyle }
animate={(filterOn) ? 'visible' : 'hidden'}
variants={FilterMotionVariants}
transition={FilterMotionDuration}
style={FilterMotionStyle}
>
<div className="full-menu-container">
<div className="full-menu-header">
@@ -108,9 +127,9 @@ export const AlimtalkFilter = ({
className="full-menu-close"
>
<img
src={ IMAGE_ROOT + '/ico_close.svg' }
src={IMAGE_ROOT + '/ico_close.svg'}
alt="닫기"
onClick={ () => onClickToClose() }
onClick={() => onClickToClose()}
/>
</button>
</div>
@@ -118,46 +137,54 @@ export const AlimtalkFilter = ({
<div className="option-list pt-16">
<FilterSelect
title='가맹점'
selectValue={ filterMid }
selectSetter={ setFilterMid }
selectOptions={ midOptions }
selectValue={filterMid}
selectSetter={setFilterMid}
selectOptions={midOptions}
></FilterSelect>
<FilterInput
title='주문번호'
inputValue={ filterMoid }
inputSetter={ setFilterMoid }
></FilterInput>
<FilterSelectInput
title='주문자,TID'
selectValue={filterSearchCl}
selectSetter={setFilterSearchCl}
selectOptions={AlimtalkSearchClOptionGroup}
inputValue={filterSearchValue}
inputSetter={setFilterSearchValue}
></FilterSelectInput>
<FilterSelect
title='결제수단'
selectValue={filterServiceCode}
selectSetter={setFilterServiceCode}
selectOptions={AlimtalkServiceCodeOptionGroup}
></FilterSelect>
<FilterButtonGroups
title='알림구분'
activeValue={filterAlimCl}
btnGroups={alimClBtnGroup}
setter={setFilterAlimCl}
></FilterButtonGroups>
<FilterCalendar
title='조회기간'
startDate={ filterFromDate }
endDate={ filterToDate }
setStartDate={ setFilterFromDate }
setEndDate={ setFilterToDate }
startDate={filterFromDate}
endDate={filterToDate}
setStartDate={setFilterFromDate}
setEndDate={setFilterToDate}
></FilterCalendar>
<FilterButtonGroups
title='결제상태'
activeValue={ filterPaymentStatus }
btnGroups={ ArsPaymentStatusBtnGroup }
setter={ setFilterPaymentStatus }
title='발송 종류'
activeValue={filterSendType}
btnGroups={AlimtalkSendTypeBtnGroup}
setter={setFilterSendType}
></FilterButtonGroups>
<FilterButtonGroups
title='주문상태'
activeValue={ filterOrderStatus }
btnGroups={ ArsOrderStatusBtnGroup }
setter={ setFilterOrderStatus }
title='발송 구분'
activeValue={filterSendCl}
btnGroups={AlimtalkSendClBtnGroup}
setter={setFilterSendCl}
></FilterButtonGroups>
<FilterRangeAmount
title='거래금액'
minAmount={ filterMinAmount }
maxAmount={ filterMaxAmount }
setMinAmount={ setFilterMinAmount }
setMaxAmount={ setFilterMaxAmount }
></FilterRangeAmount>
</div>
<div className="apply-row">
<button
className="btn-50 btn-blue flex-1"
onClick={ () => onClickToSetFilter() }
onClick={() => onClickToSetFilter()}
></button>
</div>
</div>

View File

@@ -51,8 +51,8 @@ export const FundAccountTransactionFilter = ({
const [filterMid, setFilterMid] = useState<string>(mid);
const [filterSearchCl,setFilterSearchCl] = useState<FundAccountSearchCl>(searchCl);
const [filterSearchValue, setFilterSearchValue] = useState<string>(searchValue);
const [filterFromDate, setFilterFromDate] = useState<string>(moment(fromDate).format('YYYY.MM.DD'));
const [filterToDate, setFilterToDate] = useState<string>(moment(toDate).format('YYYY.MM.DD'));
const [filterFromDate, setFilterFromDate] = useState<string>(moment(fromDate).format('YYYYMMDD'));
const [filterToDate, setFilterToDate] = useState<string>(moment(toDate).format('YYYYMMDD'));
const [filterBankCode, setFilterBankCode] = useState<string>(bankCode);
const [filterStatus, setFilterStatus] = useState<FundAccountStatus>(status);
const midOptions = useStore.getState().UserStore.selectOptionsMids;

View File

@@ -1,5 +1,5 @@
import moment from 'moment';
import { SortTypeKeys } from '@/entities/common/model/types';
import { DefaultRequestPagination, SortTypeKeys } from '@/entities/common/model/types';
import { IMAGE_ROOT } from '@/shared/constants/common';
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { JSX, useEffect, useState } from 'react';
@@ -16,38 +16,17 @@ import { SortTypeBox } from '@/entities/common/ui/sort-type-box';
import { FundAccountResultStatusBtnGroup, FundAccountStatusBtnGroup } from '../../model/fund-account/constant';
import { FundAccountResultFilter } from '../filter/fund-account-result-filter';
import { useStore } from '@/shared/model/store';
import useIntersectionObserver from '@/widgets/intersection-observer';
import { EmailBottomSheet } from '@/entities/common/ui/email-bottom-sheet';
export const FundAccountResultListWrap = () => {
const { navigate } = useNavigate();
const [onActionIntersect, setOnActionIntersect] = useState<boolean>(false);
const onIntersect: IntersectionObserverCallback = (entries: Array<IntersectionObserverEntry>) => {
entries.forEach((entry: IntersectionObserverEntry) => {
if (entry.isIntersecting) {
console.log('Element is now intersecting with the root. [' + onActionIntersect + ']');
if (onActionIntersect) {
callList();
}
}
else {
console.log('Element is no longer intersecting with the root.');
}
});
};
const { setTarget } = useIntersectionObserver({
threshold: 1,
onIntersect
});
const userMid = useStore.getState().UserStore.mid;
const [sortType, setSortType] = useState<SortTypeKeys>(SortTypeKeys.LATEST);
const [listItems, setListItems] = useState<Array<FundAccountResultContentItem>>([]);
const [filterOn, setFilterOn] = useState<boolean>(false);
const [nextCursor, setNextCursor] = useState<string | null>(null);
const [pageParam, setPageParam] = useState(DEFAULT_PAGE_PARAM);
const [pageParam, setPageParam] = useState<DefaultRequestPagination>(DEFAULT_PAGE_PARAM);
const [mid, setMid] = useState<string>(userMid);
const [searchCl, setSearchCl] = useState<FundAccountSearchCl>(FundAccountSearchCl.ACCOUNT_NAME);
@@ -74,49 +53,28 @@ export const FundAccountResultListWrap = () => {
const callList = (option?: {
sortType?: SortTypeKeys,
resultStatus?: FundAccountResultStatus,
resetPage?: boolean
resultStatus?: FundAccountResultStatus
}) => {
setOnActionIntersect(false);
const currentPageParam = option?.resetPage
? { ...DEFAULT_PAGE_PARAM, sortType: option?.sortType ?? sortType }
: { ...pageParam, sortType: option?.sortType ?? sortType };
setPageParam(currentPageParam);
let listSummaryParams: ExtensionFundAccountResultListParams = {
mid: mid,
searchCl: searchCl,
searchValue: searchValue,
searchDateType: searchDateType,
fromDate: '20240901',
toDate: '20250930',
fromDate: fromDate,
toDate: toDate,
bankCode: bankCode,
resultStatus: option?.resultStatus ?? resultStatus,
... {
page: currentPageParam
}
page: pageParam
};
if (listSummaryParams.page) {
listSummaryParams.page.sortType = option?.sortType || sortType;
setPageParam(listSummaryParams.page);
}
extensionFundAccountResultList(listSummaryParams).then((rs: any) => {
console.log(rs);
// resetPage면 기존 리스트 무시, 아니면 추가
setListItems(option?.resetPage ? rs.content : [
...listItems,
...rs.content
]);
if (rs.hasNext) {
setNextCursor(rs.nextCursor);
setPageParam({
...currentPageParam, // pageParam이 아니라 currentPageParam 사용
cursor: rs.nextCursor
});
setOnActionIntersect(true)
}
else {
setNextCursor(null);
}
setListItems(rs.content);
});
};
@@ -159,46 +117,46 @@ export const FundAccountResultListWrap = () => {
const onClickToSort = (sort: SortTypeKeys) => {
setSortType(sort);
callList({
sortType: sort,
resetPage: true
sortType: sort
});
};
const onClickToStatus = (val: FundAccountResultStatus) => {
setResultStatus(val);
callList({
resultStatus: val,
resetPage: true
resultStatus: val
});
};
const getListDateGroup = () => {
let rs: JSX.Element[] = [];
let rs = [];
let date = '';
let list: FundAccountResultContentItem[] = [];
let list = [];
for (let i = 0; i < listItems.length; i++) {
// requestDate format: "20211018140420" (YYYYMMDDHHmmss)
let requestDate = listItems[i]?.requestDate || '';
let itemDate = requestDate.substring(0, 8);
let items = listItems[i];
if (!!items) {
let requestDate = items?.requestDate;
requestDate = requestDate?.substring(0, 8);
if (!!requestDate) {
if (i === 0) {
date = itemDate;
date = requestDate;
}
if (date !== itemDate) {
// 날짜가 바뀌면 이전 리스트를 푸시 (날짜 업데이트 전에!)
if (date !== requestDate) {
date = requestDate;
if (list.length > 0) {
rs.push(
<ListDateGroup
additionalServiceCategory={AdditionalServiceCategory.FundAccountResult}
mid={mid}
key={date + '-' + i}
date={date} // 이전 날짜 사용
items={list as any}
date={date}
items={list}
></ListDateGroup>
);
}
date = itemDate; // 그 다음에 날짜 업데이트
list = [];
}
list.push(listItems[i] as any);
list.push(items);
}
}
}
if (list.length > 0) {
rs.push(
@@ -207,7 +165,7 @@ export const FundAccountResultListWrap = () => {
mid={mid}
key={date + '-last'}
date={date}
items={list as any}
items={list}
></ListDateGroup>
);
}
@@ -219,8 +177,7 @@ export const FundAccountResultListWrap = () => {
}, []);
useEffect(() => {
// 필터 조건이 변경되면 첫 페이지부터 다시 시작
callList({ resetPage: true });
callList();
}, [
mid,
searchCl,
@@ -361,7 +318,6 @@ export const FundAccountResultListWrap = () => {
<section className="transaction-list">
{getListDateGroup()}
<div ref={setTarget}></div>
</section>
<div className="apply-row">
<button

View File

@@ -25,37 +25,16 @@ import { NumericFormat } from 'react-number-format';
import { FundAccountTransactionFilter } from '../filter/fund-account-trnasaction-filter';
import { PATHS } from '@/shared/constants/paths';
import { useStore } from '@/shared/model/store';
import useIntersectionObserver from '@/widgets/intersection-observer';
import { EmailBottomSheet } from '@/entities/common/ui/email-bottom-sheet';
export const FundAccountTransferListWrap = () => {
const { navigate } = useNavigate();
const [onActionIntersect, setOnActionIntersect] = useState<boolean>(false);
const onIntersect: IntersectionObserverCallback = (entries: Array<IntersectionObserverEntry>) => {
entries.forEach((entry: IntersectionObserverEntry) => {
if (entry.isIntersecting) {
console.log('Element is now intersecting with the root. [' + onActionIntersect + ']');
if (onActionIntersect) {
callList();
}
}
else {
console.log('Element is no longer intersecting with the root.');
}
});
};
const { setTarget } = useIntersectionObserver({
threshold: 1,
onIntersect
});
const userMid = useStore.getState().UserStore.mid;
const [sortType, setSortType] = useState<SortTypeKeys>(SortTypeKeys.LATEST);
const [listItems, setListItems] = useState<Array<FundAccountTransferContentItem>>([]);
const [filterOn, setFilterOn] = useState<boolean>(false);
const [nextCursor, setNextCursor] = useState<string | null>(null);
const [pageParam, setPageParam] = useState<DefaultRequestPagination>(DEFAULT_PAGE_PARAM);
const [mid, setMid] = useState<string>(userMid);
const [searchCl, setSearchCl] = useState<FundAccountSearchCl>(FundAccountSearchCl.ACCOUNT_NAME);
@@ -65,7 +44,7 @@ export const FundAccountTransferListWrap = () => {
const [status, setStatus] = useState<FundAccountStatus>(FundAccountStatus.ALL);
const [bankCode, setBankCode] = useState<string>('');
const [email, setEmail] = useState<string>('');
const [emailBottomSheetOn, setEmailBottomSheetOn] = useState<boolean>(false);
const [balance, setBalance] = useState<number>(0);
const { mutateAsync: extensionFundAccountTransferList } = useExtensionFundAccountTransferListMutation();
@@ -74,17 +53,8 @@ export const FundAccountTransferListWrap = () => {
const callList = (option?: {
sortType?: SortTypeKeys,
status?: FundAccountStatus,
resetPage?: boolean
status?: FundAccountStatus
}) => {
setOnActionIntersect(false);
const currentPageParam = option?.resetPage
? { ...DEFAULT_PAGE_PARAM, sortType: option?.sortType ?? sortType }
: { ...pageParam, sortType: option?.sortType ?? sortType };
setPageParam(currentPageParam);
let listSummaryParams: ExtensionFundAccountTransferListParams = {
mid: mid,
searchCl: searchCl,
@@ -93,41 +63,37 @@ export const FundAccountTransferListWrap = () => {
fromDate: fromDate,
toDate: toDate,
resultStatus: option?.status ?? status,
... {
page: currentPageParam
}
page: pageParam
};
if (listSummaryParams.page) {
listSummaryParams.page.sortType = option?.sortType || sortType;
setPageParam(listSummaryParams.page);
}
extensionFundAccountTransferList(listSummaryParams).then((rs: any) => {
setListItems(option?.resetPage ? rs.content : [
...listItems,
...rs.content
]);
if (rs.hasNext) {
setNextCursor(rs.nextCursor);
setPageParam({
...currentPageParam, // pageParam이 아니라 currentPageParam 사용
cursor: rs.nextCursor
});
setOnActionIntersect(true)
}
else {
setNextCursor(null);
}
setListItems(rs.content);
});
callBalance();
};
const callDownloadExcel = () => {
let params: ExtensionFundAccountTransferExcelParams = {
const onClickToOpenEmailBottomSheet = () => {
setEmailBottomSheetOn(true);
};
const onSendRequest = (selectedEmail?: string) => {
if (selectedEmail) {
const params: ExtensionFundAccountTransferExcelParams = {
mid: mid,
email: email,
email: selectedEmail,
fromDate: fromDate,
toDate: toDate,
};
extensionFundAccountTransferExcel(params).then((rs: ExtensionFundAccountTransferExcelResponse) => {
console.log('Excel Download Status:', rs.status);
});
}
setEmailBottomSheetOn(false);
};
const callBalance = () => {
@@ -139,11 +105,6 @@ export const FundAccountTransferListWrap = () => {
});
};
const onClickToDownloadExcel = () => {
callDownloadExcel();
};
const onClickToOpenFilter = () => {
setFilterOn(!filterOn);
};
@@ -151,47 +112,47 @@ export const FundAccountTransferListWrap = () => {
const onClickToSort = (sort: SortTypeKeys) => {
setSortType(sort);
callList({
sortType: sort,
resetPage: true
sortType: sort
});
};
const onClickToStatus = (val: FundAccountStatus) => {
setStatus(val);
callList({
status: val,
resetPage: true
status: val
});
};
const getListDateGroup = () => {
let rs: JSX.Element[] = [];
let rs = [];
let date = '';
let list: FundAccountTransferContentItem[] = [];
let list = [];
for (let i = 0; i < listItems.length; i++) {
// registDate format: "20211018140420" (YYYYMMDDHHmmss)
let registDate = listItems[i]?.registDate || '';
let itemDate = registDate.substring(0, 8);
let items = listItems[i];
if (!!items) {
let registDate = items?.registDate;
registDate = registDate?.substring(0, 8);
if (!!registDate) {
if (i === 0) {
date = itemDate;
date = registDate;
}
if (date !== itemDate) {
// 날짜가 바뀌면 이전 리스트를 푸시 (날짜 업데이트 전에!)
if (date !== registDate) {
date = registDate;
if (list.length > 0) {
rs.push(
<ListDateGroup
additionalServiceCategory={AdditionalServiceCategory.FundAccountTransfer}
mid={mid}
key={date + '-' + i}
date={date} // 이전 날짜 사용
items={list as any}
date={date}
items={list}
></ListDateGroup>
);
}
date = itemDate; // 그 다음에 날짜 업데이트
list = [];
}
list.push(listItems[i] as any);
list.push(items);
}
}
}
if (list.length > 0) {
rs.push(
@@ -200,7 +161,7 @@ export const FundAccountTransferListWrap = () => {
mid={mid}
key={date + '-last'}
date={date}
items={list as any}
items={list}
></ListDateGroup>
);
}
@@ -208,8 +169,7 @@ export const FundAccountTransferListWrap = () => {
};
useEffect(() => {
// 필터 조건이 변경되면 첫 페이지부터 다시 시작
callList({ resetPage: true });
callList();
}, [
mid,
searchCl,
@@ -249,7 +209,7 @@ export const FundAccountTransferListWrap = () => {
<button
className="download-btn"
aria-label="다운로드"
onClick={() => onClickToDownloadExcel()}
onClick={onClickToOpenEmailBottomSheet}
>
<img
src={IMAGE_ROOT + '/ico_download.svg'}
@@ -298,7 +258,6 @@ export const FundAccountTransferListWrap = () => {
<section className="transaction-list pb-86">
{getListDateGroup()}
<div ref={setTarget}></div>
</section>
<div className="apply-row">
<button
@@ -324,6 +283,14 @@ export const FundAccountTransferListWrap = () => {
setBankCode={setBankCode}
setStatus={setStatus}
></FundAccountTransactionFilter>
<EmailBottomSheet
bottomSheetOn={emailBottomSheetOn}
setBottomSheetOn={setEmailBottomSheetOn}
imageSave={false}
sendEmail={true}
sendRequest={onSendRequest}
/>
</>
);
};

View File

@@ -7,38 +7,40 @@ import { JSX } from 'react';
export const KeyInPaymentList = ({
additionalServiceCategory,
listItems,
mid,
setTarget
mid
}: KeyInPaymentListProps) => {
const { navigate } = useNavigate();
const getListDateGroup = () => {
let rs: JSX.Element[] = [];
let rs = [];
let date = '';
let list: KeyInPaymentListItem[] = [];
let list = [];
for (let i = 0; i < listItems.length; i++) {
// paymentDate format: "20211018140420" (YYYYMMDDHHmmss)
let paymentDate = listItems[i]?.paymentDate || '';
let itemDate = paymentDate.substring(0, 8);
let items = listItems[i];
if (!!items) {
let paymentDate = items?.paymentDate;
paymentDate = paymentDate?.substring(0, 8)
if (!!paymentDate) {
if (i === 0) {
date = itemDate;
date = paymentDate;
}
if (date !== itemDate) {
date = itemDate;
if (date !== paymentDate) {
date = paymentDate;
if (list.length > 0) {
rs.push(
<ListDateGroup
additionalServiceCategory={additionalServiceCategory}
mid={mid}
key={date + '-' + i}
date={date}
items={list as any}
items={list}
></ListDateGroup>
);
}
list = [];
}
list.push(listItems[i] as any);
list.push(items);
}
}
}
if (list.length > 0) {
rs.push(
@@ -47,7 +49,7 @@ export const KeyInPaymentList = ({
mid={mid}
key={date + '-last'}
date={date}
items={list as any}
items={list}
></ListDateGroup>
);
}
@@ -62,7 +64,6 @@ export const KeyInPaymentList = ({
<>
<section className="transaction-list">
{getListDateGroup()}
<div ref={setTarget}></div>
</section>
<div className="apply-row">
<button

View File

@@ -5,47 +5,48 @@ import { ListDateGroup } from '../list-date-group';
export const LinkPaymentHistoryList = ({
additionalServiceCategory,
listItems,
setTarget,
mid
}: LinkPaymentHistoryListProps) => {
const getListDateGroup = () => {
let rs: JSX.Element[] = [];
let rs = [];
let date = '';
let list: LinkPaymentHistoryListItem[] = [];
let list = [];
for (let i = 0; i < listItems.length; i++) {
// sendDate(발송일자) 기준
let sendDate = listItems[i]?.sendDate || '';
let itemDate = sendDate.substring(0, 8);
let items = listItems[i];
if (!!items) {
let sendDate = items?.sendDate;
sendDate = sendDate?.substring(0, 8);
if (!!sendDate) {
if (i === 0) {
date = itemDate;
date = sendDate;
}
if (date !== itemDate) {
if (date !== sendDate) {
date = sendDate;
if (list.length > 0) {
rs.push(
<ListDateGroup
additionalServiceCategory={additionalServiceCategory}
key={date + '-' + i}
date={date}
items={list as any}
mid={mid}
items={list}
></ListDateGroup>
);
}
date = itemDate;
list = [];
}
list.push(listItems[i] as any);
list.push(items);
}
}
}
if (list.length > 0) {
rs.push(
<ListDateGroup
additionalServiceCategory={additionalServiceCategory}
mid={mid}
key={date + '-last'}
date={date}
items={list as any}
mid={mid}
items={list}
></ListDateGroup>
);
}
@@ -56,7 +57,6 @@ export const LinkPaymentHistoryList = ({
<>
<div className="transaction-list">
{getListDateGroup()}
<div ref={setTarget}></div>
</div>
</>
)

View File

@@ -13,7 +13,6 @@ import { DEFAULT_PAGE_PARAM } from '@/entities/common/model/constant';
import { useExtensionLinkPayHistoryDownloadExcelMutation } from '../../api/link-payment/use-extension-link-pay-history-download-excel-mutation';
import { useStore } from '@/shared/model/store';
import { ExtensionLinkPayHistoryListParams, LinkPaymentHistoryListItem, LinkPaymentPaymentMethod, LinkPaymentPaymentStatus, LinkPaymentSearchCl, LinkPaymentSendMethod, LinkPaymentSendStatus } from '../../model/link-pay/types';
import useIntersectionObserver from '@/widgets/intersection-observer';
const paymentResultBtnGroup = [
{ name: '전체', value: LinkPaymentPaymentStatus.ALL },
@@ -27,30 +26,10 @@ const paymentResultBtnGroup = [
export const LinkPaymentHistoryWrap = () => {
const { navigate } = useNavigate();
const userMid = useStore.getState().UserStore.mid;
const [onActionIntersect, setOnActionIntersect] = useState<boolean>(false);
const onIntersect: IntersectionObserverCallback = (entries: Array<IntersectionObserverEntry>) => {
entries.forEach((entry: IntersectionObserverEntry) => {
if (entry.isIntersecting) {
console.log('Element is now intersecting with the root. [' + onActionIntersect + ']');
if (onActionIntersect) {
callList();
}
}
else {
console.log('Element is no longer intersecting with the root.');
}
});
};
const { setTarget } = useIntersectionObserver({
threshold: 1,
onIntersect
});
const [filterOn, setFilterOn] = useState<boolean>(false);
const [sortType, setSortType] = useState<SortTypeKeys>(SortTypeKeys.LATEST);
const [listItems, setListItems] = useState<Array<LinkPaymentHistoryListItem>>([]);
const [nextCursor, setNextCursor] = useState<string | null>(null);
const [pageParam, setPageParam] = useState<DefaultRequestPagination>(DEFAULT_PAGE_PARAM);
const [mid, setMid] = useState<string>(userMid);
@@ -74,17 +53,8 @@ export const LinkPaymentHistoryWrap = () => {
const callList = (option?: {
sortType?: SortTypeKeys,
status?: LinkPaymentPaymentStatus,
resetPage?: boolean
status?: LinkPaymentPaymentStatus
}) => {
setOnActionIntersect(false);
const currentPageParam = option?.resetPage
? { ...DEFAULT_PAGE_PARAM, sortType: option?.sortType ?? sortType }
: { ...pageParam, sortType: option?.sortType ?? sortType };
setPageParam(currentPageParam); // currentPageParam으로 수정!
let listParams: ExtensionLinkPayHistoryListParams = {
mid: mid,
searchCl: searchCl,
@@ -94,27 +64,16 @@ export const LinkPaymentHistoryWrap = () => {
paymentStatus: option?.status ?? paymentStatus,
sendStatus: sendStatus,
sendMethod: sendMethod,
... {
page: currentPageParam
}
page: pageParam
};
if (listParams.page) {
listParams.page.sortType = option?.sortType || sortType;
setPageParam(listParams.page);
}
linkPayHistoryList(listParams).then((rs) => {
setListItems(option?.resetPage ? rs.content : [
...listItems,
...rs.content
]);
if (rs.hasNext) {
setNextCursor(rs.nextCursor);
setPageParam({
...currentPageParam, // pageParam이 아니라 currentPageParam 사용
cursor: rs.nextCursor
});
setOnActionIntersect(true)
}
else {
setNextCursor(null);
}
setListItems(rs.content);
});
};
@@ -138,16 +97,14 @@ export const LinkPaymentHistoryWrap = () => {
const onClickPaymentStatus = (val: LinkPaymentPaymentStatus) => {
setPaymentStatus(val);
callList({
status: val,
resetPage: true
status: val
})
}
const onClickToSort = (sort: SortTypeKeys) => {
setSortType(sort);
callList({
sortType: sort,
resetPage: true
sortType: sort
});
};
@@ -156,8 +113,7 @@ export const LinkPaymentHistoryWrap = () => {
};
useEffect(() => {
// 필터 조건이 변경되면 첫 페이지부터 다시 시작
callList({ resetPage: true });
callList();
}, [
mid,
searchCl,
@@ -227,7 +183,6 @@ export const LinkPaymentHistoryWrap = () => {
<LinkPaymentHistoryList
listItems={listItems}
additionalServiceCategory={AdditionalServiceCategory.LinkPaymentHistory}
setTarget={setTarget}
mid={mid}
></LinkPaymentHistoryList>
<div className="apply-row">

View File

@@ -5,46 +5,48 @@ import { ListDateGroup } from '../list-date-group';
export const LinkPaymentWaitList = ({
additionalServiceCategory,
listItems,
setTarget,
mid
}: LinkPaymentWaitListProps) => {
const getListDateGroup = () => {
let rs: JSX.Element[] = [];
let rs = [];
let date = '';
let list: LinkPaymentWaitListItem[] = [];
let list = [];
for (let i = 0; i < listItems.length; i++) {
// paymentDate format: "20211018140420" (YYYYMMDDHHmmss)
let scheduledSendDate = listItems[i]?.scheduledSendDate || '';
let itemDate = scheduledSendDate.substring(0, 8);
if (i === 0) {
date = itemDate;
let items = listItems[i];
if(!!items) {
let scheduledSendDate = items?.scheduledSendDate;
scheduledSendDate = scheduledSendDate?.substring(0, 8);
if(!!scheduledSendDate) {
if(i === 0) {
date = scheduledSendDate;
}
if (date !== itemDate) {
if (list.length > 0) {
if(date !== scheduledSendDate) {
date = scheduledSendDate;
if(list.length > 0) {
rs.push(
<ListDateGroup
additionalServiceCategory={additionalServiceCategory}
key={date + '-' + i}
date={date}
items={list as any}
mid={mid}
key={ date + '-' + i}
date={ date }
items={ list }
></ListDateGroup>
);
}
date = itemDate;
list = [];
}
list.push(listItems[i] as any);
list.push(items);
}
}
}
if (list.length > 0) {
rs.push(
<ListDateGroup
additionalServiceCategory={additionalServiceCategory}
mid={mid}
key={date + '-last'}
date={date}
items={list as any}
mid={mid}
items={list}
></ListDateGroup>
);
}
@@ -55,7 +57,6 @@ export const LinkPaymentWaitList = ({
<>
<div className="transaction-list">
{getListDateGroup()}
<div ref={setTarget}></div>
</div>
</>
)

View File

@@ -13,9 +13,9 @@ import { DEFAULT_PAGE_PARAM } from '@/entities/common/model/constant';
import { useExtensionLinkPayWaitDownloadExcelMutation } from '../../api/link-payment/use-extension-link-pay-wait-download-excel-mutation';
import { useStore } from '@/shared/model/store';
import { LinkPaymentProcessStatus, LinkPaymentSearchCl, LinkPaymentSendMethod, LinkPaymentSendStatus, LinkPaymentWaitListItem } from '../../model/link-pay/types';
import useIntersectionObserver from '@/widgets/intersection-observer';
import { ProcessStatusBtnGrouup } from '../../model/link-pay/constant';
import { useExtensionLinkPayWaitDeleteMutation } from '../../api/link-payment/use-extension-link-pay-wait-delete-mutation';
import { EmailBottomSheet } from '@/entities/common/ui/email-bottom-sheet';
@@ -23,26 +23,6 @@ export const LinkPaymentWaitSendWrap = () => {
const { navigate } = useNavigate();
const userMid = useStore.getState().UserStore.mid;
const [onActionIntersect, setOnActionIntersect] = useState<boolean>(false);
const onIntersect: IntersectionObserverCallback = (entries: Array<IntersectionObserverEntry>) => {
entries.forEach((entry: IntersectionObserverEntry) => {
if (entry.isIntersecting) {
console.log('Element is now intersecting with the root. [' + onActionIntersect + ']');
if (onActionIntersect) {
callList();
}
}
else {
console.log('Element is no longer intersecting with the root.');
}
});
};
const { setTarget } = useIntersectionObserver({
threshold: 1,
onIntersect
});
const [sortType, setSortType] = useState<SortTypeKeys>(SortTypeKeys.LATEST);
const [filterOn, setFilterOn] = useState<boolean>(false);
const [mid, setMid] = useState<string>(userMid);
@@ -53,7 +33,6 @@ export const LinkPaymentWaitSendWrap = () => {
const [sendMethod, setSendMethod] = useState<LinkPaymentSendMethod>(LinkPaymentSendMethod.ALL);
const [processStatus, setProcessStatus] = useState<LinkPaymentProcessStatus>(LinkPaymentProcessStatus.ALL);
const [listItems, setListItems] = useState<Array<LinkPaymentWaitListItem>>([]);
const [nextCursor, setNextCursor] = useState<string | null>(null);
const [pageParam, setPageParam] = useState<DefaultRequestPagination>(DEFAULT_PAGE_PARAM);
const [email, setEmail] = useState<string>('');
@@ -69,17 +48,8 @@ export const LinkPaymentWaitSendWrap = () => {
const callList = (option?: {
sortType?: SortTypeKeys,
status?: LinkPaymentProcessStatus,
resetPage?: boolean
status?: LinkPaymentProcessStatus
}) => {
setOnActionIntersect(false);
const currentPageParam = option?.resetPage
? { ...DEFAULT_PAGE_PARAM, sortType: option?.sortType ?? sortType }
: { ...pageParam, sortType: option?.sortType ?? sortType };
setPageParam(currentPageParam);
let listParams = {
mid: mid,
searchCl: searchType,
@@ -88,27 +58,16 @@ export const LinkPaymentWaitSendWrap = () => {
toDate: endDate,
sendMethod: sendMethod,
processStatus: option?.status ?? processStatus,
... {
page: currentPageParam
page: pageParam
}
if (listParams.page) {
listParams.page.sortType = option?.sortType || sortType;
setPageParam(listParams.page);
}
pendingSendList(listParams).then((rs) => {
setListItems(option?.resetPage ? rs.content : [
...listItems,
...rs.content
]);
if (rs.hasNext) {
setNextCursor(rs.nextCursor);
setPageParam({
...currentPageParam,
cursor: rs.nextCursor
});
setOnActionIntersect(true);
}
else {
setNextCursor(null);
}
setListItems(rs.content);
});
};
@@ -130,22 +89,19 @@ export const LinkPaymentWaitSendWrap = () => {
const onClickToSort = (sort: SortTypeKeys) => {
setSortType(sort);
callList({
sortType: sort,
resetPage: true
sortType: sort
});
};
const onClickSendingStatus = (val: LinkPaymentProcessStatus) => {
setProcessStatus(val);
callList({
status: val,
resetPage: true
status: val
});
};
useEffect(() => {
// 필터 조건이 변경되면 첫 페이지부터 다시 시작
callList({ resetPage: true });
callList();
}, [
mid,
searchType,
@@ -212,7 +168,6 @@ export const LinkPaymentWaitSendWrap = () => {
<LinkPaymentWaitList
listItems={listItems}
additionalServiceCategory={AdditionalServiceCategory.LinkPaymentWait}
setTarget={setTarget}
mid={mid}
></LinkPaymentWaitList>
<div className="apply-row">

View File

@@ -71,6 +71,8 @@ export const ListDateGroup = ({
smsCl= { items[i]?.smsCl }
onResendClick={ onResendClick }
seq= { items[i]?.seq}
></ListItem>
)
}

View File

@@ -28,6 +28,7 @@ export const ListItem = ({
paymentMethod, receiverName,
requestId,subReqId,
buyerName,receiverInfo,
seq,
smsCl,
name,
@@ -190,8 +191,7 @@ export const ListItem = ({
navigate(PATHS.additionalService.fundAccount.transferDetail, {
state: {
additionalServiceCategory: additionalServiceCategory,
mid: mid,
tid: tid
seq: seq
}
});
}

View File

@@ -6,37 +6,39 @@ export const SmsPaymentList = ({
listItems,
additionalServiceCategory,
mid,
onResendClick,
setTarget
onResendClick
}: SmsPaymentListProps) => {
const getListDateGroup = () => {
let rs = [];
let date = '';
let list: SmsPaymentListItem[] = [];
let list = [];
for (let i = 0; i < listItems.length; i++) {
let paymentDate = listItems[i]?.paymentDate || '';
let itemDate = paymentDate.substring(0, 8);
if (i === 0) {
date = itemDate;
let items = listItems[i];
if(!!items) {
let paymentDate = items?.paymentDate;
paymentDate = paymentDate?.substring(0, 8);
if(!!paymentDate) {
if(i === 0) {
date = paymentDate;
}
if (date !== itemDate) {
date = itemDate;
if (list.length > 0) {
if(date !== paymentDate) {
date = paymentDate;
if(list.length > 0) {
rs.push(
<ListDateGroup
additionalServiceCategory={additionalServiceCategory}
onResendClick={onResendClick}
mid={mid}
key={date + '-' + i}
date={date}
items={list as any}
key={ date + '-' + i}
date={ date }
items={ list }
></ListDateGroup>
);
}
list = [];
}
list.push(listItems[i] as any);
list.push(items);
}
}
}
if (list.length > 0) {
rs.push(
@@ -46,7 +48,7 @@ export const SmsPaymentList = ({
mid={mid}
key={date + '-last'}
date={date}
items={list as any}
items={list}
></ListDateGroup>
);
}
@@ -57,7 +59,6 @@ export const SmsPaymentList = ({
<>
<section className="transaction-list">
{getListDateGroup()}
<div ref={setTarget}></div>
</section>
</>
)

View File

@@ -18,12 +18,12 @@ export const EmailBottomSheet = ({
sendEmail,
sendRequest
}: EmailBottomSheetProps) => {
const [userEmail, setUserEmail] = useState<string>('');
const emailList = [
{name: 'test1@nicepay.co.kr', value: 'test1@nicepay.co.kr'},
{name: 'test2@nicepay.co.kr', value: 'test2@nicepay.co.kr'},
{name: 'test3@nicepay.co.kr', value: 'test3@nicepay.co.kr'},
];
const [userEmail, setUserEmail] = useState<string>(emailList[0]?.value || '');
const onClickToClose = () => {
setBottomSheetOn(false);
};

View File

@@ -1,4 +1,4 @@
import { useState, useRef, useEffect, ChangeEvent } from 'react';
import { useState } from 'react';
import { PATHS } from '@/shared/constants/paths';
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { HeaderType } from '@/entities/common/model/types';
@@ -10,7 +10,7 @@ import {
} from '@/widgets/sub-layout/use-sub-layout';
import { useUserChangeCancelPasswordMutation } from '@/entities/user/api/use-user-change-cancel-password-mutation';
import { useStore } from '@/shared/model/store';
import { XKeypad, XKeypadManager, createPasswordKeypad } from '@/utils/xkeypad';
import { snackBar } from '@/shared/lib/toast';
export const PasswordModifyCancelPasswordPage = () => {
const { navigate } = useNavigate();
@@ -20,69 +20,20 @@ export const PasswordModifyCancelPasswordPage = () => {
const [mid, setMid] = useState<string>(userMid);
const [password, setPassword] = useState<string>('');
const [confirmPassword, setConfirmPassword] = useState<string>('');
const [isKeypadLoaded, setIsKeypadLoaded] = useState(false);
// Input refs for xkeypad
const passwordInputRef = useRef<HTMLInputElement>(null);
const confirmPasswordInputRef = useRef<HTMLInputElement>(null);
// XKeypad instances
const passwordKeypadRef = useRef<XKeypad | null>(null);
const confirmPasswordKeypadRef = useRef<XKeypad | null>(null);
// RSA Keys (실제 프로덕션에서는 서버에서 받아와야 함)
const RSA_MODULUS = "C4F7B39E2E93DB19C016C7A0C1C05B028A1D57CB9B91E13F5B7353F8FB5AC6CE6BE31ABEB8E8F7AD18B90C08F4EBC011A6A8FCE614EA879ED5B96296B969CE92923BC9BAD6FD87F00E08F529F93010EA77E40937BDAC1C866E79ACE2F2822A3ECD982F90532D5301CF90D9BF89E953A0593AB6C5F31E99B690DD582FB85F85A9";
const RSA_EXPONENT = "10001";
const changeCancelPasswordMutation = useUserChangeCancelPasswordMutation({
onSuccess: () => {
// snackBar('비밀번호가 성공적으로 변경되었습니다.');
// Clear form and keypads
snackBar('비밀번호가 성공적으로 변경되었습니다.');
// Clear form
setPassword('');
setConfirmPassword('');
if (passwordKeypadRef.current) passwordKeypadRef.current.clear();
if (confirmPasswordKeypadRef.current) confirmPasswordKeypadRef.current.clear();
if (passwordInputRef.current) passwordInputRef.current.value = '';
if (confirmPasswordInputRef.current) confirmPasswordInputRef.current.value = '';
// Navigate back
navigate(PATHS.account.password.manage);
},
onError: (error) => {
// snackBar(error?.response?.data?.message || '비밀번호 변경에 실패했습니다.');
snackBar(error?.response?.data?.message || '비밀번호 변경에 실패했습니다.');
}
});
// Initialize XKeypad
useEffect(() => {
const initializeKeypad = async () => {
try {
const manager = XKeypadManager.getInstance({
modulus: RSA_MODULUS,
exponent: RSA_EXPONENT
});
await manager.loadScripts();
// RSA 키 설정을 명시적으로 다시 한번 수행
manager.setRSAPublicKey(RSA_MODULUS, RSA_EXPONENT);
setIsKeypadLoaded(true);
} catch (error) {
console.error('Failed to load XKeypad:', error);
}
};
initializeKeypad();
return () => {
// Cleanup keypads on unmount
if (passwordKeypadRef.current) {
passwordKeypadRef.current.destroy();
}
if (confirmPasswordKeypadRef.current) {
confirmPasswordKeypadRef.current.destroy();
}
};
}, []);
useSetHeaderTitle('거래취소 비밀번호 변경');
useSetHeaderType(HeaderType.LeftArrow);
@@ -100,97 +51,10 @@ export const PasswordModifyCancelPasswordPage = () => {
);
};
// Handle password keypad
const handlePasswordKeypad = async () => {
if (!passwordInputRef.current || !isKeypadLoaded) return;
// Close other keypad if open
if (confirmPasswordKeypadRef.current) {
confirmPasswordKeypadRef.current.close();
}
// Create or initialize password keypad
if (!passwordKeypadRef.current) {
passwordKeypadRef.current = createPasswordKeypad(passwordInputRef.current, {
keyType: 'qwertysmart',
viewType: 'half',
maxInputSize: 16,
useOverlay: true,
useModal: false,
hasPressEffect: true,
isE2E: false, // E2E 모드 비활성화
onInputChange: (length: number) => {
// Update password state as typing
if (passwordKeypadRef.current) {
const plainText = passwordKeypadRef.current.getPlainText();
console.log('passwordKeypadRef:', plainText, passwordInputRef.current?.value);
setPassword(plainText);
}
},
onKeypadClose: () => {
// Final update when keypad closes
if (passwordKeypadRef.current) {
const plainText = passwordKeypadRef.current.getPlainText();
setPassword(plainText);
}
}
});
}
const result = await passwordKeypadRef.current.initialize(passwordInputRef.current);
if (result !== 0) {
console.error('Failed to initialize password keypad');
}
};
// Handle confirm password keypad
const handleConfirmPasswordKeypad = async () => {
if (!confirmPasswordInputRef.current || !isKeypadLoaded) return;
// Close other keypad if open
if (passwordKeypadRef.current) {
passwordKeypadRef.current.close();
}
// Create or initialize confirm password keypad
if (!confirmPasswordKeypadRef.current) {
confirmPasswordKeypadRef.current = createPasswordKeypad(confirmPasswordInputRef.current, {
keyType: 'qwertysmart',
viewType: 'half',
maxInputSize: 16,
useOverlay: true,
useModal: false,
hasPressEffect: true,
isE2E: false, // E2E 모드 비활성화
onInputChange: (length: number) => {
// Update confirm password state as typing
if (confirmPasswordKeypadRef.current) {
const plainText = confirmPasswordKeypadRef.current.getPlainText();
console.log('confirmPasswordKeypadRef:', plainText, confirmPasswordInputRef.current?.value);
setConfirmPassword(plainText);
}
},
onKeypadClose: () => {
// Final update when keypad closes
if (confirmPasswordKeypadRef.current) {
const plainText = confirmPasswordKeypadRef.current.getPlainText();
setConfirmPassword(plainText);
}
}
});
}
const result = await confirmPasswordKeypadRef.current.initialize(confirmPasswordInputRef.current);
if (result !== 0) {
console.error('Failed to initialize confirm password keypad');
}
};
// 저장 버튼 클릭 핸들러
const handleSave = () => {
if (!isFormValid()) return;
// 평문 비밀번호 사용 (E2E 모드가 꺼져있으므로)
changeCancelPasswordMutation.mutate({
mid,
password: password
@@ -208,15 +72,15 @@ export const PasswordModifyCancelPasswordPage = () => {
<div className="ua-label"> <span className="red">*</span></div>
<select
className="wid-100"
value={ mid }
onChange={ (e: ChangeEvent<HTMLSelectElement>) => setMid(e.target.value) }
value={mid}
onChange={(e) => setMid(e.target.value)}
>
{
midOptions.map((value, index) => (
midOptions.map((value) => (
<option
key={ value.value }
value={ value.value }
>{ value.name }</option>
key={value.value}
value={value.value}
>{value.name}</option>
))
}
</select>
@@ -224,27 +88,21 @@ export const PasswordModifyCancelPasswordPage = () => {
<div className="ua-row">
<div className="ua-label"> <span className="red">*</span></div>
<input
ref={passwordInputRef}
className={`wid-100 ${confirmPassword && password !== confirmPassword ? 'error' : ''}`}
type="password"
placeholder="클릭하여 비밀번호 입력"
placeholder="비밀번호 입력하세요"
value={password}
onClick={handlePasswordKeypad}
readOnly
style={{ cursor: 'pointer' }}
onChange={(e) => setPassword(e.target.value)}
/>
</div>
<div className="ua-row">
<div className="ua-label"> <span className="red">*</span></div>
<input
ref={confirmPasswordInputRef}
className={`wid-100 ${confirmPassword && password !== confirmPassword ? 'error' : ''}`}
type="password"
placeholder="클릭하여 비밀번호 재입력"
placeholder="비밀번호를 다시 입력하세요"
value={confirmPassword}
onClick={handleConfirmPasswordKeypad}
readOnly
style={{ cursor: 'pointer' }}
onChange={(e) => setConfirmPassword(e.target.value)}
/>
</div>
{confirmPassword && password !== confirmPassword && (

View File

@@ -9,6 +9,7 @@ import {
useSetOnBack
} from '@/widgets/sub-layout/use-sub-layout';
import { useUserChangePasswordMutation } from '@/entities/user/api/use-user-change-password-mutation';
import { snackBar } from '@/shared/lib/toast';
export const PasswordModifyLoginPasswordPage = () => {
const { navigate } = useNavigate();
@@ -19,7 +20,7 @@ export const PasswordModifyLoginPasswordPage = () => {
const changePasswordMutation = useUserChangePasswordMutation({
onSuccess: () => {
// snackBar('비밀번호가 성공적으로 변경되었습니다.');
snackBar('비밀번호가 성공적으로 변경되었습니다.');
// Clear form
setCurrentPassword('');
setNewPassword('');
@@ -28,7 +29,7 @@ export const PasswordModifyLoginPasswordPage = () => {
navigate(PATHS.account.password.manage);
},
onError: (error) => {
// snackBar(error?.response?.data?.message || '비밀번호 변경에 실패했습니다.');
snackBar(error?.response?.data?.message || '비밀번호 변경에 실패했습니다.');
}
});

View File

@@ -12,6 +12,7 @@ import { VerificationItem } from '@/entities/account/model/types';
import { useUserCreateMutation } from '@/entities/user/api/use-user-create-mutation';
import { useUserExistsUseridQuery } from '@/entities/user/api/use-user-exists-userid-query';
import { useLocation } from 'react-router';
import { snackBar } from '@/shared/lib/toast';
export const UserAddAccountPage = () => {
const { navigate } = useNavigate();
@@ -20,10 +21,10 @@ export const UserAddAccountPage = () => {
const { mutateAsync: userCreate, isPending } = useUserCreateMutation({
onSuccess: () => {
// snackBar('사용자가 성공적으로 추가되었습니다.');
snackBar('사용자가 성공적으로 추가되었습니다.');
},
onError: (error) => {
// snackBar(error?.response?.data?.message || '사용자 추가에 실패했습니다.');
snackBar(error?.response?.data?.message || '사용자 추가에 실패했습니다.');
}
});
@@ -381,7 +382,7 @@ export const UserAddAccountPage = () => {
if (response.status) {
// 성공 시 사용자 관리 페이지로 이동
// snackBar('사용자가 성공적으로 추가되었습니다.');
snackBar('사용자가 성공적으로 추가되었습니다.');
navigate(PATHS.account.user.manage);
} else if (response.error) {
// 에러 처리
@@ -409,7 +410,7 @@ export const UserAddAccountPage = () => {
<main>
<div className="tab-content">
<div className="tab-pane sub active">
<div className="ing-list add">
<div className="ing-list pb-86">
<div className="user-add">
<div className="ua-row">
<div className="ua-label">ID <span className="red">*</span></div>
@@ -537,7 +538,7 @@ export const UserAddAccountPage = () => {
</div>
</div>
<div className="apply-row bottom-padding">
<div className="apply-row">
<button
className="btn-50 btn-blue flex-1"
type="button"

View File

@@ -12,7 +12,7 @@ import { useLocation } from 'react-router';
import { useUserMenuPermissionsSaveMutation } from '@/entities/user/api/use-user-menu-permission-save-mutation';
// import { useUserMenuPermissionsMutation } from '@/entities/user/api/use-user-menu-permission-mutation';
import { UserMenuPermissionData } from '@/entities/user/model/types';
//import { snackBar } from '@/shared/lib/toast';
import { snackBar } from '@/shared/lib/toast';
// 권한 비트 플래그 (실제 API 데이터 기준)
const PERMISSION = {
@@ -35,7 +35,7 @@ export const UserMenuAuthPage = () => {
const [isInitialLoad, setIsInitialLoad] = useState(true);
const savePermissionsMutation = useUserMenuPermissionsSaveMutation({
onSuccess: () => {
//snackBar('권한이 성공적으로 저장되었습니다.');
snackBar('권한이 성공적으로 저장되었습니다.');
navigate(PATHS.account.user.accountAuth, {
state: {
mid,
@@ -46,7 +46,7 @@ export const UserMenuAuthPage = () => {
});
},
onError: (error) => {
// snackBar(error?.response?.data?.message || '권한 저장에 실패했습니다.');
snackBar(error?.response?.data?.message || '권한 저장에 실패했습니다.');
}
});
@@ -181,7 +181,7 @@ export const UserMenuAuthPage = () => {
{ mid, namsUserMenuAccess },
{
onSuccess: () => {
alert('권한이 저장되었습니다.');
snackBar('권한이 저장되었습니다.');
// 저장 성공 후 초기값 업데이트
setInitialPermissions({...permissions});
setHasChanges(false);
@@ -199,7 +199,7 @@ export const UserMenuAuthPage = () => {
<main>
<div className="tab-content">
<div className="tab-pane pt-46 active">
<div className="ing-list sev">
<div className="ing-list pb-86">
<div className="desc service-tip"> .</div>
<div className="desc service-tip"> .</div>
@@ -281,6 +281,7 @@ export const UserMenuAuthPage = () => {
</div>
);
})}
</div>
<div className="apply-row">
<button
@@ -294,7 +295,6 @@ export const UserMenuAuthPage = () => {
</div>
</div>
</div>
</div>
</main>
</>
);

View File

@@ -1,7 +1,7 @@
import moment from 'moment';
import { PATHS } from '@/shared/constants/paths';
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { HeaderType } from '@/entities/common/model/types';
import { DefaultRequestPagination, HeaderType } from '@/entities/common/model/types';
import { IMAGE_ROOT } from '@/shared/constants/common';
import { useEffect, useState } from 'react';
import { DEFAULT_PAGE_PARAM } from '@/entities/common/model/constant';
@@ -19,21 +19,24 @@ import { AccountHolderAuthList } from '@/entities/additional-service/ui/account-
import { useExtensionAccountHolderAuthDownloadExcelMutation } from '@/entities/additional-service/api/account-holder-auth/use-extension-account-holder-auth-download-excel-mutation';
import { AccountHolderAuthFilter } from '@/entities/additional-service/ui/account-holder-auth/filter/account-holder-auth-filter';
import { useStore } from '@/shared/model/store';
import { AccountHolderAuthListItem, AuthAndTransferStatus } from '@/entities/additional-service/model/account-holder-auth/types';
import { AccountHolderAuthListItem, AuthAndTransferStatus, 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';
export const AccountHolderAuthPage = () => {
const { navigate } = useNavigate();
const userMid = useStore.getState().UserStore.mid;
const [sortType, setSortType] = useState<SortTypeKeys>(SortTypeKeys.LATEST);
const [listItems, setListItems] = useState({});
const [listItems, setListItems] = useState<Array<ExtensionAccountHolderAuthContentItem>>([]);
const [filterOn, setFilterOn] = useState<boolean>(false);
const [pageParam, setPageParam] = useState(DEFAULT_PAGE_PARAM);
const [pageParam, setPageParam] = useState<DefaultRequestPagination>(DEFAULT_PAGE_PARAM);
const [mid, setMid] = useState<string>(userMid);
const [fromDate, setFromDate] = useState(moment().format('YYYY-MM-DD'));
const [toDate, setToDate] = useState(moment().format('YYYY-MM-DD'));
const [fromDate, setFromDate] = useState(moment().format('YYYYMMDD'));
const [toDate, setToDate] = useState(moment().format('YYYYMMDD'));
const [authStatus, setAuthStatus] = useState<AuthAndTransferStatus>(AuthAndTransferStatus.ALL)
const [emailBottomSheetOn, setEmailBottomSheetOn] = useState<boolean>(false);
useSetHeaderTitle('계좌점유인증');
useSetHeaderType(HeaderType.LeftArrow);
useSetFooterMode(false);
@@ -43,12 +46,11 @@ export const AccountHolderAuthPage = () => {
const { mutateAsync: accountHolderAuthList } = useExtensionAccountHolderAuthListMutation();
const { mutateAsync: downloadExcel } = useExtensionAccountHolderAuthDownloadExcelMutation();
const callList = (option?: {
sortType?: SortTypeKeys,
val?: string
status?: AuthAndTransferStatus
}) => {
pageParam.sortType = (option?.sortType)? option.sortType: sortType;
setPageParam(pageParam);
let listParams = {
mid: mid,
fromDate: fromDate,
@@ -57,28 +59,14 @@ export const AccountHolderAuthPage = () => {
page: pageParam
};
accountHolderAuthList(listParams).then((rs) => {
setListItems(assembleData(rs.content));
});
if (listParams.page) {
listParams.page.sortType = option?.sortType || sortType;
setPageParam(listParams.page);
}
const assembleData = (content: Array<AccountHolderAuthListItem>) => {
console.log('rs.content:', content)
let data: any = {};
if (content && content.length > 0) {
for (let i = 0; i < content?.length; i++) {
let requestDate = content[i]?.requestDate?.substring(0, 8);
let groupDate = moment(requestDate).format('YYYYMMDD');
if(!!groupDate && !data.hasOwnProperty(groupDate)){
data[groupDate] = [];
}
if(!!groupDate && data.hasOwnProperty(groupDate)){
data[groupDate].push(content[i]);
}
}
}
console.log('Data : ', data);
return data;
accountHolderAuthList(listParams).then((rs) => {
setListItems(rs.content);
});
};
const onClickToDownloadExcel = () => {
@@ -100,18 +88,45 @@ export const AccountHolderAuthPage = () => {
setSortType(sort);
callList({
sortType: sort
})
});
};
const onClickToAuthStatus = (val: AuthAndTransferStatus) => {
setAuthStatus(val);
callList({ val: val });
callList({
status: val
});
};
const onClickToOpenEmailBottomSheet = () => {
setEmailBottomSheetOn(true);
};
const onSendRequest = (selectedEmail?: string) => {
if (selectedEmail) {
const params: ExtensionAccountHolderAuthDownloadExcelParams = { // 추후 수정필요
mid: mid,
//email: selectedEmail,
fromDate: fromDate,
toDate: toDate,
authStatus: authStatus
};
downloadExcel(params).then((rs: ExtensionAccountHolderAuthDownloadExcelResponse) => {
console.log('Excel Download Status:', rs.status);
});
}
setEmailBottomSheetOn(false);
};
useEffect(() => {
callList();
}, []);
}, [
mid,
fromDate,
toDate,
authStatus
]);
return (
<>
@@ -152,8 +167,8 @@ export const AccountHolderAuthPage = () => {
<div className="filter-section">
<SortTypeBox
sortType={ sortType }
onClickToSort={ onClickToSort }
sortType={sortType}
onClickToSort={onClickToSort}
></SortTypeBox>
<div className="excrow">
<div className="full-menu-keywords no-padding">
@@ -170,6 +185,7 @@ export const AccountHolderAuthPage = () => {
</div>
</div>
<AccountHolderAuthList
additionalServiceCategory={AdditionalServiceCategory.AccountHolderAuth}
listItems={listItems}
mid={mid}
></AccountHolderAuthList>
@@ -189,6 +205,14 @@ export const AccountHolderAuthPage = () => {
setAuthStatus={setAuthStatus}
>
</AccountHolderAuthFilter>
<EmailBottomSheet
bottomSheetOn={emailBottomSheetOn}
setBottomSheetOn={setEmailBottomSheetOn}
imageSave={false}
sendEmail={true}
sendRequest={onSendRequest}
/>
</>
);
};

View File

@@ -21,37 +21,16 @@ import { AccountHolderSearchList } from '@/entities/additional-service/ui/accoun
import { useStore } from '@/shared/model/store';
import { AccountHolderSearchListItem, AccountHolderSearchType } from '@/entities/additional-service/model/account-holder-search/types';
import { resultStatusBtnGroup } from '@/entities/additional-service/model/account-holder-search/constant';
import useIntersectionObserver from '@/widgets/intersection-observer';
import { EmailBottomSheet } from '@/entities/common/ui/email-bottom-sheet';
export const AccountHolderSearchPage = () => {
const { navigate } = useNavigate();
const [onActionIntersect, setOnActionIntersect] = useState<boolean>(false);
const onIntersect: IntersectionObserverCallback = (entries: Array<IntersectionObserverEntry>) => {
entries.forEach((entry: IntersectionObserverEntry) => {
if (entry.isIntersecting) {
console.log('Element is now intersecting with the root. [' + onActionIntersect + ']');
if (onActionIntersect) {
callList();
}
}
else {
console.log('Element is no longer intersecting with the root.');
}
});
};
const { setTarget } = useIntersectionObserver({
threshold: 1,
onIntersect
});
const userMid = useStore.getState().UserStore.mid;
const [sortType, setSortType] = useState<SortTypeKeys>(SortTypeKeys.LATEST);
const [listItems, setListItems] = useState<Array<AccountHolderSearchListItem>>([]);
const [pageParam, setPageParam] = useState<DefaultRequestPagination>(DEFAULT_PAGE_PARAM);
const [nextCursor, setNextCursor] = useState<string | null>(null);
const [filterOn, setFilterOn] = useState<boolean>(false);
const [mid, setMid] = useState<string>(userMid);
const [searchType, setSearchType] = useState<AccountHolderSearchType>(AccountHolderSearchType.ACCOUNT_NAME)
@@ -60,6 +39,8 @@ export const AccountHolderSearchPage = () => {
const [endDate, setEndDate] = useState(moment().format('YYYYMMDD'));
const [bank, setBank] = useState<string>('');
const [processResult, setProcessResult] = useState<ProcessResult>(ProcessResult.ALL);
const [emailBottomSheetOn, setEmailBottomSheetOn] = useState<boolean>(false);
const [email, setEmail] = useState<string>('');
useSetHeaderTitle('계좌성명조회');
useSetHeaderType(HeaderType.LeftArrow);
@@ -73,17 +54,8 @@ export const AccountHolderSearchPage = () => {
const callList = (option?: {
sortType?: SortTypeKeys,
processResult?: ProcessResult,
resetPage?: boolean
processResult?: ProcessResult
}) => {
setOnActionIntersect(false);
const currentPageParam = option?.resetPage
? { ...DEFAULT_PAGE_PARAM, sortType: option?.sortType ?? sortType }
: { ...pageParam, sortType: option?.sortType ?? sortType };
setPageParam(currentPageParam);
let listParams = {
mid: mid,
searchCl: searchType,
@@ -92,27 +64,16 @@ export const AccountHolderSearchPage = () => {
toDate: endDate,
bankCode: bank,
resultStatus: option?.processResult ?? processResult,
... {
page: currentPageParam
page: pageParam
}
if (listParams.page) {
listParams.page.sortType = option?.sortType || sortType;
setPageParam(listParams.page);
}
accountHolderSearchList(listParams).then((rs) => {
setListItems(option?.resetPage ? rs.content : [
...listItems,
...rs.content
]);
if (rs.hasNext) {
setNextCursor(rs.nextCursor);
setPageParam({
...currentPageParam,
cursor: rs.nextCursor
});
setOnActionIntersect(true)
}
else {
setNextCursor(null);
}
setListItems(rs.content);
});
}
@@ -120,6 +81,30 @@ export const AccountHolderSearchPage = () => {
setFilterOn(!filterOn);
};
const onClickToOpenEmailBottomSheet = () => {
setEmailBottomSheetOn(true);
};
const onSendRequest = (selectedEmail?: string) => {
if (selectedEmail) {
// 이메일을 설정한 후 다운로드 실행
downloadExcel({
mid: mid,
//email: selectedEmail,
searchCl: searchType,
searchValue: searchKeyword,
fromDate: startDate,
toDate: endDate,
bankCode: bank,
resultStatus: processResult
}).then((rs) => {
console.log('Excel Download Status: ' + rs.status);
});
}
setEmailBottomSheetOn(false);
};
const onClickToDownloadExcel = () => {
downloadExcel({
mid: mid,
@@ -137,22 +122,19 @@ export const AccountHolderSearchPage = () => {
const onClickToSort = (sort: SortTypeKeys) => {
setSortType(sort);
callList({
sortType: sort,
resetPage: true
sortType: sort
});
};
const onClickToTransactionStatus = (val: ProcessResult) => {
setProcessResult(val);
callList({
processResult: val,
resetPage: true
processResult: val
});
};
useEffect(() => {
// 필터 조건이 변경되면 첫 페이지부터 다시 시작
callList({ resetPage: true });
callList();
}, [
mid,
searchType,
@@ -190,11 +172,11 @@ export const AccountHolderSearchPage = () => {
</div>
<button
className="download-btn"
onClick={onClickToOpenEmailBottomSheet}
>
<img
src={IMAGE_ROOT + '/ico_download.svg'}
alt="다운로드"
onClick={() => onClickToDownloadExcel()}
/>
</button>
</div>
@@ -222,7 +204,6 @@ export const AccountHolderSearchPage = () => {
<AccountHolderSearchList
listItems={listItems}
mid={mid}
setTarget={setTarget}
></AccountHolderSearchList>
</div>
</div>
@@ -245,6 +226,14 @@ export const AccountHolderSearchPage = () => {
setBank={setBank}
setProcessResult={setProcessResult}
></AccountHolderSearchFilter>
<EmailBottomSheet
bottomSheetOn={emailBottomSheetOn}
setBottomSheetOn={setEmailBottomSheetOn}
imageSave={false}
sendEmail={true}
sendRequest={onSendRequest}
/>
</>
);
};

View File

@@ -19,7 +19,8 @@ import {
ExtensionAlimtalkDownloadExcelParams,
ExtensionAlimtalkDownloadExcelResponse,
ExtensionAlimtalkListParams,
ExtensionAlimtalkListResponse
ExtensionAlimtalkListResponse,
ServiceCode
} from '@/entities/additional-service/model/alimtalk/types';
import moment from 'moment';
import { useExtensionAlimtalkListMutation } from '@/entities/additional-service/api/alimtalk/use-extansion-alimtalk-list-mutation';
@@ -27,47 +28,29 @@ import { useExtensionAlimtalkDownloadExcelMutation } from '@/entities/additional
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 useIntersectionObserver from '@/widgets/intersection-observer';
import { snackBar } from '@/shared/lib';
import { EmailBottomSheet } from '@/entities/common/ui/email-bottom-sheet';
import { AlimtalkFilter } from '@/entities/additional-service/ui/filter/alimtalk-filter';
export const AlimtalkListPage = () => {
const { navigate } = useNavigate();
const userMid = useStore.getState().UserStore.mid;
const [onActionIntersect, setOnActionIntersect] = useState<boolean>(false);
const onIntersect: IntersectionObserverCallback = (entries: Array<IntersectionObserverEntry>) => {
entries.forEach((entry: IntersectionObserverEntry) => {
if (entry.isIntersecting) {
console.log('Element is now intersecting with the root. [' + onActionIntersect + ']');
if (onActionIntersect) {
callList();
}
}
else {
console.log('Element is no longer intersecting with the root.');
}
});
};
const { setTarget } = useIntersectionObserver({
threshold: 1,
onIntersect
});
const [sortType, setSortType] = useState<SortTypeKeys>(SortTypeKeys.LATEST);
const [listItems, setListItems] = useState<Array<AlimtalkListContent>>([]);
const [filterOn, setFilterOn] = useState<boolean>(false);
const [nextCursor, setNextCursor] = useState<string | null>(null);
const [pageParam, setPageParam] = useState<DefaultRequestPagination>(DEFAULT_PAGE_PARAM);
const [mid, setMid] = useState<string>(userMid);
const [searchCl, setSearchCl] = useState<AlimtalkSearchCl>(AlimtalkSearchCl.BUYER_NAME);
const [searchValue, setSearchValue] = useState<string>();
const [paymentMethod, setPaymentMethod] = useState<string>();
const [searchValue, setSearchValue] = useState<string>('');
const [serviceCode, setServiceCode] = useState<ServiceCode>(ServiceCode.CARD);
const [alimCl, setAlimCl] = useState<AlimtalkAlimCl>(AlimtalkAlimCl.DEPOSIT_REQUEST);
const [fromDate, setFromDate] = useState<string>(moment().format('YYYYMMDD'));
const [toDate, setToDate] = useState<string>(moment().format('YYYYMMDD'));
const [sendType, setSendType] = useState<AlimtalkSendType>(AlimtalkSendType.ALL);
const [sendCl, setSendCl] = useState<AlimTalkSendCl>(AlimTalkSendCl.ALL);
const [emailBottomSheetOn, setEmailBottomSheetOn] = useState<boolean>(false);
const { mutateAsync: extensionAlimtalkList } = useExtensionAlimtalkListMutation();
const { mutateAsync: extensionAlimtalkDownloadExcel } = useExtensionAlimtalkDownloadExcelMutation();
@@ -79,86 +62,81 @@ export const AlimtalkListPage = () => {
});
const callList = (option?: {
sortType?: SortTypeKeys,
resetPage?: boolean
sortType?: SortTypeKeys
}) => {
setOnActionIntersect(false);
const currentPageParam = option?.resetPage
? { ...DEFAULT_PAGE_PARAM, sortType: option?.sortType ?? sortType }
: { ...pageParam, sortType: option?.sortType ?? sortType };
setPageParam(currentPageParam);
let params: ExtensionAlimtalkListParams = {
mid: mid,
searchCl: searchCl,
searchValue: searchValue,
serviceCode: paymentMethod,
fromDate: fromDate,
toDate: toDate,
sendType: sendType,
sendCl: sendCl,
page: currentPageParam
};
extensionAlimtalkList(params).then((rs: ExtensionAlimtalkListResponse) => {
setListItems(option?.resetPage ? rs.content : [
...listItems,
...rs.content
]);
if (rs.hasNext) {
setNextCursor(rs.nextCursor);
setPageParam({
...currentPageParam,
cursor: rs.nextCursor
});
setOnActionIntersect(true);
}
else {
setNextCursor(null);
}
});
};
const callDownloadExcel = () => {
let params: ExtensionAlimtalkDownloadExcelParams = {
mid: mid,
searchCl: searchCl,
searchValue: searchValue,
paymentMethod: paymentMethod,
serviceCode: serviceCode,
alimCl: alimCl,
fromDate: fromDate,
toDate: toDate,
sendType: sendType,
sendCl: sendCl
sendCl: sendCl,
page: pageParam
};
if (params.page) {
params.page.sortType = option?.sortType || sortType;
setPageParam(params.page);
}
extensionAlimtalkList(params).then((rs: ExtensionAlimtalkListResponse) => {
setListItems(rs.content);
});
};
const onClickToOpenEmailBottomSheet = () => {
setEmailBottomSheetOn(true);
}
const onSendRequest = (selectedEmail?: string) => {
if (selectedEmail) {
const params: ExtensionAlimtalkDownloadExcelParams = {
mid: mid,
searchCl: searchCl,
searchValue: searchValue,
serviceCode: serviceCode,
alimCl: alimCl,
fromDate: fromDate,
toDate: toDate,
sendType: sendType,
sendCl: sendCl,
//email: selectedEmail
};
extensionAlimtalkDownloadExcel(params).then((rs: ExtensionAlimtalkDownloadExcelResponse) => {
console.log('Excel Download Status:', rs.status);
});
};
setEmailBottomSheetOn(false);
};
const onClickToNavigate = () => {
navigate(PATHS.additionalService.alimtalk.setting);
};
const onClickToDownloadExcel = () => {
callDownloadExcel();
};
const onClickToOpenFilter = () => {
setFilterOn(!filterOn);
};
const getAlimtalkList = () => {
let rs: JSX.Element[] = [];
let rs = [];
let date = '';
let list: AlimtalkListContent[] = [];
let list = [];
for (let i = 0; i < listItems.length; i++) {
let item = listItems[i];
if (!!item) {
// sendDate format: "20211018140420" (YYYYMMDDHHmmss)
let sendDate = listItems[i]?.sendDate || '';
let sendDate = item?.sendDate || '';
let itemDate = sendDate.substring(0, 8);
if (!!itemDate) {
if (i === 0) {
date = itemDate;
}
if (date !== itemDate) {
// 날짜가 바뀌면 이전 리스트를 푸시
date = itemDate;
if (list.length > 0) {
rs.push(
<ListDateGroup
@@ -170,10 +148,11 @@ export const AlimtalkListPage = () => {
></ListDateGroup>
);
}
date = itemDate;
list = [];
}
list.push(listItems[i] as any);
list.push(item);
}
}
}
if (list.length > 0) {
rs.push(
@@ -190,13 +169,13 @@ export const AlimtalkListPage = () => {
}
useEffect(() => {
// 필터 조건이 변경되면 첫 페이지부터 다시 시작
callList({ resetPage: true });
callList();
}, [
mid,
searchCl,
searchValue,
paymentMethod,
serviceCode,
alimCl,
fromDate,
toDate,
sendType,
@@ -214,16 +193,16 @@ export const AlimtalkListPage = () => {
<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>
@@ -231,10 +210,10 @@ export const AlimtalkListPage = () => {
<button
className="download-btn"
aria-label="다운로드"
onClick={ () => onClickToDownloadExcel() }
onClick={() => onClickToOpenEmailBottomSheet()}
>
<img
src={ IMAGE_ROOT + '/ico_download.svg' }
src={IMAGE_ROOT + '/ico_download.svg'}
alt="다운로드"
/>
</button>
@@ -242,8 +221,7 @@ export const AlimtalkListPage = () => {
</section>
<section className="transaction-list">
{ getAlimtalkList() }
<div ref={setTarget}></div>
{getAlimtalkList()}
</section>
</div>
</div>
@@ -251,9 +229,39 @@ export const AlimtalkListPage = () => {
<div className="apply-row">
<button
className="btn-50 btn-blue flex-1"
onClick={ () => onClickToNavigate() }
onClick={() => onClickToNavigate()}
> </button>
</div>
<AlimtalkFilter
filterOn={filterOn}
setFilterOn={setFilterOn}
mid={mid}
searchCl={searchCl}
searchValue={searchValue}
fromDate={fromDate}
toDate={toDate}
serviceCode={serviceCode}
alimCl={alimCl}
sendType={sendType}
sendCl={sendCl}
setMid={setMid}
setSearchCl={setSearchCl}
setSearchValue={setSearchValue}
setFromDate={setFromDate}
setToDate={setToDate}
setServiceCode={setServiceCode}
setAlimCl={setAlimCl}
setSendType={setSendType}
setSendCl={setSendCl}
></AlimtalkFilter>
<EmailBottomSheet
bottomSheetOn={emailBottomSheetOn}
setBottomSheetOn={setEmailBottomSheetOn}
imageSave={false}
sendEmail={true}
sendRequest={onSendRequest}
>
</EmailBottomSheet>
</>
);
};

View File

@@ -20,37 +20,15 @@ import { SortTypeBox } from '@/entities/common/ui/sort-type-box';
import { ArsPaymentStatusBtnGroup } from '@/entities/additional-service/model/ars/constant';
import { ArsFilter } from '@/entities/additional-service/ui/filter/ars-filter';
import { useStore } from '@/shared/model/store';
import useIntersectionObserver from '@/widgets/intersection-observer';
export const ArsListPage = () => {
const { navigate } = useNavigate();
const [onActionIntersect, setOnActionIntersect] = useState<boolean>(false);
const onIntersect: IntersectionObserverCallback = (entries: Array<IntersectionObserverEntry>) => {
entries.forEach((entry: IntersectionObserverEntry) => {
if (entry.isIntersecting) {
console.log('Element is now intersecting with the root. [' + onActionIntersect + ']');
if (onActionIntersect) {
callList();
}
}
else {
console.log('Element is no longer intersecting with the root.');
}
});
};
const { setTarget } = useIntersectionObserver({
threshold: 1,
onIntersect
});
const userMid = useStore.getState().UserStore.mid;
const [sortType, setSortType] = useState<SortTypeKeys>(SortTypeKeys.LATEST);
const [listItems, setListItems] = useState<Array<ArsListContent>>([]);
const [filterOn, setFilterOn] = useState<boolean>(false);
const [nextCursor, setNextCursor] = useState<string | null>(null);
const [pageParam, setPageParam] = useState<DefaultRequestPagination>(DEFAULT_PAGE_PARAM);
const [mid, setMid] = useState<string>(userMid);
const [moid, setMoid] = useState<string>('');
@@ -73,17 +51,8 @@ export const ArsListPage = () => {
const callList = (option?: {
sortType?: SortTypeKeys,
paymentStatus?: PaymentStatus,
resetPage?: boolean
paymentStatus?: PaymentStatus
}) => {
setOnActionIntersect(false);
const currentPageParam = option?.resetPage
? { ...DEFAULT_PAGE_PARAM, sortType: option?.sortType ?? sortType }
: { ...pageParam, sortType: option?.sortType ?? sortType };
setPageParam(currentPageParam);
let params: ExtensionArsListParams = {
mid: mid,
moid: moid,
@@ -93,25 +62,16 @@ export const ArsListPage = () => {
orderStatus: orderStatus,
minAmount: minAmount,
maxAmount: maxAmount,
page: currentPageParam
page: pageParam
};
if (params.page) {
params.page.sortType = option?.sortType || sortType;
setPageParam(params.page);
}
extensionArsList(params).then((rs: ExtensionArsListResponse) => {
// resetPage면 기존 리스트 무시, 아니면 추가
setListItems(option?.resetPage ? rs.content : [
...listItems,
...rs.content
]);
if (rs.hasNext) {
setNextCursor(rs.nextCursor);
setPageParam({
...currentPageParam,
cursor: rs.nextCursor
});
setOnActionIntersect(true)
}
else {
setNextCursor(null);
}
setListItems(rs.content);
});
};
@@ -146,21 +106,21 @@ export const ArsListPage = () => {
const onClickToSort = (sort: SortTypeKeys) => {
setSortType(sort);
callList({
sortType: sort,
resetPage: true
sortType: sort
});
};
const onClickToPaymentStatus = (val: PaymentStatus) => {
setPaymentStatus(val);
callList({
paymentStatus: val,
resetPage: true
paymentStatus: val
});
};
useEffect(() => {
// 필터 조건이 변경되면 첫 페이지부터 다시 시작
callList({ resetPage: true });
callList();
}, []);
useEffect(() => {
callList();
}, [
mid,
moid,
@@ -173,18 +133,20 @@ export const ArsListPage = () => {
]);
const getListDateGroup = () => {
let rs: JSX.Element[] = [];
let rs = [];
let date = '';
let list: ArsListContent[] = [];
let list = [];
for (let i = 0; i < listItems.length; i++) {
// paymentDate format: "20211018140420" (YYYYMMDDHHmmss)
let paymentDate = listItems[i]?.paymentDate || '';
let item = listItems[i];
if (!!item) {
let paymentDate = item?.paymentDate || '';
let itemDate = paymentDate.substring(0, 8);
if (!!itemDate) {
if (i === 0) {
date = itemDate;
}
if (date !== itemDate) {
// 날짜가 바뀌면 이전 리스트를 푸시 (날짜 업데이트 전에!)
date = itemDate;
if (list.length > 0) {
rs.push(
<ListDateGroup
@@ -192,14 +154,15 @@ export const ArsListPage = () => {
mid={mid}
key={date + '-' + i}
date={date}
items={list as any}
items={list}
></ListDateGroup>
);
}
date = itemDate; // 그 다음에 날짜 업데이트
list = [];
}
list.push(listItems[i] as any);
list.push(item);
}
}
}
if (list.length > 0) {
rs.push(
@@ -226,16 +189,16 @@ export const ArsListPage = () => {
<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>
@@ -243,10 +206,10 @@ export const ArsListPage = () => {
<button
className="download-btn"
aria-label="다운로드"
onClick={ () => onClickToDownloadExcel() }
onClick={() => onClickToDownloadExcel()}
>
<img
src={ IMAGE_ROOT +'/ico_download.svg' }
src={IMAGE_ROOT + '/ico_download.svg'}
alt="다운로드"
/>
</button>
@@ -255,18 +218,18 @@ export const ArsListPage = () => {
<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">
{
ArsPaymentStatusBtnGroup.map((value, index) => (
<span
key={ `key-service-code=${ index }` }
className={ `keyword-tag ${(paymentStatus === value.value)? 'active': ''}` }
onClick={ () => onClickToPaymentStatus(value.value) }
>{ value.name }</span>
key={`key-service-code=${index}`}
className={`keyword-tag ${(paymentStatus === value.value) ? 'active' : ''}`}
onClick={() => onClickToPaymentStatus(value.value)}
>{value.name}</span>
))
}
</div>
@@ -274,37 +237,36 @@ export const ArsListPage = () => {
</section>
<section className="transaction-list">
{ getListDateGroup() }
<div ref={setTarget}></div>
{getListDateGroup()}
</section>
<div className="apply-row">
<button
className="btn-50 btn-blue flex-1"
onClick={ () => onClickToNavigate() }
onClick={() => onClickToNavigate()}
> </button>
</div>
</div>
</div>
</main>
<ArsFilter
filterOn={ filterOn }
setFilterOn={ setFilterOn }
mid={ mid }
moid={ moid }
fromDate={ fromDate }
toDate={ toDate }
paymentStatus={ paymentStatus }
orderStatus={ orderStatus }
minAmount={ minAmount }
maxAmount={ maxAmount }
setMid={ setMid }
setMoid={ setMoid }
setFromDate={ setFromDate }
setToDate={ setToDate }
setPaymentStatus={ setPaymentStatus }
setOrderStatus={ setOrderStatus }
setMinAmount={ setMinAmount }
setMaxAmount={ setMaxAmount }
filterOn={filterOn}
setFilterOn={setFilterOn}
mid={mid}
moid={moid}
fromDate={fromDate}
toDate={toDate}
paymentStatus={paymentStatus}
orderStatus={orderStatus}
minAmount={minAmount}
maxAmount={maxAmount}
setMid={setMid}
setMoid={setMoid}
setFromDate={setFromDate}
setToDate={setToDate}
setPaymentStatus={setPaymentStatus}
setOrderStatus={setOrderStatus}
setMinAmount={setMinAmount}
setMaxAmount={setMaxAmount}
></ArsFilter>
</>
);

View File

@@ -11,11 +11,14 @@ import { useLocation } from 'react-router';
import { useEffect, useState } from 'react';
import { NumericFormat } from 'react-number-format';
import {
ExtensionFundAccountDownloadReceiptParams,
ExtensionFundAccountDownloadReceiptResponse,
ExtensionFundAccountResultDetailParams,
ExtensionFundAccountResultDetailResponse,
} from '@/entities/additional-service/model/fund-account/types';
import moment from 'moment';
import { useExtensionFundAccountResultDetailMutation } from '@/entities/additional-service/api/fund-account/use-extension-fund-account-result-detail-mutation';
import { useExtensionFundAccountDownloadReceiptMutation } from '@/entities/additional-service/api/fund-account/use-extension-fund-account-download-certificate-mutation';
export const FundAccountResultDetailPage = () => {
const { navigate } = useNavigate();
@@ -25,8 +28,10 @@ export const FundAccountResultDetailPage = () => {
const mid = location.state.mid;
const [detail, setDetail] = useState<ExtensionFundAccountResultDetailResponse>();
const [email, setEmail] = useState<string>('');
const { mutateAsync: extensionFundAccountResultDetail } = useExtensionFundAccountResultDetailMutation();
const { mutateAsync: extensionFundAccountDownlaodReceipt } = useExtensionFundAccountDownloadReceiptMutation();
const callDetail = () => {
let params: ExtensionFundAccountResultDetailParams = {
@@ -39,6 +44,17 @@ export const FundAccountResultDetailPage = () => {
});
};
const onClickToDownload = () => {
let params: ExtensionFundAccountDownloadReceiptParams = {
mid: mid,
tid: tid,
email: email
};
extensionFundAccountDownlaodReceipt(params).then((rs: ExtensionFundAccountDownloadReceiptResponse) => {
console.log(rs);
});
};
useSetHeaderTitle('자금이체 상세');
useSetHeaderType(HeaderType.LeftArrow);
useSetFooterMode(false);
@@ -72,7 +88,11 @@ export const FundAccountResultDetailPage = () => {
{/* ✅ resultMessage가 "정상"일 때만 표시 */}
{detail?.resultMessage === '정상' && (
<div className="receipt-row">
<button type="button" className="receipt-btn">
<button
type="button"
className="receipt-btn"
onClick={ onClickToDownload }
>
<span className="icon-24 download"></span>
<span></span>
</button>
@@ -104,7 +124,7 @@ export const FundAccountResultDetailPage = () => {
</li>
<li className="kv-row">
<span className="k"></span>
<span className="v">{detail?.bankCode}</span>
<span className="v">{detail?.bankName}</span>
</li>
<li className="kv-row">
<span className="k"></span>

View File

@@ -11,27 +11,25 @@ import { useLocation } from 'react-router';
import { useEffect, useState } from 'react';
import { NumericFormat } from 'react-number-format';
import { useExtensionFundAccountTransferDetailMutation } from '@/entities/additional-service/api/fund-account/use-extension-fund-account-transfer-detail-mutation';
import { ExtensionFundAccountTransferDetailParams, ExtensionFundAccountTransferDetailResponse, ExtensionFundAccountTransferRequestParams, ExtensionFundAccountTransferRequestResponse, FundAccountStatus } from '@/entities/additional-service/model/fund-account/types';
import { ExtensionFundAccountTransferDetailParams, ExtensionFundAccountTransferDetailResponse, ExtensionFundAccountTransferRegistParams, ExtensionFundAccountTransferRequestResponse, FundAccountStatus } from '@/entities/additional-service/model/fund-account/types';
import { getFundAccountStatusName } from '@/entities/additional-service/model/fund-account/constant';
import moment from 'moment';
import { useExtensionFundAccountTransferRequestMutation } from '@/entities/additional-service/api/fund-account/use-extension-fund-account-transfer-request-mutation';
import { useExtensionFundAccountTransferRegistMutation } from '@/entities/additional-service/api/fund-account/use-extension-fund-account-transfer-regist-mutation';
export const FundAccountTransferDetailPage = () => {
const { navigate } = useNavigate();
const location = useLocation();
const tid = location.state.tid;
const mid = location.state.mid;
const seq = location.state.seq;
const [detail, setDetail] = useState<ExtensionFundAccountTransferDetailResponse>();
const { mutateAsync: extensionFundAccountTransferDetail } = useExtensionFundAccountTransferDetailMutation();
const { mutateAsync: extensionFundAccountTransferRequest } = useExtensionFundAccountTransferRequestMutation();
const { mutateAsync: extensionFundAccountTransferRequest } = useExtensionFundAccountTransferRegistMutation();
const callDetail = () => {
let params: ExtensionFundAccountTransferDetailParams = {
tid: tid,
mid: mid,
seq: seq
};
extensionFundAccountTransferDetail(params).then((rs: ExtensionFundAccountTransferDetailResponse) => {
@@ -50,26 +48,26 @@ export const FundAccountTransferDetailPage = () => {
callDetail();
}, []);
const onClickToRequest = () => {
if (!detail) {
alert('상세 정보를 불러오는 중입니다.');
return;
}
// const onClickToRequest = () => {
// if (!detail) {
// alert('상세 정보를 불러오는 중입니다.');
// return;
// }
let params: ExtensionFundAccountTransferRequestParams = {
mid: mid,
bankCode: detail.bankCode || '',
accountNo: detail.accountNo || '',
accountName: detail.accountName || '',
amount: detail.amount || 0,
moid: detail.moid || ''
};
extensionFundAccountTransferRequest(params).then((rs: ExtensionFundAccountTransferRequestResponse) => {
console.log(rs)
alert(rs.status ? '이체 요청이 완료되었습니다.' : '이체 요청에 실패했습니다.');
navigate(PATHS.additionalService.fundAccount.transferList);
});
};
// let params: ExtensionFundAccountTransferRegistParams = {
// mid: mid,
// bankCode: detail.bankCode || '',
// accountNo: detail.accountNo || '',
// accountName: detail.accountName || '',
// amount: detail.amount || 0,
// moid: detail.moid || ''
// };
// extensionFundAccountTransferRequest(params).then((rs: ExtensionFundAccountTransferRequestResponse) => {
// console.log(rs)
// alert(rs.status ? '이체 요청이 완료되었습니다.' : '이체 요청에 실패했습니다.');
// navigate(PATHS.additionalService.fundAccount.transferList);
// });
// };
return (
<>
@@ -138,7 +136,7 @@ export const FundAccountTransferDetailPage = () => {
<div className="apply-row">
<button
className="btn-50 btn-blue flex-1"
onClick={() => onClickToRequest()}
//onClick={() => onClickToRequest()}
disabled={detail?.resultStatus !== FundAccountStatus.REGIST_COMPLETE}
> </button>
</div>

View File

@@ -7,15 +7,15 @@ import {
useSetFooterMode,
useSetOnBack
} from '@/widgets/sub-layout/use-sub-layout';
import { ChangeEvent, useEffect, useState } from 'react';
import { useExtensionFundAccountTransferRequestMutation } from '@/entities/additional-service/api/fund-account/use-extension-fund-account-transfer-request-mutation';
import { ExtensionFundAccountTransferRequestParams, ExtensionFundAccountTransferRequestResponse } from '@/entities/additional-service/model/fund-account/types';
import { ChangeEvent, useState } from 'react';
import { ExtensionFundAccountTransferRegistParams, ExtensionFundAccountTransferRegistResponse } from '@/entities/additional-service/model/fund-account/types';
import { useStore } from '@/shared/model/store';
import { snackBar } from '@/shared/lib';
import { useExtensionFundAccountTransferRegistMutation } from '@/entities/additional-service/api/fund-account/use-extension-fund-account-transfer-regist-mutation';
export const FundAccountTransferRequestPage = () => {
const { navigate } = useNavigate();
const midOptions = useStore.getState().UserStore.selectOptionsMids;
const userMid = useStore.getState().UserStore.mid;
@@ -27,7 +27,7 @@ export const FundAccountTransferRequestPage = () => {
const [moid, setMoid] = useState<string>('');
const [depositParameter, setDepositParameter] = useState<string>('');
const { mutateAsync: extensionFundAccountRequest } = useExtensionFundAccountTransferRequestMutation();
const { mutateAsync: extensionFundAccountRegist } = useExtensionFundAccountTransferRegistMutation();
useSetHeaderTitle('자금이체 이체등록');
useSetHeaderType(HeaderType.RightClose);
@@ -36,8 +36,17 @@ export const FundAccountTransferRequestPage = () => {
navigate(PATHS.additionalService.fundAccount.transferList);
});
const callExtensionFundAccountTransferRequest = () => {
let params: ExtensionFundAccountTransferRequestParams = {
const resetForm = () => {
setBankCode('');
setAccountNo('');
setAccountName('');
setAmount(0);
setMoid('');
setDepositParameter('');
};
const callExtensionFundAccountTransferRegist = () => {
let params: ExtensionFundAccountTransferRegistParams = {
mid: mid,
bankCode: bankCode,
accountNo: accountNo,
@@ -46,8 +55,13 @@ export const FundAccountTransferRequestPage = () => {
moid: moid,
depositParameter: depositParameter
};
extensionFundAccountRequest(params).then((rs: ExtensionFundAccountTransferRequestResponse) => {
navigate(PATHS.additionalService.payout.list);
extensionFundAccountRegist(params).then((rs: ExtensionFundAccountTransferRegistResponse) => {
if (rs.status) {
snackBar("이체등록을 성공하였습니다.")
resetForm();
} else {
snackBar("이체등록이 실패하였습니다.")
}
});
};
@@ -72,10 +86,7 @@ export const FundAccountTransferRequestPage = () => {
<div className="billing-row">
<div className="billing-label"><span>*</span></div>
<div className="billing-field">
<select
value={ mid }
onChange={ (e: ChangeEvent<HTMLSelectElement>) => setMid(e.target.value) }
>
<select value={mid} onChange={(e) => setMid(e.target.value)}>
{
midOptions.map((value, index) => (
<option
@@ -154,7 +165,7 @@ export const FundAccountTransferRequestPage = () => {
<div className="apply-row">
<button
className="btn-50 btn-blue flex-1"
onClick={callExtensionFundAccountTransferRequest}
onClick={callExtensionFundAccountTransferRegist}
disabled={!isFormValid()}
></button>
</div>

View File

@@ -21,7 +21,6 @@ import { KeyInPaymentList } from '@/entities/additional-service/ui/key-in-paymen
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 useIntersectionObserver from '@/widgets/intersection-observer';
export const KeyInPaymentPage = () => {
const { navigate } = useNavigate();
@@ -31,32 +30,12 @@ export const KeyInPaymentPage = () => {
const [listItems, setListItems] = useState<Array<KeyInPaymentListItem>>([]);
const [filterOn, setFilterOn] = useState<boolean>(false);
const [pageParam, setPageParam] = useState<DefaultRequestPagination>(DEFAULT_PAGE_PARAM);
const [nextCursor, setNextCursor] = useState<string | null>(null);
const [mid, setMid] = useState<string>(userMid);
const [startDate, setStartDate] = useState(moment().format('YYYY-MM-DD'));
const [endDate, setEndDate] = useState(moment().format('YYYY-MM-DD'));
const [paymentStatus, setPaymentStatus] = useState<KeyInPaymentPaymentStatus>(KeyInPaymentPaymentStatus.ALL)
const [minAmount, setMinAmount] = useState<number>();
const [maxAmount, setMaxAmount] = useState<number>();
const [onActionIntersect, setOnActionIntersect] = useState<boolean>(false);
const onIntersect: IntersectionObserverCallback = (entries: Array<IntersectionObserverEntry>) => {
entries.forEach((entry: IntersectionObserverEntry) => {
if (entry.isIntersecting) {
console.log('Element is now intersecting with the root. [' + onActionIntersect + ']');
if (onActionIntersect) {
callList();
}
}
else {
console.log('Element is no longer intersecting with the root.');
}
});
};
const { setTarget } = useIntersectionObserver({
threshold: 1,
onIntersect
});
useSetHeaderTitle('KEY-IN 결제');
useSetHeaderType(HeaderType.LeftArrow);
@@ -70,17 +49,8 @@ export const KeyInPaymentPage = () => {
const callList = (option?: {
sortType?: SortTypeKeys,
status?: KeyInPaymentPaymentStatus,
resetPage?: boolean
status?: KeyInPaymentPaymentStatus
}) => {
setOnActionIntersect(false);
const currentPageParam = option?.resetPage
? { ...DEFAULT_PAGE_PARAM, sortType: option?.sortType ?? sortType }
: { ...pageParam, sortType: option?.sortType ?? sortType };
setPageParam(currentPageParam);
let newMinAmount = minAmount;
if (!!minAmount && typeof (minAmount) === 'string') {
newMinAmount = parseInt(minAmount);
@@ -96,28 +66,16 @@ export const KeyInPaymentPage = () => {
paymentStatus: paymentStatus,
minAmount: newMinAmount,
maxAmount: newMaxAmount,
... {
page: currentPageParam
}
page: pageParam
};
if (listParams.page) {
listParams.page.sortType = option?.sortType || sortType;
setPageParam(listParams.page);
}
keyinList(listParams).then((rs) => {
// resetPage면 기존 리스트 무시, 아니면 추가
setListItems(option?.resetPage ? rs.content : [
...listItems,
...rs.content
]);
if (rs.hasNext) {
setNextCursor(rs.nextCursor);
setPageParam({
...currentPageParam, // pageParam이 아니라 currentPageParam 사용
cursor: rs.nextCursor
});
setOnActionIntersect(true)
}
else {
setNextCursor(null);
}
setListItems(rs.content);
});
}
@@ -149,21 +107,19 @@ export const KeyInPaymentPage = () => {
const onClickToSort = (sort: SortTypeKeys) => {
setSortType(sort);
callList({
sortType: sort,
resetPage: true
sortType: sort
});
};
const onClickToPaymentStatus = (val: KeyInPaymentPaymentStatus) => {
setPaymentStatus(val);
callList({
status: val,
resetPage: true
status: val
});
};
useEffect(() => {
callList({resetPage: true});
callList();
}, [
mid,
startDate,
@@ -234,7 +190,6 @@ export const KeyInPaymentPage = () => {
listItems={listItems}
additionalServiceCategory={AdditionalServiceCategory.KeyInPayment}
mid={mid}
setTarget={setTarget}
></KeyInPaymentList>
</div>
</div>

View File

@@ -256,7 +256,12 @@ export const LinkPaymentSeparateApprovalPage = () => {
</li>
<li>
<span className="label"> :</span>
<span className="value">{item.paymentLimitDate}</span>
<span className="value">
{item.paymentLimitDate
? moment(item.paymentLimitDate, 'YYYYMMDD').format('YYYY/MM/DD')
: '-'
}
</span>
</li>
<li>
<span className="label"> :</span>
@@ -272,13 +277,11 @@ export const LinkPaymentSeparateApprovalPage = () => {
onChange={(e) => handleExtendPeriodChange(itemId, e.target.value)}
>
<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>
{[1, 2, 3, 4, 5, 6, 7].map(days => {
const baseDate = moment(item.paymentLimitDate, 'YYYYMMDD');
const targetDate = baseDate.clone().add(days, 'days').format('YYYY/MM/DD');
return <option key={days} value={days.toString()}>{targetDate}</option>;
})}
</select>
</div>
</div>

View File

@@ -28,36 +28,14 @@ import { PayoutDisbursementStatusBtnGroup } from '@/entities/additional-service/
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 useIntersectionObserver from '@/widgets/intersection-observer';
export const PayoutListPage = () => {
const { navigate } = useNavigate();
const userMid = useStore.getState().UserStore.mid;
const [onActionIntersect, setOnActionIntersect] = useState<boolean>(false);
const onIntersect: IntersectionObserverCallback = (entries: Array<IntersectionObserverEntry>) => {
entries.forEach((entry: IntersectionObserverEntry) => {
if (entry.isIntersecting) {
console.log('Element is now intersecting with the root. [' + onActionIntersect + ']');
if (onActionIntersect) {
callExtensionPayoutList();
}
}
else {
console.log('Element is no longer intersecting with the root.');
}
});
};
const { setTarget } = useIntersectionObserver({
threshold: 1,
onIntersect
});
const [sortType, setSortType] = useState<SortTypeKeys>(SortTypeKeys.LATEST);
const [listItems, setListItems] = useState<Array<PayoutContent>>([]);
const [filterOn, setFilterOn] = useState<boolean>(false);
const [nextCursor, setNextCursor] = useState<string | null>(null);
const [pageParam, setPageParam] = useState<DefaultRequestPagination>(DEFAULT_PAGE_PARAM);
const [mid, setMid] = useState<string>(userMid);
const [searchDateType, setSearchDateType] = useState<PayoutSearchDateType>(PayoutSearchDateType.REQUEST_DATE);
@@ -83,17 +61,8 @@ export const PayoutListPage = () => {
const callExtensionPayoutList = (option?: {
sortType?: SortTypeKeys,
status?: PayoutDisbursementStatus,
resetPage?: boolean
status?: PayoutDisbursementStatus
}) => {
setOnActionIntersect(false);
const currentPageParam = option?.resetPage
? { ...DEFAULT_PAGE_PARAM, sortType: option?.sortType ?? sortType }
: { ...pageParam, sortType: option?.sortType ?? sortType };
setPageParam(currentPageParam);
let newMinAmount = minAmount;
if(!!minAmount && typeof(minAmount) === 'string'){
newMinAmount = parseInt(minAmount);
@@ -110,25 +79,16 @@ export const PayoutListPage = () => {
status: option?.status ?? status,
minAmount: newMinAmount,
maxAmount: newMaxAmount,
page: currentPageParam
page: pageParam
};
if(params.page){
params.page.sortType = option?.sortType || sortType;
setPageParam(params.page);
}
extensionPayoutList(params).then((rs: ExtensionPayoutListResponse) => {
// resetPage면 기존 리스트 무시, 아니면 추가
setListItems(option?.resetPage ? rs.content : [
...listItems,
...rs.content
]);
if (rs.hasNext) {
setNextCursor(rs.nextCursor);
setPageParam({
...currentPageParam,
cursor: rs.nextCursor
});
setOnActionIntersect(true)
}
else {
setNextCursor(null);
}
setListItems(rs.content);
});
};
@@ -156,21 +116,18 @@ export const PayoutListPage = () => {
const onClickToSort = (sort: SortTypeKeys) => {
setSortType(sort);
callExtensionPayoutList({
sortType: sort,
resetPage: true
sortType: sort
});
};
const onClickToDisbursementStatus = (val: PayoutDisbursementStatus) => {
setStatus(val);
callExtensionPayoutList({
status: val,
resetPage: true
status: val
});
};
useEffect(() => {
// 필터 조건이 변경되면 첫 페이지부터 다시 시작
callExtensionPayoutList({ resetPage: true });
callExtensionPayoutList();
}, [
mid,
searchDateType,
@@ -298,7 +255,6 @@ export const PayoutListPage = () => {
</section>
<section className="transaction-list">
{ getListDateGroup() }
<div ref={setTarget}></div>
</section>
<div className="apply-row">
<button

View File

@@ -18,7 +18,6 @@ import { SmsPaymentList } from '@/entities/additional-service/ui/sms-payment/sms
import { SmsPaymentFilter } from '@/entities/additional-service/ui/sms-payment/sms-payment-filter';
import { useExtensionSmsDetailMutation } from '@/entities/additional-service/api/sms-payment/use-extension-sms-detail-mutation';
import { useStore } from '@/shared/model/store';
import useIntersectionObserver from '@/widgets/intersection-observer';
import { AdditionalServiceCategory } from '@/entities/additional-service/model/types';
import { PATHS } from '@/shared/constants/paths';
@@ -27,31 +26,10 @@ export const SmsPaymentPage = () => {
const { navigate } = useNavigate();
const userMid = useStore.getState().UserStore.mid;
const [onActionIntersect, setOnActionIntersect] = useState<boolean>(false);
const onIntersect: IntersectionObserverCallback = (entries: Array<IntersectionObserverEntry>) => {
entries.forEach((entry: IntersectionObserverEntry) => {
if (entry.isIntersecting) {
console.log('Element is now intersecting with the root. [' + onActionIntersect + ']');
if (onActionIntersect) {
callList();
}
}
else {
console.log('Element is no longer intersecting with the root.');
}
});
};
const { setTarget } = useIntersectionObserver({
threshold: 1,
onIntersect
});
const [bottomSmsPaymentDetailResendOn, setBottomSmsPaymentDetailResendOn] = useState<boolean>(false)
const [sortType, setSortType] = useState<SortTypeKeys>(SortTypeKeys.LATEST);
const [listItems, setListItems] = useState<Array<SmsPaymentListItem>>([]);
const [nextCursor, setNextCursor] = useState<string | null>(null);
const [pageParam, setPageParam] = useState<DefaultRequestPagination>(DEFAULT_PAGE_PARAM);
const [filterOn, setFilterOn] = useState<boolean>(false);
const [mid, setMid] = useState<string>(userMid);
@@ -75,15 +53,8 @@ export const SmsPaymentPage = () => {
navigate(PATHS.home);
});
const callList = (option?: {
sortType?: SortTypeKeys,
resetPage?: boolean
sortType?: SortTypeKeys
}) => {
const currentPageParam = option?.resetPage
? { ...DEFAULT_PAGE_PARAM, sortType: option?.sortType ?? sortType }
: { ...pageParam, sortType: option?.sortType ?? sortType };
setPageParam(currentPageParam);
let listParams: ExtensionSmsPaymentListParams = {
mid: mid,
searchCl: searchCl,
@@ -91,26 +62,16 @@ export const SmsPaymentPage = () => {
fromDate: fromDate,
toDate: toDate,
smsCl: smsCl,
... {
page: currentPageParam
page: pageParam
}
if (listParams.page) {
listParams.page.sortType = option?.sortType || sortType;
setPageParam(listParams.page);
}
smsPaymentList(listParams).then((rs) => {
setListItems(option?.resetPage ? rs.content : [
...listItems,
...rs.content
]);
if (rs.hasNext) {
setNextCursor(rs.nextCursor);
setPageParam({
...currentPageParam,
cursor: rs.nextCursor
});
setOnActionIntersect(true)
} else {
setNextCursor(null);
}
setListItems(rs.content);
});
}
@@ -150,7 +111,7 @@ export const SmsPaymentPage = () => {
};
useEffect(() => {
callList({resetPage: true});
callList();
}, [
mid,
searchCl,
@@ -203,7 +164,6 @@ export const SmsPaymentPage = () => {
additionalServiceCategory={AdditionalServiceCategory.SMSPayment}
mid={mid}
onResendClick={onClickToShowDetail}
setTarget={setTarget}
></SmsPaymentList>
</div>
</div>

View File

@@ -173,6 +173,10 @@ export const API_URL_ADDITIONAL_SERVICE = {
},
// Fund Account Management 부가서비스 > 자금이체 API
extensionFundAccountTransferRegist: () => {
// POST: 자금이체 > 이체등록
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/extension/fund-account/transfer/regist`
},
extensionFundAccountTransferRequest: () => {
// POST: 자금이체 > 이체신청
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/extension/fund-account/transfer/request`;

View File

@@ -176,16 +176,22 @@ main.home-main{
}
.approval-cards-wrapper {
display: flex;
flex-direction: column;
gap: 16px;
padding: 16px;
padding-bottom: 2px;
}
.separate-approval-main .apply-row.two-button {
display: flex;
gap: 8px;
flex-shrink: 0;
position: sticky;
bottom: 0;
background: white;
z-index: 10;
padding: 16px;
}
/* 분할승인 안내 박스 */
@@ -215,13 +221,15 @@ main.home-main{
border: 2px solid var(--color-d6d6d6);
border-radius: 16px;
padding: 16px;
margin-bottom: 16px;
transition: all 0.4s ease;
margin-bottom: 0;
transition: all 0.3s ease;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.approval-card.selected {
border-color: var(--color-3E6AFC);
background: var(--color-F4F8FF);
box-shadow: 0 4px 12px rgba(62, 106, 252, 0.2);
}
.approval-card .card-checkbox {
@@ -270,6 +278,8 @@ main.home-main{
/* 분할승인 카드 헤더 */
.approval-card .card-header {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 16px;
padding-bottom: 12px;
@@ -309,6 +319,8 @@ main.home-main{
}
.approval-card .info-list {
display: flex;
flex-direction: column;
list-style: none;
padding: 0;
margin: 0;
@@ -316,6 +328,7 @@ main.home-main{
}
.approval-card .info-list li {
display: flex;
align-items: center;
font-size: var(--fs-14);
color: var(--color-2D3436);
@@ -351,6 +364,7 @@ main.home-main{
}
.approval-card .period-selector select {
flex: 1;
height: 36px;
font-size: var(--fs-14);
padding: 6px 30px 6px 12px;
@@ -358,6 +372,7 @@ main.home-main{
border-radius: 4px;
background-color: var(--color-white);
transition: all 0.2s ease;
cursor: pointer;
}
/* Scrollbar hide utility class */

View File

@@ -166,6 +166,12 @@ export const SubLayout = () => {
id: 'nictest00',
password: 'nictest00'
};
// userParmas = {
// id: 'medi9332',
// password: 'medi9332'
// };
}
callLogin(userParmas).then(() => {
callHomeGroups();