통합 거래내역 필터

This commit is contained in:
focp212@naver.com
2025-09-16 10:46:04 +09:00
parent 756a3ef541
commit bfb492f887
10 changed files with 454 additions and 222 deletions

View File

@@ -1,4 +1,8 @@
import {
AllTransactionMoidTid,
AllTransactionSearchCl,
AllTransactionServiceCode,
AllTransactionStateCode,
BillingPaymentMethod,
BillingProcessResult,
BillingRequestStatus,
@@ -11,6 +15,46 @@ import {
EscrowSettlementStatus
} from '@/entities/transaction/model/types';
export const FilterMotionVariants = {
hidden: {x: '100%' },
visible: { x: '0%' },
};
export const FilterMotionDuration = {
duration: 0.3
};
export const FilterMotionStyle = {
width: '100%',
height: '100%'
};
export const AllTransactionMoidTidOptionsGroup = [
{name: '주문번호', value: AllTransactionMoidTid.MOID},
{name: 'TID', value: AllTransactionMoidTid.TID},
];
export const AllTransactionStateCodeBtnGroup = [
{name: '전체', value: AllTransactionStateCode.ALL},
{name: '승인/입금완료', value: AllTransactionStateCode.APPROVAL},
{name: '전취소/취소', value: AllTransactionStateCode.CANCEL},
{name: '후취소/환불', value: AllTransactionStateCode.REFUND}
];
export const AllTransactionServiceCodeOptionsGroup = [
{name: '전체', value: AllTransactionServiceCode.ALL},
{name: '신용카드', value: AllTransactionServiceCode.CREDIT_CARD},
{name: '가상계좌', value: AllTransactionServiceCode.VIRTUAL_ACCOUNT},
{name: '계좌이체', value: AllTransactionServiceCode.ACCOUNT_TRANSFER},
{name: '계좌간편결제', value: AllTransactionServiceCode.ACCOUNT_SIMPLE_TRANSFER},
{name: '휴대폰', value: AllTransactionServiceCode.MOBILE_PAYMENT},
{name: 'SSG 머니', value: AllTransactionServiceCode.SSGMONEY},
{name: 'SSG 은행계좌', value: AllTransactionServiceCode.SSGBANK},
{name: '문화상품권', value: AllTransactionServiceCode.CULT},
{name: '티머니페이', value: AllTransactionServiceCode.TMONEY},
];
export const AllTransactionCardBankCodeOptionsGroup = {
};
export const CashReceiptPurposeTypeBtnGroup = [
{name: '전체', value: CashReceiptPurposeType.ALL},
{name: '소득공제', value: CashReceiptPurposeType.INCOME_DEDUCTION},
@@ -44,7 +88,7 @@ export const EscrowDeliveryStatusBtnGroup = [
{name: '환불처리', value: EscrowDeliveryStatus.RETURN_PROCESSING},
{name: '지급완료', value: EscrowDeliveryStatus.DEPOSIT_COMPLETE},
];
export let EscrowSettlementStatusBtnGroup = [
export const EscrowSettlementStatusBtnGroup = [
{name: '전체', value: EscrowSettlementStatus.ALL},
{name: '신용카드', value: EscrowSettlementStatus.CREDIT_CARD},
{name: '가상계좌', value: EscrowSettlementStatus.REAL_ACCOUNT},

View File

@@ -33,6 +33,44 @@ export enum ProcessStep {
One = 'One',
Two = 'Two',
};
export enum AllTransactionMoidTid {
MOID = 'MOID',
TID = 'TID'
};
export enum AllTransactionStateCode {
ALL = '0',
APPROVAL = '1',
CANCEL = '2',
REFUND = '3'
};
export enum AllTransactionServiceCode {
ALL = 'ALL',
CREDIT_CARD = 'CREDIT_CARD',
VIRTUAL_ACCOUNT = 'VIRTUAL_ACCOUNT',
ACCOUNT_TRANSFER = 'ACCOUNT_TRANSFER',
ACCOUNT_SIMPLE_TRANSFER = 'ACCOUNT_SIMPLE_TRANSFER',
MOBILE_PAYMENT = 'MOBILE_PAYMENT',
SSGMONEY = 'SSGMONEY',
SSGBANK = 'SSGBANK',
CULT = 'CULT',
TMONEY = 'TMONEY '
};
export enum AllTransactionSearchCl {
ALL = 'ALL',
CARD_NO = 'CARD_NO',
CARD_APPROVAL_NO = 'CARD_APPROVAL_NO',
BANK_BUYER_NM = 'BANK_BUYER_NM',
VACCT_NO = 'VACCT_NO',
VACCT_DEPOSIT_NM = 'VACCT_DEPOSIT_NM',
TEL_NO = 'TEL_NO',
SSGMONEY_GIFT_NO = 'SSGMONEY_GIFT_NO',
SSGBANK_APPROVAL_NO = 'SSGBANK_APPROVAL_NO',
CMSBANK_USER_ID = 'CMSBANK_USER_ID',
CULT_USER_ID = 'CULT_USER_ID',
TMONEY_CARD_NO = 'TMONEY_CARD_NO',
};
export enum CashReceiptPurposeType {
ALL = 'ALL',
INCOME_DEDUCTION = 'INCOME_DEDUCTION',
@@ -205,14 +243,14 @@ export interface AllTransactionListParams {
toDate: string;
stateCode: string;
serviceCode: string;
minAmount: number;
maxAmount: number;
minAmount?: number | string;
maxAmount?: number | string;
dateCl: string;
goodsName: string;
cardCode: string;
bankCode: string;
searchCl: string;
searchValue: string;
cardCode?: string;
bankCode?: string;
searchCl?: AllTransactionSearchCl;
searchValue?: string;
page?: DefaultRequestPagination;
};
@@ -482,6 +520,30 @@ export interface FilterProps {
setFilterOn: (filterOn: boolean) => void;
};
export interface AllTransactionFilterProps extends FilterProps {
mid: string;
fromDate: string;
toDate: string;
stateCode: AllTransactionStateCode;
serviceCode: AllTransactionServiceCode;
minAmount?: number | string;
maxAmount?: number | string;
cardCode?: string;
bankCode?: string;
searchCl?: AllTransactionSearchCl;
searchValue?: string;
setMid: (mid: string) => void;
setMoid: (moid: string) => void;
setTid: (tid: string) => void;
setFromDate: (fromDate: string) => void;
setToDate: (endDate: string) => void;
setStateCode: (stateCode: AllTransactionStateCode) => void;
setServiceCode: (serviceCode: AllTransactionServiceCode) => void;
setMinAmount: (minAmount: string | number) => void;
setMaxAmount: (maxAmount: string | number) => void;
setCardCode: (cardCode: string | undefined) => void;
setBankCode: (bankCode: string | undefined) => void;
setSearchCl: (searchCl: AllTransactionSearchCl | undefined) => void;
setSearchValue: (searchValue: string | undefined) => void;
};
export interface CashReceiptFilterProps extends FilterProps {

View File

@@ -1,20 +1,157 @@
import { useEffect } from 'react';
import { useState } from 'react';
import { motion } from 'framer-motion';
import { IMAGE_ROOT } from '@/shared/constants/common';
import { FilterProps } from '../../model/types';
import { FilterSelect } from '@/shared/ui/filter/select';
import { FilterSelectInput } from '@/shared/ui/filter/select-input';
import { FilterCalendar } from '@/shared/ui/filter/calendar';
import { FilterButtonGroups } from '@/shared/ui/filter/button-groups';
import { FilterRangeAmount } from '@/shared/ui/filter/range-amount';
import {
FilterMotionVariants,
FilterMotionDuration,
FilterMotionStyle,
AllTransactionMoidTidOptionsGroup,
AllTransactionStateCodeBtnGroup,
AllTransactionServiceCodeOptionsGroup,
AllTransactionCardBankCodeOptionsGroup,
} from '@/entities/transaction/model/contant';
import {
AllTransactionFilterProps,
AllTransactionSearchCl,
AllTransactionStateCode,
AllTransactionServiceCode,
AllTransactionMoidTid
} from '../../model/types';
export const AllTransactionFilter = ({
filterOn,
setFilterOn
}: FilterProps) => {
setFilterOn,
mid,
fromDate,
toDate,
stateCode,
serviceCode,
minAmount,
maxAmount,
cardCode,
bankCode,
searchCl,
searchValue,
setMid,
setMoid,
setTid,
setFromDate,
setToDate,
setStateCode,
setServiceCode,
setMinAmount,
setMaxAmount,
setCardCode,
setBankCode,
setSearchCl,
setSearchValue,
}: AllTransactionFilterProps) => {
const variants = {
hidden: { x: '100%' },
visible: { x: '0%' },
};
const [filterMid, setFilterMid] = useState<string>(mid);
const [filterMoidTidType, setFilterMoidTidType] = useState<AllTransactionMoidTid>(AllTransactionMoidTid.MOID);
const [filterMoidTidValue, setFilterMoidTidValue] = useState<string>('');
const [filterFromDate, setFilterFromDate] = useState<string>(fromDate);
const [filterToDate, setFilterToDate] = useState<string>(toDate);
const [filterStateCode, setFilterStateCode] = useState<AllTransactionStateCode>(stateCode);
const [filterServiceCode, setFilterServiceCode] = useState<AllTransactionServiceCode>(serviceCode);
const [filterMinAmount, setFilterMinAmount] = useState<number | string>(minAmount || '');
const [filterMaxAmount, setFilterMaxAmount] = useState<number | string>(maxAmount || '');
const [filterCardCode, setFilterCardCode] = useState<string | undefined>(cardCode);
const [filterBankCode, setFilterBankCode] = useState<string | undefined>(bankCode);
const [filterCardBankCode, setFilterCardBankCode] = useState<string>('');
const [filterSearchCl, setFilterSearchCl] = useState<AllTransactionSearchCl | undefined>(searchCl);
const [filterSearchValue, setFilterSearchValue] = useState<string | undefined>(searchValue);
const [searchClOptionsGroup, setSearchClOptionsGroup] = useState<Array<Record<string, string>>>([]);
const onClickToClose = () => {
setFilterOn(false);
};
const setNewDate = (newDate: any) => {
console.log(newDate)
};
const onClickToSetFilter = () => {
setMid(filterMid);
if(filterMoidTidType === AllTransactionMoidTid.MOID){
setMoid(filterMoidTidValue);
setTid('');
}
else if(filterMoidTidType === AllTransactionMoidTid.TID){
setMoid('');
setTid(filterMoidTidValue);
}
setFromDate(filterFromDate);
setToDate(filterToDate);
setStateCode(filterStateCode);
setServiceCode(filterServiceCode);
setMinAmount(filterMinAmount);
setMaxAmount(filterMaxAmount);
setBankCode(filterBankCode);
setCardCode(filterCardCode);
setSearchCl(filterSearchCl);
setSearchValue(filterSearchValue);
onClickToClose();
};
let MidOptions = [
{name: 'nictest001m', value: 'nictest001m'}
];
let setSearchClOptions = (value: AllTransactionServiceCode) => {
let options = [];
setFilterServiceCode(value);
if(value === AllTransactionServiceCode.ALL){
}
else if(value === AllTransactionServiceCode.CREDIT_CARD){
options.push({name: '카드번호', value: AllTransactionSearchCl.CARD_NO});
options.push({name: '승인번호', value: AllTransactionSearchCl.CARD_APPROVAL_NO});
}
else if(value === AllTransactionServiceCode.VIRTUAL_ACCOUNT){
options.push({name: '가상계좌번호', value: AllTransactionSearchCl.VACCT_NO});
options.push({name: '입금자명', value: AllTransactionSearchCl.VACCT_DEPOSIT_NM});
}
else if(value === AllTransactionServiceCode.ACCOUNT_TRANSFER){
options.push({name: '구매자명', value: AllTransactionSearchCl.BANK_BUYER_NM});
}
else if(value === AllTransactionServiceCode.ACCOUNT_SIMPLE_TRANSFER){
}
else if(value === AllTransactionServiceCode.MOBILE_PAYMENT){
options.push({name: '휴대폰번호', value: AllTransactionSearchCl.TEL_NO});
}
else if(value === AllTransactionServiceCode.SSGMONEY){
options.push({name: '상품권번호', value: AllTransactionSearchCl.SSGMONEY_GIFT_NO});
}
else if(value === AllTransactionServiceCode.SSGBANK){
options.push({name: '승인번호', value: AllTransactionSearchCl.SSGBANK_APPROVAL_NO});
}
else if(value === AllTransactionServiceCode.CULT){
options.push({name: '컬처랜드ID', value: AllTransactionSearchCl.SSGBANK_APPROVAL_NO});
}
else if(value === AllTransactionServiceCode.TMONEY){
options.push({name: '티머니번호', value: AllTransactionSearchCl.TMONEY_CARD_NO});
}
setSearchClOptionsGroup(options);
};
/*
useEffect(() => {
setFilterDeliveryStatus(deliveryStatus);
}, [deliveryStatus]);
*/
return (
<>
<motion.div
@@ -22,12 +159,9 @@ export const AllTransactionFilter = ({
className="full-menu-modal"
initial="hidden"
animate={ (filterOn)? 'visible': 'hidden' }
variants={ variants }
transition={{ duration: 0.3 }}
style={{
width: '100%',
height: '100%',
}}
variants={ FilterMotionVariants }
transition={ FilterMotionDuration }
style={ FilterMotionStyle }
>
<div className="full-menu-container">
<div className="full-menu-header">
@@ -46,139 +180,72 @@ export const AllTransactionFilter = ({
</div>
</div>
<div className="option-list pb-120">
<div className="opt-field">
<div className="opt-label"></div>
<div className="opt-controls">
<select className="flex-1">
<option>nictest001m</option>
</select>
</div>
</div>
<div className="opt-field">
<div className="opt-label">/ID</div>
<div className="opt-controls">
<select className="w-110">
<option></option>
<option>ID</option>
</select>
<input
className="flex-1"
type="text"
placeholder=""
/>
</div>
</div>
<div className="opt-field">
<div className="opt-label"></div>
<div className="opt-controls col below h36">
<div className="chip-row">
<span className="keyword-tag active"></span>
<span className="keyword-tag"></span>
<span className="keyword-tag">1</span>
<span className="keyword-tag"></span>
</div>
<div className="range-row">
<div className="input-wrapper date">
<input
className="date-input"
type="text"
placeholder="날짜 선택"
value="2025.06.08"
readOnly={ true }
/>
<button
type="button"
className="date-btn"
>
<img
src={ IMAGE_ROOT + '/ico_date.svg' }
alt="날짜 선택"
/>
</button>
</div>
<span className="beetween">~</span>
<div className="input-wrapper date">
<input
className="date-input"
type="text"
placeholder="날짜 선택"
value="2025.06.08"
readOnly={ true }
/>
<button
type="button"
className="date-btn"
>
<img
src={ IMAGE_ROOT + '/ico_date.svg' }
alt="날짜 선택"
/>
</button>
</div>
</div>
</div>
</div>
<div className="opt-field">
<div className="opt-label"></div>
<div className="opt-controls col below h36">
<div className="chip-row">
<span className="keyword-tag active"></span>
<span className="keyword-tag"></span>
<span className="keyword-tag"></span>
<span className="keyword-tag"></span>
</div>
</div>
</div>
<div className="opt-field">
<div className="opt-label"></div>
<div className="opt-controls col below h36">
<div className="chip-row">
<span className="keyword-tag active"></span>
<span className="keyword-tag"></span>
<span className="keyword-tag"></span>
<span
className="keyword-tag"
style={{ visibility: 'hidden' }}
></span>
</div>
</div>
</div>
<div className="opt-field">
<div className="opt-label"></div>
<div className="opt-controls">
<select className="flex-1">
<option></option>
</select>
</div>
</div>
<div className="opt-field">
<div className="opt-label"></div>
<div className="opt-controls">
<div className="input-wrapper ">
<input
type="text"
placeholder=""
/>
</div>
<span> ~ </span>
<div className="input-wrapper date">
<input
type="text"
placeholder=""
/>
</div>
</div>
</div>
<div className="option-list pt-16">
<FilterSelect
title='가맹점'
selectValue={ filterMid }
selectSetter={ setMid }
selectOptions={ MidOptions }
></FilterSelect>
<FilterSelectInput
title='주문번호/TID'
selectValue={ filterMoidTidType }
selectSetter={ setFilterMoidTidType }
selectOptions={ AllTransactionMoidTidOptionsGroup }
inputValue={ filterMoidTidValue }
inputSetter={ setFilterMoidTidValue }
></FilterSelectInput>
<FilterCalendar
title='조회기간'
startDate={ filterFromDate }
endDate={ filterToDate }
setStartDate={ setFilterFromDate }
setEndDate={ setFilterToDate }
></FilterCalendar>
<FilterButtonGroups
title='거래상태'
activeValue={ filterStateCode }
btnGroups={ AllTransactionStateCodeBtnGroup }
setter={ setFilterStateCode }
></FilterButtonGroups>
<FilterSelect
title='결제수단'
selectValue={ filterServiceCode }
selectSetter={ setSearchClOptions }
selectOptions={ AllTransactionServiceCodeOptionsGroup }
></FilterSelect>
<FilterRangeAmount
title='거래금액'
minAmount={ filterMinAmount }
maxAmount={ filterMaxAmount }
setMinAmount={ setFilterMinAmount }
setMaxAmount={ setFilterMaxAmount }
></FilterRangeAmount>
{/*
<FilterSelect
title='카드사/은행'
selectValue={}
selectSetter={}
selectOptions={}
></FilterSelect>
*/}
<FilterSelectInput
title='상세조회'
selectValue={ filterSearchCl }
selectSetter={ setFilterSearchCl }
selectOptions={ searchClOptionsGroup }
inputValue={ filterSearchValue }
inputSetter={ setFilterSearchValue }
></FilterSelectInput>
</div>
<div className="apply-row">
<button className="btn-50 btn-blue flex-1"></button>
<button
className="btn-50 btn-blue flex-1"
onClick={ () => onClickToSetFilter() }
></button>
</div>
</div>
</motion.div>

View File

@@ -8,6 +8,9 @@ import { FilterCalendar } from '@/shared/ui/filter/calendar';
import { FilterButtonGroups } from '@/shared/ui/filter/button-groups';
import { FilterRangeAmount } from '@/shared/ui/filter/range-amount';
import {
FilterMotionDuration,
FilterMotionVariants,
FilterMotionStyle,
BillingSearchTypeOptionsGroup,
BillingRequestStatusBtnGroup,
BillingProcessResultBtnGroup,
@@ -57,11 +60,6 @@ export const BillingFilter = ({
const [filterMinAmount, setFilterMinAmount] = useState<number | string>(minAmount || '');
const [filterMaxAmount, setFilterMaxAmount] = useState<number | string>(maxAmount || '');
const variants = {
hidden: { x: '100%' },
visible: { x: '0%' },
};
const onClickToClose = () => {
setFilterOn(false);
};
@@ -99,12 +97,9 @@ export const BillingFilter = ({
className="full-menu-modal"
initial="hidden"
animate={ (filterOn)? 'visible': 'hidden' }
variants={ variants }
transition={{ duration: 0.3 }}
style={{
width: '100%',
height: '100%',
}}
variants={ FilterMotionVariants }
transition={ FilterMotionDuration }
style={ FilterMotionStyle }
>
<div className="full-menu-container">
<div className="full-menu-header">
@@ -131,7 +126,7 @@ export const BillingFilter = ({
selectOptions={ MidOptions }
></FilterSelect>
<FilterSelectInput
title='주문번호/ID'
title='주문번호/TID'
selectValue={ filterSearchType }
selectSetter={ setFilterSearchType }
selectOptions={ BillingSearchTypeOptionsGroup }

View File

@@ -7,6 +7,9 @@ import { FilterSelectInput } from '@/shared/ui/filter/select-input';
import { FilterCalendar } from '@/shared/ui/filter/calendar';
import { FilterButtonGroups } from '@/shared/ui/filter/button-groups';
import {
FilterMotionVariants,
FilterMotionDuration,
FilterMotionStyle,
CashReceiptPurposeTypeBtnGroup,
CashReceiptIssueStatusBtnGroup,
CashReceiptProcessResultBtnGroup
@@ -42,10 +45,12 @@ export const CashReceiptFilter = ({
const [filterIssueStatus, setFilterIssueStatus] = useState<CashReceiptIssueStatus>(issueStatus);
const [filterProcessResult, setFilterProcessResult] = useState<CashReceiptProcessResult>(processResult);
const variants = {
hidden: { x: '100%' },
visible: { x: '0%' },
};
const [filterIssueType, setFilterIssueType] = useState<string>('');
const [filterIssueNumber, setFilterIssueNumber] = useState<string>('');
const issueTypeOptionsGroup = [
{name: '승인번호', value: 'issue'},
{name: '발행번호', value: 'issue2'},
];
const onClickToClose = () => {
setFilterOn(false);
@@ -79,12 +84,9 @@ export const CashReceiptFilter = ({
className="full-menu-modal"
initial="hidden"
animate={ (filterOn)? 'visible': 'hidden' }
variants={ variants }
transition={{ duration: 0.3 }}
style={{
width: '100%',
height: '100%',
}}
variants={ FilterMotionVariants }
transition={ FilterMotionDuration }
style={ FilterMotionStyle }
>
<div className="full-menu-container">
<div className="full-menu-header">
@@ -136,7 +138,14 @@ export const CashReceiptFilter = ({
btnGroups={ CashReceiptProcessResultBtnGroup }
setter={ setFilterProcessResult }
></FilterButtonGroups>
<FilterSelectInput
title='승인번호/발행번호'
selectValue={ filterIssueType }
selectSetter={ setFilterIssueType }
selectOptions={ issueTypeOptionsGroup }
inputValue={ filterIssueNumber }
inputSetter={ setFilterIssueNumber }
></FilterSelectInput>
</div>
<div className="apply-row">
<button

View File

@@ -8,8 +8,12 @@ import { FilterCalendar } from '@/shared/ui/filter/calendar';
import { FilterButtonGroups } from '@/shared/ui/filter/button-groups';
import { FilterRangeAmount } from '@/shared/ui/filter/range-amount';
import {
FilterMotionVariants,
FilterMotionDuration,
FilterMotionStyle,
EscrowDeliveryStatusBtnGroup,
EscrowSettlementStatusBtnGroup
EscrowSettlementStatusBtnGroup,
EscrowSearchTypeOptionsGroup
} from '@/entities/transaction/model/contant';
import {
EscrowFilterProps,
@@ -51,11 +55,6 @@ export const EscrowFilter = ({
const [filterMinAmount, setFilterMinAmount] = useState<number | string>(minAmount || '');
const [filterMaxAmount, setFilterMaxAmount] = useState<number | string>(maxAmount || '');
const variants = {
hidden: { x: '100%' },
visible: { x: '0%' },
};
const onClickToClose = () => {
setFilterOn(false);
};
@@ -79,11 +78,7 @@ export const EscrowFilter = ({
let MidOptions = [
{name: 'nictest001m', value: 'nictest001m'}
];
let SearchTypeOptions = [
{name: '주문번호', value: EscrowSearchType.ORDER_NUMBER },
{name: 'TID', value: EscrowSearchType.TID }
];
useEffect(() => {
setFilterDeliveryStatus(deliveryStatus);
}, [deliveryStatus]);
@@ -95,12 +90,9 @@ export const EscrowFilter = ({
className="full-menu-modal"
initial="hidden"
animate={ (filterOn)? 'visible': 'hidden' }
variants={ variants }
transition={{ duration: 0.3 }}
style={{
width: '100%',
height: '100%',
}}
variants={ FilterMotionVariants }
transition={ FilterMotionDuration }
style={ FilterMotionStyle }
>
<div className="full-menu-container">
<div className="full-menu-header">
@@ -127,10 +119,10 @@ export const EscrowFilter = ({
selectOptions={ MidOptions }
></FilterSelect>
<FilterSelectInput
title='주문번호/ID'
title='주문번호/TID'
selectValue={ filterSearchType }
selectSetter={ setSearchType }
selectOptions={ SearchTypeOptions }
selectOptions={ EscrowSearchTypeOptionsGroup }
inputValue={ searchKeyword }
inputSetter={ setSearchKeyword }
></FilterSelectInput>