링크결제[발송내역,발송대기] 필터 추가

This commit is contained in:
HyeonJongKim
2025-09-15 10:33:27 +09:00
parent 9b8378ccad
commit 601f92369c
18 changed files with 569 additions and 322 deletions

View File

@@ -0,0 +1,174 @@
import moment from 'moment';
import { useEffect } from 'react';
import { IMAGE_ROOT } from '@/shared/constants/common';
import { motion } from 'framer-motion';
import { ChangeEvent, useState } from 'react';
import {
LinkPaymentPendingSendFilterProps,
LinkPaymentSearchType,
LinkPaymentSendMethod,
LinkPaymentSendingStatus,
} from "../../../model/types";
import { FilterSelect } from '@/shared/ui/filter/select';
import { FilterSelectInput } from '@/shared/ui/filter/select-input';
import { FilterDateOptions } from '@/entities/common/model/types';
import { FilterCalendar } from '@/shared/ui/filter/filter-calendar';
import { FilterButtonGroups } from '@/shared/ui/filter/button-groups';
export const LinkPaymentPendingSendFilter = ({
filterOn,
setFilterOn,
mid,
searchType,
searchKeyword,
startDate,
endDate,
sendMethod,
sendingStatus,
setMid,
setSearchType,
setSearchKeyword,
setStartDate,
setEndDate,
setSendMethod,
setSendingStatus
}: LinkPaymentPendingSendFilterProps) => {
const [filterMid, setFilterMid] = useState<string>(mid);
const [filterSearchType, setFilterSearchType] = useState<LinkPaymentSearchType>(searchType);
const [filterSearchKeyword, setFilterSearchKeyword] = useState<string>(searchKeyword);
const [filterStartDate, setFilterStartDate] = useState<string>(startDate);
const [filterEndDate, setFilterEndDate] = useState<string>(endDate);
const [filterSendMethod, setFilterSendMethod] = useState<LinkPaymentSendMethod>(sendMethod)
const [filterSendingStatus, setFilterSendingStatus] = useState<LinkPaymentSendingStatus>(sendingStatus);
const [dateReadOnly, setDateReadyOnly] = useState<boolean>(true);
const [filterDateOptionsBtn, setFilterDateOptionsBtn] = useState<FilterDateOptions>(FilterDateOptions.Input);
const [calendarOpen, setCalendarOpen] = useState<boolean>(false);
const variants = {
hidden: { x: '100%' },
visible: { x: '0%' },
};
const onClickToClose = () => {
setFilterOn(false);
};
const setNewDate = (newDate: any) => {
console.log(newDate)
};
const onClickToSetFilter = () => {
setMid(filterMid);
setSearchType(filterSearchType);
setSearchKeyword(filterSearchKeyword);
setStartDate(filterStartDate);
setEndDate(filterEndDate);
setSendMethod(filterSendMethod);
setSendingStatus(filterSendingStatus);
};
let MidOptions = [
{ name: 'nictest001m', value: 'nictest001m' },
{ name: 'nictest002m', value: 'nictest002m' }
];
let searchTypeOption = [
{ name: '휴대폰번호', value: LinkPaymentSearchType.PHONE },
{ name: '이메일', value: LinkPaymentSearchType.EMAIL },
]
let sendMethodOption = [
{ name: '전체', value: LinkPaymentSendMethod.ALL },
{ name: 'SMS', value: LinkPaymentSendMethod.SMS },
{ name: '이메일', value: LinkPaymentSendMethod.EMAIL },
{ name: '카카오', value: LinkPaymentSendMethod.KAKAO },
]
let sendingStatusOption = [
{ name: '전체', value: LinkPaymentSendingStatus.ALL },
{ name: '발송요청', value: LinkPaymentSendingStatus.SEND_REQUEST },
{ name: '발송취소', value: LinkPaymentSendingStatus.SEND_CANCEL },
]
return (
<>
<motion.div
id="fullMenuModal"
className="full-menu-modal"
initial="hidden"
animate={(filterOn) ? 'visible' : 'hidden'}
variants={variants}
transition={{ duration: 0.3 }}
style={{
width: '100%',
height: '100%',
}}
>
<div className="full-menu-container">
<div className="full-menu-header">
<div className="full-menu-title center"></div>
<div className="full-menu-actions">
<button
id="closeFullMenu"
className="full-menu-close"
>
<img
src={IMAGE_ROOT + '/ico_close.svg'}
alt="닫기"
onClick={() => onClickToClose()}
/>
</button>
</div>
</div>
<div className="option-list pt-16">
<FilterSelect
title='가맹점'
selectValue={mid}
selectSetter={setFilterMid}
selectOptions={MidOptions}
></FilterSelect>
<FilterSelectInput
title='휴대폰번호/이메일'
selectValue={searchType}
selectSetter={setFilterSearchType}
selectOptions={searchTypeOption}
inputValue={searchKeyword}
inputSetter={setSearchKeyword}
></FilterSelectInput>
<FilterCalendar
startDate={filterStartDate}
endDate={filterEndDate}
setStartDate={setFilterStartDate}
setEndDate={setFilterEndDate}
></FilterCalendar>
<FilterButtonGroups
title='발송수단'
activeValue={filterSendMethod}
btnGroups={sendMethodOption}
setter={setFilterSendMethod}
></FilterButtonGroups>
<FilterButtonGroups
title='진행상태'
activeValue={filterSendingStatus}
btnGroups={sendingStatusOption}
setter={setFilterSendingStatus}
></FilterButtonGroups>
</div>
<div className="apply-row">
<button
className="btn-50 btn-blue flex-1"
onClick={() => onClickToSetFilter()}
></button>
</div>
</div>
</motion.div>
</>
)
}

View File

@@ -0,0 +1,195 @@
import moment from 'moment';
import { useEffect } from 'react';
import { IMAGE_ROOT } from '@/shared/constants/common';
import { motion } from 'framer-motion';
import { ChangeEvent, useState } from 'react';
import {
LinkPaymentSearchType,
LinkPaymentSendMethod,
LinkPaymentShippingHistoryFilterProps,
LinkPaymentTransactionStatus,
ProcessResult
} from "../../../model/types";
import { FilterSelect } from '@/shared/ui/filter/select';
import { FilterSelectInput } from '@/shared/ui/filter/select-input';
import { FilterDateOptions } from '@/entities/common/model/types';
import { FilterCalendar } from '@/shared/ui/filter/filter-calendar';
import { FilterButtonGroups } from '@/shared/ui/filter/button-groups';
export const LinkPaymentShippingHistoryFilter = ({
filterOn,
setFilterOn,
mid,
searchType,
searchKeyword,
startDate,
endDate,
transactionStatus,
processResult,
sendMethod,
setMid,
setSearchType,
setSearchKeyword,
setStartDate,
setEndDate,
setTransactionStatus,
setProcessResult,
setSendMethod
}: LinkPaymentShippingHistoryFilterProps) => {
const [filterMid, setFilterMid] = useState<string>(mid);
const [filterSearchType, setFilterSearchType] = useState<LinkPaymentSearchType>(searchType);
const [filterSearchKeyword, setFilterSearchKeyword] = useState<string>(searchKeyword);
const [filterStartDate, setFilterStartDate] = useState<string>(startDate);
const [filterEndDate, setFilterEndDate] = useState<string>(endDate);
const [filterTransactionStatus, setFilterTransactionStatus] = useState<LinkPaymentTransactionStatus>(transactionStatus)
const [filterProcessResult, setFilterProcessResult] = useState<ProcessResult>(processResult);
const [filterSendMethod, setFilterSendMethod] = useState<LinkPaymentSendMethod>(sendMethod);
const [dateReadOnly, setDateReadyOnly] = useState<boolean>(true);
const [filterDateOptionsBtn, setFilterDateOptionsBtn] = useState<FilterDateOptions>(FilterDateOptions.Input);
const [calendarOpen, setCalendarOpen] = useState<boolean>(false);
const variants = {
hidden: { x: '100%' },
visible: { x: '0%' },
};
const onClickToClose = () => {
setFilterOn(false);
};
const setNewDate = (newDate: any) => {
console.log(newDate)
};
const onClickToSetFilter = () => {
setMid(filterMid);
setSearchType(filterSearchType);
setSearchKeyword(filterSearchKeyword);
setStartDate(filterStartDate);
setEndDate(filterEndDate);
setTransactionStatus(filterTransactionStatus);
setProcessResult(filterProcessResult);
setSendMethod(filterSendMethod);
};
let MidOptions = [
{ name: 'nictest001m', value: 'nictest001m' },
{ name: 'nictest002m', value: 'nictest002m' }
];
let searchTypeOption = [
{ name: '휴대폰번호', value: LinkPaymentSearchType.PHONE },
{ name: '이메일', value: LinkPaymentSearchType.EMAIL },
]
let transactionStatusOption = [
{ name: '전체', value: LinkPaymentTransactionStatus.ALL },
{ name: '미완료/활성화', value: LinkPaymentTransactionStatus.ACTIVATE },
{ name: '입금요청', value: LinkPaymentTransactionStatus.DEPOSIT_REQUEST },
{ name: '결제완료', value: LinkPaymentTransactionStatus.TRANSACTION_COMPLETE },
{ name: '결제실패', value: LinkPaymentTransactionStatus.TRANSACTION_FAIL },
{ name: '결제중단/비활성화', value: LinkPaymentTransactionStatus.INACTIVE },
]
let processResultOption = [
{ name: '전체', value: ProcessResult.ALL },
{ name: '성공', value: ProcessResult.SUCCESS },
{ name: '실패', value: ProcessResult.FAILURE },
]
let sendMethodOption = [
{ name: '전체', value: LinkPaymentSendMethod.ALL },
{ name: 'SMS', value: LinkPaymentSendMethod.SMS },
{ name: '이메일', value: LinkPaymentSendMethod.EMAIL },
{ name: '카카오', value: LinkPaymentSendMethod.KAKAO },
]
return (
<>
<motion.div
id="fullMenuModal"
className="full-menu-modal"
initial="hidden"
animate={(filterOn) ? 'visible' : 'hidden'}
variants={variants}
transition={{ duration: 0.3 }}
style={{
width: '100%',
height: '100%',
}}
>
<div className="full-menu-container">
<div className="full-menu-header">
<div className="full-menu-title center"></div>
<div className="full-menu-actions">
<button
id="closeFullMenu"
className="full-menu-close"
>
<img
src={IMAGE_ROOT + '/ico_close.svg'}
alt="닫기"
onClick={() => onClickToClose()}
/>
</button>
</div>
</div>
<div className="option-list pt-16">
<FilterSelect
title='가맹점'
selectValue={filterMid}
selectSetter={setFilterMid}
selectOptions={MidOptions}
></FilterSelect>
<FilterSelectInput
title='휴대폰번호/이메일'
selectValue={filterSearchType}
selectSetter={setFilterSearchType}
selectOptions={searchTypeOption}
inputValue={searchKeyword}
inputSetter={setSearchKeyword}
></FilterSelectInput>
<FilterCalendar
startDate={filterStartDate}
endDate={filterEndDate}
setStartDate={setFilterStartDate}
setEndDate={setFilterEndDate}
></FilterCalendar>
<FilterButtonGroups
title='거래상태'
activeValue={filterTransactionStatus}
btnGroups={transactionStatusOption}
setter={setFilterTransactionStatus}
></FilterButtonGroups>
<FilterButtonGroups
title='전송결과'
activeValue={filterProcessResult}
btnGroups={processResultOption}
setter={setFilterProcessResult}
></FilterButtonGroups>
<FilterButtonGroups
title='발송수단'
activeValue={filterSendMethod}
btnGroups={sendMethodOption}
setter={setFilterSendMethod}
></FilterButtonGroups>
</div>
<div className="apply-row">
<button
className="btn-50 btn-blue flex-1"
onClick={() => onClickToSetFilter()}
></button>
</div>
</div>
</motion.div>
</>
)
}

View File

@@ -1,193 +0,0 @@
import { motion } from 'framer-motion';
import {IMAGE_ROOT} from "@/shared/constants/common";
import {LinkPaymentFilterProps} from "@/entities/additional-service/model/types";
export const LinkPaymentFilter = ({
filterOn,
setFilterOn
}: LinkPaymentFilterProps) => {
const variants = {
hidden:{ x: '100%'},
visible: {x: '0%'}
};
const onClickToClose = () => {
setFilterOn(false);
};
return (
<>
<motion.div
id="fullMenuModal"
className="full-menu-modal"
initial="hidden"
animate={ (filterOn)? 'visible': 'hidden' }
variants={ variants }
transition={{ duration: 0.3 }}
style={{
width: '100%',
height: '100%',
}}
>
<div className="full-menu-container">
<div className="full-menu-header">
<div className="full-menu-title center"></div>
<div className="full-menu-actions">
<button
id="closeFullMenu"
className="full-menu-close"
>
<img
src={ IMAGE_ROOT + '/ico_close.svg' }
alt="닫기"
onClick={ () => onClickToClose() }
/>
</button>
</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">, </div>
<div className="opt-controls">
<select className="flex-1">
<option></option>
<option></option>
</select>
<input
type="text"/>
</div>
</div>
<div className="opt-field">
<div className="opt-label"></div>
<div className="opt-controls">
<select className="flex-1">
<option>nictext001m</option>
</select>
</div>
</div>
<div className="opt-field mt_top">
<div className="opt-label"></div>
<div className="opt-controls col below h36">
<div className="chip-row">
<span className="keyword-tag"></span>
<span className="keyword-tag"></span>
<span className="keyword-tag">1</span>
<span className="keyword-tag active"></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
className="date-btn"
type="button"
>
<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
className="date-btn"
type="button"
>
<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 flex-1 active"></span>
<span className="keyword-tag flex-1">/ <br/> </span>
<span className="keyword-tag flex-1"></span>
<span className="keyword-tag flex-1"></span>
<span
className="keyword-tag"
style={{ visibility: 'hidden' }}
></span>
</div>
</div>
<div className="opt-controls col below h50 mt-10">
<div className="chip-row">
<span className="keyword-tag flex-1"></span>
<span className="keyword-tag flex-1">/ <br/> </span>
<span
className="keyword-tag"
style={{ visibility: 'hidden' }}
></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 col below h36">
<div className="chip-row">
<span className="keyword-tag flex-1 active"></span>
<span className="keyword-tag flex-1"></span>
<span className="keyword-tag flex-1"></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 flex-1 active"></span>
<span className="keyword-tag flex-1">SMS</span>
<span className="keyword-tag flex-1"></span>
<span className="keyword-tag flex-1"></span>
</div>
</div>
</div>
<div className="apply-row">
<button className="btn-50 btn-blue flex-1"></button>
</div>
</div>
</div>
</motion.div>
</>
)
}

View File

@@ -1,22 +1,33 @@
import moment from 'moment';
import { IMAGE_ROOT } from "@/shared/constants/common";
import { useState, useEffect } from "react";
import { LinkPaymentFilter } from "./link-payment-filter";
import { LinkPaymentPendingSendFilter } from "./filter/link-payment-pending-send-filter";
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { PATHS } from "@/shared/constants/paths";
import { LinkPaymentPendingList } from "./link-payment-pending-list";
import { LinkPaymentSearchType, LinkPaymentSendingStatus, LinkPaymentSendMethod } from "../../model/types";
export const LinkPaymentPendingSendWrap = () => {
const { navigate } = useNavigate();
const [filterOn, setFilterOn] = useState<boolean>(false);
const [mid, setMid] = useState<string>('nictest001m');
const [searchType, setSearchType] = useState<LinkPaymentSearchType>(LinkPaymentSearchType.ALL)
const [searchKeyword, setSearchKeyword] = useState<string>('');
const [startDate, setStartDate] = useState(moment().format('YYYY-MM-DD'));
const [endDate, setEndDate] = useState(moment().format('YYYY-MM-DD'));
const [sendMethod, setSendMethod] = useState<LinkPaymentSendMethod>(LinkPaymentSendMethod.ALL);
const [sendingStatus, setSendingStatus] = useState<LinkPaymentSendingStatus>(LinkPaymentSendingStatus.ALL);
const [listItems, setListItems] = useState({});
const onClickToOpenFilter = () => {
setFilterOn(!filterOn);
};
const onClickToNavigate = () => {
navigate(PATHS.additionalService.linkPayment.request)
}
const callList = () => {
setListItems({
'20250608': [
@@ -28,7 +39,7 @@ export const LinkPaymentPendingSendWrap = () => {
amount: 5254000
},
{
transactionId: 'pending2',
transactionId: 'pending2',
customerName: '김*환(7000)',
status: '발송요청',
channel: 'SMS',
@@ -111,7 +122,7 @@ export const LinkPaymentPendingSendWrap = () => {
</div>
</section>
<LinkPaymentPendingList
<LinkPaymentPendingList
listItems={listItems}
/>
<div className="apply-row">
@@ -120,10 +131,24 @@ export const LinkPaymentPendingSendWrap = () => {
onClick={() => onClickToNavigate()}
> </button>
</div>
<LinkPaymentFilter
<LinkPaymentPendingSendFilter
filterOn={filterOn}
setFilterOn={setFilterOn}
></LinkPaymentFilter>
mid={mid}
searchType={searchType}
searchKeyword={searchKeyword}
startDate={startDate}
endDate={endDate}
sendMethod={sendMethod}
sendingStatus={sendingStatus}
setMid={setMid}
setSearchType={setSearchType}
setSearchKeyword={setSearchKeyword}
setStartDate={setStartDate}
setEndDate={setEndDate}
setSendMethod={setSendMethod}
setSendingStatus={setSendingStatus}
></LinkPaymentPendingSendFilter>
</>
)
}

View File

@@ -1,18 +1,28 @@
import moment from 'moment';
import { IMAGE_ROOT } from "@/shared/constants/common";
import { useState, useEffect } from "react";
import { LinkPaymentFilter } from "./link-payment-filter";
import { LinkPaymentShippingHistoryFilter } from "./filter/link-payment-shipping-history-filter";
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { PATHS } from "@/shared/constants/paths";
import { LinkPaymentList } from "./link-payment-list";
import { SortOptionsBox } from "./sort-options-box";
import { SortByKeys } from "../../model/types";
import { LinkPaymentSendMethod, LinkPaymentTransactionStatus, ProcessResult, SortByKeys } from "../../model/types";
import { LinkPaymentSearchType, } from "../../model/types";
export const LinkPaymentDispatchListWrap = () => {
export const LinkPaymentShippingHistoryWrap = () => {
const { navigate } = useNavigate();
const [filterOn, setFilterOn] = useState<boolean>(false);
const [sortBy, setSortBy] = useState<SortByKeys>(SortByKeys.New);
const [listItems, setListItems] = useState({});
const [mid, setMid] = useState<string>('nictest001m');
const [searchType, setSearchType] = useState<LinkPaymentSearchType>(LinkPaymentSearchType.ALL)
const [searchKeyword, setSearchKeyword] = useState<string>('');
const [startDate, setStartDate] = useState(moment().format('YYYY-MM-DD'));
const [endDate, setEndDate] = useState(moment().format('YYYY-MM-DD'));
const [transactionStatus, setTransactionStatus] = useState<LinkPaymentTransactionStatus>(LinkPaymentTransactionStatus.ALL)
const [processResult, setProcessResult] = useState<ProcessResult>(ProcessResult.ALL)
const [sendMethod, setSendMethod] = useState<LinkPaymentSendMethod>(LinkPaymentSendMethod.ALL)
const onClickToOpenFilter = () => {
setFilterOn(!filterOn);
@@ -25,7 +35,7 @@ export const LinkPaymentDispatchListWrap = () => {
callList({ sortBy: sort });
};
const callList = (option?: {sortBy?: string, val?: string}) => {
const callList = (option?: { sortBy?: string, val?: string }) => {
setListItems({
'20250608': [
{
@@ -134,10 +144,26 @@ export const LinkPaymentDispatchListWrap = () => {
onClick={() => onClickToNavigate()}
> </button>
</div>
<LinkPaymentFilter
<LinkPaymentShippingHistoryFilter
filterOn={filterOn}
setFilterOn={setFilterOn}
></LinkPaymentFilter>
mid={mid}
searchType={searchType}
searchKeyword={searchKeyword}
startDate={startDate}
endDate={endDate}
transactionStatus={transactionStatus}
processResult={processResult}
sendMethod={sendMethod}
setMid={setMid}
setSearchType={setSearchType}
setSearchKeyword={setSearchKeyword}
setStartDate={setStartDate}
setEndDate={setEndDate}
setTransactionStatus={setTransactionStatus}
setProcessResult={setProcessResult}
setSendMethod={setSendMethod}
></LinkPaymentShippingHistoryFilter>
</>
)
}

View File

@@ -12,8 +12,8 @@ export const LinkPaymentTab = ({
const onClickToNavigation = (tab: LinkPaymentTabKeys) => {
if(activeTab !== tab){
if(tab === LinkPaymentTabKeys.DispatchList){
navigate(PATHS.additionalService.linkPayment.dispatchList);
if(tab === LinkPaymentTabKeys.ShippingHistory){
navigate(PATHS.additionalService.linkPayment.shippingHistory);
}
else if(tab === LinkPaymentTabKeys.PendingSend){
navigate(PATHS.additionalService.linkPayment.pendingSend);
@@ -25,8 +25,8 @@ export const LinkPaymentTab = ({
<>
<div className="subTab">
<button
className={`subtab-btn ${(activeTab === LinkPaymentTabKeys.DispatchList)? 'active': ''}` }
onClick={ () => onClickToNavigation(LinkPaymentTabKeys.DispatchList) }
className={`subtab-btn ${(activeTab === LinkPaymentTabKeys.ShippingHistory)? 'active': ''}` }
onClick={ () => onClickToNavigation(LinkPaymentTabKeys.ShippingHistory) }
></button>
<button
className={`subtab-btn ${(activeTab === LinkPaymentTabKeys.PendingSend)? 'active': ''}` }