첫 커밋
This commit is contained in:
29
src/entities/tax/api/use-invoice-detail-mutation.ts
Normal file
29
src/entities/tax/api/use-invoice-detail-mutation.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import axios from 'axios';
|
||||
import { API_URL } from '@/shared/api/urls';
|
||||
import { resultify } from '@/shared/lib/resultify';
|
||||
import { CBDCAxiosError } from '@/shared/@types/error';
|
||||
import {
|
||||
InvoiceDetailParams,
|
||||
InvoiceDetailResponse
|
||||
} from '../model/types';
|
||||
import {
|
||||
useMutation,
|
||||
UseMutationOptions
|
||||
} from '@tanstack/react-query';
|
||||
|
||||
export const invoiceDetail = (params: InvoiceDetailParams) => {
|
||||
return resultify(
|
||||
axios.post<InvoiceDetailResponse>(API_URL.allTransactionList(), params),
|
||||
);
|
||||
};
|
||||
|
||||
export const useInvoiceDetailMutation = (options?: UseMutationOptions<InvoiceDetailResponse, CBDCAxiosError, InvoiceDetailParams>) => {
|
||||
const mutation = useMutation<InvoiceDetailResponse, CBDCAxiosError, InvoiceDetailParams>({
|
||||
...options,
|
||||
mutationFn: (params: InvoiceDetailParams) => invoiceDetail(params),
|
||||
});
|
||||
|
||||
return {
|
||||
...mutation,
|
||||
};
|
||||
};
|
||||
87
src/entities/tax/model/types.ts
Normal file
87
src/entities/tax/model/types.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
export enum TaxTabKeys {
|
||||
InvoiceList = 'InvoiceList',
|
||||
VatReference = 'VatReference',
|
||||
};
|
||||
export interface TaxTabProps {
|
||||
activeTab: TaxTabKeys;
|
||||
};
|
||||
export interface InvoiceFilterProps {
|
||||
filterOn: boolean;
|
||||
setFilterOn: (filterOn: boolean) => void;
|
||||
};
|
||||
export enum SortByKeys {
|
||||
New = 'New',
|
||||
Amount = 'Amount',
|
||||
};
|
||||
export interface SortOptionsBoxProps {
|
||||
sortBy: SortByKeys;
|
||||
onCliCkToSort: (sortBy: SortByKeys) => void;
|
||||
};
|
||||
export enum AltMsgKeys {
|
||||
Fold = '접기',
|
||||
UnFold = '펼치기',
|
||||
};
|
||||
export enum DetailInfoSectionKeys {
|
||||
Amount = 'Amount',
|
||||
Publish = 'Publish',
|
||||
Receiver = 'Receiver',
|
||||
Supplier = 'Supplier',
|
||||
};
|
||||
export interface InvoiceArrowProps {
|
||||
show?: boolean;
|
||||
};
|
||||
export interface InvoiceListParams {
|
||||
|
||||
};
|
||||
export interface invoiceListResponse {
|
||||
|
||||
};
|
||||
export interface ListItem {
|
||||
tid?: string;
|
||||
pname?: string;
|
||||
userid?: string;
|
||||
idate?: string;
|
||||
kind?: string;
|
||||
amount?: number;
|
||||
};
|
||||
export interface ListItemProps extends ListItem{
|
||||
|
||||
};
|
||||
export interface ListDateGroupProps {
|
||||
date: string;
|
||||
items: Array<ListItemProps>
|
||||
}
|
||||
export interface InvoiceListProps {
|
||||
listItems: Record<string, Array<ListItemProps>>
|
||||
};
|
||||
export interface InvoiceDetailParams {
|
||||
svcCd?: string;
|
||||
tid: string;
|
||||
};
|
||||
export interface InvoiceDetailResponse {
|
||||
|
||||
};
|
||||
export interface DetailAmountInfoProps {
|
||||
|
||||
};
|
||||
export interface DetailPublishInfoProps {
|
||||
|
||||
};
|
||||
export interface DetailReceiverInfoProps {
|
||||
|
||||
};
|
||||
export interface DetailSupplierInfoProps {
|
||||
|
||||
};
|
||||
export interface DetailResponse {
|
||||
amountInfo?: DetailAmountInfoProps;
|
||||
publishInfo?: DetailPublishInfoProps;
|
||||
receiverInfo?: DetailReceiverInfoProps;
|
||||
supplierInfo?: DetailSupplierInfoProps;
|
||||
};
|
||||
|
||||
export interface DetailInfoSectionProps extends DetailResponse {
|
||||
show?: boolean;
|
||||
tid?: string;
|
||||
onClickToShowInfo?: (info: DetailInfoSectionKeys) => void;
|
||||
};
|
||||
47
src/entities/tax/ui/detail-amount-info-section.tsx
Normal file
47
src/entities/tax/ui/detail-amount-info-section.tsx
Normal file
@@ -0,0 +1,47 @@
|
||||
import { DetailInfoSectionProps } from '../model/types';
|
||||
import { InvoiceArrow } from './invoice-arrow';
|
||||
|
||||
export const DetailAmountInfoSection = ({
|
||||
amountInfo,
|
||||
show,
|
||||
onClickToShowInfo
|
||||
}: DetailInfoSectionProps) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="txn-num-group">
|
||||
<div className="txn-amount">
|
||||
<div className="value">48,125,100<span className="unit">원</span></div>
|
||||
<button
|
||||
className="chip-btn"
|
||||
type="button"
|
||||
>
|
||||
<span>금액상세</span> <InvoiceArrow show={ show }></InvoiceArrow>
|
||||
</button>
|
||||
</div>
|
||||
<div className="amount-expand">
|
||||
<ul className="amount-list">
|
||||
<li className="amount-item">
|
||||
<span className="label">· 공급가액</span>
|
||||
<span className="value">43,750,000 원</span>
|
||||
</li>
|
||||
<li className="amount-item">
|
||||
<span className="label">· VAT</span>
|
||||
<span className="value">4,375,100 원</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="txn-mid">
|
||||
<span className="value">croquis01m</span>
|
||||
</div>
|
||||
<div className="txn-mid">
|
||||
<span className="value">2025.08.19</span>
|
||||
</div>
|
||||
<div className="txn-doc">
|
||||
<button className="doc-btn" type="button">세금계산서</button>
|
||||
<button className="doc-btn" type="button">상세자료</button>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
46
src/entities/tax/ui/detail-publish-info-section.tsx
Normal file
46
src/entities/tax/ui/detail-publish-info-section.tsx
Normal file
@@ -0,0 +1,46 @@
|
||||
import { DetailInfoSectionProps } from '../model/types';
|
||||
|
||||
export const DetailPublishInfoSection = ({
|
||||
publishInfo,
|
||||
show,
|
||||
onClickToShowInfo
|
||||
}: DetailInfoSectionProps) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="txn-section">
|
||||
<div className="section-title">발행 정보</div>
|
||||
<ul className="kv-list">
|
||||
<li className="kv-row">
|
||||
<span className="k">MID</span>
|
||||
<span className="v">nictest01m</span>
|
||||
</li>
|
||||
<li className="kv-row">
|
||||
<span className="k">발행대상일자</span>
|
||||
<span className="v">2025.06.01 ~ 2025.06.30</span>
|
||||
</li>
|
||||
<li className="kv-row">
|
||||
<span className="k">발행일자</span>
|
||||
<span className="v">2025.06.30</span>
|
||||
</li>
|
||||
<li className="kv-row">
|
||||
<span className="k">적요</span>
|
||||
<span className="v">PG 수수료</span>
|
||||
</li>
|
||||
<li className="kv-row">
|
||||
<span className="k">발행대상</span>
|
||||
<span className="v">일반</span>
|
||||
</li>
|
||||
<li className="kv-row">
|
||||
<span className="k">영수구분</span>
|
||||
<span className="v">영수</span>
|
||||
</li>
|
||||
<li className="kv-row">
|
||||
<span className="k">Email</span>
|
||||
<span className="v">test@nicepay.co.kr</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
30
src/entities/tax/ui/detail-receiver-info-section.tsx
Normal file
30
src/entities/tax/ui/detail-receiver-info-section.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
import { DetailInfoSectionProps } from '../model/types';
|
||||
|
||||
export const DetailReceiverInfoSection = ({
|
||||
receiverInfo,
|
||||
show,
|
||||
onClickToShowInfo
|
||||
}: DetailInfoSectionProps) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="txn-section">
|
||||
<div className="section-title">공급받는 자 정보</div>
|
||||
</div>
|
||||
<ul className="kv-list">
|
||||
<li className="kv-row">
|
||||
<span className="k">사업자등록번호</span>
|
||||
<span className="v">123-12-12345</span>
|
||||
</li>
|
||||
<li className="kv-row">
|
||||
<span className="k">상호명</span>
|
||||
<span className="v">와와디디</span>
|
||||
</li>
|
||||
<li className="kv-row">
|
||||
<span className="k">대표자명</span>
|
||||
<span className="v">김테스트</span>
|
||||
</li>
|
||||
</ul>
|
||||
</>
|
||||
);
|
||||
};
|
||||
26
src/entities/tax/ui/detail-supplier-info-section.tsx
Normal file
26
src/entities/tax/ui/detail-supplier-info-section.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import { DetailInfoSectionProps } from '../model/types';
|
||||
|
||||
export const DetailSupplierInfoSection = ({
|
||||
supplierInfo,
|
||||
show,
|
||||
onClickToShowInfo
|
||||
}: DetailInfoSectionProps) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="txn-section">
|
||||
<div className="section-title">공급자 정보</div>
|
||||
</div>
|
||||
<ul className="kv-list">
|
||||
<li className="kv-row">
|
||||
<span className="k">사업자등록번호</span>
|
||||
<span className="v">222-22-22222</span>
|
||||
</li>
|
||||
<li className="kv-row">
|
||||
<span className="k">상호명</span>
|
||||
<span className="v">나이스페이먼츠</span>
|
||||
</li>
|
||||
</ul>
|
||||
</>
|
||||
);
|
||||
};
|
||||
23
src/entities/tax/ui/invoice-arrow.tsx
Normal file
23
src/entities/tax/ui/invoice-arrow.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { IMAGE_ROOT } from '@/shared/constants/common';
|
||||
import { AltMsgKeys, InvoiceArrowProps } from '../model/types';
|
||||
|
||||
export const InvoiceArrow = ({ show }: InvoiceArrowProps) => {
|
||||
const [altMsg, setAltMsg] = useState<AltMsgKeys>(AltMsgKeys.Fold);
|
||||
const [className, setClassName] = useState<string>('ic20 rot-180');
|
||||
|
||||
useEffect(() => {
|
||||
setAltMsg((show)? AltMsgKeys.Fold: AltMsgKeys.UnFold);
|
||||
setClassName(`ic20 ${(show)? 'rot-180': ''}`);
|
||||
}, [show]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<img
|
||||
className={ className }
|
||||
src={ IMAGE_ROOT + '/select_arrow.svg' }
|
||||
alt={ altMsg }
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
143
src/entities/tax/ui/invoice-filter.tsx
Normal file
143
src/entities/tax/ui/invoice-filter.tsx
Normal file
@@ -0,0 +1,143 @@
|
||||
import { motion } from 'framer-motion';
|
||||
import { IMAGE_ROOT } from '@/shared/constants/common';
|
||||
import { InvoiceFilterProps } from '../model/types';
|
||||
|
||||
export const InvoiceFilter = ({
|
||||
filterOn,
|
||||
setFilterOn
|
||||
}: InvoiceFilterProps) => {
|
||||
const variants = {
|
||||
hidden: { x: '100%' },
|
||||
visible: { x: '0%' },
|
||||
};
|
||||
|
||||
const onClickToClose = () => {
|
||||
setFilterOn(false);
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<motion.div
|
||||
id="fullMenuModal"
|
||||
className="full-menu-modal"
|
||||
initial="hidden"
|
||||
animate={ (filterOn)? 'visible': 'hidden' }
|
||||
variants={ variants }
|
||||
transition={{ duration: 0.3 }}
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
}}
|
||||
>
|
||||
<div className="full-menu-container">
|
||||
<div className="full-menu-header">
|
||||
<div className="full-menu-title center">필터</div>
|
||||
<div className="full-menu-actions">
|
||||
<button
|
||||
className="full-menu-close"
|
||||
onClick={ () => onClickToClose() }
|
||||
>
|
||||
<img
|
||||
src={ IMAGE_ROOT + '/ico_close.svg' }
|
||||
alt="닫기"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="option-list pb-120">
|
||||
<div className="opt-field">
|
||||
<div className="opt-label">가맹점</div>
|
||||
<div className="opt-controls">
|
||||
<select className="flex-1">
|
||||
<option>nictest001m</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="opt-field mt_top">
|
||||
<div className="opt-label">발행월</div>
|
||||
<div className="opt-controls col below h36">
|
||||
<div className="chip-row">
|
||||
<span className="keyword-tag active">당월</span>
|
||||
<span className="keyword-tag">2개월</span>
|
||||
<span className="keyword-tag">3개월</span>
|
||||
<span className="keyword-tag">직접입력</span>
|
||||
</div>
|
||||
<div className="range-row">
|
||||
<div className="input-wrapper date">
|
||||
<input
|
||||
className="date-input"
|
||||
type="text"
|
||||
placeholder="날짜 선택"
|
||||
value="2025.06.08"
|
||||
readOnly={ true }
|
||||
/>
|
||||
<button
|
||||
className="date-btn"
|
||||
type="button"
|
||||
>
|
||||
<img
|
||||
src={ IMAGE_ROOT + '/ico_date.svg' }
|
||||
alt="날짜 선택"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<span className="beetween">~</span>
|
||||
<div className="input-wrapper date">
|
||||
<input
|
||||
className="date-input"
|
||||
type="text"
|
||||
placeholder="날짜 선택"
|
||||
value="2025.06.08"
|
||||
readOnly={ true }
|
||||
/>
|
||||
<button
|
||||
className="date-btn"
|
||||
type="button"
|
||||
>
|
||||
<img
|
||||
src={ IMAGE_ROOT + '/ico_date.svg' }
|
||||
alt="날짜 선택"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="opt-field">
|
||||
<div className="opt-label">영수 구분</div>
|
||||
<div className="opt-controls col below h36">
|
||||
<div className="chip-row">
|
||||
<span className="keyword-tag active">전체</span>
|
||||
<span className="keyword-tag">영수</span>
|
||||
<span className="keyword-tag">청구</span>
|
||||
<span
|
||||
className="keyword-tag"
|
||||
style={{ visibility: 'hidden' }}
|
||||
></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="opt-field">
|
||||
<div className="opt-label">발행 대상</div>
|
||||
<div className="opt-controls col below h36">
|
||||
<div className="chip-row">
|
||||
<span className="keyword-tag active">전체</span>
|
||||
<span className="keyword-tag">일반</span>
|
||||
<span className="keyword-tag">차액정산</span>
|
||||
<span className="keyword-tag">환급정산</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div className="apply-row">
|
||||
<button className="btn-50 btn-blue flex-1">적용</button>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
117
src/entities/tax/ui/invoice-list-wrap.tsx
Normal file
117
src/entities/tax/ui/invoice-list-wrap.tsx
Normal file
@@ -0,0 +1,117 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { IMAGE_ROOT } from '@/shared/constants/common';
|
||||
import { InvoiceFilter } from './invoice-filter';
|
||||
import { SortOptionsBox } from './sort-options-box';
|
||||
import { SortByKeys } from '../model/types';
|
||||
import { InvoiceList } from './invoice-list';
|
||||
|
||||
export const InvoiceListWrap = () => {
|
||||
const [filterOn, setFilterOn] = useState<boolean>(false);
|
||||
const [sortBy, setSortBy] = useState<SortByKeys>(SortByKeys.New);
|
||||
const [listItems, setListItems] = useState({});
|
||||
|
||||
const callList = () => {
|
||||
setListItems({
|
||||
'20250601': [
|
||||
{tid: 'a1234567', pname: '와와디디', userid: 'nictest01m', idate: '20250630', kind: 'PG수수료', amount: 48125100},
|
||||
{tid: 'b34534534', pname: '와와디디', userid: 'wadizcop@m', idate: '20250630', kind: 'PG수수료', amount: 23845000},
|
||||
]
|
||||
})
|
||||
};
|
||||
const onClickToOpenFIlter = () => {
|
||||
setFilterOn(true);
|
||||
};
|
||||
const onCliCkToSort = (sort: SortByKeys) => {
|
||||
setSortBy(sort);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
callList();
|
||||
}, []);
|
||||
return (
|
||||
<>
|
||||
<div className="summary-section">
|
||||
<div className="credit-controls">
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
className="credit-period"
|
||||
value="2025.06.01 ~ 2025.06.31"
|
||||
readOnly={ true }
|
||||
/>
|
||||
<button
|
||||
className="filter-btn"
|
||||
onClick={ () => onClickToOpenFIlter() }
|
||||
>
|
||||
<img
|
||||
src={ IMAGE_ROOT + '/ico_setting.svg' }
|
||||
alt="검색옵션"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<button className="download-btn">
|
||||
<img
|
||||
src={ IMAGE_ROOT + '/ico_download.svg' }
|
||||
alt="다운로드"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="filter-section mt-10">
|
||||
<SortOptionsBox
|
||||
sortBy={ sortBy }
|
||||
onCliCkToSort={ onCliCkToSort }
|
||||
></SortOptionsBox>
|
||||
</div>
|
||||
<InvoiceList
|
||||
listItems={ listItems }
|
||||
></InvoiceList>
|
||||
{/*
|
||||
<div className="transaction-list">
|
||||
<div className="date-group">
|
||||
<div className="date-header">25.06</div>
|
||||
|
||||
<div className="transaction-item approved">
|
||||
<div className="transaction-status">
|
||||
<div className="status-dot blue"></div>
|
||||
</div>
|
||||
<div className="transaction-content">
|
||||
<div className="transaction-title">와와디디 (nictest01m)</div>
|
||||
<div className="transaction-details">
|
||||
<span>2025.06.30</span>
|
||||
<span className="separator">|</span>
|
||||
<span>PG수수료</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="transaction-amount">48,125,100원</div>
|
||||
</div>
|
||||
|
||||
<div className="transaction-item refund">
|
||||
<div className="transaction-status">
|
||||
<div className="status-dot gray"></div>
|
||||
</div>
|
||||
<div className="transaction-content">
|
||||
<div className="transaction-title">와와디디 (wadizcop@m)</div>
|
||||
<div className="transaction-details">
|
||||
<span>2025.06.30</span>
|
||||
<span className="separator">|</span>
|
||||
<span>PG수수료</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="transaction-amount">23,845,000원</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
*/
|
||||
}
|
||||
<div className="apply-row bottom-padding">
|
||||
<button className="btn-50 btn-blue flex-1">수기발행</button>
|
||||
</div>
|
||||
<InvoiceFilter
|
||||
filterOn={ filterOn }
|
||||
setFilterOn={ setFilterOn }
|
||||
></InvoiceFilter>
|
||||
</>
|
||||
);
|
||||
};
|
||||
29
src/entities/tax/ui/invoice-list.tsx
Normal file
29
src/entities/tax/ui/invoice-list.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import { InvoiceListProps } from '../model/types';
|
||||
import { ListDateGroup } from './list-date-group';
|
||||
|
||||
export const InvoiceList = ({
|
||||
listItems
|
||||
}: InvoiceListProps) => {
|
||||
|
||||
const getListDateGroup = () => {
|
||||
let rs = [];
|
||||
for (const [key, value] of Object.entries(listItems)) {
|
||||
rs.push(
|
||||
<ListDateGroup
|
||||
key={ key }
|
||||
date={ key }
|
||||
items={ value }
|
||||
></ListDateGroup>
|
||||
);
|
||||
}
|
||||
return rs;
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="transaction-list">
|
||||
{ getListDateGroup() }
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
};
|
||||
46
src/entities/tax/ui/list-date-group.tsx
Normal file
46
src/entities/tax/ui/list-date-group.tsx
Normal file
@@ -0,0 +1,46 @@
|
||||
import moment from 'moment';
|
||||
import 'moment/dist/locale/ko';
|
||||
import { ListDateGroupProps } from '../model/types';
|
||||
import { ListItem } from './list-item';
|
||||
|
||||
export const ListDateGroup = ({
|
||||
date,
|
||||
items
|
||||
}: ListDateGroupProps) => {
|
||||
moment.locale('ko');
|
||||
const getStateDate = () => {
|
||||
let stateDate = moment(date).format('YY.MM');
|
||||
return stateDate;
|
||||
};
|
||||
|
||||
const getListItem = () => {
|
||||
let rs = [];
|
||||
if(!!items && items.length>0){
|
||||
for(let i=0;i<items.length;i++){
|
||||
let key = 'ListItem-'+i;
|
||||
rs.push(
|
||||
<ListItem
|
||||
key={ key }
|
||||
tid={ items[i]?.tid }
|
||||
pname={ items[i]?.pname }
|
||||
userid={ items[i]?.userid }
|
||||
idate={ items[i]?.idate }
|
||||
kind={ items[i]?.kind }
|
||||
amount={ items[i]?.amount }
|
||||
></ListItem>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return rs;
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="date-group">
|
||||
<div className="date-header">{ getStateDate() }</div>
|
||||
{ getListItem() }
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
54
src/entities/tax/ui/list-item.tsx
Normal file
54
src/entities/tax/ui/list-item.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
import { NumericFormat } from 'react-number-format';
|
||||
import { PATHS } from '@/shared/constants/paths';
|
||||
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
|
||||
import { ListItemProps } from '../model/types';
|
||||
import moment from 'moment';
|
||||
|
||||
export const ListItem = ({
|
||||
tid,
|
||||
pname,
|
||||
userid,
|
||||
idate,
|
||||
kind,
|
||||
amount
|
||||
}: ListItemProps) => {
|
||||
const { navigate } = useNavigate();
|
||||
|
||||
const onClickToNavigate = () => {
|
||||
navigate(PATHS.tax.invoice.detail, {
|
||||
state: {
|
||||
tid: tid
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className="transaction-item approved"
|
||||
onClick={ () => onClickToNavigate() }
|
||||
>
|
||||
<div className="transaction-status">
|
||||
<div className="status-dot blue"></div>
|
||||
</div>
|
||||
<div className="transaction-content">
|
||||
<div className="transaction-title">{ pname } ({ userid })</div>
|
||||
<div className="transaction-details">
|
||||
<span>{ moment(idate).format('YYYY.MM.DD') }</span>
|
||||
<span className="separator">|</span>
|
||||
<span>{ kind }</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="transaction-amount">
|
||||
<NumericFormat
|
||||
value={ amount }
|
||||
thousandSeparator
|
||||
displayType="text"
|
||||
suffix={ '원' }
|
||||
></NumericFormat>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
25
src/entities/tax/ui/sort-options-box.tsx
Normal file
25
src/entities/tax/ui/sort-options-box.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import {
|
||||
SortByKeys,
|
||||
SortOptionsBoxProps
|
||||
} from '../model/types';
|
||||
export const SortOptionsBox = ({
|
||||
sortBy,
|
||||
onCliCkToSort
|
||||
}: SortOptionsBoxProps) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="sort-options">
|
||||
<button
|
||||
className={ `sort-btn ${(sortBy === SortByKeys.New)? 'active': ''}` }
|
||||
onClick={ () => onCliCkToSort(SortByKeys.New) }
|
||||
>최신순</button>
|
||||
<span className="sort-divider">|</span>
|
||||
<button
|
||||
className={ `sort-btn ${(sortBy === SortByKeys.Amount)? 'active': ''}` }
|
||||
onClick={ () => onCliCkToSort(SortByKeys.Amount) }
|
||||
>고액순</button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
37
src/entities/tax/ui/tax-tab.tsx
Normal file
37
src/entities/tax/ui/tax-tab.tsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import { PATHS } from '@/shared/constants/paths';
|
||||
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
|
||||
import {
|
||||
TaxTabKeys,
|
||||
TaxTabProps
|
||||
} from '../model/types';
|
||||
|
||||
export const TaxTab = ({
|
||||
activeTab
|
||||
}: TaxTabProps) => {
|
||||
const { navigate } = useNavigate();
|
||||
|
||||
const onClickToNavigation = (tab: TaxTabKeys) => {
|
||||
if(activeTab !== tab){
|
||||
if(tab === TaxTabKeys.InvoiceList){
|
||||
navigate(PATHS.tax.invoice.list);
|
||||
}
|
||||
else if(tab === TaxTabKeys.VatReference){
|
||||
navigate(PATHS.tax.vatReference);
|
||||
}
|
||||
}
|
||||
};
|
||||
return(
|
||||
<>
|
||||
<div className="subTab">
|
||||
<button
|
||||
className={`subtab-btn ${(activeTab === TaxTabKeys.InvoiceList)? 'active': ''}` }
|
||||
onClick={ () => onClickToNavigation(TaxTabKeys.InvoiceList) }
|
||||
>세금 계산서</button>
|
||||
<button
|
||||
className={`subtab-btn ${(activeTab === TaxTabKeys.VatReference)? 'active': ''}` }
|
||||
onClick={ () => onClickToNavigation(TaxTabKeys.VatReference) }
|
||||
>부가세 참고</button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
26
src/entities/tax/ui/var-reference-req-fail.tsx
Normal file
26
src/entities/tax/ui/var-reference-req-fail.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
export const VatReferenceReqFail = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="success-page">
|
||||
<div className="success-body">
|
||||
<div className="error-icon" aria-hidden="true"></div>
|
||||
<h1 className="success-title">
|
||||
<span>부가세 참고 자료</span>
|
||||
<br/>
|
||||
<span>신청 실패하였습니다</span>
|
||||
</h1>
|
||||
<div className="success-result">
|
||||
<p className="result-text align-left position_label">
|
||||
<span>결과 :</span>
|
||||
<span>[9997] 키인가맹점이 아닙니다.<br/>NICEPAY로 문의하세요.</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="apply-row">
|
||||
<button className="btn-50 btn-blue flex-1">확인</button>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
29
src/entities/tax/ui/vat-reference-req-success.tsx
Normal file
29
src/entities/tax/ui/vat-reference-req-success.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
export const VatReferenceReqSuccess = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="success-page">
|
||||
<div className="success-body">
|
||||
<div className="success-icon" aria-hidden="true"></div>
|
||||
<h1 className="success-title">
|
||||
<span>부가세 참고 자료</span>
|
||||
<br/>
|
||||
<span>신청이 완료되었습니다.</span>
|
||||
</h1>
|
||||
<p className="success-subtitle">파일은 선택한 수령 방법으로 제공됩니다.</p>
|
||||
<div className="success-result">
|
||||
<p className="result-text">
|
||||
<span>신청일 :</span> <span>2025.06.04</span>
|
||||
<br/>
|
||||
<span>메일주소 :</span> <span>TEST@NICEPAY.CO.KR</span>
|
||||
</p>
|
||||
</div>
|
||||
<p className="success-note dot">참고용 자료이므로 반드시 내부 회계자료 등과<br/>비교 후 사용해 주세요.</p>
|
||||
</div>
|
||||
<div className="apply-row">
|
||||
<button className="btn-50 btn-blue flex-1">확인</button>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
8
src/entities/tax/ui/vat-reference-wrap.tsx
Normal file
8
src/entities/tax/ui/vat-reference-wrap.tsx
Normal file
@@ -0,0 +1,8 @@
|
||||
export const VatReferenceWrap = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
</>
|
||||
)
|
||||
};
|
||||
Reference in New Issue
Block a user