계좌성명 조회 페이지 UI 추가 (내역,상세,요청,필터)

This commit is contained in:
HyeonJongKim
2025-09-12 17:32:48 +09:00
parent 65bbfc12b9
commit 3b89dbdbb6
12 changed files with 782 additions and 144 deletions

View File

@@ -23,6 +23,16 @@ export enum SortByKeys {
New = 'New',
Amount = 'Amount',
};
export enum AccountHolderSearchType {
ALL = 'ALL',
ACCOUNT_HOLDER = 'ACCOUNT_HOLDER',
ACCOUNT_NUMBER = 'ACCOUNT_NUMBER'
};
export enum AccountHolderSearchProcessResult {
ALL = 'ALL',
SUCCESS = 'SUCCESS',
FAILURE = 'FAILURE'
};
export interface SortOptionsBoxProps {
sortBy: SortByKeys;
onClickToSort: (sortBy: SortByKeys) => void;
@@ -232,7 +242,7 @@ export interface ExtensionAlimtalkSettingSaveResponse {
};
export interface ExtensionAlimtalkSettingDetailParams extends ExtensionRequestParams {
};
export interface ExtensionAlimtalkSettingDetailItem {
sendMerchantInfo: SendMerchantInfoItem;
@@ -311,10 +321,34 @@ export interface SettlementAgencyBottomAgreeProps {
bottomAgreeOn: boolean;
setBottomAgreeOn: (bottomAgreeOn: boolean) => void;
};
export interface LinkPaymentFilterProps {
filterOn: boolean;
setFilterOn: (filterOn: boolean) => void;
/**
* FilterProps
*/
export interface FilterProps {
filterOn: boolean;
setFilterOn: (filterOn: boolean) => void;
};
export interface AccountHolderSearchFilterProps extends FilterProps {
mid: string;
searchType: AccountHolderSearchType;
searchKeyword: string;
startDate: string;
endDate: string;
bank: string;
processResult: AccountHolderSearchProcessResult;
setMid: (mid: string) => void;
setSearchType: (searchType: AccountHolderSearchType) => void;
setSearchKeyword: (searchKeyWorld: string) => void;
setStartDate: (startDate: string) => void;
setEndDate: (endDate: string) => void;
setBank: (bank: string) => void;
setProcessResult: (processResult: AccountHolderSearchProcessResult) => void;
}
export interface LinkPaymentFilterProps extends FilterProps {
};
export enum DetailInfoSectionKeys {
Payment = 'Payment',
Deets = 'Deets'

View File

@@ -0,0 +1,210 @@
import moment from 'moment';
import { IMAGE_ROOT } from '@/shared/constants/common';
import { motion } from 'framer-motion';
import { ChangeEvent, useState } from 'react';
import {
AccountHolderSearchType,
AccountHolderSearchFilterProps,
AccountHolderSearchProcessResult
} from '../../model/types';
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 AccountHolderSearchFilter = ({
filterOn,
setFilterOn,
mid,
searchType,
searchKeyword,
startDate,
endDate,
bank,
processResult,
setMid,
setSearchType,
setSearchKeyword,
setStartDate,
setEndDate,
setBank,
setProcessResult
}: AccountHolderSearchFilterProps) => {
const [filterMid, setFilterMid] = useState<string>(mid);
const [filterSearchType, setFilterSearchType] = useState<AccountHolderSearchType>(searchType);
const [filterSearchKeyword, setFilterSearchKeyword] = useState<string>(searchKeyword);
const [filterStartDate, setFilterStartDate] = useState<string>(startDate);
const [filterEndDate, setFilterEndDate] = useState<string>(endDate);
const [filterBank, setFilterBank] = useState<string>(bank)
const [filterProcessResult, setFilterProcessResult] = useState<AccountHolderSearchProcessResult>(processResult);
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 setFilterDate = (dateOptions: FilterDateOptions) => {
if (dateOptions === FilterDateOptions.Today) {
setFilterStartDate(moment().format('YYYY-MM-DD'));
setFilterEndDate(moment().format('YYYY-MM-DD'));
setDateReadyOnly(true);
setFilterDateOptionsBtn(FilterDateOptions.Today);
}
else if (dateOptions === FilterDateOptions.Week) {
setFilterStartDate(moment().subtract(1, 'week').format('YYYY-MM-DD'));
setFilterEndDate(moment().format('YYYY-MM-DD'));
setDateReadyOnly(true);
setFilterDateOptionsBtn(FilterDateOptions.Week);
}
else if (dateOptions === FilterDateOptions.Month) {
setFilterStartDate(moment().subtract(1, 'month').format('YYYY-MM-DD'));
setFilterEndDate(moment().format('YYYY-MM-DD'));
setDateReadyOnly(true);
setFilterDateOptionsBtn(FilterDateOptions.Month);
}
else if (dateOptions === FilterDateOptions.Input) {
setDateReadyOnly(false);
setFilterDateOptionsBtn(FilterDateOptions.Input);
}
};
const onClickToOpenCalendar = () => {
if (!dateReadOnly) {
setCalendarOpen(true);
}
else {
setCalendarOpen(false);
}
};
const setNewDate = (newDate: any) => {
console.log(newDate)
};
const onClickToSetFilter = () => {
setMid(filterMid);
setSearchType(filterSearchType);
setSearchKeyword(filterSearchKeyword);
setStartDate(filterStartDate);
setEndDate(filterEndDate);
setBank(filterBank);
setProcessResult(filterProcessResult);
};
let processResultBtnGroup = [
{ name: '전체', value: AccountHolderSearchProcessResult.ALL },
{ name: '성공', value: AccountHolderSearchProcessResult.SUCCESS },
{ name: '실패', value: AccountHolderSearchProcessResult.FAILURE },
];
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">
<div className="opt-field">
<div className="opt-label"></div>
<div className="opt-controls">
<select
className="flex-1"
value={filterMid}
onChange={(e: any) => setFilterMid(e.target.value)}
>
<option>nictest001m</option>
<option>nictest002m</option>
</select>
</div>
</div>
<div className="opt-field">
<div className="opt-label">/</div>
<div className="opt-controls">
<select
className="w-110"
value={filterSearchType}
onChange={(e: any) => setFilterSearchType(e.target.value)}
>
<option value={AccountHolderSearchType.ACCOUNT_HOLDER}></option>
<option value={AccountHolderSearchType.ACCOUNT_NUMBER}></option>
</select>
<input
className="flex-1"
type="text"
placeholder=""
value={filterSearchKeyword}
onChange={(e: ChangeEvent<HTMLInputElement>) => setFilterSearchKeyword(e.target.value)}
/>
</div>
</div>
<FilterCalendar
startDate={filterStartDate}
endDate={filterEndDate}
setStartDate={setFilterStartDate}
setEndDate={setFilterEndDate}
></FilterCalendar>
<div className="opt-field">
<div className="opt-label"></div>
<div className="opt-controls">
<select
className="flex-1"
value={filterBank}
onChange={(e: any) => setFilterBank(e.target.value)}
>
<option></option>
<option></option>
</select>
</div>
</div>
<FilterButtonGroups
title='조회결과'
activeValue={filterProcessResult}
btnGroups={processResultBtnGroup}
setter={setFilterProcessResult}
></FilterButtonGroups>
</div>
<div className="apply-row">
<button
className="btn-50 btn-blue flex-1"
onClick={() => onClickToSetFilter()}
></button>
</div>
</div>
</motion.div>
</>
)
}

View File

@@ -36,7 +36,7 @@ export const LinkPaymentStep1 = () => {
<div className="issue-row gap-10">
<div className="issue-label"></div>
<div className="issue-field">
<select
<select
className="wid-100"
value={formData.merchant}
onChange={(e) => handleInputChange('merchant', e.target.value)}
@@ -50,19 +50,19 @@ export const LinkPaymentStep1 = () => {
<div className="issue-label"> </div>
<div className="issue-field">
<div className="chip-row">
<span
<span
className={`keyword-tag flex-1 ${selectedPaymentMethod === 'SMS' ? 'active' : ''}`}
onClick={() => handlePaymentMethodChange('SMS')}
>
SMS
</span>
<span
<span
className={`keyword-tag flex-1 ${selectedPaymentMethod === '이메일' ? 'active' : ''}`}
onClick={() => handlePaymentMethodChange('이메일')}
>
</span>
<span
<span
className={`keyword-tag flex-1 ${selectedPaymentMethod === '카카오' ? 'active' : ''}`}
onClick={() => handlePaymentMethodChange('카카오')}
>
@@ -75,9 +75,9 @@ export const LinkPaymentStep1 = () => {
<div className="issue-row gap-10">
<div className="issue-label"></div>
<div className="issue-field">
<input
type="text"
placeholder=""
<input
type="text"
placeholder=""
value={formData.productName}
onChange={(e) => handleInputChange('productName', e.target.value)}
/>
@@ -87,9 +87,9 @@ export const LinkPaymentStep1 = () => {
<div className="issue-row gap-10">
<div className="issue-label"></div>
<div className="issue-field">
<input
type="text"
placeholder=""
<input
type="text"
placeholder=""
value={formData.productPrice}
onChange={(e) => handleInputChange('productPrice', e.target.value)}
/>
@@ -99,9 +99,9 @@ export const LinkPaymentStep1 = () => {
<div className="issue-row gap-10">
<div className="issue-label"> </div>
<div className="issue-field">
<input
type="text"
placeholder=""
<input
type="text"
placeholder=""
value={formData.orderNumber}
onChange={(e) => handleInputChange('orderNumber', e.target.value)}
/>
@@ -113,15 +113,15 @@ export const LinkPaymentStep1 = () => {
<div className="issue-field">
<div className="link-apply-date">
<div className="input-wrapper date">
<input
type="text"
value={formData.validDate}
<input
type="text"
value={formData.validDate}
className="date-input"
onChange={(e) => handleInputChange('validDate', e.target.value)}
/>
<button type="button" className="date-btn">
<img
src={IMAGE_ROOT + '/ico_date.svg'}
<img
src={IMAGE_ROOT + '/ico_date.svg'}
alt="날짜 선택"
/>
</button>