현금영수증 리스트

This commit is contained in:
focp212@naver.com
2025-10-21 16:21:57 +09:00
parent 81d977b97d
commit 841a9d8542
44 changed files with 1208 additions and 717 deletions

View File

@@ -0,0 +1,4 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="20" height="20" rx="10" fill="#666666"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.622 6.78805C12.7847 6.62534 13.0485 6.62534 13.2113 6.78805C13.374 6.95077 13.374 7.21459 13.2113 7.37731L10.5892 9.99935L13.2113 12.6214C13.374 12.7841 13.374 13.0479 13.2113 13.2106C13.0485 13.3734 12.7847 13.3734 12.622 13.2106L9.99996 10.5886L7.37792 13.2106C7.2152 13.3734 6.95138 13.3734 6.78866 13.2106C6.62595 13.0479 6.62595 12.7841 6.78866 12.6214L9.4107 9.99935L6.78867 7.37731C6.62595 7.21459 6.62595 6.95077 6.78867 6.78805C6.95138 6.62534 7.2152 6.62534 7.37792 6.78805L9.99996 9.41009L12.622 6.78805Z" fill="white" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 804 B

BIN
public/images/ico_sign.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -40,7 +40,7 @@ export interface UserAccountAuthWrapProps {
status: string;
};
export interface PermItem {
menuId?: string;
menuId?: number;
menuName?: string;
subMenu?: Array<PermItem>;
};

View File

@@ -48,64 +48,64 @@ export const UserAccountAuthWrap = ({
}, [currentStatus, currentIdCL, status, idCL]);
let menuItems = [
{menuId: '30', parent: '30', menuName: '거래조회', subMenu:
{menuId: 30, parent: 30, menuName: '거래조회', subMenu:
[
{menuId: '31', parent: '30', menuName: '거래내역조회'},
{menuId: '32', parent: '30', menuName: '현금영수증발행'},
{menuId: '33', parent: '30', menuName: '에스크로'},
{menuId: '34', parent: '30', menuName: '빌링'}
{menuId: 31, parent: 30, menuName: '거래내역조회'},
{menuId: 32, parent: 30, menuName: '현금영수증발행'},
{menuId: 33, parent: 30, menuName: '에스크로'},
{menuId: 34, parent: 30, menuName: '빌링'}
]
},
{menuId: '35', parent: '35', menuName: '정산조회', subMenu:
{menuId: 35, parent: 35, menuName: '정산조회', subMenu:
[
{menuId: '36', parent: '35', menuName: '정산달력'},
{menuId: '37', parent: '35', menuName: '정산내역'},
{menuId: 36, parent: 35, menuName: '정산달력'},
{menuId: 37, parent: 35, menuName: '정산내역'},
]
},
{menuId: '38', parent: '38', menuName: '가맹점관리', subMenu:
{menuId: 38, parent: 38, menuName: '가맹점관리', subMenu:
[
{menuId: '39', parent: '38', menuName: '가맹점정보'},
{menuId: '40', parent: '38', menuName: '등록현황'},
{menuId: 39, parent: 38, menuName: '가맹점정보'},
{menuId: 40, parent: 38, menuName: '등록현황'},
]
},
{menuId: '41', parent: '41', menuName: '결제관리', subMenu:
{menuId: 41, parent: 41, menuName: '결제관리', subMenu:
[
{menuId: '42', parent: '41', menuName: '결제정보'},
{menuId: '43', parent: '41', menuName: '결제데이터통보'},
{menuId: 42, parent: 41, menuName: '결제정보'},
{menuId: 43, parent: 41, menuName: '결제데이터통보'},
]
},
{menuId: '44', parent: '44', menuName: '계정관리', subMenu:
{menuId: 44, parent: 44, menuName: '계정관리', subMenu:
[
{menuId: '45', parent: '44', menuName: '사용자관리'},
{menuId: '46', parent: '44', menuName: '비밀번호관리'},
{menuId: 45, parent: 44, menuName: '사용자관리'},
{menuId: 46, parent: 44, menuName: '비밀번호관리'},
]
},
{menuId: '47', parent: '47', menuName: '부가세신고자료', subMenu:
{menuId: 47, parent: 47, menuName: '부가세신고자료', subMenu:
[
{menuId: '48', parent: '47', menuName: '세금계산서'},
{menuId: '49', parent: '47', menuName: '부가세참고'},
{menuId: 48, parent: 47, menuName: '세금계산서'},
{menuId: 49, parent: 47, menuName: '부가세참고'},
]
},
{menuId: '50', parent: '50', menuName: '부가서비스', subMenu:
{menuId: 50, parent: 50, menuName: '부가서비스', subMenu:
[
{menuId: '51', parent: '50', menuName: '부가서비스소개'},
{menuId: '52', parent: '50', menuName: '신용카드ARS카드결제'},
{menuId: '53', parent: '50', menuName: '지급대행'},
{menuId: '54', parent: '50', menuName: '링크결제'},
{menuId: '55', parent: '50', menuName: '자금이체'},
{menuId: '56', parent: '50', menuName: 'KEY-IN결제'},
{menuId: '57', parent: '50', menuName: 'SMS결제통보'},
{menuId: '58', parent: '50', menuName: '알림톡결제통보'},
{menuId: '59', parent: '50', menuName: '계좌점유인증'},
{menuId: '60', parent: '50', menuName: '계좌성명조회'},
{menuId: '65', parent: '50', menuName: '안면인증'},
{menuId: 51, parent: 50, menuName: '부가서비스소개'},
{menuId: 52, parent: 50, menuName: '신용카드ARS카드결제'},
{menuId: 53, parent: 50, menuName: '지급대행'},
{menuId: 54, parent: 50, menuName: '링크결제'},
{menuId: 55, parent: 50, menuName: '자금이체'},
{menuId: 56, parent: 50, menuName: 'KEY-IN결제'},
{menuId: 57, parent: 50, menuName: 'SMS결제통보'},
{menuId: 58, parent: 50, menuName: '알림톡결제통보'},
{menuId: 59, parent: 50, menuName: '계좌점유인증'},
{menuId: 60, parent: 50, menuName: '계좌성명조회'},
{menuId: 65, parent: 50, menuName: '안면인증'},
]
},
{menuId: '61', parent: '61', menuName: '고객지원', subMenu:
{menuId: 61, parent: 61, menuName: '고객지원', subMenu:
[
{menuId: '62', parent: '61', menuName: '공지사항'},
{menuId: '63', parent: '61', menuName: '자주묻는질문'},
{menuId: '64', parent: '61', menuName: '1:1문의'},
{menuId: 62, parent: 61, menuName: '공지사항'},
{menuId: 63, parent: 61, menuName: '자주묻는질문'},
{menuId: 64, parent: 61, menuName: '1:1문의'},
]
},
]

View File

@@ -1,11 +1,6 @@
import { DefaulResponsePagination, DefaultRequestPagination } from '@/entities/common/model/types';
export interface AlarmItemProps {
title?: string;
name?: string;
category?: string;
date?: string;
};
export interface AppAlarmMarkParams {
appNotificationSequence: number;

View File

@@ -1,13 +1,22 @@
import { PATHS } from '@/shared/constants/paths';
import { IMAGE_ROOT } from '@/shared/constants/common';
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { AlarmItemProps } from '../model/types';
import moment from 'moment';
export interface AlarmItemProps {
appNotificationCategory?: string;
notificationReceivedDate?: string;
appNotificationTitle?: string;
appNotificationContent?: string;
appNotificationLink?: string;
};
export const AlarmItem = ({
title,
name,
category,
date
appNotificationCategory,
notificationReceivedDate,
appNotificationTitle,
appNotificationContent,
appNotificationLink
}: AlarmItemProps) => {
const { navigate } = useNavigate();
const onClickToNavigate = (alarmId: number) => {
@@ -18,10 +27,10 @@ export const AlarmItem = ({
return (
<div className="notice-item">
<div className="notice-content">
<div className="notice-title">{ title }</div>
<div className="notice-title">{ appNotificationTitle }</div>
<div className="notice-meta">
<strong>{ name }</strong>
<span>{ date }</span>
<strong>{ appNotificationCategory }</strong>
<span>{ moment(notificationReceivedDate).format('YYYY.MM.DD HH:mm:ss') }</span>
</div>
</div>
<div
@@ -30,7 +39,7 @@ export const AlarmItem = ({
>
<img
src={ IMAGE_ROOT + '/Forward.svg' }
alt={ category + '바로가기' }
alt={ appNotificationCategory + ' 바로가기' }
/>
</div>
</div>

View File

@@ -1,6 +1,13 @@
import { IMAGE_ROOT } from '@/shared/constants/common';
import { AlarmItem } from './alarm-item';
import { AlarmItemProps } from '../model/types';
import { AlarmListContent, AppAlarmListParams, AppAlarmListResponse, MERCHANT_ADMIN_APP } from '../model/types';
import { useEffect, useState } from 'react';
import { useAppAlarmListMutation } from '../api/use-app-alarm-list-mutation';
import { DEFAULT_PAGE_PARAM } from '@/entities/common/model/constant';
import { useTranslation } from 'react-i18next';
import { useNavigate } from '@/shared/lib/hooks';
import useIntersectionObserver from '@/widgets/intersection-observer';
import { useStore } from '@/shared/model/store';
export interface AlarmListProps {
category: string;
@@ -9,35 +16,106 @@ export interface AlarmListProps {
export const AlarmList = ({
category
}: AlarmListProps) => {
const { navigate } = useNavigate();
const { t } = useTranslation();
const userInfo = useStore.getState().UserStore.userInfo;
const [onActionIntersect, setOnActionIntersect] = useState<boolean>(false);
const [pageParam, setPageParam] = useState(DEFAULT_PAGE_PARAM);
const [nextCursor, setNextCursor] = useState<string | null>(null);
const [appCl, setAppCl] = useState<MERCHANT_ADMIN_APP>(MERCHANT_ADMIN_APP.MERCHANT_ADMIN_APP)
const [appNotificationCategory, setAppNotificationCategory] = useState<string>('');
const [resultList, setResultList] = useState<Array<AlarmListContent>>([]);
const [selectedCategory, setSelectedCategory] = useState<string>('');
const { mutateAsync: appAlarmList } = useAppAlarmListMutation();
const alarmItems: Array<AlarmItemProps> = [
{title: '시스템 안정화를 위한 정기 점검이 예정되어 있습니다.', name: '공지사항', category: 'notice', date: '2025.06.01 10:00:00'},
{title: '가맹점 관리 메뉴에 거래내역 엑셀 다운로드 기능이 추가 되었습니다.', name: '공지사항', category: 'notice', date: '2025.06.01 10:00:00'},
{title: '신규 가맹점을 대상으로 거래수수료 인하 혜택을 12월까지 제공합니다.', name: '공지사항', category: 'notice', date: '2025.06.01 10:00:00'},
{title: '앱의 안정성과 사용성을 개선한 버전 2.3.1이 출시되었습니다.', name: '공지사항', category: 'notice', date: '2025.06.01 10:00:00'},
{title: '점검 시간 동안 일부 서비스 이용이 제한될 수 있으니 미리 확인해주세요.', name: '공지사항', category: 'notice', date: '2025.06.01 10:00:00'},
{title: '가맹점 관리 메뉴에 거래내역 엑셀 다운로드 기능이 추가 되었습니다.', name: '공지사항', category: 'notice', date: '2025.06.01 10:00:00'},
{title: '신규 가맹점을 대상으로 거래수수료 인하 혜택을 12월까지 제공합니다.', name: '공지사항', category: 'notice', date: '2025.06.01 10:00:00'},
{title: '앱의 안정성과 사용성을 개선한 버전 2.3.1이 출시되었습니다.', name: '공지사항', category: 'notice', date: '2025.06.01 10:00:00'},
{title: '점검 시간 동안 일부 서비스 이용이 제한될 수 있으니 미리 확인해주세요.', name: '공지사항', category: 'notice', date: '2025.06.01 10:00:00'},
];
const getAlarmItems = () => {
let rs = [];
for(let i=0;i<alarmItems.length;i++){
if(category === 'all' || (alarmItems[i]?.category === category)){
rs.push(
<AlarmItem
title={ alarmItems[i]?.title }
name={ alarmItems[i]?.name }
category={ alarmItems[i]?.category }
date={ alarmItems[i]?.date }
></AlarmItem>
)
}
for(let i=0;i<resultList.length;i++){
rs.push(
<AlarmItem
appNotificationCategory={ resultList[i]?.appNotificationCategory }
notificationReceivedDate={ resultList[i]?.notificationReceivedDate }
appNotificationTitle={ resultList[i]?.appNotificationTitle }
appNotificationContent={ resultList[i]?.appNotificationContent }
appNotificationLink={ resultList[i]?.appNotificationLink }
></AlarmItem>
)
}
return rs;
};
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 && !!nextCursor){
callList('page');
}
}
else{
console.log('Element is no longer intersecting with the root.');
}
});
};
const { setTarget } = useIntersectionObserver({
threshold: 1,
onIntersect
});
const callList = (type?: string) => {
if(userInfo.usrid){
let params: AppAlarmListParams = {
usrid: userInfo.usrid,
appCl: appCl,
appNotificationCategory: appNotificationCategory,
...{
page: pageParam
}
}
if(type === 'page'){
if(params.page){
params.page.cursor = nextCursor;
}
}
else{
setNextCursor(null);
if(params.page){
params.page.cursor = null;
}
}
appAlarmList(params).then((rs: AppAlarmListResponse) => {
if(rs){
if(type === 'page'){
setResultList([
...resultList,
...rs.content
]);
}
else{
setResultList(rs.content);
}
if(rs.hasNext){
setNextCursor(rs.nextCursor);
setOnActionIntersect(true);
}
else{
setNextCursor(null);
}
}
});
}
};
useEffect(() => {
callList();
}, [selectedCategory]);
return (
<>
<div className="notice-box sub">

View File

@@ -38,95 +38,95 @@ export const BottomSheetMotionDuration = {
export const MenuItems = [
{
menuId: '30',
parent: '30',
menuId: 30,
parent: 30,
menuName: '거래조회',
menuIcon: 'transaction-icon',
subMenu: [
{menuId: '31', parent: '30', menuName: '거래내역조회', path: PATHS.transaction.allTransaction.list},
{menuId: '32', parent: '30', menuName: '현금영수증발행', path: PATHS.transaction.cashReceipt.list},
{menuId: '33', parent: '30', menuName: '에스크로', path: PATHS.transaction.escrow.list},
{menuId: '34', parent: '30', menuName: '빌링', path: PATHS.transaction.billing.list}
{menuId: 31, parent: 30, menuName: '거래내역조회', menuNameEng: '', programPath: PATHS.transaction.allTransaction.list},
{menuId: 32, parent: 30, menuName: '현금영수증발행', menuNameEng: '', programPath: PATHS.transaction.cashReceipt.list},
{menuId: 33, parent: 30, menuName: '에스크로', menuNameEng: '', programPath: PATHS.transaction.escrow.list},
{menuId: 34, parent: 30, menuName: '빌링', menuNameEng: '', programPath: PATHS.transaction.billing.list}
]
},
{
menuId: '35',
parent: '35',
menuId: 35,
parent: 35,
menuName: '정산조회',
menuIcon: 'settlement-icon',
subMenu: [
{menuId: '36', parent: '35', menuName: '정산달력', path: PATHS.settlement.calendar},
{menuId: '37', parent: '35', menuName: '정산내역', path: PATHS.settlement.list}
{menuId: 36, parent: 35, menuName: '정산달력', menuNameEng: '', programPath: PATHS.settlement.calendar},
{menuId: 37, parent: 35, menuName: '정산내역', menuNameEng: '', programPath: PATHS.settlement.list}
]
},
{
menuId: '38',
parent: '38',
menuId: 38,
parent: 38,
menuName: '가맹점관리',
menuIcon: 'merchant-icon',
subMenu: [
{menuId: '39', parent: '38', menuName: '가맹점정보', path: PATHS.merchant.info},
{menuId: '40', parent: '38', menuName: '등록현황', path: PATHS.merchant.registrationStatus}
{menuId: 39, parent: 38, menuName: '가맹점정보', menuNameEng: '', programPath: PATHS.merchant.info},
{menuId: 40, parent: 38, menuName: '등록현황', menuNameEng: '', programPath: PATHS.merchant.registrationStatus}
]
},
{
menuId: '41',
parent: '41',
menuId: 41,
parent: 41,
menuName: '결제관리',
menuIcon: 'payment-icon',
subMenu: [
{menuId: '42', parent: '41', menuName: '결제정보', path: PATHS.payment.info},
{menuId: '43', parent: '41', menuName: '결제데이터통보', path: PATHS.payment.notificationData},
{menuId: 42, parent: 41, menuName: '결제정보', menuNameEng: '', programPath: PATHS.payment.info},
{menuId: 43, parent: 41, menuName: '결제데이터통보', menuNameEng: '', programPath: PATHS.payment.notificationData},
]
},
{
menuId: '44',
parent: '44',
menuId: 44,
parent: 44,
menuName: '계정관리',
menuIcon: 'account-icon',
subMenu: [
{menuId: '45', parent: '44', menuName: '사용자관리', path: PATHS.account.user.manage},
{menuId: '46', parent: '44', menuName: '비밀번호관리', path: PATHS.account.password.manage},
{menuId: 45, parent: 44, menuName: '사용자관리', menuNameEng: '', programPath: PATHS.account.user.manage},
{menuId: 46, parent: 44, menuName: '비밀번호관리', menuNameEng: '', programPath: PATHS.account.password.manage},
]
},
{
menuId: '47',
parent: '47',
menuId: 47,
parent: 47,
menuName: '부가세신고자료',
menuIcon: 'vat-icon',
subMenu: [
{menuId: '48', parent: '47', menuName: '세금계산서', path: PATHS.vatReturn.list},
{menuId: '49', parent: '47', menuName: '부가세참고', path: PATHS.vatReturn.reference},
{menuId: 48, parent: 47, menuName: '세금계산서', menuNameEng: '', programPath: PATHS.vatReturn.list},
{menuId: 49, parent: 47, menuName: '부가세참고', menuNameEng: '', programPath: PATHS.vatReturn.reference},
]
},
{
menuId: '50',
parent: '50',
menuId: 50,
parent: 50,
menuName: '부가서비스',
menuIcon: 'service-icon',
subMenu: [
{menuId: '51', parent: '50', menuName: '부가서비스소개', path: PATHS.additionalService.list},
{menuId: '52', parent: '50', menuName: '신용카드ARS카드결제', path: PATHS.additionalService.ars.list},
{menuId: '53', parent: '50', menuName: '지급대행', path: PATHS.additionalService.payout.list},
{menuId: '54', parent: '50', menuName: '링크결제', path: PATHS.additionalService.linkPayment.shippingHistory},
{menuId: '55', parent: '50', menuName: '자금이체', path: PATHS.additionalService.fundAccount.transferList},
{menuId: '56', parent: '50', menuName: 'KEY-IN결제', path: PATHS.additionalService.keyInPayment.list},
{menuId: '57', parent: '50', menuName: 'SMS결제통보', path: PATHS.additionalService.smsPaymentNotification},
{menuId: '58', parent: '50', menuName: '알림톡결제통보', path: PATHS.additionalService.alimtalk.list},
{menuId: '59', parent: '50', menuName: '계좌점유인증', path: PATHS.additionalService.accountHolderAuth.list},
{menuId: '60', parent: '50', menuName: '계좌성명조회', path: PATHS.additionalService.accountHolderSearch.list},
{menuId: '65', parent: '50', menuName: '안면인증', path: PATHS.additionalService.faceAuth.list},
{menuId: 51, parent: 50, menuName: '부가서비스소개', menuNameEng: '', programPath: PATHS.additionalService.list},
{menuId: 52, parent: 50, menuName: '신용카드ARS카드결제', menuNameEng: '', programPath: PATHS.additionalService.ars.list},
{menuId: 53, parent: 50, menuName: '지급대행', menuNameEng: '', programPath: PATHS.additionalService.payout.list},
{menuId: 54, parent: 50, menuName: '링크결제', menuNameEng: '', programPath: PATHS.additionalService.linkPayment.shippingHistory},
{menuId: 55, parent: 50, menuName: '자금이체', menuNameEng: '', programPath: PATHS.additionalService.fundAccount.transferList},
{menuId: 56, parent: 50, menuName: 'KEY-IN결제', menuNameEng: '', programPath: PATHS.additionalService.keyInPayment.list},
{menuId: 57, parent: 50, menuName: 'SMS결제통보', menuNameEng: '', programPath: PATHS.additionalService.smsPaymentNotification},
{menuId: 58, parent: 50, menuName: '알림톡결제통보', menuNameEng: '', programPath: PATHS.additionalService.alimtalk.list},
{menuId: 59, parent: 50, menuName: '계좌점유인증', menuNameEng: '', programPath: PATHS.additionalService.accountHolderAuth.list},
{menuId: 60, parent: 50, menuName: '계좌성명조회', menuNameEng: '', programPath: PATHS.additionalService.accountHolderSearch.list},
{menuId: 65, parent: 50, menuName: '안면인증', menuNameEng: '', programPath: PATHS.additionalService.faceAuth.list},
]
},
{
menuId: '61',
parent: '61',
menuId: 61,
parent: 61,
menuName: '고객지원',
menuIcon: 'support-icon',
subMenu: [
{menuId: '62', parent: '61', menuName: '공지사항', path: PATHS.support.notice.list},
{menuId: '63', parent: '61', menuName: '자주묻는질문', path: PATHS.support.faq.list},
{menuId: '64', parent: '61', menuName: '1:1문의', path: PATHS.support.qna.list},
{menuId: 62, parent: 61, menuName: '공지사항', menuNameEng: '', programPath: PATHS.support.notice.list},
{menuId: 63, parent: 61, menuName: '자주묻는질문', menuNameEng: '', programPath: PATHS.support.faq.list},
{menuId: 64, parent: 61, menuName: '1:1문의', menuNameEng: '', programPath: PATHS.support.qna.list},
]
},
];

View File

@@ -36,8 +36,11 @@ export const FavoriteWrapper = ({
const [favoriteItems, setFavoriteItems] = useState<Array<UserFavorite>>([]);
const itemAdd: UserFavorite = {
img: IMAGE_ROOT + '/ico_menu_plus.svg',
title: '편집하기'
menuId: 0,
menuName: '편집하기',
menuNameEng: 'edit',
iconFilePath: IMAGE_ROOT + '/ico_menu_plus.svg',
programPath: '',
};
const onClickToFavoriteEdit = () => {
@@ -67,15 +70,15 @@ export const FavoriteWrapper = ({
<SwiperSlide key={ `favorite-slide-key-${i}` }>
<div
className="swiper-item"
onClick={ () => onClickToNavigate(favoriteItems[i]?.path) }
onClick={ () => onClickToNavigate(favoriteItems[i]?.programPath) }
>
<div className="swiper-icon coin-icon">
<img
src={ favoriteItems[i]?.img }
alt={ favoriteItems[i]?.title }
src={ favoriteItems[i]?.iconFilePath || '' }
alt={ favoriteItems[i]?.menuName }
/>
</div>
<span className="swiper-text">{ favoriteItems[i]?.title }</span>
<span className="swiper-text">{ favoriteItems[i]?.menuName }</span>
</div>
</SwiperSlide>
);
@@ -93,11 +96,11 @@ export const FavoriteWrapper = ({
>
<div className="swiper-icon coin-icon">
<img
src={ itemAdd.img }
alt={ itemAdd.title }
src={ itemAdd.iconFilePath || '' }
alt={ itemAdd.menuName }
/>
</div>
<span className="swiper-text">{ itemAdd.title }</span>
<span className="swiper-text">{ itemAdd.menuName }</span>
</div>
</SwiperSlide>
);

View File

@@ -1,11 +1,12 @@
import { RefObject } from "react";
export interface MenuItem {
menuId?: string;
parent?: string;
menuId?: number;
parent?: number;
menuName: string;
menuIcon?: string;
path?: string;
menuNameEng?: string;
iconFilePath?: string;
programPath?: string;
subMenu?: Array<MenuItem>
};

View File

@@ -8,13 +8,13 @@ import { PATHS } from '@/shared/constants/paths';
import { MenuItem } from '../model/types';
export interface MenuCategoryProps {
menuId?: string;
menuId?: number;
menuIcon?: string;
menuName?: string;
subMenu?: Array<MenuItem>;
setMenuOn?: (menuOn: boolean) => void;
editMode?: boolean;
setChangeMenuId: (menuId?: string) => void;
setChangeMenuId: (menuIdChecked?: string) => void;
buttonRefs: RefObject<Array<HTMLDivElement>>;
itemIndex: number;
};
@@ -34,7 +34,7 @@ export const MenuCategory = ({
const location = useLocation();
const [favoriteItems, setFavoriteItems] = useState<Array<UserFavorite>>([]);
const [menuIds, setMenuIds] = useState<Array<string | undefined>>([]);
const [menuIds, setMenuIds] = useState<Array<number | undefined>>([]);
const onClickToNavigate = (path?: string) => {
if(!!path && !!setMenuOn && !editMode){
@@ -45,9 +45,11 @@ export const MenuCategory = ({
const favoriteSetting = (
checked: boolean,
title?: string,
path?: string,
menuId?: string
menuId?: number,
menuName?: string,
menuNameEng?: string,
iconFilePath?: string,
programPath?: string,
) => {
let userFavorite = useStore.getState().UserStore.userFavorite;
let randomNum = Math.floor(Math.random() * 3) + 1;
@@ -55,10 +57,11 @@ export const MenuCategory = ({
userFavorite = [
...userFavorite,
{
title: title,
img: `${IMAGE_ROOT}/ico_menu_0${randomNum}.svg`,
path: path,
menuId: menuId
menuId: menuId,
menuName: menuName,
menuNameEng: menuNameEng,
iconFilePath: `${IMAGE_ROOT}/ico_menu_0${randomNum}.svg`,
programPath: programPath
}
];
}
@@ -78,7 +81,7 @@ export const MenuCategory = ({
const callFavoiteItems = () => {
let userFavorite = useStore.getState().UserStore.userFavorite;
setFavoriteItems(userFavorite);
let newArr: Array<string | undefined> = userFavorite.map((value, index) => {
let newArr: Array<number | undefined> = userFavorite.map((value, index) => {
return value.menuId;
});
setMenuIds(newArr);
@@ -88,15 +91,22 @@ export const MenuCategory = ({
callFavoiteItems();
}, []);
useEffect(() => {
if(menuIds.length > 0) {
// callShortcutSave();
}
}, [menuIds]);
const getMenuItems = () => {
let rs = [];
if(subMenu){
for(let i=0;i<subMenu.length;i++){
if(!!editMode){
if(!!editMode && subMenu[i] && subMenu[i]?.menuId){
rs.push(
<li
key={ `menu-item-key-${menuId}-${i}` }
onClick={ () => onClickToNavigate(subMenu[i]?.path) }
onClick={ () => onClickToNavigate(subMenu[i]?.programPath) }
>
<span>{ subMenu[i]?.menuName }</span>
<div className="check_box_scrap">
@@ -107,9 +117,11 @@ export const MenuCategory = ({
checked={ menuIds.includes(subMenu[i]?.menuId)? true: false }
onChange={ (e) => favoriteSetting(
e.target.checked,
subMenu[i]?.menuName,
subMenu[i]?.path,
subMenu[i]?.menuId
subMenu[i]?.menuId,
subMenu[i]?.menuName,
subMenu[i]?.menuNameEng,
subMenu[i]?.iconFilePath,
subMenu[i]?.programPath,
)}
/>
<label
@@ -124,7 +136,7 @@ export const MenuCategory = ({
rs.push(
<li
key={ `menu-item-key-${i}` }
onClick={ () => onClickToNavigate(subMenu[i]?.path) }
onClick={ () => onClickToNavigate(subMenu[i]?.programPath) }
>{ subMenu[i]?.menuName }</li>
);
}

View File

@@ -40,7 +40,7 @@ export interface SettlementsTransactionSummaryParams {
endDate: string;
paymentMethod: SettlementPaymentMethod;
transactionIds?: Array<string>;
pagination: DefaultRequestPagination
page: DefaultRequestPagination
};
export interface SettlementsTransactionSummaryResponse {
settlementAmount?: number;
@@ -57,7 +57,7 @@ export interface SettlementsTransactionListParams {
startDate: string;
endDate: string;
paymentMethod: SettlementPaymentMethod;
pagination: DefaultRequestPagination;
page: DefaultRequestPagination;
};
export interface SettlementsTransactionListResponse extends DefaulResponsePagination {
content: Array<SettlementsTransactionListContent>;
@@ -108,7 +108,7 @@ export interface SettlementsHistoryParams {
startDate: string;
endDate: string;
paymentMethod: SettlementPaymentMethod;
pagination: DefaultRequestPagination
page: DefaultRequestPagination
};
export interface SettlementsHistoryResponse extends DefaulResponsePagination {
content: Array<SettlementsHistoryContent>;
@@ -178,7 +178,7 @@ export interface ListDateGroupProps {
};
export interface ListItemProps extends SettlementsHistoryContent, SettlementsTransactionListContent {
periodType: SettlementPeriodType;
}
};
export interface AmountInfoWrapProps {
periodType: SettlementPeriodType;

View File

@@ -19,7 +19,7 @@ export const CalendarWrap = () => {
const userMid = useStore.getState().UserStore.mid;
const [mid, setMid] = useState<string>(userMid);
const [yearMonth, setYearMonth] = useState<string>(moment().format('YYYY-MM'));
const [yearMonth, setYearMonth] = useState<string>(moment().format('YYYYMM'));
const [totalCompletedAmount, setTotalCompletedAmount] = useState<number>(0);
const [totalScheduledAmount, setTotalScheduledAmount] = useState<number>(0);
const [scheduledList, setScheduledList] = useState<Array<SettlementDays | undefined>>([]);
@@ -62,11 +62,11 @@ export const CalendarWrap = () => {
setCompletedDateList(completedDateArr);
}
}).finally(() => {
let maxYearMonth = moment().format('YYYY-MM');
let maxYearMonthValue = moment(maxYearMonth).format('YYYYMM');
let newYearMonth = moment(yearMonth).add(1, 'month').format('YYYY-MM');
let newYearMonthValue = moment(newYearMonth).format('YYYYMM');
if(parseInt(newYearMonthValue) <= parseInt(maxYearMonthValue)){
let maxYearMonth = moment().format('YYYYMM');
// let maxYearMonthValue = moment(maxYearMonth).format('YYYYMM');
let newYearMonth = moment(yearMonth).add(1, 'month').format('YYYYMM');
// let newYearMonthValue = moment(newYearMonth).format('YYYYMM');
if(parseInt(newYearMonth) <= parseInt(maxYearMonth)){
setLastMonth(false);
}
else{
@@ -76,13 +76,13 @@ export const CalendarWrap = () => {
};
const onClickToMoveMonthPrev = () => {
let newYearMonth = moment(yearMonth).subtract(1, 'month').format('YYYY-MM');
let newYearMonth = moment(yearMonth).subtract(1, 'month').format('YYYYMM');
setYearMonth(newYearMonth);
};
const onClickToMoveMonthNext = () => {
let maxYearMonth = moment().format('YYYY-MM');
let maxYearMonth = moment().format('YYYYMM');
let maxYearMonthValue = moment(maxYearMonth).format('YYYYMM');
let newYearMonth = moment(yearMonth).add(1, 'month').format('YYYY-MM');
let newYearMonth = moment(yearMonth).add(1, 'month').format('YYYYMM');
let newYearMonthValue = moment(newYearMonth).format('YYYYMM');
if(parseInt(newYearMonthValue) <= parseInt(maxYearMonthValue)){
setYearMonth(newYearMonth);

View File

@@ -22,9 +22,13 @@ import {
SettlementPaymentMethod,
SettlementsHistoryContent,
ListDateGroupProps,
SettlementsTransactionListContent
SettlementsTransactionListContent,
SettlementsHistoryParams,
SettlementsHistoryResponse,
SettlementsHistorySummaryParams,
SettlementsHistorySummaryResponse
} from '../model/types';
import { SortTypeKeys } from '@/entities/common/model/types';
import { DefaultRequestPagination, SortTypeKeys } from '@/entities/common/model/types';
import { useStore } from '@/shared/model/store';
export interface ListWrapProps {
@@ -40,14 +44,14 @@ export const ListWrap = ({
const userMid = useStore.getState().UserStore.mid;
const [sortType, setSortType] = useState<SortTypeKeys>(SortTypeKeys.LATEST);
const [settlementDateListItems, setSettlementDateListItems] = useState<Record<string, Array<SettlementsHistoryContent>>>({});
const [transactionDatelistItems, setTransactionDateListItems] = useState<Record<string, Array<SettlementsTransactionListContent>>>({});
const [settlementDateListItems, setSettlementDateListItems] = useState<Array<SettlementsHistoryContent>>([]);
const [transactionDatelistItems, setTransactionDateListItems] = useState<Array<SettlementsTransactionListContent>>([]);
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 [periodType, setPeriodType] = useState<SettlementPeriodType>(SettlementPeriodType.SETTLEMENT_DATE);
const [startDate, setStartDate] = useState(startDateFromCalendar? moment(startDateFromCalendar).format('YYYY-MM-DD'): moment().format('YYYY-MM-DD'));
const [endDate, setEndDate] = useState(endDateFromCalendar? moment(endDateFromCalendar).format('YYYY-MM-DD'): moment().format('YYYY-MM-DD'));
const [startDate, setStartDate] = useState(startDateFromCalendar? moment(startDateFromCalendar).format('YYYYMMDD'): moment().format('YYYYMMDD'));
const [endDate, setEndDate] = useState(endDateFromCalendar? moment(endDateFromCalendar).format('YYYYMMDD'): moment().format('YYYYMMDD'));
const [paymentMethod, setPaymentMethod] = useState<SettlementPaymentMethod>(SettlementPaymentMethod.ALL);
const [settlementAmount, setSettlementAmount] = useState<number>();
@@ -61,7 +65,7 @@ export const ListWrap = ({
const [authFeeAmount, setAuthFeeAmount] = useState<number>();
const [vatAmount, setVatAmount] = useState<number>();
const [preSettlementCancelOffset, setPreSettlementCancelOffset] = useState<number>();
const [transactionIds, setTransactionIds] = useState<Array<string>>([]);
const [isOpenSummary, setIsOpenSummary] = useState<boolean>(false);
const { mutateAsync: settlementsHistory } = useSettlementsHistoryMutation();
@@ -83,24 +87,28 @@ export const ListWrap = ({
sortType?: SortTypeKeys,
val?: string
}) => {
let listSummaryParams = {
let listSummaryParams: SettlementsHistorySummaryParams = {
mid: mid,
periodType: periodType,
startDate: startDate,
endDate: endDate,
paymentMethod: paymentMethod,
};
pageParam.sortType = (option?.sortType)? option.sortType: sortType;
setPageParam(pageParam);
let listParams = {
let listParams: SettlementsHistoryParams = {
...listSummaryParams,
...{pagination: pageParam}
...{
page: pageParam
}
};
settlementsHistory(listParams).then((rs) => {
setSettlementDateListItems(assembleData(rs.content));
if(listParams.page){
listParams.page.sortType = (option?.sortType)? option.sortType: sortType;
setPageParam(listParams.page);
}
settlementsHistory(listParams).then((rs: SettlementsHistoryResponse) => {
setSettlementDateListItems(rs.content);
});
settlementsHistorySummary(listSummaryParams).then((rs) => {
settlementsHistorySummary(listSummaryParams).then((rs: SettlementsHistorySummaryResponse) => {
setSettlementAmount(rs.settlementAmount);
setTransactionAmount(rs.transactionAmount);
setPgFeeAmount(rs.pgFeeAmount);
@@ -113,27 +121,28 @@ export const ListWrap = ({
sortType?: SortTypeKeys,
val?: string
}) => {
pageParam.sortType = (option?.sortType)? option.sortType: sortType;
setPageParam(pageParam);
let params = {
mid: mid,
periodType: periodType,
startDate: startDate,
endDate: endDate,
paymentMethod: paymentMethod,
pagination: pageParam
page: pageParam
};
let summaryParams = {
...params,
transactionIds: [
"TXN_20250608_001",
"TXN_20250608_002"
]
...{
transactionIds: transactionIds
}
};
if(params.page){
params.page.sortType = (option?.sortType)? option.sortType: sortType;
setPageParam(params.page);
}
settlementsTransactionList(params).then((rs) => {
setTransactionDateListItems(assembleData(rs.content));
setTransactionDateListItems(rs.content);
});
settlementsTransactionSummary(summaryParams).then((rs) => {
setSettlementAmount(rs.settlementAmount);
@@ -145,22 +154,7 @@ export const ListWrap = ({
setPreSettlementCancelOffset(rs.preSettlementCancelOffset);
});
};
const assembleData = (content: Array<SettlementsHistoryContent>) => {
let data: any = {};
if(content && content.length > 0){
for(let i=0;i<content?.length;i++){
let groupDate = moment(content[i]?.settlementDate).format('YYYYMMDD');
if(!!groupDate && !data.hasOwnProperty(groupDate)){
data[groupDate] = [];
}
if(!!groupDate && data.hasOwnProperty(groupDate)){
data[groupDate].push(content[i]);
}
}
}
return data;
};
const onClickToSort = (sort: SortTypeKeys) => {
setSortType(sort);
if(periodType === SettlementPeriodType.SETTLEMENT_DATE){
@@ -185,40 +179,111 @@ export const ListWrap = ({
}
}
};
useEffect(() => {
setTransactionIds([
'TXN_20250608_001',
'TXN_20250608_002'
]);
}, []);
useEffect(() => {
callList();
}, [periodType]);
const getSettlementDateListDateGroup = () => {
let rs = [];
if(Object.keys(settlementDateListItems).length > 0){
for (const [key, value] of Object.entries(settlementDateListItems)) {
rs.push(
<ListDateGroup
key={ key }
periodType={ periodType }
date={ key }
items={ value }
></ListDateGroup>
);
let date = '';
let list: Array<SettlementsHistoryContent> = [];
if(settlementDateListItems){
}
for(let i=0;i<settlementDateListItems.length;i++){
let listItem = settlementDateListItems[i];
if(!!listItem){
let settlementDateTime = listItem?.settlementDate;
let settlementDate = settlementDateTime?.substr(0, 8);
if(settlementDateListItems[i] && settlementDate){
if(i === 0){
date = settlementDate;
}
if(date !== settlementDate){
date = settlementDate;
if(list.length > 0){
rs.push(
<ListDateGroup
key={ date + '-' + i }
periodType={ periodType }
date={ date }
items={ list }
></ListDateGroup>
);
}
list = [];
}
list.push(listItem);
}
}
}
if(list.length > 0){
rs.push(
<ListDateGroup
key={ date + '-last' }
periodType={ periodType }
date={ date }
items={ list }
></ListDateGroup>
);
}
return rs;
};
const getTransactionDateListDateGroup = () => {
let rs = [];
if(Object.keys(transactionDatelistItems).length > 0){
for (const [key, value] of Object.entries(transactionDatelistItems)) {
rs.push(
<ListDateGroup
key={ key }
periodType={ periodType }
date={ key }
items={ value }
></ListDateGroup>
);
let date = '';
let list: Array<SettlementsTransactionListContent> = [];
for(let i=0;i<transactionDatelistItems.length;i++){
let listItem = transactionDatelistItems[i];
if(!!listItem){
let settlementDateTime = listItem.settlementDate;
let settlementDate = settlementDateTime?.substr(0, 8);
if(settlementDate){
if(i === 0){
date = settlementDate;
}
if(date !== settlementDate){
date = settlementDate;
if(list.length > 0){
rs.push(
<ListDateGroup
key={ date + '-' + i }
periodType={ periodType }
date={ date }
items={ list }
></ListDateGroup>
);
}
list = [];
}
list.push(listItem);
}
}
}
if(list.length > 0){
rs.push(
<ListDateGroup
key={ date + '-last' }
periodType={ periodType }
date={ date }
items={ list }
></ListDateGroup>
);
}
return rs;
};
const onClickToOpenFilter = () => {

View File

@@ -0,0 +1,29 @@
import axios from 'axios';
import { API_URL_TRANSACTION } from '@/shared/api/api-url-transaction';
import { resultify } from '@/shared/lib/resultify';
import { CBDCAxiosError } from '@/shared/@types/error';
import {
CashReceiptReceiptDownloadParams,
CashReceiptReceiptDownloadResponse
} from '../model/types';
import {
useMutation,
UseMutationOptions
} from '@tanstack/react-query';
export const cashReceiptReceiptDownload = (params: CashReceiptReceiptDownloadParams) => {
return resultify(
axios.post<CashReceiptReceiptDownloadResponse>(API_URL_TRANSACTION.cashReceiptReceiptDownload(), params),
);
};
export const useCashReceiptReceiptDownloadMutation = (options?: UseMutationOptions<CashReceiptReceiptDownloadResponse, CBDCAxiosError, CashReceiptReceiptDownloadParams>) => {
const mutation = useMutation<CashReceiptReceiptDownloadResponse, CBDCAxiosError, CashReceiptReceiptDownloadParams>({
...options,
mutationFn: (params: CashReceiptReceiptDownloadParams) => cashReceiptReceiptDownload(params),
});
return {
...mutation,
};
};

View File

@@ -0,0 +1,29 @@
import axios from 'axios';
import { API_URL_TRANSACTION } from '@/shared/api/api-url-transaction';
import { resultify } from '@/shared/lib/resultify';
import { CBDCAxiosError } from '@/shared/@types/error';
import {
CashReceiptSummaryParams,
CashReceiptSummaryResponse
} from '../model/types';
import {
useMutation,
UseMutationOptions
} from '@tanstack/react-query';
export const cashReceiptSummary = (params: CashReceiptSummaryParams) => {
return resultify(
axios.post<CashReceiptSummaryResponse>(API_URL_TRANSACTION.cashReceiptSummary(), params),
);
};
export const useCashReceiptSummaryMutation = (options?: UseMutationOptions<CashReceiptSummaryResponse, CBDCAxiosError, CashReceiptSummaryParams>) => {
const mutation = useMutation<CashReceiptSummaryResponse, CBDCAxiosError, CashReceiptSummaryParams>({
...options,
mutationFn: (params: CashReceiptSummaryParams) => cashReceiptSummary(params),
});
return {
...mutation,
};
};

View File

@@ -3,13 +3,13 @@ import {
AllTransactionSearchCl,
AllTransactionServiceCode,
AllTransactionStatusCode,
CashReceiptPurposeType,
CashReceiptTransactionType,
CashReceiptProcessResult,
BillingPaymentMethod,
BillingProcessResult,
BillingRequestStatus,
BillingSearchType,
CashReceiptIssueStatus,
CashReceiptProcessResult,
CashReceiptPurposeType,
EscrowDeliveryStatus,
EscrowSearchType,
EscrowSettlementStatus
@@ -145,10 +145,10 @@ export const CashReceiptPurposeTypeBtnGroup = [
{name: '소득공제', value: CashReceiptPurposeType.INCOME_DEDUCTION},
{name: '지출증빙', value: CashReceiptPurposeType.EXPENSE_PROOF},
];
export const CashReceiptIssueStatusBtnGroup = [
{name: '전체', value: CashReceiptIssueStatus.ALL},
{name: '승인', value: CashReceiptIssueStatus.APPROVAL},
{name: '취소', value: CashReceiptIssueStatus.CANCEL},
export const CashReceiptTransactionTypeBtnGroup = [
{name: '전체', value: CashReceiptTransactionType.ALL},
{name: '승인', value: CashReceiptTransactionType.APPROVAL},
{name: '취소', value: CashReceiptTransactionType.CANCEL},
];
export const CashReceiptProcessResultBtnGroup = [
{name: '전체', value: CashReceiptProcessResult.ALL},

View File

@@ -1,4 +1,10 @@
import { DefaulResponsePagination, DefaultRequestPagination, SortTypeKeys, SuccessResult } from '@/entities/common/model/types';
import {
DefaulResponsePagination,
DefaultRequestPagination,
SortTypeKeys,
SuccessResult
} from '@/entities/common/model/types';
import { MerchantInfo } from '@/entities/payment/model/types';
export enum CancelTabKeys {
All = 'All',
@@ -68,7 +74,7 @@ export enum CashReceiptPurposeType {
INCOME_DEDUCTION = 'INCOME_DEDUCTION',
EXPENSE_PROOF = 'EXPENSE_PROOF',
};
export enum CashReceiptIssueStatus {
export enum CashReceiptTransactionType {
ALL = 'ALL',
APPROVAL = 'APPROVAL',
CANCEL = 'CANCEL',
@@ -82,6 +88,10 @@ export enum CashReceiptProcessResult {
REQUEST_FAIL = 'REQUEST_FAIL',
ISSUE_FAIL = 'ISSUE_FAIL',
};
export enum CashReceiptSearchNumberType {
APPROVAL_NUMBER = 'APPROVAL_NUMBER',
ISSUE_NUMBER = 'ISSUE_NUMBER'
};
export enum EscrowSearchType {
ALL = 'ALL',
ORDER_NUMBER = 'ORDER_NUMBER',
@@ -136,19 +146,19 @@ export interface ListDateGroupProps {
};
export interface AllTransactionListProps {
transactionCategory: TransactionCategory;
listItems: Array<any>;
listItems: Array<ListItemProps>;
};
export interface CashReceiptListProps {
transactionCategory: TransactionCategory;
listItems: Record<string, Array<ListItemProps>>
listItems: Array<ListItemProps>;
};
export interface EscrowListProps {
transactionCategory: TransactionCategory;
listItems: Record<string, Array<ListItemProps>>
listItems: Array<ListItemProps>;
};
export interface BillingListProps {
transactionCategory: TransactionCategory;
listItems: Record<string, Array<ListItemProps>>
listItems: Array<ListItemProps>;
};
export interface AllTransactionListItem {
tid?: string;
@@ -162,23 +172,25 @@ export interface AllTransactionListItem {
goodsAmount?: number;
};
export interface CashReceiptListItem {
id?: number;
amount?: number;
transactionDate?: string;
transactionTime?: string;
customerName?: string;
issueNumber?: number;
issueStatus?: string;
paymentMethod?: string;
issueNumber?: string;
approvalNumber?: string;
amount?: number;
processResult?: string;
transactionDateTime?: string;
paymentMethod?: string;
transactionType?: string;
};
export interface EscrowListItem {
id?: number;
tid?: string;
mid?: string;
transactionDateTime?: string;
transactionDate?: string;
transactionTime?: string;
customerName?: string;
issueNumber?: number;
issueNumber?: string;
transactionAmount?: number;
deliveryStatus?: string;
deliveryStatus?: EscrowDeliveryStatus;
settlementStatus?: string;
cancelStatus?: string;
};
@@ -190,16 +202,12 @@ export interface BillingItem {
billKey?: string;
tid?: string;
orderNumber?: string;
approvalNumber?: string;
approvalDate?: string;
transactionDateTime?: string;
transactionDate?: string;
transactionTime?: string;
transactionAmount?: number;
requestStatus?: string;
processResult?: string;
paymentMethod?: string;
installmentMonth?: string;
productName?: string;
buyerName?: string;
};
export interface AllTransactionListResponse extends DefaulResponsePagination {
content: Array<ListItemProps>;
@@ -212,12 +220,9 @@ export interface EscrowListResponse extends DefaulResponsePagination {
};
export interface BillingListResponse extends DefaulResponsePagination {
content: Array<ListItemProps>;
};
export interface AllTransactionListSummaryParams extends AllTransactionListParams {
}
export interface AllTransactionListSummaryParams extends AllTransactionListParams {}
export interface AllTransactionListSummaryResponse {
totalCount: number;
@@ -243,15 +248,36 @@ export interface AllTransactionListParams {
};
export interface CashReceiptListParams {
mid: string;
startDate: string;
endDate: string;
purposeType: CashReceiptPurposeType;
issueStatus: string;
processResult: string;
pagination: DefaultRequestPagination
mid?: string;
startDate?: string;
endDate?: string;
purposeType?: CashReceiptPurposeType;
transactionType?: CashReceiptTransactionType;
processResult?: CashReceiptProcessResult;
searchNumberType?: CashReceiptSearchNumberType;
searchNumber?: string;
page?: DefaultRequestPagination
};
export interface CashReceiptSummaryParams extends CashReceiptListParams {};
export interface CashReceiptSummaryResponse {
approvalCount: number;
approvalAmount: number;
cancelCount: number;
cancelAmount: number;
totalCount: number;
};
export interface CashReceiptReceiptDownloadParams {
approvalNumber: string;
};
export interface CashReceiptReceiptDownloadResponse {
issueInfo: IssueInfo;
merchantInfo: MerchantInfo;
transactionInfo: TransactionInfo;
amountInfo: AmountInfo;
customerInfo: CustomerInfo;
productInfo: ProductInfo;
};
export interface EscrowListParams {
mid?: string;
searchType?: string;
@@ -262,7 +288,7 @@ export interface EscrowListParams {
settlementStatus?: string;
minAmount?: number;
maxAmount?: number;
pagination?: DefaultRequestPagination;
page?: DefaultRequestPagination;
};
export interface BillingListParams {
@@ -276,7 +302,7 @@ export interface BillingListParams {
paymentMethod?: string;
minAmount?: number;
maxAmount?: number;
pagination?: DefaultRequestPagination
page?: DefaultRequestPagination
};
export interface AllTransactionDetailParams {
@@ -320,7 +346,7 @@ export interface ImportantInfo {
requestDate?: string;
cancelDate?: string;
goodsName?: string;
orderNumber?: string;
};
export interface PaymentInfo {
@@ -387,15 +413,24 @@ export interface PartCancelInfo {
};
export interface IssueInfo {
approvalNumber?: number;
issueNumber?: number;
issueDateTime?: string;
approvalNumber?: string;
issueDate?: string;
issueTime?: string;
purpose?: CashReceiptPurposeType;
paymentMethod?: string;
productName?: string;
transmissionStatus?: string;
transactionType?: string;
};
export interface CustomerInfo {
customerName: string;
customerIdentity: string;
};
export interface ProductInfo {
productName: string;
};
export interface DetailInfo {
cancelDate?: string;
cancelApprovalNumber?: number;
@@ -569,18 +604,22 @@ export interface AllTransactionFilterProps extends FilterProps {
serviceCodeOptions?: Array<Record<string, any>>;
};
export interface CashReceiptFilterProps extends FilterProps {
mid : string;
mid: string;
startDate: string;
endDate: string;
purposeType: CashReceiptPurposeType;
issueStatus: CashReceiptIssueStatus;
transactionType: CashReceiptTransactionType;
processResult: CashReceiptProcessResult;
searchNumberType: CashReceiptSearchNumberType;
searchNumber: string;
setMid: (mid: string) => void;
setStartDate: (startDate: string) => void;
setEndDate: (endDate: string) => void;
setPurposeType: (purposeType: CashReceiptPurposeType) => void;
setIssueStatus: (issueStatus: CashReceiptIssueStatus) => void;
setTransactionType: (issueStatus: CashReceiptTransactionType) => void;
setProcessResult: (processResult: CashReceiptProcessResult) => void;
setSearchNumberType: (searchNumberType: CashReceiptSearchNumberType) => void;
setSearchNumber: (searchNumber: string) => void;
};
export interface EscrowFilterProps extends FilterProps {
mid: string;

View File

@@ -1,4 +1,4 @@
import { AllTransactionListProps } from '../model/types';
import { AllTransactionListProps, ListItemProps } from '../model/types';
import { ListDateGroup } from './list-date-group';
export const AllTransactionList = ({
@@ -8,28 +8,33 @@ export const AllTransactionList = ({
const getListDateGroup = () => {
let rs = [];
let date = '';
let list = [];
let list: Array<ListItemProps> = [];
for(let i=0;i<listItems.length;i++){
let transactionDateTime = listItems[i].transactionDateTime;
let transactionDate = transactionDateTime.substr(0, 8);
if(i === 0){
date = transactionDate;
}
if(date !== transactionDate){
date = transactionDate;
if(list.length > 0){
rs.push(
<ListDateGroup
transactionCategory={ transactionCategory }
key={ date + '-' + i }
date={ date }
items={ list }
></ListDateGroup>
)
let items = listItems[i];
if(!!items){
let transactionDateTime = items.transactionDateTime;
let transactionDate = transactionDateTime?.substr(0, 8);
if(!!transactionDate){
if(i === 0){
date = transactionDate;
}
if(date !== transactionDate){
date = transactionDate;
if(list.length > 0){
rs.push(
<ListDateGroup
transactionCategory={ transactionCategory }
key={ date + '-' + i }
date={ date }
items={ list }
></ListDateGroup>
);
}
list = [];
}
list.push(items);
}
list = [];
}
list.push(listItems[i]);
}
if(list.length > 0){
rs.push(
@@ -39,7 +44,7 @@ export const AllTransactionList = ({
date={ date }
items={ list }
></ListDateGroup>
)
);
}
return rs;
};

View File

@@ -11,15 +11,43 @@ export const BillingList = ({
const getListDateGroup = () => {
let rs = [];
for (const [key, value] of Object.entries(listItems)) {
let date = '';
let list = [];
for(let i=0;i<listItems.length;i++){
let items = listItems[i];
if(!!items){
let transactionDate = items.transactionDate;
if(!!transactionDate){
if(i === 0){
date = transactionDate;
}
if(date !== transactionDate){
date = transactionDate;
if(list.length > 0){
rs.push(
<ListDateGroup
transactionCategory={ transactionCategory }
key={ date + '-' + i }
date={ date }
items={ list }
></ListDateGroup>
);
}
list = [];
}
list.push(items);
}
}
}
if(list.length > 0){
rs.push(
<ListDateGroup
transactionCategory={ transactionCategory }
key={ key }
date={ key }
items={ value }
key={ date + '-last' }
date={ date }
items={ list }
></ListDateGroup>
);
);
}
return rs;
};

View File

@@ -11,15 +11,43 @@ export const CashReceiptList = ({
const getListDateGroup = () => {
let rs = [];
for (const [key, value] of Object.entries(listItems)) {
let date = '';
let list = [];
for(let i=0;i<listItems.length;i++){
let items = listItems[i];
if(!!items){
let transactionDate = items.transactionDate;
if(!!transactionDate){
if(i === 0){
date = transactionDate;
}
if(date !== transactionDate){
date = transactionDate;
if(list.length > 0){
rs.push(
<ListDateGroup
transactionCategory={ transactionCategory }
key={ date + '-' + i }
date={ date }
items={ list }
></ListDateGroup>
);
}
list = [];
}
list.push(items);
}
}
}
if(list.length > 0){
rs.push(
<ListDateGroup
transactionCategory={ transactionCategory }
key={ key }
date={ key }
items={ value }
key={ date + '-last' }
date={ date }
items={ list }
></ListDateGroup>
);
);
}
return rs;
};
@@ -31,13 +59,13 @@ export const CashReceiptList = ({
return (
<>
<div className="transaction-list">
{ getListDateGroup() }
<div className="apply-row bottom-padding">
<button
className="btn-50 btn-blue flex-1"
onClick={ () => onClickToNavigate() }
></button>
</div>
{ getListDateGroup() }
</div>
<div className="apply-row">
<button
className="btn-50 btn-blue flex-1"
onClick={ () => onClickToNavigate() }
></button>
</div>
</>
);

View File

@@ -8,19 +8,47 @@ export const EscrowList = ({
const getListDateGroup = () => {
let rs = [];
for (const [key, value] of Object.entries(listItems)) {
let date = '';
let list = [];
for(let i=0;i<listItems.length;i++){
let items = listItems[i];
if(!!items){
let transactionDate = items.transactionDate;
if(!!transactionDate){
if(i === 0){
date = transactionDate;
}
if(date !== transactionDate){
date = transactionDate;
if(list.length > 0){
rs.push(
<ListDateGroup
transactionCategory={ transactionCategory }
key={ date + '-' + i }
date={ date }
items={ list }
></ListDateGroup>
);
}
list = [];
}
list.push(items);
}
}
}
if(list.length > 0){
rs.push(
<ListDateGroup
transactionCategory={ transactionCategory }
key={ key }
date={ key }
items={ value }
key={ date + '-last' }
date={ date }
items={ list }
></ListDateGroup>
);
);
}
return rs;
};
return (
<>
<div className="transaction-list">

View File

@@ -8,14 +8,15 @@ import { FilterCalendar } from '@/shared/ui/filter/calendar';
import { FilterButtonGroups } from '@/shared/ui/filter/button-groups';
import {
CashReceiptPurposeTypeBtnGroup,
CashReceiptIssueStatusBtnGroup,
CashReceiptTransactionTypeBtnGroup,
CashReceiptProcessResultBtnGroup
} from '@/entities/transaction/model/contant';
import {
CashReceiptFilterProps,
CashReceiptPurposeType,
CashReceiptIssueStatus,
CashReceiptProcessResult
CashReceiptTransactionType,
CashReceiptProcessResult,
CashReceiptSearchNumberType
} from '../../model/types';
import {
FilterMotionDuration,
@@ -31,22 +32,25 @@ export const CashReceiptFilter = ({
startDate,
endDate,
purposeType,
issueStatus,
transactionType,
processResult,
searchNumberType,
setMid,
setStartDate,
setEndDate,
setPurposeType,
setIssueStatus,
setProcessResult
setTransactionType,
setProcessResult,
setSearchNumberType
}: CashReceiptFilterProps) => {
const [filterMid, setFilterMid] = useState<string>(mid);
const [filterStartDate, setFilterStartDate] = useState<string>(startDate);
const [filterEndDate, setFilterEndDate] = useState<string>(endDate);
const [filterPurposeType, setFilterPurposeType] = useState<CashReceiptPurposeType>(purposeType);
const [filterIssueStatus, setFilterIssueStatus] = useState<CashReceiptIssueStatus>(issueStatus);
const [filterTransactionType, setFilterTransactionType] = useState<CashReceiptTransactionType>(transactionType);
const [filterProcessResult, setFilterProcessResult] = useState<CashReceiptProcessResult>(processResult);
const [filterSearchNumberType, setFilterSearchNumberType] = useState<CashReceiptSearchNumberType>(searchNumberType);
const [filterIssueType, setFilterIssueType] = useState<string>('');
const [filterIssueNumber, setFilterIssueNumber] = useState<string>('');
@@ -70,14 +74,14 @@ export const CashReceiptFilter = ({
setStartDate(filterStartDate);
setEndDate(filterEndDate);
setPurposeType(filterPurposeType);
setIssueStatus(filterIssueStatus);
setTransactionType(filterTransactionType);
setProcessResult(filterProcessResult);
onClickToClose();
};
useEffect(() => {
setFilterIssueStatus(issueStatus);
}, [issueStatus]);
setFilterTransactionType(transactionType);
}, [transactionType]);
return (
<>
@@ -129,9 +133,9 @@ export const CashReceiptFilter = ({
></FilterButtonGroups>
<FilterButtonGroups
title='거래구분'
activeValue={ filterIssueStatus }
btnGroups={ CashReceiptIssueStatusBtnGroup }
setter={ setFilterIssueStatus }
activeValue={ filterTransactionType }
btnGroups={ CashReceiptTransactionTypeBtnGroup }
setter={ setFilterTransactionType }
></FilterButtonGroups>
<FilterButtonGroups
title='진행상태'
@@ -141,8 +145,8 @@ export const CashReceiptFilter = ({
></FilterButtonGroups>
<FilterSelectInput
title='승인번호/발행번호'
selectValue={ filterIssueType }
selectSetter={ setFilterIssueType }
selectValue={ filterSearchNumberType }
selectSetter={ setFilterSearchNumberType }
selectOptions={ issueTypeOptionsGroup }
inputValue={ filterIssueNumber }
inputSetter={ setFilterIssueNumber }

View File

@@ -51,11 +51,9 @@ export const ListDateGroup = ({
serviceDetailName={ items[i]?.serviceDetailName }
goodsAmount={ items[i]?.goodsAmount }
id={ items[i]?.id }
amount={ items[i]?.amount }
customerName={ items[i]?.customerName }
issueNumber={ items[i]?.issueNumber }
issueStatus={ items[i]?.issueStatus }
paymentMethod={ items[i]?.paymentMethod }
processResult={ items[i]?.processResult }
transactionDateTime={ items[i]?.transactionDateTime }

View File

@@ -11,8 +11,8 @@ export const ListItem = ({
tid, mid, statusCode,
installmentMonth, serviceName, serviceCode,
serviceDetailName, goodsAmount,
id, amount, customerName, issueNumber,
issueStatus, paymentMethod, processResult,
amount, customerName, issueNumber,
paymentMethod, processResult,
transactionDateTime, transactionAmount,
deliveryStatus, settlementStatus,
cancelStatus, billKey, orderNumber
@@ -173,7 +173,7 @@ export const ListItem = ({
<div className="transaction-details">
<span>{ getTime() }</span>
<span className="separator">|</span>
<span>{ issueStatus }</span>
<span>{ }</span>
<span className="separator">|</span>
<span>{ paymentMethod }</span>
<span className="separator">|</span>

View File

@@ -19,11 +19,11 @@ export const IssueInfoSection = ({
</li>
<li className="kv-row">
<span className="k"></span>
<span className="v">{ issueInfo?.issueNumber }</span>
<span className="v">{ }</span>
</li>
<li className="kv-row">
<span className="k"></span>
<span className="v">{ moment(issueInfo?.issueDateTime).format('YYYY.MM.DD HH:mm:ss') }</span>
<span className="v">{ }</span>
</li>
<li className="kv-row">
<span className="k"></span>

View File

@@ -0,0 +1,29 @@
import axios from 'axios';
import { API_URL_USER } from '@/shared/api/api-url-user';
import { resultify } from '@/shared/lib/resultify';
import { CBDCAxiosError } from '@/shared/@types/error';
import {
ShortcutDefaultParams,
ShortcutDefaultResponse
} from '../model/types';
import {
useMutation,
UseMutationOptions
} from '@tanstack/react-query';
export const shortcutDefault = (params: ShortcutDefaultParams) => {
return resultify(
axios.post<ShortcutDefaultResponse>(API_URL_USER.shortcutDefault(), params),
);
};
export const useShortcutDefaultMutation = (options?: UseMutationOptions<ShortcutDefaultResponse, CBDCAxiosError, ShortcutDefaultParams>) => {
const mutation = useMutation<ShortcutDefaultResponse, CBDCAxiosError, ShortcutDefaultParams>({
...options,
mutationFn: (params: ShortcutDefaultParams) => shortcutDefault(params),
});
return {
...mutation,
};
};

View File

@@ -0,0 +1,29 @@
import axios from 'axios';
import { API_URL_USER } from '@/shared/api/api-url-user';
import { resultify } from '@/shared/lib/resultify';
import { CBDCAxiosError } from '@/shared/@types/error';
import {
ShortcutSaveParams,
ShortcutSaveResponse
} from '../model/types';
import {
useMutation,
UseMutationOptions
} from '@tanstack/react-query';
export const shortcutSave = (params: ShortcutSaveParams) => {
return resultify(
axios.post<ShortcutSaveResponse>(API_URL_USER.shortcutSave(), params),
);
};
export const useShortcutSaveMutation = (options?: UseMutationOptions<ShortcutSaveResponse, CBDCAxiosError, ShortcutSaveParams>) => {
const mutation = useMutation<ShortcutSaveResponse, CBDCAxiosError, ShortcutSaveParams>({
...options,
mutationFn: (params: ShortcutSaveParams) => shortcutSave(params),
});
return {
...mutation,
};
};

View File

@@ -0,0 +1,29 @@
import axios from 'axios';
import { API_URL_USER } from '@/shared/api/api-url-user';
import { resultify } from '@/shared/lib/resultify';
import { CBDCAxiosError } from '@/shared/@types/error';
import {
ShortcutUserParams,
ShortcutUserResponse
} from '../model/types';
import {
useMutation,
UseMutationOptions
} from '@tanstack/react-query';
export const shortcutUser = (params: ShortcutUserParams) => {
return resultify(
axios.post<ShortcutUserResponse>(API_URL_USER.shortcutUser(), params),
);
};
export const useShortcutUserMutation = (options?: UseMutationOptions<ShortcutUserResponse, CBDCAxiosError, ShortcutUserParams>) => {
const mutation = useMutation<ShortcutUserResponse, CBDCAxiosError, ShortcutUserParams>({
...options,
mutationFn: (params: ShortcutUserParams) => shortcutUser(params),
});
return {
...mutation,
};
};

View File

@@ -29,10 +29,12 @@ export interface LoginResponse {
};
export interface UserFavorite {
title?: string;
img?: string;
path?: string;
menuId?: string;
seq?: number;
menuId?: number;
menuName?: string;
menuNameEng?: string;
iconFilePath?: string | null;
programPath?: string;
};
export interface UserInfo extends LoginResponse {
status: boolean;
@@ -221,9 +223,40 @@ export interface AuthMethodItem {
authMethodType: string;
sequence: number;
content: string;
}
};
export interface UserAuthMethodData {
emails: Array<AuthMethodItem>;
phones: Array<AuthMethodItem>;
}
};
export interface ShortcutDefaultParams {
usrid: string;
};
export interface ShortcutDefaultResponse {
shortcuts: Array<Shortcuts>;
usingDefault: boolean;
};
export interface Shortcuts {
seq: number;
menuId: number;
menuName: string;
menuNameEng: string;
iconFilePath: string;
programPath: string;
};
export interface ShortcutSaveParams {
usrid: string;
isDefault: boolean;
menuIds: Array<number | undefined>;
};
export interface ShortcutSaveResponse {
};
export interface ShortcutUserParams {
usrid: string;
};
export interface ShortcutUserResponse {
shortcuts: Array<Shortcuts>;
usingDefault: boolean;
};

View File

@@ -5,14 +5,14 @@ import { IMAGE_ROOT } from '@/shared/constants/common';
import { PATHS } from '@/shared/constants/paths';
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { AllTransactionList } from '@/entities/transaction/ui/all-transaction-list';
import { AllTransactionListItem, TransactionCategory, AllTransactionStatusCode, AllTransactionServiceCode, AllTransactionSearchCl, AllTransactionListParams } from '@/entities/transaction/model/types';
import { AllTransactionListItem, TransactionCategory, AllTransactionStatusCode, AllTransactionServiceCode, AllTransactionSearchCl, AllTransactionListParams, ListItemProps, AllTransactionListSummaryParams, AllTransactionListResponse, AllTransactionListSummaryResponse } from '@/entities/transaction/model/types';
import { useAllTransactionListMutation } from '@/entities/transaction/api/use-all-transaction-list-mutation';
import { useAllTransactionListSummaryMutation } from '@/entities/transaction/api/use-all-transaction-list-summary-mutation';
import { useDownloadExcelMutation } from '@/entities/transaction/api/use-download-excel-mutation';
import { DEFAULT_PAGE_PARAM } from '@/entities/common/model/constant';
import { AllTransactionFilter } from '@/entities/transaction/ui/filter/all-transaction-filter';
import { SortTypeBox } from '@/entities/common/ui/sort-type-box';
import { SortTypeKeys, HeaderType } from '@/entities/common/model/types';
import { SortTypeKeys, HeaderType, DefaultRequestPagination } from '@/entities/common/model/types';
import {
useSetOnBack,
useSetHeaderTitle,
@@ -29,9 +29,9 @@ export const AllTransactionListPage = () => {
const [serviceCodeOptions, setServiceCodeOptions] = useState<Array<Record<string, any>>>();
const [sortType, setSortType] = useState<SortTypeKeys>(SortTypeKeys.LATEST);
const [listItems, setListItems] = useState<Array<any>>([]);
const [listItems, setListItems] = useState<Array<ListItemProps>>([]);
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 [moid, setMoid] = useState<string>('');
const [tid, setTid] = useState<string>('');
@@ -69,7 +69,7 @@ export const AllTransactionListPage = () => {
sortType?: SortTypeKeys,
val?: string
}) => {
let listSummaryParams: AllTransactionListParams = {
let listSummaryParams: AllTransactionListSummaryParams = {
moid: moid,
tid: tid,
fromDate: fromDate,
@@ -86,18 +86,23 @@ export const AllTransactionListPage = () => {
searchValue: searchValue,
sortType: sortType
};
pageParam.sortType = (option?.sortType)? option.sortType: sortType;
setPageParam(pageParam);
let listParams = {
let listParams: AllTransactionListParams = {
...listSummaryParams,
...{page: pageParam}
...{
page: pageParam
}
};
allTransactionList(listParams).then((rs) => {
if(listParams.page){
listParams.page.sortType = (option?.sortType)? option.sortType: sortType;
setPageParam(listParams.page);
}
allTransactionList(listParams).then((rs: AllTransactionListResponse) => {
console.log(rs.content)
setListItems(rs.content);
});
allTransactionListSummary(listSummaryParams).then((rs) => {
allTransactionListSummary(listSummaryParams).then((rs: AllTransactionListSummaryResponse) => {
setTotalAmount(rs.totalAmount);
setTotalCount(rs.totalCount);
});

View File

@@ -5,14 +5,14 @@ import { IMAGE_ROOT } from '@/shared/constants/common';
import { PATHS } from '@/shared/constants/paths';
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { BillingList } from '@/entities/transaction/ui/billing-list';
import { BillingListItem, TransactionCategory, BillingRequestStatus, BillingProcessResult, BillingPaymentMethod, BillingSearchType } from '@/entities/transaction/model/types';
import { BillingListItem, TransactionCategory, BillingRequestStatus, BillingProcessResult, BillingPaymentMethod, BillingSearchType, ListItemProps, BillingListParams, BillingListResponse } from '@/entities/transaction/model/types';
import { useBillingListMutation } from '@/entities/transaction/api/use-billing-list-mutation';
import { useDownloadExcelMutation } from '@/entities/transaction/api/use-download-excel-mutation';
import { DEFAULT_PAGE_PARAM } from '@/entities/common/model/constant';
import { BillingFilter } from '@/entities/transaction/ui/filter/billing-filter';
import { SortTypeBox } from '@/entities/common/ui/sort-type-box';
import { BillingRequestStatusBtnGroup } from '@/entities/transaction/model/contant';
import { SortTypeKeys, HeaderType } from '@/entities/common/model/types';
import { SortTypeKeys, HeaderType, DefaultRequestPagination } from '@/entities/common/model/types';
import {
useSetOnBack,
useSetHeaderTitle,
@@ -26,9 +26,9 @@ export const BillingListPage = () => {
const userInfo = useStore((state) => state.UserStore.userInfo);
const [sortType, setSortType] = useState<SortTypeKeys>(SortTypeKeys.LATEST);
const [listItems, setListItems] = useState({});
const [listItems, setListItems] = useState<Array<ListItemProps>>([]);
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 [searchType, setSearchType] = useState<BillingSearchType>(BillingSearchType.ALL);
const [searchKeyword, setSearchKeyword] = useState<string>('');
@@ -55,8 +55,6 @@ export const BillingListPage = () => {
sortType?: SortTypeKeys,
val?: string
}) => {
pageParam.sortType = (option?.sortType)? option.sortType: sortType;
setPageParam(pageParam);
let newMinAmount = minAmount;
if(!!minAmount && typeof(minAmount) === 'string'){
newMinAmount = parseInt(minAmount);
@@ -65,7 +63,7 @@ export const BillingListPage = () => {
if(!!maxAmount && typeof(maxAmount) === 'string'){
newMaxAmount = parseInt(maxAmount);
}
let listParams = {
let listParams: BillingListParams = {
mid: mid,
searchType: searchType,
searchKeyword: searchKeyword,
@@ -76,30 +74,18 @@ export const BillingListPage = () => {
paymentMethod: paymentMethod,
minAmount: newMinAmount,
maxAmount: newMaxAmount,
pagination: pageParam
};
billingList(listParams).then((rs) => {
setListItems(assembleData(rs.content));
page: pageParam
};
if(listParams.page){
listParams.page.sortType = (option?.sortType)? option.sortType: sortType;
setPageParam(listParams.page);
}
billingList(listParams).then((rs: BillingListResponse) => {
setListItems(rs.content);
});
}
const assembleData = (content: Array<BillingListItem>) => {
let data: any = {};
if(content && content.length > 0){
for(let i=0;i<content?.length;i++){
let groupDate = moment(content[i]?.transactionDateTime).format('YYYYMMDD');
if(!!groupDate && !data.hasOwnProperty(groupDate)){
data[groupDate] = [];
}
if(!!groupDate && data.hasOwnProperty(groupDate)){
data[groupDate].push(content[i]);
}
}
}
return data;
};
const onClickToOpenFilter = () => {
setFilterOn(!filterOn);
};

View File

@@ -5,36 +5,44 @@ import { IMAGE_ROOT } from '@/shared/constants/common';
import { PATHS } from '@/shared/constants/paths';
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { CashReceiptList } from '@/entities/transaction/ui/cash-receipt-list';
import { CashReceiptListItem, TransactionCategory, CashReceiptPurposeType, CashReceiptIssueStatus, CashReceiptProcessResult } from '@/entities/transaction/model/types';
import { CashReceiptListItem, TransactionCategory, CashReceiptPurposeType, CashReceiptProcessResult, ListItemProps, CashReceiptListParams, CashReceiptTransactionType, CashReceiptSearchNumberType, CashReceiptSummaryParams, CashReceiptListResponse, CashReceiptSummaryResponse } from '@/entities/transaction/model/types';
import { useCashReceiptListMutation } from '@/entities/transaction/api/use-cash-receipt-list-mutation';
import { useDownloadExcelMutation } from '@/entities/transaction/api/use-download-excel-mutation';
import { DEFAULT_PAGE_PARAM } from '@/entities/common/model/constant';
import { CashReceiptFilter } from '@/entities/transaction/ui/filter/cash-receipt-filter';
import { SortTypeBox } from '@/entities/common/ui/sort-type-box';
import { SortTypeKeys, HeaderType } from '@/entities/common/model/types';
import { SortTypeKeys, HeaderType, DefaultRequestPagination } from '@/entities/common/model/types';
import {
useSetOnBack,
useSetHeaderTitle,
useSetHeaderType,
useSetFooterMode
} from '@/widgets/sub-layout/use-sub-layout';
import { CashReceiptIssueStatusBtnGroup } from '@/entities/transaction/model/contant';
import { CashReceiptTransactionTypeBtnGroup } from '@/entities/transaction/model/contant';
import { useStore } from '@/shared/model/store';
import { useCashReceiptSummaryMutation } from '@/entities/transaction/api/use-cash-receipt-summary-mutation';
export const CashReceiptListPage = () => {
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<ListItemProps>>([]);
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 [startDate, setStartDate] = useState(moment().subtract(1, 'month').format('YYYY-MM-DD'));
const [endDate, setEndDate] = useState(moment().format('YYYY-MM-DD'));
const [startDate, setStartDate] = useState(moment().subtract(1, 'month').format('YYYYMMDD'));
const [endDate, setEndDate] = useState(moment().format('YYYYMMDD'));
const [purposeType, setPurposeType] = useState<CashReceiptPurposeType>(CashReceiptPurposeType.ALL);
const [issueStatus, setIssueStatus] = useState<CashReceiptIssueStatus>(CashReceiptIssueStatus.ALL);
const [transactionType, setTransactionType] = useState<CashReceiptTransactionType>(CashReceiptTransactionType.ALL);
const [processResult, setProcessResult] = useState<CashReceiptProcessResult>(CashReceiptProcessResult.ALL);
const [searchNumberType, setSearchNumberType] = useState<CashReceiptSearchNumberType>(CashReceiptSearchNumberType.APPROVAL_NUMBER);
const [searchNumber, setSearchNumber] = useState<string>('');
const [approvalCount, setApprovalCount] = useState<number>(0);
const [approvalAmount, setApprovalAmount] = useState<number>(0);
const [cancelCount, setCancelCount] = useState<number>(0);
const [cancelAmount, setCancelAmount] = useState<number>(0);
const [totalCount, setTotalCount] = useState<number>(0);
useSetHeaderTitle('현금영수증');
useSetHeaderType(HeaderType.LeftArrow);
@@ -44,47 +52,48 @@ export const CashReceiptListPage = () => {
useSetFooterMode(false);
const { mutateAsync: cashReceiptList } = useCashReceiptListMutation();
const { mutateAsync: cashReceiptSummary } = useCashReceiptSummaryMutation();
const { mutateAsync: downloadExcel } = useDownloadExcelMutation();
const callList = (option?: {
sortType?: SortTypeKeys,
val?: string
}) => {
pageParam.sortType = (option?.sortType)? option.sortType: sortType;
setPageParam(pageParam);
let listParams = {
let listSummaryParams: CashReceiptSummaryParams = {
mid: mid,
startDate: startDate,
endDate: endDate,
purposeType: purposeType,
issueStatus: issueStatus,
transactionType: transactionType,
processResult: processResult,
pagination: pageParam
searchNumberType: searchNumberType,
searchNumber: searchNumber,
page: pageParam
};
let listParams: CashReceiptListParams = {
...listSummaryParams,
...{
page: pageParam
}
};
if(listParams.page){
listParams.page.sortType = (option?.sortType)? option.sortType: sortType;
setPageParam(listParams.page);
}
cashReceiptList(listParams).then((rs) => {
console.log(rs);
setListItems(assembleData(rs.content));
cashReceiptList(listParams).then((rs: CashReceiptListResponse) => {
setListItems(rs.content);
});
cashReceiptSummary(listSummaryParams).then((rs: CashReceiptSummaryResponse) => {
setApprovalCount(rs.approvalCount);
setApprovalAmount(rs.approvalAmount);
setCancelCount(rs.cancelCount);
setCancelAmount(rs.cancelAmount);
setTotalCount(rs.totalCount);
});
};
const assembleData = (content: Array<CashReceiptListItem>) => {
let data: any = {};
if(content && content.length > 0){
for (let i=0;i<content?.length;i++){
let groupDate = moment(content[i]?.transactionDateTime).format('YYYYMMDD');
if(!!groupDate && !data.hasOwnProperty(groupDate)){
data[groupDate] = [];
}
if(!!groupDate && data.hasOwnProperty(groupDate)){
data[groupDate].push(content[i]);
}
}
}
return data;
};
const onClickToOpenFilter = () => {
setFilterOn(!filterOn);
};
@@ -103,8 +112,8 @@ export const CashReceiptListPage = () => {
});
};
const onClickToIssueStatus = (val: CashReceiptIssueStatus) => {
setIssueStatus(val);
const onClickToTransactionType = (val: CashReceiptTransactionType) => {
setTransactionType(val);
callList({
val: val
});
@@ -113,6 +122,14 @@ export const CashReceiptListPage = () => {
useEffect(() => {
callList();
}, []);
useEffect(() => {
callList();
}, [
mid, startDate, endDate,
purposeType, transactionType,
processResult, searchNumberType,
searchNumber
]);
return (
<>
@@ -149,7 +166,7 @@ export const CashReceiptListPage = () => {
<span className="label"></span>
<strong className="amount22">
<NumericFormat
value={ 83745200 }
value={ approvalAmount }
thousandSeparator
displayType="text"
suffix='원'
@@ -157,7 +174,7 @@ export const CashReceiptListPage = () => {
</strong>
<span className="count">
<NumericFormat
value={ 2745 }
value={ approvalCount }
thousandSeparator
displayType="text"
prefix='('
@@ -169,7 +186,7 @@ export const CashReceiptListPage = () => {
<span className="label"></span>
<strong className="amount19">
<NumericFormat
value={ 534407 }
value={ cancelAmount }
thousandSeparator
displayType="text"
suffix='원'
@@ -177,7 +194,7 @@ export const CashReceiptListPage = () => {
</strong>
<span className="count">
<NumericFormat
value={ 32 }
value={ cancelCount }
thousandSeparator
displayType="text"
prefix='('
@@ -196,11 +213,11 @@ export const CashReceiptListPage = () => {
<div>
<div className="full-menu-keywords no-padding">
{
CashReceiptIssueStatusBtnGroup.map((value, index) => (
CashReceiptTransactionTypeBtnGroup.map((value, index) => (
<span
key={`key-service-code=${index}`}
className={`keyword-tag ${(issueStatus === value.value) ? 'active' : ''}`}
onClick={() => onClickToIssueStatus(value.value)}
className={`keyword-tag ${(transactionType === value.value) ? 'active' : ''}`}
onClick={() => onClickToTransactionType(value.value)}
>{value.name}</span>
))
}
@@ -221,14 +238,18 @@ export const CashReceiptListPage = () => {
startDate={ startDate }
endDate={ endDate }
purposeType={ purposeType }
issueStatus={ issueStatus }
transactionType={ transactionType }
processResult={ processResult }
searchNumberType={ searchNumberType }
searchNumber={ searchNumber }
setMid={ setMid }
setStartDate={ setStartDate }
setEndDate={ setEndDate }
setPurposeType={ setPurposeType }
setIssueStatus={ setIssueStatus }
setTransactionType={ setTransactionType }
setProcessResult={ setProcessResult }
setSearchNumberType={ setSearchNumberType }
setSearchNumber={ setSearchNumber }
></CashReceiptFilter>
</>
);

View File

@@ -5,14 +5,14 @@ import { IMAGE_ROOT } from '@/shared/constants/common';
import { PATHS } from '@/shared/constants/paths';
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { EscrowList } from '@/entities/transaction/ui/escrow-list';
import { EscrowListItem, TransactionCategory, EscrowDeliveryStatus, EscrowSearchType, EscrowSettlementStatus } from '@/entities/transaction/model/types';
import { EscrowListItem, TransactionCategory, EscrowDeliveryStatus, EscrowSearchType, EscrowSettlementStatus, ListItemProps } from '@/entities/transaction/model/types';
import { useEscrowListMutation } from '@/entities/transaction/api/use-escrow-list-mutation';
import { useDownloadExcelMutation } from '@/entities/transaction/api/use-download-excel-mutation';
import { DEFAULT_PAGE_PARAM } from '@/entities/common/model/constant';
import { EscrowFilter } from '@/entities/transaction/ui/filter/escrow-filter';
import { EscrowDeliveryStatusBtnGroup } from '@/entities/transaction/model/contant';
import { SortTypeBox } from '@/entities/common/ui/sort-type-box';
import { SortTypeKeys, HeaderType } from '@/entities/common/model/types';
import { SortTypeKeys, HeaderType, DefaultRequestPagination } from '@/entities/common/model/types';
import {
useSetOnBack,
useSetHeaderTitle,
@@ -26,9 +26,9 @@ export const EscrowListPage = () => {
const userMid = useStore.getState().UserStore.mid;
const [sortType, setSortType] = useState<SortTypeKeys>(SortTypeKeys.LATEST);
const [listItems, setListItems] = useState({});
const [listItems, setListItems] = useState<Array<ListItemProps>>([]);
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 [searchType, setSearchType] = useState<EscrowSearchType>(EscrowSearchType.ALL);
const [searchKeyword, setSearchKeyword] = useState<string>('');
@@ -54,8 +54,6 @@ export const EscrowListPage = () => {
sortType?: SortTypeKeys,
val?: string
}) => {
pageParam.sortType = (option?.sortType)? option.sortType: sortType;
setPageParam(pageParam);
let newMinAmount = minAmount;
if(!!minAmount && typeof(minAmount) === 'string'){
newMinAmount = parseInt(minAmount);
@@ -74,30 +72,18 @@ export const EscrowListPage = () => {
settlementStatus: settlementStatus,
minAmount: newMinAmount,
maxAmount: newMaxAmount,
pagination: pageParam
page: pageParam
};
if(listParams.page){
listParams.page.sortType = (option?.sortType)? option.sortType: sortType;
setPageParam(listParams.page);
}
escrowList(listParams).then((rs) => {
setListItems(assembleData(rs.content));
setListItems(rs.content);
});
};
const assembleData = (content: Array<EscrowListItem>) => {
let data: any = {};
if(content && content.length > 0){
for(let i=0;i<content?.length;i++){
let groupDate = moment(content[i]?.transactionDateTime).format('YYYYMMDD');
if(!!groupDate && !data.hasOwnProperty(groupDate)){
data[groupDate] = [];
}
if(!!groupDate && data.hasOwnProperty(groupDate)){
data[groupDate].push(content[i]);
}
}
}
return data;
};
const onClickToOpenFilter = () => {
setFilterOn(!filterOn);
};

View File

@@ -41,6 +41,10 @@ export const API_URL_TRANSACTION = {
// POST: 현금영수증 목록 조회
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/cash-receipt/list`;
},
cashReceiptSummary: () => {
// POST: 현금영수증 합계 조회
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/cash-receipt/summary`;
},
cashReceiptDetail: () => {
// POST: 현금영수증 상세 조회
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/cash-receipt/detail`;
@@ -53,6 +57,10 @@ export const API_URL_TRANSACTION = {
// POST: 현금영수증 용도 변경
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/cash-receipt/manual/issue`;
},
cashReceiptReceiptDownload: () => {
// POST: 현금영수증 거래확인서 다운로드
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/cash-receipt/receipt/download`;
},
/* Escro Management - 에스크로 API */
escrowList: () => {

View File

@@ -1,47 +1,61 @@
import {
API_BASE_URL,
API_URL_KEY,
} from './../constants/url';
API_BASE_URL,
API_URL_KEY,
} from './../constants/url';
export const API_URL_USER = {
userExistsUserid: (usrid: string) => {
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/exists/${usrid}`;
},
userCreate: () => {
// 사용자 추가
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/create`;
},
findUser: () => {
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/find`;
},
existsUserid: () => {
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/exists/userid`;
},
deleteUser: () => {
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/delete`;
},
createUser: () => {
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/create`;
},
findAuthMethod: () => {
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/tfa/find`;
},
modifyAuthMethod: () => {
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/tfa/modify`;
},
updatePermissions: () => {
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/permissions/update`;
},
findMenuPermissions: () => {
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/menu/permissions`;
},
saveMenuPermissions: () => {
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/menu/permissions/save`;
},
changePassword: () => {
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/password`;
},
userChangeCancelPassword: () => {
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/cancle/change`;
}
userExistsUserid: (usrid: string) => {
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/exists/${usrid}`;
},
userCreate: () => {
// 사용자 추가
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/create`;
},
findUser: () => {
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/find`;
},
existsUserid: () => {
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/exists/userid`;
},
deleteUser: () => {
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/delete`;
},
createUser: () => {
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/create`;
},
findAuthMethod: () => {
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/tfa/find`;
},
modifyAuthMethod: () => {
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/tfa/modify`;
},
updatePermissions: () => {
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/permissions/update`;
},
findMenuPermissions: () => {
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/menu/permissions`;
},
saveMenuPermissions: () => {
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/menu/permissions/save`;
},
changePassword: () => {
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/password`;
},
userChangeCancelPassword: () => {
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/user/cancle/change`;
},
// 바로가기 메뉴 API
shortcutDefault: () => {
// 기본 바로가기 메뉴 조회
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/shortcut/default`;
},
shortcutSave: () => {
// 바로가기 메뉴 저장
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/shortcut/save`;
},
shortcutUser: () => {
// 사용자 바로가기 메뉴 조회
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/shortcut/user`;
}
}

View File

@@ -362,6 +362,8 @@ export const PATHS: RouteNamesType = {
base: generatePath(ROUTE_NAMES.alarm.base),
list: generatePath(ROUTE_NAMES.alarm.base, ROUTE_NAMES.alarm.list),
},
xkeypad: generatePath(ROUTE_NAMES.xkeypad),
xkeypadSample: generatePath(ROUTE_NAMES.xkeypadSample),
};
export const BACK_BLOCKED_PATHS = {

View File

@@ -295,12 +295,6 @@ footer {
justify-content: space-around;
align-items: center;
z-index: 1000;
border-top: 0.1px solid var(--color-E5E5E5);
will-change: transform;
}
.bottom-tabbar.snapping {
transition: transform 0.3s cubic-bezier(0.4, 0.0, 0.2, 1);
}
.tab-button {
@@ -1267,7 +1261,7 @@ input[type="radio"] {
border-radius: 50%;
background: var(--color-CCCCCC);
cursor: pointer;
transition: all 0.4s ease;
transition: all 0.2s ease;
}
.banner-dot.active {
@@ -1499,7 +1493,7 @@ input[type="radio"] {
}
.option-list {
padding: 0 10px;
padding: 0 10px 10px 10px;
display: flex;
flex-direction: column;
gap: 16px;
@@ -2397,13 +2391,13 @@ div .credit-period {
bottom: 0;
left: 0;
right: 0;
padding: 20px 26px calc(env(safe-area-inset-bottom, 0px) + 26px) 26px;
padding: 20px 26px 16px 26px;
z-index: 500;
background: var(--color-white);
}
.apply-row.bottom-padding {
bottom: calc(env(safe-area-inset-bottom) + 26px) !important;
bottom: 70px !important;
}
.apply-row.two-button button:first-child {
@@ -2902,6 +2896,10 @@ div .credit-period {
width: 100%;
}
.bottomsheet-content.expand {
margin-bottom: 0;
}
.bottom-btn {
display: flex;
justify-content: space-between;
@@ -4155,6 +4153,14 @@ ul.txn-amount-detail li span:last-child {
font-size: 5px;
}
.label.desc.dot {
padding-left: 23px;
}
.label.desc.dot::before {
left: 8px;
}
.kv-row.pl-10 {
padding-left: 15px;
}
@@ -5626,8 +5632,8 @@ ul.txn-amount-detail li span:last-child {
display: flex;
align-items: center;
gap: 10px;
height: 40px;
padding: 0;
padding-bottom: 16px;
}
.faq-search .ic16.search {
position: absolute;
@@ -5646,9 +5652,14 @@ ul.txn-amount-detail li span:last-child {
}
.faq-filter {
display: flex;
align-items: center;
justify-content: space-between;
height: 40px;
padding: 0 12px;
border: 1px solid #D9D9D9;
border-radius: 8px;
margin-top: 10px;
}
.faq-filter .text {
font-size: 15px;
color: var(--color-2D3436);
@@ -5954,228 +5965,140 @@ ul.txn-amount-detail li span:last-child {
box-sizing: border-box;
}
/* 분할승인 상세 */
.separate-approval-main {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
/* 82 bottomsheet - 세금 계산서 세부내역 조회 (아코디언 펼침) */
.bottomsheet .tax-detail-accordion {
padding: 0;
}
.separate-approval-main .tab-content {
height: 100%;
}
.separate-approval-main .tab-pane.sub.active {
height: 100%;
.bottomsheet .tax-detail-accordion .summary {
display: flex;
flex-direction: column;
}
.separate-approval-section {
padding: 0;
flex: 1;
overflow-y: auto;
overflow-x: hidden;
-webkit-overflow-scrolling: touch;
}
.approval-cards-wrapper {
gap: 16px;
padding-bottom: 20px;
}
.separate-approval-main .apply-row.two-button {
flex-shrink: 0;
position: sticky;
bottom: 0;
background: white;
z-index: 10;
}
/* 분할승인 안내 박스 */
.approval-notice-box {
background: var(--color-white);
padding: 8px;
margin-bottom: 16px;
border-radius: 12px;
flex-shrink: 0;
}
.approval-notice-box p {
font-size: var(--fs-15);
color: var(--color-666666);
line-height: 1.5;
margin: 0;
}
.approval-notice-box p + p {
margin-top: 4px;
}
/* 분할승인 카드 */
.approval-card {
position: relative;
background: var(--color-white);
border: 2px solid var(--color-d6d6d6);
border-radius: 16px;
padding: 16px;
margin-bottom: 16px;
transition: all 0.4s ease;
}
.approval-card.selected {
border-color: var(--color-3E6AFC);
background: var(--color-F4F8FF);
}
/* 분할승인 체크박스 */
.approval-card .card-checkbox {
display: block !important;
position: absolute;
top: 16px;
left: 16px;
width: 24px;
height: 24px;
margin: 0;
padding: 0;
appearance: none;
border: 2px solid var(--color-d6d6d6);
border-radius: 5px;
background-color: var(--color-white);
cursor: pointer;
outline: none;
box-sizing: border-box;
z-index: 1;
}
.approval-card .card-checkbox:focus,
.approval-card .card-checkbox:active {
outline: none !important;
box-shadow: none !important;
border-color: var(--color-d6d6d6);
}
.approval-card .card-checkbox:checked {
background-color: var(--color-3E6AFC);
border-color: var(--color-3E6AFC);
outline: none;
}
.approval-card .card-checkbox:checked::after {
content: '';
position: absolute;
left: 5px;
top: 2px;
width: 6px;
height: 11px;
border: solid white;
border-width: 0 2px 2px 0;
transform: rotate(45deg);
}
/* 분할승인 카드 헤더 */
.approval-card .card-header {
.bottomsheet .tax-detail-accordion .summary .row {
display: flex;
gap: 10px;
align-items: center;
gap: 8px;
margin-bottom: 16px;
padding-bottom: 12px;
padding-left: 36px;
border-bottom: 1px solid var(--color-E5E5E5);
}
.approval-card .card-tag {
font-size: var(--fs-14);
font-weight: var(--fw-700);
padding: 2px 8px;
border-radius: 4px;
color: var(--color-666666);
background: var(--color-F3F3F3);
transition: all 0.4s ease;
}
.approval-card .card-tag.main-tag {
color: var(--color-3E6AFC);
background: var(--color-E9F1FB);
}
.approval-card.selected .card-tag {
color: var(--color-3E6AFC);
background: var(--color-E9F1FB);
}
.approval-card .card-tid {
font-size: var(--fs-16);
.bottomsheet .tax-detail-accordion .summary .label {
flex: 1 1 auto;
color: var(--color-2D3436);
font-weight: var(--fw-500);
letter-spacing: -0.5px;
}
/* 분할승인 카드 바디 */
.approval-card .card-body {
margin-bottom: 16px;
.bottomsheet .tax-detail-accordion .summary .value {
flex: 0 0 auto;
font-family: Pretendard;
font-weight: 500;
font-size: 17px;
line-height: 1.5;
color: var(--color-2D3436);
}
.approval-card .info-list {
list-style: none;
padding: 0;
margin: 0;
.bottomsheet .tax-detail-accordion .list {
display: flex;
flex-direction: column;
gap: 8px;
gap: 5px;
}
.approval-card .info-list li {
.bottomsheet .tax-detail-accordion .list-header {
display: flex;
gap: 10px;
padding: 10px 0 6px 0;
border-bottom: 1px solid #D9D9D9;
}
.bottomsheet .tax-detail-accordion .list-header .head-date {
flex: 1 1 auto;
font-size: 15px;
color: #666;
}
.bottomsheet .tax-detail-accordion .list-header .head-amount {
flex: 0 0 auto;
font-size: 15px;
color: #666;
margin-left: auto;
}
.bottomsheet .tax-detail-accordion .item {
position: relative;
display: flex;
align-items: center;
font-size: var(--fs-14);
gap: 10px;
padding: 6px 0 6px 6px;
}
.bottomsheet .tax-detail-accordion .item .dot {
width: 9px;
height: 9px;
border-radius: 50%;
background: var(--color-3E6AFC);
}
.bottomsheet .tax-detail-accordion .item .date {
font-size: 17px;
color: #666;
}
.bottomsheet .tax-detail-accordion .item .amount {
margin-left: auto;
display: flex;
align-items: center;
gap: 10px;
height: 30px;
padding-right: 30px;
}
.bottomsheet .tax-detail-accordion .item .amount .text {
font-size: 17px;
font-weight: 500;
color: var(--color-2D3436);
}
.approval-card .info-list .label {
min-width: 85px;
color: var(--color-666666);
font-weight: var(--fw-400);
.bottomsheet .tax-detail-accordion .item .amount .arrow {
width: 25px;
height: 25px;
transform: rotate(90deg);
top: 8px;
}
.approval-card .info-list .value {
color: var(--color-2D3436);
font-weight: var(--fw-500);
.bottomsheet .tax-detail-accordion .item .amount .arrow.up {
transform: rotate(270deg);
}
/* 분할승인 카드 푸터 */
.approval-card .card-footer {
padding-top: 12px;
border-top: 1px solid var(--color-E5E5E5);
}
.approval-card .period-selector {
.bottomsheet .tax-detail-accordion .item-detail {
display: flex;
align-items: center;
gap: 12px;
flex-direction: column;
gap: 6px;
background: #F4F8FF;
padding: 10px 0;
}
.approval-card .period-selector label {
font-size: var(--fs-14);
color: var(--color-666666);
font-weight: var(--fw-500);
min-width: 60px;
.bottomsheet .tax-detail-accordion .item-detail .labels,
.bottomsheet .tax-detail-accordion .item-detail .values {
width: 100%;
display: flex;
justify-content: space-between;
flex-direction: row;
}
.approval-card .period-selector select {
.bottomsheet .tax-detail-accordion .item-detail .labels span {
display: inline-block;
flex: 1;
height: 36px;
font-size: var(--fs-14);
padding: 6px 30px 6px 12px;
border: 1px solid var(--color-d6d6d6);
border-radius: 4px;
background-color: var(--color-white);
transition: all 0.2s ease;
text-align: center;
font-size: 15px;
color: var(--color-2D3436);
}
.bottomsheet .tax-detail-accordion .item-detail .values span {
flex: 1;
text-align: center;
font-size: 16px;
font-weight: 600;
color: var(--color-2D3436);
}
/* Scrollbar hide utility class */
.scrollbar-hide::-webkit-scrollbar {
display: none; /* Chrome, Safari, Opera */
}

View File

@@ -0,0 +1,4 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="20" height="20" rx="10" fill="#666666"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.622 6.78805C12.7847 6.62534 13.0485 6.62534 13.2113 6.78805C13.374 6.95077 13.374 7.21459 13.2113 7.37731L10.5892 9.99935L13.2113 12.6214C13.374 12.7841 13.374 13.0479 13.2113 13.2106C13.0485 13.3734 12.7847 13.3734 12.622 13.2106L9.99996 10.5886L7.37792 13.2106C7.2152 13.3734 6.95138 13.3734 6.78866 13.2106C6.62595 13.0479 6.62595 12.7841 6.78866 12.6214L9.4107 9.99935L6.78867 7.37731C6.62595 7.21459 6.62595 6.95077 6.78867 6.78805C6.95138 6.62534 7.2152 6.62534 7.37792 6.78805L9.99996 9.41009L12.622 6.78805Z" fill="white" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 804 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -9,6 +9,8 @@ import { FilterMotionDuration, FilterMotionStyle, FilterMotionVariants, MenuItem
import { useEffect, useRef, useState } from 'react';
import { useLocation } from 'react-router';
import { setHomeReloadKey } from '@/pages/home/home-page';
import { useShortcutSaveMutation } from '@/entities/user/api/use-shortcut-save-mutation';
import { ShortcutSaveParams, ShortcutSaveResponse } from '@/entities/user/model/types';
// 상수 정의
const SCROLL_ANIMATION_DURATION = 800;
@@ -17,7 +19,7 @@ const BUTTON_SCROLL_OFFSET = 30;
// 타입 정의
interface ShortButton {
menuId: string;
menuId: number;
menuName: string;
index: number;
}
@@ -34,12 +36,15 @@ export const Menu = ({
favoriteEdit
}: MenuProps) => {
const userMids = useStore.getState().UserStore.userMids;
const userInfo = useStore.getState().UserStore.userInfo;
const location = useLocation();
const { navigate } = useNavigate();
const { mutateAsync: shortcutSave } = useShortcutSaveMutation();
const [shortBtns, setShortBtns] = useState<ShortButton[]>([]);
const [editMode, setEditMode] = useState(false);
const [changeMenuId, setChangeMenuId] = useState<string | undefined>();
const [changeMenuId, setChangeMenuId] = useState<string>();
const [shortBtnIdx, setShortBtnIdx] = useState(0);
const buttonRefs = useRef<Array<HTMLDivElement>>([]);
@@ -48,6 +53,25 @@ export const Menu = ({
const isButtonScrolling = useRef<boolean>(false);
const scrollTimer = useRef<NodeJS.Timeout | null>(null);
const lastScrollTop = useRef<number>(0);
// const [menuIds, setMenuIds] = useState<Array<number | undefined>>([]);
const callShortcutSave = () => {
if(userInfo.usrid){
let userFavorite = useStore.getState().UserStore.userFavorite;
let menuIds = userFavorite.map((value, index) => {
return value.menuId;
});
let params: ShortcutSaveParams = {
usrid: userInfo.usrid,
isDefault: false,
menuIds: menuIds
};
shortcutSave(params).then((rs: ShortcutSaveResponse) => {
});
}
};
const onClickToNavigate = (path: string) => {
onClickToMenuClose();
@@ -65,7 +89,7 @@ export const Menu = ({
}
};
const onClickToMenuNavigate = (menuId: string, index: number) => {
const onClickToMenuNavigate = (menuId: number, index: number) => {
isButtonScrolling.current = true;
setShortBtnIdx(index);
scrollCategoryButtonToLeft(index);
@@ -102,6 +126,9 @@ export const Menu = ({
const onClickToMenuClose = () => {
if(editMode){
setEditMode(false);
callShortcutSave();
// 여기에 저장 로직?
}
else{
setMenuOn(false);
@@ -114,20 +141,23 @@ export const Menu = ({
const getMenuCategory = () => {
let rs = [];
for(let i=0;i<MenuItems.length;i++){
rs.push(
<MenuCategory
key={ `menu-category-${i}` }
menuId={ MenuItems[i]?.menuId }
menuIcon={ MenuItems[i]?.menuIcon }
menuName={ MenuItems[i]?.menuName }
subMenu={ MenuItems[i]?.subMenu }
setMenuOn={ setMenuOn }
editMode={ editMode }
setChangeMenuId= { setChangeMenuId }
buttonRefs={ buttonRefs }
itemIndex={ i }
/>
);
if(MenuItems[i]){
rs.push(
<MenuCategory
key={ `menu-category-${i}` }
menuId={ MenuItems[i]?.menuId }
menuIcon={ MenuItems[i]?.menuIcon }
menuName={ MenuItems[i]?.menuName }
subMenu={ MenuItems[i]?.subMenu }
setMenuOn={ setMenuOn }
editMode={ editMode }
setChangeMenuId= { setChangeMenuId }
buttonRefs={ buttonRefs }
itemIndex={ i }
/>
);
}
}
return rs;
};
@@ -255,7 +285,7 @@ export const Menu = ({
>
<img
src={ IMAGE_ROOT + '/ico_close.svg' }
alt="설정"
alt="닫기"
/>
</button>
</div>

View File

@@ -18,8 +18,10 @@ import { useStore } from '@/shared/model/store';
import { getLocalStorage, setLocalStorage } from '@/shared/lib';
import { StorageKeys } from '@/shared/constants/local-storage';
import { HomeGroupsParams, HomeGroupsResponse } from '@/entities/home/model/types';
import { LoginResponse } from '@/entities/user/model/types';
import { LoginResponse, ShortcutUserParams, ShortcutUserResponse } from '@/entities/user/model/types';
import { useCodesListByCodeClMutation } from '@/entities/common/api/use-codes-list-by-codeCl-mutaion';
import { useShortcutUserMutation } from '@/entities/user/api/use-shortcut-user-mutation';
import { useShortcutDefaultMutation } from '@/entities/user/api/use-shortcut-detault-mutation';
export interface ContextType {
setOnBack: (onBack: () => void) => void;
@@ -58,7 +60,8 @@ export const SubLayout = () => {
const { isNativeEnvironment } = useAppBridge();
const { mutateAsync: homeGroups } = useHomeGroupsMutation();
const { mutateAsync: codesListByCodeCl} = useCodesListByCodeClMutation();
const { mutateAsync: shortcutUser } = useShortcutUserMutation();
const { mutateAsync: shortcutDefault } = useShortcutDefaultMutation();
const wrapperClassName = 'wrapper';
@@ -91,6 +94,39 @@ export const SubLayout = () => {
});
};
const callSortcutDefault = () => {
let userInfo = useStore.getState().UserStore.userInfo;
if(userInfo.usrid){
let params: ShortcutUserParams = {
usrid: userInfo.usrid
};
shortcutUser(params).then((rs: ShortcutUserResponse) => {
useStore.getState().UserStore.setUserFavorite(rs.shortcuts);
});
}
};
const callShortcutUser = () => {
let userInfo = useStore.getState().UserStore.userInfo;
if(userInfo.usrid){
let params: ShortcutUserParams = {
usrid: userInfo.usrid
};
shortcutUser(params).then((rs: ShortcutUserResponse) => {
if(rs.shortcuts){
if(rs.shortcuts.length > 0){
useStore.getState().UserStore.setUserFavorite(rs.shortcuts);
}
else{
callSortcutDefault();
}
}
});
}
};
const handleLogin = useCallback(async () => {
let userParmas;
@@ -102,6 +138,7 @@ export const SubLayout = () => {
}
callLogin(userParmas).then(() => {
callHomeGroups();
callShortcutUser();
}).catch((error: any) => {
setLoginSuccess(false);
});