상세 수정
This commit is contained in:
@@ -16,6 +16,23 @@ export const DEFAULT_PAGE_PARAM = {
|
||||
sortType: SortTypeKeys.LATEST,
|
||||
};
|
||||
|
||||
export const DetailMotionVariants = {
|
||||
hidden: {
|
||||
x: '100%'
|
||||
},
|
||||
visible: {
|
||||
x: '0%'
|
||||
},
|
||||
};
|
||||
export const DetailMotionDuration = {
|
||||
duration: 0.3
|
||||
};
|
||||
export const DetailMotionStyle = {
|
||||
width: '100%',
|
||||
height: '100%'
|
||||
};
|
||||
|
||||
|
||||
export const FilterMotionVariants = {
|
||||
hidden: {
|
||||
x: '100%'
|
||||
|
||||
@@ -6,21 +6,19 @@ import { useTranslation } from 'react-i18next';
|
||||
import { IMAGE_ROOT } from '@/shared/constants/common';
|
||||
|
||||
export const HomeNoticeItem = ({
|
||||
seq,
|
||||
title,
|
||||
informCl,
|
||||
regDt,
|
||||
noticeItem,
|
||||
setDetailData,
|
||||
}: NoticeItemProps) => {
|
||||
const { navigate } = useNavigate();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const onClickToDetail = () => {
|
||||
navigate(PATHS.support.notice.detail, {
|
||||
state: {
|
||||
seq: seq,
|
||||
from: PATHS.home
|
||||
}
|
||||
})
|
||||
if(setDetailData){
|
||||
setDetailData({
|
||||
seq: noticeItem.seq,
|
||||
detailOn: true
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -30,8 +28,8 @@ export const HomeNoticeItem = ({
|
||||
onClick={ () => onClickToDetail() }
|
||||
>
|
||||
<div className="notice-content">
|
||||
<div className="notice-title">{ title }</div>
|
||||
<div className="notice-meta">{ t(`support.notice.categories.${informCl}`) }<span>{ moment(regDt).format('YY년 MM월 DD일') }</span></div>
|
||||
<div className="notice-title">{ noticeItem.title }</div>
|
||||
<div className="notice-meta">{ t(`support.notice.categories.${noticeItem.informCl}`) }<span>{ noticeItem.regDt? moment(noticeItem.regDt).format('YY년 MM월 DD일'): '' }</span></div>
|
||||
</div>
|
||||
<div className="notice-arrow">
|
||||
<img
|
||||
|
||||
@@ -1,31 +1,43 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useNoticeListMutation } from '@/entities/support/api/use-notice-list-mutation';
|
||||
import { DEFAULT_PAGE_PARAM } from '@/entities/common/model/constant';
|
||||
import { NoticeItem } from '@/entities/support/model/types';
|
||||
import { DetailData, NoticeItem } from '@/entities/support/model/types';
|
||||
import { HomeNoticeItem } from './home-notice-item';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { NoticeDetail } from '@/entities/support/ui/detail/notice-detail';
|
||||
|
||||
export const HomeNoticeList = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [pageParam, setPageParam] = useState(DEFAULT_PAGE_PARAM);
|
||||
const [resultList, setResultList] = useState<Array<NoticeItem>>([]);
|
||||
const [detailOn, setDetailOn] = useState<boolean>(false);
|
||||
const [detailSeq, setDetailSeq] = useState<number>(0);
|
||||
|
||||
const { mutateAsync: noticeList } = useNoticeListMutation();
|
||||
|
||||
const setDetailData = (detailData: DetailData) => {
|
||||
setDetailOn(detailData.detailOn);
|
||||
if(detailData?.seq){
|
||||
setDetailSeq(detailData?.seq);
|
||||
}
|
||||
};
|
||||
|
||||
const getItems = () => {
|
||||
let rs = [];
|
||||
let maxCnt = (!!resultList && resultList.length < 4)? resultList.length: 4;
|
||||
for(let i=0;i<maxCnt;i++){
|
||||
rs.push(
|
||||
<HomeNoticeItem
|
||||
key={ `key-home-notice-item-${i}` }
|
||||
seq={ resultList[i]?.seq }
|
||||
title={ resultList[i]?.title }
|
||||
informCl={ resultList[i]?.informCl }
|
||||
regDt={ resultList[i]?.regDt }
|
||||
></HomeNoticeItem>
|
||||
);
|
||||
let noticeItem = resultList[i];
|
||||
if(noticeItem){
|
||||
rs.push(
|
||||
<HomeNoticeItem
|
||||
key={ `key-home-notice-item-${i}` }
|
||||
noticeItem={ noticeItem }
|
||||
setDetailData={ setDetailData }
|
||||
></HomeNoticeItem>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
return rs;
|
||||
};
|
||||
@@ -56,6 +68,11 @@ export const HomeNoticeList = () => {
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<NoticeDetail
|
||||
detailOn={ detailOn }
|
||||
setDetailOn={ setDetailOn }
|
||||
seq={ detailSeq }
|
||||
></NoticeDetail>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
0
src/entities/settlement/ui/detail/list-detail.tsx
Normal file
0
src/entities/settlement/ui/detail/list-detail.tsx
Normal file
@@ -21,9 +21,10 @@ export interface FaqListResponse extends DefaulResponsePagination {
|
||||
hasNext: boolean;
|
||||
nextCursor: string | null;
|
||||
};
|
||||
export interface FaqItemProps extends FaqItem {
|
||||
|
||||
}
|
||||
export interface FaqItemProps {
|
||||
faqItem: FaqItem,
|
||||
setDetailData?: (detailData: DetailData) => void;
|
||||
};
|
||||
export interface QnaListParams extends SupportParams {
|
||||
statusCode?: string;
|
||||
page?: DefaultRequestPagination;
|
||||
@@ -45,8 +46,15 @@ export interface QnaItem {
|
||||
export interface QnaListResponse extends DefaulResponsePagination {
|
||||
content: Array<QnaItem>
|
||||
};
|
||||
export interface QnaItemProps extends QnaItem {
|
||||
|
||||
export interface DetailData {
|
||||
qnaItem?: QnaItem;
|
||||
faqItem?: FaqItem;
|
||||
seq?: number;
|
||||
detailOn: boolean;
|
||||
};
|
||||
export interface QnaItemProps {
|
||||
qnaItem: QnaItem;
|
||||
setDetailData?: (detailData: DetailData) => void;
|
||||
};
|
||||
export interface QnaSaveParams extends SupportParams {
|
||||
requestType: string;
|
||||
@@ -100,6 +108,7 @@ export interface NoticeDetailParams {
|
||||
export interface NoticeDetailResponse extends NoticeItem {
|
||||
|
||||
};
|
||||
export interface NoticeItemProps extends NoticeItem {
|
||||
|
||||
}
|
||||
export interface NoticeItemProps {
|
||||
noticeItem: NoticeItem;
|
||||
setDetailData?: (detailData: DetailData) => void;
|
||||
};
|
||||
71
src/entities/support/ui/detail/faq-detail.tsx
Normal file
71
src/entities/support/ui/detail/faq-detail.tsx
Normal file
@@ -0,0 +1,71 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FaqItem } from '../../model/types';
|
||||
import { DetailMotionDuration, DetailMotionStyle, DetailMotionVariants } from '@/entities/common/model/constant';
|
||||
import { FullMenuClose } from '@/entities/common/ui/full-menu-close';
|
||||
|
||||
export interface FaqDetaillProps {
|
||||
detailOn: boolean;
|
||||
setDetailOn: (detailOn: boolean) => void;
|
||||
faqItem: FaqItem
|
||||
};
|
||||
export const FaqDetail = ({
|
||||
detailOn,
|
||||
setDetailOn,
|
||||
faqItem
|
||||
}: FaqDetaillProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [cursorId, setCursorId] = useState<number>();
|
||||
const [seq, setSeq] = useState<string>();
|
||||
const [category, setCategory] = useState<string>();
|
||||
const [title, setTitle] = useState<string>();
|
||||
const [contents, setContents] = useState<string>();
|
||||
|
||||
const onClickToClose = () => {
|
||||
setDetailOn(false);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setCursorId(faqItem?.cursorId);
|
||||
setSeq(faqItem?.seq);
|
||||
setCategory(faqItem?.category);
|
||||
setTitle(faqItem?.title);
|
||||
setContents(faqItem?.contents);
|
||||
}, [faqItem]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<motion.div
|
||||
className="full-menu-modal"
|
||||
initial="hidden"
|
||||
animate={ (detailOn)? 'visible': 'hidden' }
|
||||
variants={ DetailMotionVariants }
|
||||
transition={ DetailMotionDuration }
|
||||
style={ DetailMotionStyle }
|
||||
>
|
||||
{ contents &&
|
||||
<div className="full-menu-container pdw-16">
|
||||
<div className="full-menu-header">
|
||||
<div className="full-menu-title center">{ t('support.qna.title') }</div>
|
||||
<div className="full-menu-actions">
|
||||
<FullMenuClose
|
||||
addClass="full-menu-close"
|
||||
onClickToCallback={ onClickToClose }
|
||||
></FullMenuClose>
|
||||
</div>
|
||||
</div>
|
||||
<div className="tab-pane sub active">
|
||||
<div className="faq-detail">
|
||||
<div className="faq-detail__title">{ title }</div>
|
||||
<div className="faq-detail__divider"></div>
|
||||
<div className="faq-detail__body" dangerouslySetInnerHTML={{ __html: contents || '' }}></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</motion.div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
81
src/entities/support/ui/detail/notice-detail.tsx
Normal file
81
src/entities/support/ui/detail/notice-detail.tsx
Normal file
@@ -0,0 +1,81 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { motion } from 'framer-motion';
|
||||
import { useLocation } from 'react-router';
|
||||
import { NoticeDetailParams, NoticeDetailResponse, NoticeItem } from '../../model/types';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useNoticeDetailMutation } from '../../api/use-notice-detail-mutation';
|
||||
import moment from 'moment';
|
||||
import { DetailMotionDuration, DetailMotionStyle, DetailMotionVariants } from '@/entities/common/model/constant';
|
||||
import { FullMenuClose } from '@/entities/common/ui/full-menu-close';
|
||||
|
||||
export interface NoticeDetaillProps {
|
||||
detailOn: boolean;
|
||||
setDetailOn: (detailOn: boolean) => void;
|
||||
seq: number;
|
||||
};
|
||||
export const NoticeDetail = ({
|
||||
detailOn,
|
||||
setDetailOn,
|
||||
seq
|
||||
}: NoticeDetaillProps) => {
|
||||
const location = useLocation();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [result, setResult] = useState<NoticeItem>({});
|
||||
|
||||
const { mutateAsync: noticeDetail } = useNoticeDetailMutation();
|
||||
|
||||
const callDetail = () => {
|
||||
let detailParams: NoticeDetailParams = {
|
||||
seq: seq,
|
||||
};
|
||||
noticeDetail(detailParams).then((rs: NoticeDetailResponse) => {
|
||||
setResult(rs);
|
||||
});
|
||||
};
|
||||
|
||||
const onClickToClose = () => {
|
||||
setDetailOn(false);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
callDetail();
|
||||
}, [seq]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<motion.div
|
||||
className="full-menu-modal"
|
||||
initial="hidden"
|
||||
animate={ (detailOn)? 'visible': 'hidden' }
|
||||
variants={ DetailMotionVariants }
|
||||
transition={ DetailMotionDuration }
|
||||
style={ DetailMotionStyle }
|
||||
>
|
||||
{ result.informCl &&
|
||||
<div className="full-menu-container pdw-16">
|
||||
<div className="full-menu-header">
|
||||
<div className="full-menu-title center">{ t('support.notice.title') }</div>
|
||||
<div className="full-menu-actions">
|
||||
<FullMenuClose
|
||||
addClass="full-menu-close"
|
||||
onClickToCallback={ onClickToClose }
|
||||
></FullMenuClose>
|
||||
</div>
|
||||
</div>
|
||||
<div className="tab-pane sub active">
|
||||
<div className="option-list">
|
||||
<div className="notice-detail">
|
||||
<div className="notice-detail__title">{ result.title }</div>
|
||||
<div className="notice-detail__meta">{ result.regDt? moment(result.regDt).format('YYYY.MM.DD'): '' } | { t(`support.notice.categories.${result.informCl}`) }</div>
|
||||
<div className="notice-detail__divider"></div>
|
||||
<div className="notice-detail__body" dangerouslySetInnerHTML={{ __html: result.contents || '' }}></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</motion.div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
110
src/entities/support/ui/detail/qna-detail.tsx
Normal file
110
src/entities/support/ui/detail/qna-detail.tsx
Normal file
@@ -0,0 +1,110 @@
|
||||
import moment from 'moment';
|
||||
import { motion } from 'framer-motion';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { QnaItem } from '../../model/types';
|
||||
import { DetailMotionDuration, DetailMotionStyle, DetailMotionVariants } from '@/entities/common/model/constant';
|
||||
import { FullMenuClose } from '@/entities/common/ui/full-menu-close';
|
||||
|
||||
export interface qnaDetaillProps {
|
||||
detailOn: boolean;
|
||||
setDetailOn: (detailOn: boolean) => void;
|
||||
qnaItem: QnaItem;
|
||||
};
|
||||
export const QnaDetail = ({
|
||||
detailOn,
|
||||
setDetailOn,
|
||||
qnaItem
|
||||
}: qnaDetaillProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [answer, setAnswer] = useState<string>();
|
||||
const [answerDate, setAnswerDate] = useState<string>();
|
||||
const [contents, setContents] = useState<string>();
|
||||
const [corpName, setCorpName] = useState<string | null>();
|
||||
const [cursorId, setCursorId] = useState<number>();
|
||||
const [requestDate, setRequestDate] = useState<string>();
|
||||
const [requestName, setRequestName] = useState<string>();
|
||||
const [requestType, setRequestType] = useState<string>();
|
||||
const [sendEmail, setSendEmail] = useState<string | null>();
|
||||
const [seq, setSeq] = useState<string>();
|
||||
const [statusCode, setStatusCode] = useState<string>();
|
||||
const [title, setTitle] = useState<string>();
|
||||
|
||||
const onClickToClose = () => {
|
||||
setDetailOn(false);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setAnswer(qnaItem?.answer);
|
||||
setAnswerDate(qnaItem?.answerDate);
|
||||
setContents(qnaItem?.contents);
|
||||
setCorpName(qnaItem?.corpName);
|
||||
setCursorId(qnaItem?.cursorId);
|
||||
setRequestDate(qnaItem?.requestDate);
|
||||
setRequestName(qnaItem?.requestName);
|
||||
setRequestType(qnaItem?.requestType);
|
||||
setSendEmail(qnaItem?.sendEmail);
|
||||
setSeq(qnaItem?.seq);
|
||||
setStatusCode(qnaItem?.statusCode);
|
||||
setTitle(qnaItem?.title);
|
||||
}, [qnaItem]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<motion.div
|
||||
className="full-menu-modal"
|
||||
initial="hidden"
|
||||
animate={ (detailOn)? 'visible': 'hidden' }
|
||||
variants={ DetailMotionVariants }
|
||||
transition={ DetailMotionDuration }
|
||||
style={ DetailMotionStyle }
|
||||
>
|
||||
{ statusCode &&
|
||||
<div className="full-menu-container pdw-16">
|
||||
<div className="full-menu-header">
|
||||
<div className="full-menu-title center">{ t('support.qna.title') }</div>
|
||||
<div className="full-menu-actions">
|
||||
<FullMenuClose
|
||||
addClass="full-menu-close"
|
||||
onClickToCallback={ onClickToClose }
|
||||
></FullMenuClose>
|
||||
</div>
|
||||
</div>
|
||||
<div className="tab-pane active">
|
||||
<div className="inq-detail">
|
||||
<div className="inq-detail__head">
|
||||
<div className="inq-detail__row">
|
||||
<span className="inq-badge">{t('support.qna.detailLabels.title')}</span>
|
||||
<span className="inq-head-text bold">{ title }</span>
|
||||
</div>
|
||||
<div className="inq-detail__row">
|
||||
<span className="inq-badge">{t('support.qna.detailLabels.type')}</span>
|
||||
<span className="inq-head-text">{ t(`support.qna.categories.${requestType}`) }</span>
|
||||
</div>
|
||||
<div className="inq-detail__row">
|
||||
<span className="inq-badge">{t('support.qna.detailLabels.registrationDate')}</span>
|
||||
<span className="inq-head-text">{ !!requestDate? moment(requestDate).format('YYYY.MM.DD'): '' }</span>
|
||||
</div>
|
||||
<div className="inq-detail__row">
|
||||
<span className="inq-badge">{t('support.qna.detailLabels.answerDate')}</span>
|
||||
<span className="inq-head-text">{ !!answerDate? moment(answerDate).format('YYYY.MM.DD'): '' }</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="inq-detail__divider"></div>
|
||||
<div className="inq-detail__section">
|
||||
<div className="inq-detail__section-title">{t('support.qna.detailLabels.inquiryAnswer')}</div>
|
||||
<div className="inq-detail__body" dangerouslySetInnerHTML={{ __html: answer || '' }}></div>
|
||||
</div>
|
||||
<div className="inq-detail__section">
|
||||
<div className="inq-detail__section-title">{t('support.qna.detailLabels.inquiryContents')}</div>
|
||||
<div className="inq-detail__body" dangerouslySetInnerHTML={{ __html: contents || '' }}></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</motion.div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -4,36 +4,29 @@ import { FaqItemProps } from '../model/types';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const SupportFaqItem = ({
|
||||
cursorId,
|
||||
seq,
|
||||
category,
|
||||
title,
|
||||
contents,
|
||||
faqItem,
|
||||
setDetailData
|
||||
}: FaqItemProps) => {
|
||||
const { navigate } = useNavigate();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const onClickToDetail = () => {
|
||||
navigate(PATHS.support.faq.detail, {
|
||||
state: {
|
||||
cursorId,
|
||||
seq,
|
||||
category,
|
||||
title,
|
||||
contents
|
||||
}
|
||||
});
|
||||
if(setDetailData){
|
||||
setDetailData({
|
||||
faqItem: faqItem,
|
||||
detailOn: true
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className="faq-row"
|
||||
onClick={ () => onClickToDetail() }
|
||||
onClick={ onClickToDetail }
|
||||
>
|
||||
<div className="faq-txt">
|
||||
<div className="faq-title">{ title }</div>
|
||||
<div className="faq-tag">{ t('support.faq.categories.' + category) }</div>
|
||||
<div className="faq-title">{ faqItem.title }</div>
|
||||
<div className="faq-tag">{ t('support.faq.categories.' + faqItem.category) }</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -5,21 +5,19 @@ import { NoticeItemProps } from '../model/types';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const SupportNoticeItem = ({
|
||||
seq,
|
||||
title,
|
||||
informCl,
|
||||
regDt,
|
||||
noticeItem,
|
||||
setDetailData,
|
||||
}: NoticeItemProps) => {
|
||||
const { navigate } = useNavigate();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const onClickToDetail = () => {
|
||||
navigate(PATHS.support.notice.detail, {
|
||||
state: {
|
||||
seq: seq,
|
||||
from: PATHS.support.notice.list
|
||||
}
|
||||
})
|
||||
if(setDetailData){
|
||||
setDetailData({
|
||||
seq: noticeItem.seq,
|
||||
detailOn: true
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -29,9 +27,9 @@ export const SupportNoticeItem = ({
|
||||
onClick={ () => onClickToDetail() }
|
||||
>
|
||||
<div className="notice-txt">
|
||||
<div className="notice-title-114">{ title }</div>
|
||||
<div className="notice-title-114">{ noticeItem.title }</div>
|
||||
<div className="notice-meta-114">
|
||||
<span className="blue">{ t(`support.notice.categories.${informCl}`) }</span> ㅣ <span>{ moment(regDt).format('YYYY.MM.DD HH:mm:ss') }</span>
|
||||
<span className="blue">{ t(`support.notice.categories.${noticeItem.informCl}`) }</span> ㅣ <span>{ noticeItem.regDt? moment(noticeItem.regDt).format('YYYY.MM.DD HH:mm:ss'): '' }</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,42 +1,19 @@
|
||||
import moment from 'moment';
|
||||
import { PATHS } from '@/shared/constants/paths';
|
||||
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
|
||||
import { QnaItemProps } from '../model/types';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const SupportQnaItem = ({
|
||||
answer,
|
||||
answerDate,
|
||||
contents,
|
||||
corpName,
|
||||
cursorId,
|
||||
requestDate,
|
||||
requestName,
|
||||
requestType,
|
||||
sendEmail,
|
||||
seq,
|
||||
statusCode,
|
||||
title
|
||||
qnaItem,
|
||||
setDetailData
|
||||
}: QnaItemProps) => {
|
||||
const { navigate } = useNavigate();
|
||||
const { t } = useTranslation();
|
||||
const onClickToDetail = () => {
|
||||
navigate(PATHS.support.qna.detail, {
|
||||
state: {
|
||||
answer: answer,
|
||||
answerDate: answerDate,
|
||||
contents: contents,
|
||||
corpName: corpName,
|
||||
cursorId: cursorId,
|
||||
requestDate: requestDate,
|
||||
requestName: requestName,
|
||||
requestType: requestType,
|
||||
sendEmail: sendEmail,
|
||||
seq: seq,
|
||||
statusCode: statusCode,
|
||||
title: title
|
||||
}
|
||||
});
|
||||
if(setDetailData){
|
||||
setDetailData({
|
||||
qnaItem: qnaItem,
|
||||
detailOn: true
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -46,12 +23,12 @@ export const SupportQnaItem = ({
|
||||
onClick={ () => onClickToDetail() }
|
||||
>
|
||||
<div className="inq-line">
|
||||
<div className="inq-title-text">{ title }</div>
|
||||
<div className="inq-title-text">{ qnaItem.title }</div>
|
||||
<div className="inq-meta">
|
||||
{t('support.qna.registrationDate')}<span>{ moment(requestDate).format('YYYY.MM.DD') }</span>
|
||||
<span className="sai">ㅣ</span>{t('support.qna.status')} <span>[{t(`support.qna.statusCode.${statusCode}`)}]</span>
|
||||
{t('support.qna.registrationDate')}<span>{ qnaItem.requestDate? moment(qnaItem.requestDate).format('YYYY.MM.DD'): '' }</span>
|
||||
<span className="sai">ㅣ</span>{t('support.qna.status')} <span>[{t(`support.qna.statusCode.${qnaItem.statusCode}`)}]</span>
|
||||
</div>
|
||||
<span className={`dot ${(statusCode === '03')? 'blue': 'gray'}`}></span>
|
||||
<span className={`dot ${(qnaItem.statusCode === '03')? 'blue': 'gray'}`}></span>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -136,29 +136,40 @@ export enum BillingPaymentMethod {
|
||||
MOBILE_PAYMENT = 'MOBILE_PAYMENT'
|
||||
};
|
||||
|
||||
export interface DetailData {
|
||||
tid: string;
|
||||
serviceCode?: string;
|
||||
detailOn: boolean;
|
||||
}
|
||||
export interface ListItemProps extends AllTransactionListItem, CashReceiptListItem, EscrowListItem, BillingListItem {
|
||||
transactionCategory?: TransactionCategory;
|
||||
setDetailData?: (detailData: DetailData) => void;
|
||||
};
|
||||
export interface ListDateGroupProps {
|
||||
transactionCategory?: TransactionCategory;
|
||||
date?: string;
|
||||
items?: Array<ListItemProps>;
|
||||
setDetailData?: (detailData: DetailData) => void;
|
||||
};
|
||||
export interface AllTransactionListProps {
|
||||
transactionCategory: TransactionCategory;
|
||||
listItems: Array<ListItemProps>;
|
||||
setDetailData: (detailData: DetailData) => void;
|
||||
};
|
||||
export interface CashReceiptListProps {
|
||||
transactionCategory: TransactionCategory;
|
||||
listItems: Array<ListItemProps>;
|
||||
setDetailData: (detailData: DetailData) => void;
|
||||
};
|
||||
export interface EscrowListProps {
|
||||
transactionCategory: TransactionCategory;
|
||||
listItems: Array<ListItemProps>;
|
||||
setDetailData: (detailData: DetailData) => void;
|
||||
};
|
||||
export interface BillingListProps {
|
||||
transactionCategory: TransactionCategory;
|
||||
listItems: Array<ListItemProps>;
|
||||
setDetailData: (detailData: DetailData) => void;
|
||||
};
|
||||
export interface AllTransactionListItem {
|
||||
tid?: string;
|
||||
|
||||
@@ -28,12 +28,7 @@ export const AllTransactionCancelPreventBond = ({
|
||||
const { navigate } = useNavigate();
|
||||
const [item, setItem] = useState<DebtPreventionCancelDisplayInfo | null | undefined>(debtPreventionCancelDisplayInfo);
|
||||
const onClickToClose = () => {
|
||||
navigate(PATHS.transaction.allTransaction.detail, {
|
||||
state: {
|
||||
serviceCode: serviceCode,
|
||||
tid: tid
|
||||
}
|
||||
});
|
||||
setCancelPreventBondOn(false);
|
||||
};
|
||||
const callTransactionCancel = () => {
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@ import { ListDateGroup } from './list-date-group';
|
||||
|
||||
export const AllTransactionList = ({
|
||||
transactionCategory,
|
||||
listItems
|
||||
listItems,
|
||||
setDetailData
|
||||
}: AllTransactionListProps) => {
|
||||
const getListDateGroup = () => {
|
||||
let rs = [];
|
||||
@@ -26,6 +27,7 @@ export const AllTransactionList = ({
|
||||
key={ date + '-' + i }
|
||||
date={ date }
|
||||
items={ list }
|
||||
setDetailData={ setDetailData }
|
||||
></ListDateGroup>
|
||||
);
|
||||
}
|
||||
@@ -43,6 +45,7 @@ export const AllTransactionList = ({
|
||||
key={ date + '-last' }
|
||||
date={ date }
|
||||
items={ list }
|
||||
setDetailData={ setDetailData }
|
||||
></ListDateGroup>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,10 +6,9 @@ import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const BillingList = ({
|
||||
transactionCategory,
|
||||
listItems
|
||||
listItems,
|
||||
setDetailData
|
||||
}: BillingListProps) => {
|
||||
const { navigate } = useNavigate();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const getListDateGroup = () => {
|
||||
let rs = [];
|
||||
@@ -31,6 +30,7 @@ export const BillingList = ({
|
||||
key={ date + '-' + i }
|
||||
date={ date }
|
||||
items={ list }
|
||||
setDetailData={ setDetailData }
|
||||
></ListDateGroup>
|
||||
);
|
||||
}
|
||||
@@ -48,27 +48,20 @@ export const BillingList = ({
|
||||
key={ date + '-last' }
|
||||
date={ date }
|
||||
items={ list }
|
||||
setDetailData={ setDetailData }
|
||||
></ListDateGroup>
|
||||
);
|
||||
}
|
||||
return rs;
|
||||
};
|
||||
|
||||
const onClickToNavigate = () => {
|
||||
navigate(PATHS.transaction.billing.charge);
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="transaction-list">
|
||||
{ getListDateGroup() }
|
||||
</div>
|
||||
<div className="apply-row">
|
||||
<button
|
||||
className="btn-50 btn-blue flex-1"
|
||||
onClick={ () => onClickToNavigate() }
|
||||
>{ t('transaction.list.paymentRequest') }</button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -6,7 +6,8 @@ import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const CashReceiptList = ({
|
||||
transactionCategory,
|
||||
listItems
|
||||
listItems,
|
||||
setDetailData
|
||||
}: CashReceiptListProps) => {
|
||||
const { navigate } = useNavigate();
|
||||
const { t } = useTranslation();
|
||||
@@ -31,6 +32,7 @@ export const CashReceiptList = ({
|
||||
key={ date + '-' + i }
|
||||
date={ date }
|
||||
items={ list }
|
||||
setDetailData={ setDetailData }
|
||||
></ListDateGroup>
|
||||
);
|
||||
}
|
||||
@@ -48,27 +50,19 @@ export const CashReceiptList = ({
|
||||
key={ date + '-last' }
|
||||
date={ date }
|
||||
items={ list }
|
||||
setDetailData={ setDetailData }
|
||||
></ListDateGroup>
|
||||
);
|
||||
}
|
||||
return rs;
|
||||
};
|
||||
|
||||
const onClickToNavigate = () => {
|
||||
navigate(PATHS.transaction.cashReceipt.handWrittenIssuance);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="transaction-list">
|
||||
{ getListDateGroup() }
|
||||
</div>
|
||||
<div className="apply-row">
|
||||
<button
|
||||
className="btn-50 btn-blue flex-1"
|
||||
onClick={ () => onClickToNavigate() }
|
||||
>{ t('transaction.list.manualIssuance') }</button>
|
||||
</div>
|
||||
|
||||
</>
|
||||
);
|
||||
};
|
||||
238
src/entities/transaction/ui/detail/all-transaction-detail.tsx
Normal file
238
src/entities/transaction/ui/detail/all-transaction-detail.tsx
Normal file
@@ -0,0 +1,238 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
import { PATHS } from '@/shared/constants/paths';
|
||||
import { Dialog } from '@/shared/ui/dialogs/dialog';
|
||||
import { overlay } from 'overlay-kit';
|
||||
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
|
||||
import { useAllTransactionDetailMutation } from '@/entities/transaction/api/use-all-transaction-detail-mutation';
|
||||
import { AmountInfoSection } from '@/entities/transaction/ui/section/amount-info-section';
|
||||
import { ImportantInfoSection } from '@/entities/transaction/ui/section/important-info-section';
|
||||
import { PaymentInfoSection } from '@/entities/transaction/ui/section/payment-info-section';
|
||||
import { TransactionInfoSection } from '@/entities/transaction/ui/section/transaction-info-section';
|
||||
import { SettlementInfoSection } from '@/entities/transaction/ui/section/settlement-info-section';
|
||||
import { PartCancelInfoSection } from '@/entities/transaction/ui/section/part-cancel-info-section';
|
||||
import {
|
||||
TransactionCategory,
|
||||
AllTransactionDetailParams,
|
||||
DetailResponse,
|
||||
AmountInfo,
|
||||
ImportantInfo,
|
||||
PaymentInfo,
|
||||
TransactionInfo,
|
||||
SettlementInfo,
|
||||
PartCancelInfo,
|
||||
InfoSectionKeys
|
||||
} from '@/entities/transaction/model/types';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
DetailMotionDuration,
|
||||
DetailMotionStyle,
|
||||
DetailMotionVariants
|
||||
} from '@/entities/common/model/constant';
|
||||
import { FullMenuClose } from '@/entities/common/ui/full-menu-close';
|
||||
|
||||
export interface AllTransactionDetailProps {
|
||||
detailOn: boolean;
|
||||
setDetailOn: (detailOn: boolean) => void;
|
||||
tid: string;
|
||||
serviceCode: string;
|
||||
};
|
||||
|
||||
export const AllTransactionDetail = ({
|
||||
detailOn,
|
||||
setDetailOn,
|
||||
tid,
|
||||
serviceCode
|
||||
}: AllTransactionDetailProps) => {
|
||||
const { navigate } = useNavigate();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [amountInfo, setAmountInfo] = useState<AmountInfo>();
|
||||
const [importantInfo, setImportantInfo] = useState<ImportantInfo>();
|
||||
const [paymentInfo, setPaymentInfo] = useState<PaymentInfo>();
|
||||
const [transactionInfo, setTransactionInfo] = useState<TransactionInfo>();
|
||||
const [settlementInfo, setSettlementInfo] = useState<SettlementInfo>();
|
||||
const [partCancelInfo, setPartCancelInfo] = useState<PartCancelInfo>();
|
||||
const [showAmountInfo, setShowAmountInfo] = useState<boolean>(false);
|
||||
const [showPaymentInfo, setShowPaymentInfo] = useState<boolean>(false);
|
||||
const [showTransactionInfo, setShowTransactionInfo] = useState<boolean>(false);
|
||||
const [showSettlementInfo, setShowSettlementInfo] = useState<boolean>(false);
|
||||
const [showPartCancelInfo, setShowPartCancelInfo] = useState<boolean>(false);
|
||||
|
||||
const { mutateAsync: allTransactionDetail } = useAllTransactionDetailMutation();
|
||||
|
||||
const callDetail = () => {
|
||||
let allTransactionDetailParams: AllTransactionDetailParams = {
|
||||
serviceCode: serviceCode,
|
||||
tid: tid
|
||||
};
|
||||
allTransactionDetail(allTransactionDetailParams).then((rs: DetailResponse) => {
|
||||
setAmountInfo(rs.amountInfo);
|
||||
setImportantInfo(rs.importantInfo);
|
||||
setPaymentInfo(rs.paymentInfo);
|
||||
setTransactionInfo(rs.transactionInfo);
|
||||
setSettlementInfo(rs.settlementInfo);
|
||||
setPartCancelInfo(rs.partCancelInfo);
|
||||
});
|
||||
};
|
||||
useEffect(() => {
|
||||
if(!!detailOn && serviceCode && tid){
|
||||
callDetail();
|
||||
}
|
||||
}, [detailOn]);
|
||||
|
||||
const onClickToNavigate = (path: string) => {
|
||||
let timeout = setTimeout(() => {
|
||||
clearTimeout(timeout);
|
||||
navigate(PATHS.transaction.allTransaction.cancel, {
|
||||
state: {
|
||||
serviceCode: serviceCode,
|
||||
tid: tid
|
||||
}
|
||||
});
|
||||
}, 10)
|
||||
};
|
||||
|
||||
const onClickToCancel = () => {
|
||||
let msg = t('transaction.confirmCancel');
|
||||
|
||||
overlay.open(({
|
||||
isOpen,
|
||||
close,
|
||||
unmount
|
||||
}) => {
|
||||
return (
|
||||
<Dialog
|
||||
afterLeave={ unmount }
|
||||
open={ isOpen }
|
||||
onClose={ close }
|
||||
onConfirmClick={ () => onClickToNavigate(PATHS.transaction.allTransaction.cancel) }
|
||||
// onConfirmClick={ () => callCancelInfo() }
|
||||
message={ msg }
|
||||
buttonLabel={[t('common.cancel'), t('common.confirm')]}
|
||||
/>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
const onClickToClose = () => {
|
||||
setDetailOn(false);
|
||||
};
|
||||
|
||||
const onClickToOpenInfo = (infoSectionKey: InfoSectionKeys) => {
|
||||
if(infoSectionKey === InfoSectionKeys.Amount){
|
||||
setShowAmountInfo(!showAmountInfo);
|
||||
}
|
||||
else if(infoSectionKey === InfoSectionKeys.Payment){
|
||||
setShowPaymentInfo(!showPaymentInfo);
|
||||
}
|
||||
else if(infoSectionKey === InfoSectionKeys.Transaction){
|
||||
setShowTransactionInfo(!showTransactionInfo);
|
||||
}
|
||||
else if(infoSectionKey === InfoSectionKeys.Settlement){
|
||||
setShowSettlementInfo(!showSettlementInfo);
|
||||
}
|
||||
else if(infoSectionKey === InfoSectionKeys.PartCancel){
|
||||
setShowPartCancelInfo(!showPartCancelInfo);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<motion.div
|
||||
className="full-menu-modal"
|
||||
initial="hidden"
|
||||
animate={ (detailOn)? 'visible': 'hidden' }
|
||||
variants={ DetailMotionVariants }
|
||||
transition={ DetailMotionDuration }
|
||||
style={ DetailMotionStyle }
|
||||
>
|
||||
<div className="full-menu-container pdw-16">
|
||||
<div className="full-menu-header">
|
||||
<div className="full-menu-title center">{ t('transaction.detailTitle') }</div>
|
||||
<div className="full-menu-actions">
|
||||
<FullMenuClose
|
||||
addClass="full-menu-close"
|
||||
onClickToCallback={ onClickToClose }
|
||||
></FullMenuClose>
|
||||
</div>
|
||||
</div>
|
||||
<div className="tab-pane sub active">
|
||||
<div className="option-list pb-86">
|
||||
<div className="txn-detail">
|
||||
<AmountInfoSection
|
||||
transactionCategory={ TransactionCategory.AllTransaction }
|
||||
amountInfo={ amountInfo }
|
||||
isOpen={ showAmountInfo }
|
||||
tid={ tid }
|
||||
serviceCode={ serviceCode }
|
||||
onClickToOpenInfo={ (infoSectionKey) => onClickToOpenInfo(infoSectionKey) }
|
||||
></AmountInfoSection>
|
||||
<div className="txn-divider minus"></div>
|
||||
<ImportantInfoSection
|
||||
transactionCategory={ TransactionCategory.AllTransaction }
|
||||
importantInfo={ importantInfo }
|
||||
serviceCode={ serviceCode }
|
||||
></ImportantInfoSection>
|
||||
{ !!paymentInfo &&
|
||||
<>
|
||||
<div className="txn-divider"></div>
|
||||
<PaymentInfoSection
|
||||
transactionCategory={ TransactionCategory.AllTransaction }
|
||||
paymentInfo={ paymentInfo }
|
||||
serviceCode={ serviceCode }
|
||||
isOpen={ showPaymentInfo }
|
||||
onClickToOpenInfo={ (infoSectionKey) => onClickToOpenInfo(infoSectionKey) }
|
||||
></PaymentInfoSection>
|
||||
</>
|
||||
}
|
||||
{ !!transactionInfo &&
|
||||
<>
|
||||
<div className="txn-divider"></div>
|
||||
<TransactionInfoSection
|
||||
transactionCategory={ TransactionCategory.AllTransaction }
|
||||
transactionInfo={ transactionInfo }
|
||||
serviceCode={ serviceCode }
|
||||
isOpen={ showTransactionInfo }
|
||||
onClickToOpenInfo={ (infoSectionKey) => onClickToOpenInfo(infoSectionKey) }
|
||||
></TransactionInfoSection>
|
||||
</>
|
||||
}
|
||||
{ !!settlementInfo &&
|
||||
<>
|
||||
<div className="txn-divider"></div>
|
||||
<SettlementInfoSection
|
||||
transactionCategory={ TransactionCategory.AllTransaction }
|
||||
settlementInfo={ settlementInfo }
|
||||
serviceCode={ serviceCode }
|
||||
isOpen={ showSettlementInfo }
|
||||
onClickToOpenInfo={ (infoSectionKey) => onClickToOpenInfo(infoSectionKey) }
|
||||
></SettlementInfoSection>
|
||||
</>
|
||||
}
|
||||
{ !!partCancelInfo &&
|
||||
<>
|
||||
<div className="txn-divider"></div>
|
||||
<PartCancelInfoSection
|
||||
transactionCategory={ TransactionCategory.AllTransaction }
|
||||
partCancelInfo={ partCancelInfo }
|
||||
serviceCode={ serviceCode }
|
||||
isOpen={ showPartCancelInfo }
|
||||
onClickToOpenInfo={ (infoSectionKey) => onClickToOpenInfo(infoSectionKey) }
|
||||
></PartCancelInfoSection>
|
||||
</>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="apply-row">
|
||||
<button
|
||||
className="btn-50 btn-blue flex-1"
|
||||
onClick={ () => onClickToCancel() }
|
||||
>{t('transaction.cancelTransaction')}</button>
|
||||
</div>
|
||||
</motion.div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
107
src/entities/transaction/ui/detail/billing-detail.tsx
Normal file
107
src/entities/transaction/ui/detail/billing-detail.tsx
Normal file
@@ -0,0 +1,107 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { motion } from 'framer-motion';
|
||||
import { useBillingDetailMutation } from '@/entities/transaction/api/use-billing-detail-mutation';
|
||||
import { BillingInfoSection } from '@/entities/transaction/ui/section/billing-info-section';
|
||||
import {
|
||||
TransactionCategory,
|
||||
BillingDetailParams,
|
||||
BillingDetailResponse,
|
||||
BillingInfo,
|
||||
AmountInfo
|
||||
} from '@/entities/transaction/model/types';
|
||||
import { NumericFormat } from 'react-number-format';
|
||||
import { DetailMotionDuration, DetailMotionStyle, DetailMotionVariants } from '@/entities/common/model/constant';
|
||||
import { FullMenuClose } from '@/entities/common/ui/full-menu-close';
|
||||
|
||||
export interface BillingDetailProps {
|
||||
detailOn: boolean;
|
||||
setDetailOn: (detailOn: boolean) => void;
|
||||
tid: string;
|
||||
};
|
||||
|
||||
export const BillingDetail = ({
|
||||
detailOn,
|
||||
setDetailOn,
|
||||
tid
|
||||
}: BillingDetailProps) => {
|
||||
const { t, i18n } = useTranslation();
|
||||
|
||||
const [billingInfo, setBillingInfo] = useState<BillingInfo>();
|
||||
const [amountInfo, setAmountInfo] = useState<AmountInfo>();
|
||||
|
||||
const { mutateAsync: billingDetail } = useBillingDetailMutation();
|
||||
|
||||
const callDetail = () => {
|
||||
let billingDetailParams: BillingDetailParams = {
|
||||
tid: tid
|
||||
};
|
||||
billingDetail(billingDetailParams).then((rs: BillingDetailResponse) => {
|
||||
setBillingInfo(rs);
|
||||
setAmountInfo({
|
||||
transactionAmount: rs.transactionAmount,
|
||||
buyerName: rs.buyerName
|
||||
})
|
||||
});
|
||||
};
|
||||
const onClickToClose = () => {
|
||||
setDetailOn(false);
|
||||
};
|
||||
useEffect(() => {
|
||||
if(!!detailOn && tid){
|
||||
callDetail();
|
||||
}
|
||||
}, [detailOn]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<motion.div
|
||||
className="full-menu-modal"
|
||||
initial="hidden"
|
||||
animate={ (detailOn)? 'visible': 'hidden' }
|
||||
variants={ DetailMotionVariants }
|
||||
transition={ DetailMotionDuration }
|
||||
style={ DetailMotionStyle }
|
||||
>
|
||||
<div className="full-menu-container pdw-16">
|
||||
<div className="full-menu-header">
|
||||
<div className="full-menu-title center">{ t('billing.detailTitle') }</div>
|
||||
<div className="full-menu-actions">
|
||||
<FullMenuClose
|
||||
addClass="full-menu-close"
|
||||
onClickToCallback={ onClickToClose }
|
||||
></FullMenuClose>
|
||||
</div>
|
||||
</div>
|
||||
<div className="tab-pane sub active">
|
||||
<div className="option-list">
|
||||
<div className="txn-detail">
|
||||
<div className="txn-num-group">
|
||||
<div className="txn-amount">
|
||||
<div className="value">
|
||||
{ i18n.language === 'en' && <span className="unit">{ t('home.currencySymbol') }</span> }
|
||||
<NumericFormat
|
||||
value={ amountInfo?.transactionAmount }
|
||||
thousandSeparator
|
||||
displayType="text"
|
||||
></NumericFormat>
|
||||
{ i18n.language !== 'en' && <span className="unit">{ t('home.currencyWon') }</span> }
|
||||
</div>
|
||||
</div>
|
||||
<div className="txn-mid">
|
||||
<span className="value">{ amountInfo?.buyerName }</span>
|
||||
</div>
|
||||
<div className="txn-doc"></div>
|
||||
</div>
|
||||
<div className="txn-divider"></div>
|
||||
<BillingInfoSection
|
||||
billingInfo={ billingInfo }
|
||||
></BillingInfoSection>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
178
src/entities/transaction/ui/detail/cash-receit-detail.tsx
Normal file
178
src/entities/transaction/ui/detail/cash-receit-detail.tsx
Normal file
@@ -0,0 +1,178 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useLocation } from 'react-router';
|
||||
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
|
||||
import { useCashReceiptDetailMutation } from '@/entities/transaction/api/use-cash-receipt-detail-mutation';
|
||||
import { IssueInfoSection } from '@/entities/transaction/ui/section/issue-info-section';
|
||||
import { DetailInfoSection } from '@/entities/transaction/ui/section/detail-info-section';
|
||||
import {
|
||||
TransactionCategory,
|
||||
CashReceiptDetailParams,
|
||||
DetailResponse,
|
||||
IssueInfo,
|
||||
DetailInfo,
|
||||
InfoSectionKeys,
|
||||
CashReceiptPurposeType,
|
||||
AmountInfo,
|
||||
CashReceiptPurposeUpdateParams,
|
||||
CashReceiptTransactionType
|
||||
} from '@/entities/transaction/model/types';
|
||||
import { CashReceitPurposeUpdateBottomSheet } from '@/entities/transaction/ui/cash-receit-purpose-update-bottom-sheet';
|
||||
import { useCashReceiptPurposeUpdateMutation } from '@/entities/transaction/api/use-cash-receipt-purpose-update-mutation';
|
||||
import { AmountInfoSection } from '@/entities/transaction/ui/section/amount-info-section';
|
||||
import { snackBar } from '@/shared/lib';
|
||||
import { DetailMotionDuration, DetailMotionStyle, DetailMotionVariants } from '@/entities/common/model/constant';
|
||||
import { FullMenuClose } from '@/entities/common/ui/full-menu-close';
|
||||
|
||||
export interface CashReceiptDetailProps {
|
||||
detailOn: boolean;
|
||||
setDetailOn: (detailOn: boolean) => void;
|
||||
tid: string;
|
||||
};
|
||||
|
||||
export const CashReceiptDetail = ({
|
||||
detailOn,
|
||||
setDetailOn,
|
||||
tid
|
||||
}: CashReceiptDetailProps) => {
|
||||
const { navigate, reload } = useNavigate();
|
||||
const { t } = useTranslation();
|
||||
const location = useLocation();
|
||||
|
||||
const [amountInfo, setAmountInfo] = useState<AmountInfo>();
|
||||
const [issueInfo, setIssueInfo] = useState<IssueInfo>();
|
||||
const [detailInfo, setDetailInfo] = useState<DetailInfo>();
|
||||
const [showAmountInfo, setShowAmountInfo] = useState<boolean>(false);
|
||||
const [showDetailInfo, setShowDetailInfo] = useState<boolean>(false);
|
||||
const [bottomSheetOn, setBottomSheetOn] = useState<boolean>(false);
|
||||
const [purposeType, setPurposeType] = useState<string>();
|
||||
const [canDownloadReceipt, setCanDownloadReceipt] = useState<boolean>(false);
|
||||
|
||||
const { mutateAsync: cashReceiptDetail } = useCashReceiptDetailMutation();
|
||||
const { mutateAsync: cashReceiptPurposeUpdate } = useCashReceiptPurposeUpdateMutation();
|
||||
|
||||
const callPurposeUpdate = () => {
|
||||
let newPurpose = (purposeType === CashReceiptPurposeType.EXPENSE_PROOF)
|
||||
? CashReceiptPurposeType.INCOME_DEDUCTION: CashReceiptPurposeType.EXPENSE_PROOF;
|
||||
let params: CashReceiptPurposeUpdateParams = {
|
||||
tid: tid,
|
||||
newPurpose: newPurpose
|
||||
};
|
||||
cashReceiptPurposeUpdate(params).then((rs) => {
|
||||
setPurposeType(rs.afterPurposeType);
|
||||
setBottomSheetOn(false);
|
||||
snackBar('용도 변경을 성공하였습니다.', function(){
|
||||
reload();
|
||||
}, 2000);
|
||||
});
|
||||
};
|
||||
|
||||
const callDetail = () => {
|
||||
let cashReceitDetailParams: CashReceiptDetailParams = {
|
||||
tid: tid
|
||||
};
|
||||
cashReceiptDetail(cashReceitDetailParams).then((rs: DetailResponse) => {
|
||||
if(rs.amountDetail){
|
||||
rs.amountDetail.customerName = rs.customerName;
|
||||
}
|
||||
setAmountInfo(rs.amountDetail || {});
|
||||
setIssueInfo(rs.issueInfo || {});
|
||||
setDetailInfo(rs.detailInfo || {});
|
||||
setCanDownloadReceipt(rs.detailInfo?.canDownloadReceipt || false);
|
||||
if(rs.issueInfo){
|
||||
setPurposeType(rs.issueInfo.purpose);
|
||||
}
|
||||
});
|
||||
};
|
||||
useEffect(() => {
|
||||
if(!!detailOn && tid){
|
||||
callDetail();
|
||||
}
|
||||
}, [tid]);
|
||||
|
||||
const onClickToOpenInfo = (infoSectionKey: InfoSectionKeys) => {
|
||||
if(infoSectionKey === InfoSectionKeys.Amount){
|
||||
setShowAmountInfo(!showAmountInfo);
|
||||
}
|
||||
else if(infoSectionKey === InfoSectionKeys.Detail){
|
||||
setShowDetailInfo(!showDetailInfo);
|
||||
}
|
||||
};
|
||||
|
||||
const onClickToClose = () => {
|
||||
setDetailOn(false);
|
||||
};
|
||||
|
||||
const onClickToPurposeUpdate = () => {
|
||||
setBottomSheetOn(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<motion.div
|
||||
className="full-menu-modal"
|
||||
initial="hidden"
|
||||
animate={ (detailOn)? 'visible': 'hidden' }
|
||||
variants={ DetailMotionVariants }
|
||||
transition={ DetailMotionDuration }
|
||||
style={ DetailMotionStyle }
|
||||
>
|
||||
<div className="full-menu-container pdw-16">
|
||||
<div className="full-menu-header">
|
||||
<div className="full-menu-title center">{ t('cashReceipt.detailTitle') }</div>
|
||||
<div className="full-menu-actions">
|
||||
<FullMenuClose
|
||||
addClass="full-menu-close"
|
||||
onClickToCallback={ onClickToClose }
|
||||
></FullMenuClose>
|
||||
</div>
|
||||
</div>
|
||||
<div className="tab-pane sub active">
|
||||
<div className={ `option-list ${(detailInfo?.canDownloadReceipt)? 'pb-86': ''}` }>
|
||||
<div className="txn-detail">
|
||||
<AmountInfoSection
|
||||
transactionCategory={ TransactionCategory.CashReceipt }
|
||||
amountInfo={ amountInfo }
|
||||
isOpen={ showAmountInfo }
|
||||
onClickToOpenInfo={ (infoSectionKey) => onClickToOpenInfo(infoSectionKey) }
|
||||
purposeType={ purposeType }
|
||||
canDownloadReceipt={ canDownloadReceipt }
|
||||
></AmountInfoSection>
|
||||
<div className="txn-divider"></div>
|
||||
<IssueInfoSection
|
||||
transactionCategory={ TransactionCategory.CashReceipt }
|
||||
issueInfo={ issueInfo }
|
||||
purposeType={ purposeType }
|
||||
></IssueInfoSection>
|
||||
<div className="txn-divider minus"></div>
|
||||
{ !!detailInfo &&
|
||||
<DetailInfoSection
|
||||
transactionCategory={ TransactionCategory.CashReceipt }
|
||||
detailInfo={ detailInfo }
|
||||
isOpen={ showDetailInfo }
|
||||
onClickToOpenInfo={ (infoSectionKey) => onClickToOpenInfo(infoSectionKey) }
|
||||
></DetailInfoSection>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
{ (issueInfo?.transactionType === CashReceiptTransactionType.APPROVAL) &&
|
||||
(issueInfo?.processResult === '발급완료') &&
|
||||
<div className="apply-row">
|
||||
<button
|
||||
className="btn-50 btn-blue flex-1"
|
||||
onClick={ () => onClickToPurposeUpdate() }
|
||||
>{ t('cashReceipt.changePurpose') }</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
<CashReceitPurposeUpdateBottomSheet
|
||||
setBottomSheetOn={ setBottomSheetOn }
|
||||
bottomSheetOn={ bottomSheetOn }
|
||||
callPurposeUpdate={ callPurposeUpdate }
|
||||
></CashReceitPurposeUpdateBottomSheet>
|
||||
</>
|
||||
);
|
||||
};
|
||||
225
src/entities/transaction/ui/detail/escrow-detail.tsx
Normal file
225
src/entities/transaction/ui/detail/escrow-detail.tsx
Normal file
@@ -0,0 +1,225 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { motion } from 'framer-motion';
|
||||
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
|
||||
import { useEscrowDetailMutation } from '@/entities/transaction/api/use-escrow-detail-mutation';
|
||||
import { ImportantInfoSection } from '@/entities/transaction/ui/section/important-info-section';
|
||||
import { EscrowInfoSection } from '@/entities/transaction/ui/section/escrow-info-section';
|
||||
import { PaymentInfoSection } from '@/entities/transaction/ui/section/payment-info-section';
|
||||
import { TransactionInfoSection } from '@/entities/transaction/ui/section/transaction-info-section';
|
||||
import { SettlementInfoSection } from '@/entities/transaction/ui/section/settlement-info-section';
|
||||
import {
|
||||
TransactionCategory,
|
||||
EscrowDetailParams,
|
||||
DetailResponse,
|
||||
ImportantInfo,
|
||||
EscrowInfo,
|
||||
PaymentInfo,
|
||||
TransactionInfo,
|
||||
SettlementInfo,
|
||||
InfoSectionKeys,
|
||||
MerchantInfo,
|
||||
AmountInfo
|
||||
} from '@/entities/transaction/model/types';
|
||||
import { useEscrowMailResendMutation } from '@/entities/transaction/api/use-escrow-mail-resend-mutation';
|
||||
import { MerchantInfoSection } from '@/entities/transaction/ui/section/merchant-info-section';
|
||||
import { AmountInfoSection } from '@/entities/transaction/ui/section/amount-info-section';
|
||||
import { EmailBottomSheet } from '@/entities/common/ui/email-bottom-sheet';
|
||||
import { DetailMotionDuration, DetailMotionStyle, DetailMotionVariants } from '@/entities/common/model/constant';
|
||||
import { FullMenuClose } from '@/entities/common/ui/full-menu-close';
|
||||
|
||||
export interface EscrowDetailProps {
|
||||
detailOn: boolean;
|
||||
setDetailOn: (detailOn: boolean) => void;
|
||||
tid: string;
|
||||
serviceCode: string;
|
||||
};
|
||||
|
||||
export const EscrowDetail = ({
|
||||
detailOn,
|
||||
setDetailOn,
|
||||
tid,
|
||||
serviceCode
|
||||
}: EscrowDetailProps) => {
|
||||
const { navigate } = useNavigate();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [amountInfo, setAmountInfo] = useState<AmountInfo>();
|
||||
const [importantInfo, setImportantInfo] = useState<ImportantInfo>();
|
||||
const [escrowInfo, setEscrowInfo] = useState<EscrowInfo>();
|
||||
const [paymentInfo, setPaymentInfo] = useState<PaymentInfo>();
|
||||
const [transactionInfo, setTransactionInfo] = useState<TransactionInfo>();
|
||||
const [settlementInfo, setSettlementInfo] = useState<SettlementInfo>();
|
||||
const [merchantInfo, setMerchantInfo] = useState<MerchantInfo>();
|
||||
|
||||
const [showAmountInfo, setShowAmountInfo] = useState<boolean>(false);
|
||||
const [showImportantInfo, setShowImportantInfo] = useState<boolean>(false);
|
||||
const [showEscroInfo, setShowEscroInfo] = useState<boolean>(false);
|
||||
const [showPaymentInfo, setShowPaymentInfo] = useState<boolean>(false);
|
||||
const [showTransactionInfo, setShowTransactionInfo] = useState<boolean>(false);
|
||||
const [showSettlementInfo, setShowSettlementInfo] = useState<boolean>(false);
|
||||
const [showMerchantInfo, setShowMerchantInfo] = useState<boolean>(false);
|
||||
|
||||
const [bottomSheetOn, setBottomSheetOn] = useState<boolean>(false);
|
||||
|
||||
const [orderNumber, setOrderNumber] = useState<string>();
|
||||
|
||||
const { mutateAsync: escrowDetail } = useEscrowDetailMutation();
|
||||
const { mutateAsync: escrowMailResend } = useEscrowMailResendMutation()
|
||||
|
||||
const callDetail = () => {
|
||||
let escroDetailParams: EscrowDetailParams = {
|
||||
tid: tid,
|
||||
};
|
||||
escrowDetail(escroDetailParams).then((rs: DetailResponse) => {
|
||||
setAmountInfo(rs.paymentInfo || {});
|
||||
setImportantInfo(rs.importantInfo || {});
|
||||
setEscrowInfo(rs.escrowInfo || {});
|
||||
setPaymentInfo(rs.paymentInfo || {});
|
||||
setTransactionInfo(rs.transactionInfo || {});
|
||||
setSettlementInfo(rs.settlementInfo || {});
|
||||
setMerchantInfo(rs.merchantInfo || {});
|
||||
|
||||
setOrderNumber(rs.importantInfo?.orderNumber);
|
||||
});
|
||||
};
|
||||
useEffect(() => {
|
||||
if(!!detailOn && serviceCode && tid){
|
||||
callDetail();
|
||||
}
|
||||
}, [detailOn]);
|
||||
|
||||
|
||||
const onClickToShowMailResend = () => {
|
||||
setBottomSheetOn(true);
|
||||
};
|
||||
|
||||
const callMailResend = () => {
|
||||
let params = {
|
||||
orderNumber: orderNumber,
|
||||
tid: tid,
|
||||
};
|
||||
escrowMailResend(params).then((rs: any) => {
|
||||
console.log(rs);
|
||||
});
|
||||
};
|
||||
|
||||
const onClickToClose = () => {
|
||||
setDetailOn(false);
|
||||
};
|
||||
|
||||
const onClickToOpenInfo = (infoSectionKey: InfoSectionKeys) => {
|
||||
if(infoSectionKey === InfoSectionKeys.Amount){
|
||||
setShowAmountInfo(!showAmountInfo);
|
||||
}
|
||||
else if(infoSectionKey === InfoSectionKeys.Important){
|
||||
setShowImportantInfo(!showImportantInfo);
|
||||
}
|
||||
else if(infoSectionKey === InfoSectionKeys.Escrow){
|
||||
setShowEscroInfo(!showEscroInfo);
|
||||
}
|
||||
else if(infoSectionKey === InfoSectionKeys.Payment){
|
||||
setShowPaymentInfo(!showPaymentInfo);
|
||||
}
|
||||
else if(infoSectionKey === InfoSectionKeys.Transaction){
|
||||
setShowTransactionInfo(!showTransactionInfo);
|
||||
}
|
||||
else if(infoSectionKey === InfoSectionKeys.Settlement){
|
||||
setShowSettlementInfo(!showSettlementInfo);
|
||||
}
|
||||
else if(infoSectionKey === InfoSectionKeys.Merchant){
|
||||
setShowMerchantInfo(!showMerchantInfo);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<motion.div
|
||||
className="full-menu-modal"
|
||||
initial="hidden"
|
||||
animate={ (detailOn)? 'visible': 'hidden' }
|
||||
variants={ DetailMotionVariants }
|
||||
transition={ DetailMotionDuration }
|
||||
style={ DetailMotionStyle }
|
||||
>
|
||||
<div className="full-menu-container pdw-16">
|
||||
<div className="full-menu-header">
|
||||
<div className="full-menu-title center">{ t('escrow.detailTitle') }</div>
|
||||
<div className="full-menu-actions">
|
||||
<FullMenuClose
|
||||
addClass="full-menu-close"
|
||||
onClickToCallback={ onClickToClose }
|
||||
></FullMenuClose>
|
||||
</div>
|
||||
</div>
|
||||
<div className="tab-pane sub active">
|
||||
<div className="option-list">
|
||||
<div className="txn-detail">
|
||||
<AmountInfoSection
|
||||
transactionCategory={ TransactionCategory.Escrow }
|
||||
amountInfo={ amountInfo }
|
||||
isOpen={ showAmountInfo }
|
||||
tid={ tid }
|
||||
serviceCode={ serviceCode }
|
||||
onClickToOpenInfo={ (infoSectionKey) => onClickToOpenInfo(infoSectionKey) }
|
||||
></AmountInfoSection>
|
||||
<div className="txn-divider minus"></div>
|
||||
<ImportantInfoSection
|
||||
transactionCategory={ TransactionCategory.Escrow }
|
||||
importantInfo={ importantInfo }
|
||||
></ImportantInfoSection>
|
||||
<div className="txn-divider minus"></div>
|
||||
<EscrowInfoSection
|
||||
escrowInfo={ escrowInfo }
|
||||
isOpen={ showEscroInfo }
|
||||
onClickToOpenInfo={ (infoSectionKey) => onClickToOpenInfo(infoSectionKey) }
|
||||
></EscrowInfoSection>
|
||||
<div className="txn-divider minus"></div>
|
||||
<PaymentInfoSection
|
||||
transactionCategory={ TransactionCategory.Escrow }
|
||||
paymentInfo={ paymentInfo }
|
||||
isOpen={ showPaymentInfo }
|
||||
serviceCode={ serviceCode }
|
||||
onClickToOpenInfo={ (infoSectionKey) => onClickToOpenInfo(infoSectionKey) }
|
||||
></PaymentInfoSection>
|
||||
<div className="txn-divider"></div>
|
||||
<TransactionInfoSection
|
||||
transactionCategory={ TransactionCategory.Escrow }
|
||||
transactionInfo={ transactionInfo }
|
||||
isOpen={ showTransactionInfo }
|
||||
onClickToOpenInfo={ (infoSectionKey) => onClickToOpenInfo(infoSectionKey) }
|
||||
></TransactionInfoSection>
|
||||
<div className="txn-divider"></div>
|
||||
<SettlementInfoSection
|
||||
transactionCategory={ TransactionCategory.Escrow }
|
||||
settlementInfo={ settlementInfo }
|
||||
isOpen={ showSettlementInfo }
|
||||
onClickToOpenInfo={ (infoSectionKey) => onClickToOpenInfo(infoSectionKey) }
|
||||
></SettlementInfoSection>
|
||||
<div className="txn-divider"></div>
|
||||
<MerchantInfoSection
|
||||
merchantInfo={ merchantInfo }
|
||||
isOpen={ showMerchantInfo }
|
||||
onClickToOpenInfo={ (infoSectionKey) => onClickToOpenInfo(infoSectionKey) }
|
||||
></MerchantInfoSection>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="apply-row">
|
||||
<button
|
||||
className="btn-50 btn-blue flex-1"
|
||||
onClick={ () => onClickToShowMailResend() }
|
||||
>메일 재발송</button>
|
||||
</div>
|
||||
</motion.div>
|
||||
<EmailBottomSheet
|
||||
setBottomSheetOn={ setBottomSheetOn }
|
||||
bottomSheetOn={ bottomSheetOn }
|
||||
imageSave={ false }
|
||||
sendEmail={ true }
|
||||
sendRequest={ callMailResend }
|
||||
></EmailBottomSheet>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -3,7 +3,8 @@ import { ListDateGroup } from './list-date-group';
|
||||
|
||||
export const EscrowList = ({
|
||||
transactionCategory,
|
||||
listItems
|
||||
listItems,
|
||||
setDetailData
|
||||
}: EscrowListProps) => {
|
||||
|
||||
const getListDateGroup = () => {
|
||||
@@ -26,6 +27,7 @@ export const EscrowList = ({
|
||||
key={ date + '-' + i }
|
||||
date={ date }
|
||||
items={ list }
|
||||
setDetailData={ setDetailData }
|
||||
></ListDateGroup>
|
||||
);
|
||||
}
|
||||
@@ -43,6 +45,7 @@ export const EscrowList = ({
|
||||
key={ date + '-last' }
|
||||
date={ date }
|
||||
items={ list }
|
||||
setDetailData={ setDetailData }
|
||||
></ListDateGroup>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,8 @@ import { useTranslation } from 'react-i18next';
|
||||
export const ListDateGroup = ({
|
||||
transactionCategory,
|
||||
date,
|
||||
items
|
||||
items,
|
||||
setDetailData
|
||||
}: ListDateGroupProps) => {
|
||||
const { t, i18n } = useTranslation();
|
||||
|
||||
@@ -93,6 +94,8 @@ export const ListDateGroup = ({
|
||||
|
||||
billKey={ items[i]?.billKey }
|
||||
orderNumber={ items[i]?.orderNumber }
|
||||
|
||||
setDetailData={ setDetailData }
|
||||
></ListItem>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import { NumericFormat } from 'react-number-format';
|
||||
import { PATHS } from '@/shared/constants/paths';
|
||||
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
|
||||
import { BillingRequestStatus, CashReceiptTransactionType, EscrowDeliveryStatus, ListItemProps, TransactionCategory } from '../model/types';
|
||||
import moment from 'moment';
|
||||
import { useStore } from '@/shared/model/store';
|
||||
import { getAllTransactionStatusCode, getPaymentMethodName } from '../model/contant';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
@@ -16,9 +13,9 @@ export const ListItem = ({
|
||||
paymentMethod, processResult, transactionType,
|
||||
transactionDateTime, transactionAmount,
|
||||
deliveryStatus, settlementStatus,
|
||||
cancelStatus, billKey, orderNumber, requestStatus
|
||||
cancelStatus, billKey, orderNumber, requestStatus,
|
||||
setDetailData
|
||||
}: ListItemProps) => {
|
||||
const { navigate } = useNavigate();
|
||||
const { t } = useTranslation();
|
||||
const getItemClass = () => {
|
||||
let rs = '';
|
||||
@@ -88,34 +85,38 @@ export const ListItem = ({
|
||||
|
||||
const onClickToNavigate = () => {
|
||||
if(transactionCategory === TransactionCategory.AllTransaction){
|
||||
navigate(PATHS.transaction.allTransaction.detail, {
|
||||
state: {
|
||||
if(setDetailData && tid){
|
||||
setDetailData({
|
||||
tid: tid,
|
||||
serviceCode: serviceCode
|
||||
}
|
||||
});
|
||||
serviceCode: serviceCode,
|
||||
detailOn: true
|
||||
});
|
||||
}
|
||||
}
|
||||
else if(transactionCategory === TransactionCategory.CashReceipt){
|
||||
navigate(PATHS.transaction.cashReceipt.detail, {
|
||||
state: {
|
||||
tid: tid
|
||||
}
|
||||
});
|
||||
if(setDetailData && tid){
|
||||
setDetailData({
|
||||
tid: tid,
|
||||
detailOn: true
|
||||
});
|
||||
}
|
||||
}
|
||||
else if(transactionCategory === TransactionCategory.Escrow){
|
||||
navigate(PATHS.transaction.escrow.detail, {
|
||||
state: {
|
||||
tid: tid,
|
||||
serviceCode: serviceCode
|
||||
}
|
||||
});
|
||||
if(setDetailData && tid){
|
||||
setDetailData({
|
||||
tid: tid,
|
||||
serviceCode: serviceCode,
|
||||
detailOn: true
|
||||
});
|
||||
}
|
||||
}
|
||||
else if(transactionCategory === TransactionCategory.Billing){
|
||||
navigate(PATHS.transaction.billing.detail, {
|
||||
state: {
|
||||
if(setDetailData && tid){
|
||||
setDetailData({
|
||||
tid: tid,
|
||||
}
|
||||
});
|
||||
detailOn: true
|
||||
});
|
||||
}
|
||||
}
|
||||
else{
|
||||
alert(t('common.error'));
|
||||
|
||||
@@ -51,7 +51,8 @@ export interface VatReturnListResponse extends DefaulResponsePagination {
|
||||
};
|
||||
|
||||
export interface VatReturnListContent {
|
||||
id?: number
|
||||
id?: number;
|
||||
taxInvoiceNumber?: string;
|
||||
companyName?: string;
|
||||
mid?: string;
|
||||
issueDate?: string;
|
||||
@@ -61,15 +62,22 @@ export interface VatReturnListContent {
|
||||
|
||||
export interface ListDateGroupProps {
|
||||
date?: string;
|
||||
items?: Array<VatReturnListContent>
|
||||
}
|
||||
items?: Array<VatReturnListContent>;
|
||||
setDetailData?: (detailData: DetailData) => void;
|
||||
};
|
||||
|
||||
export interface DetailData {
|
||||
taxInvoiceNumber: string;
|
||||
detailOn: boolean;
|
||||
};
|
||||
export interface ListItemProps {
|
||||
id?: number;
|
||||
taxInvoiceNumber?: string;
|
||||
companyName?: string;
|
||||
mid?: string;
|
||||
issueDate?: string;
|
||||
paymentMethod?: string;
|
||||
amount?: number;
|
||||
setDetailData?: (detailData: DetailData) => void;
|
||||
}
|
||||
export interface VatReturnDetailParams {
|
||||
taxInvoiceNumber?: string;
|
||||
|
||||
162
src/entities/vat-return/ui/detail/tax-invoice-detail.tsx
Normal file
162
src/entities/vat-return/ui/detail/tax-invoice-detail.tsx
Normal file
@@ -0,0 +1,162 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { motion } from 'framer-motion';
|
||||
import { PATHS } from '@/shared/constants/paths';
|
||||
import { useLocation } from 'react-router';
|
||||
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
|
||||
import { useVatReturnDetailMutation } from '@/entities/vat-return/api/use-vat-return-detail-mutation';
|
||||
import { HeaderType } from '@/entities/common/model/types';
|
||||
import {
|
||||
Breakdown,
|
||||
VatReturnBreakdownParams,
|
||||
VatReturnBreakdownResponse,
|
||||
VatReturnDetailParams,
|
||||
VatReturnDetailResponse
|
||||
} from '@/entities/vat-return/model/types';
|
||||
import {
|
||||
useSetOnBack,
|
||||
useSetHeaderTitle,
|
||||
useSetHeaderType,
|
||||
useSetFooterMode
|
||||
} from '@/widgets/sub-layout/use-sub-layout';
|
||||
import { SupplierSection } from '@/entities/vat-return/ui/section/supplier-section';
|
||||
import { ReceiverSection } from '@/entities/vat-return/ui/section/receiver-section';
|
||||
import { IssueSection } from '@/entities/vat-return/ui/section/issue-section';
|
||||
import { AmountSection } from '@/entities/vat-return/ui/section/amount-section';
|
||||
import { useVatReturnTaxInvoiceMutation } from '@/entities/vat-return/api/use-vat-return-tax-invoice-mutation';
|
||||
import { VatReturnListDetailBottomSheet } from '@/entities/vat-return/ui/list-detail-bottom-sheet';
|
||||
import { useVatReturnBreakdownMutation } from '@/entities/vat-return/api/use-vat-return-breakdown-mutation';
|
||||
import { DetailMotionDuration, DetailMotionStyle, DetailMotionVariants } from '@/entities/common/model/constant';
|
||||
import { FullMenuClose } from '@/entities/common/ui/full-menu-close';
|
||||
|
||||
export interface TaxInvoiceDetailProps {
|
||||
detailOn: boolean;
|
||||
setDetailOn: (detailOn: boolean) => void;
|
||||
taxInvoiceNumber: string;
|
||||
};
|
||||
|
||||
export const TaxInvoiceDetail = ({
|
||||
detailOn,
|
||||
setDetailOn,
|
||||
taxInvoiceNumber
|
||||
}: TaxInvoiceDetailProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { navigate } = useNavigate();
|
||||
const location = useLocation();
|
||||
|
||||
// taxInvoiceNumber = 'TAX202506300001';
|
||||
|
||||
const [openAmount, setOpenAmount] = useState<boolean>(false);
|
||||
const [bottomSheetOn, setBottomSheetOn] = useState<boolean>(false);
|
||||
const [detail, setDetail] = useState<VatReturnDetailResponse>({});
|
||||
const [breakdown, setBreakdown] = useState<Array<Breakdown>>([]);
|
||||
|
||||
useSetHeaderTitle(t('vatReturn.taxInvoiceDetail'));
|
||||
useSetHeaderType(HeaderType.RightClose);
|
||||
useSetOnBack(() => {
|
||||
navigate(PATHS.vatReturn.list);
|
||||
});
|
||||
useSetFooterMode(false);
|
||||
|
||||
const { mutateAsync: vatReturnTaxInvoice } = useVatReturnTaxInvoiceMutation();
|
||||
const { mutateAsync: vatReturnDetail } = useVatReturnDetailMutation();
|
||||
const { mutateAsync: vatReturnBreakdown } = useVatReturnBreakdownMutation();
|
||||
|
||||
const callTaxInvoice = () => {
|
||||
if(taxInvoiceNumber){
|
||||
let params: VatReturnDetailParams = {
|
||||
taxInvoiceNumber: taxInvoiceNumber,
|
||||
};
|
||||
vatReturnDetail(params).then((rs: VatReturnDetailResponse) => {
|
||||
setDetail(rs);
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
const callVatReturnBreakdown = async() => {
|
||||
let params: VatReturnBreakdownParams = {
|
||||
taxInvoiceNumber: taxInvoiceNumber,
|
||||
};
|
||||
vatReturnBreakdown(params).then((rs: VatReturnBreakdownResponse) => {
|
||||
setBreakdown(rs.breakdown);
|
||||
});
|
||||
};
|
||||
|
||||
const onClickToOpenBottomSheet = () => {
|
||||
setBottomSheetOn(true);
|
||||
};
|
||||
|
||||
const onClickToClose = () => {
|
||||
setDetailOn(false);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if(!!detailOn && taxInvoiceNumber){
|
||||
callTaxInvoice();
|
||||
callVatReturnBreakdown();
|
||||
}
|
||||
}, [detailOn]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<motion.div
|
||||
className="full-menu-modal"
|
||||
initial="hidden"
|
||||
animate={ (detailOn)? 'visible': 'hidden' }
|
||||
variants={ DetailMotionVariants }
|
||||
transition={ DetailMotionDuration }
|
||||
style={ DetailMotionStyle }
|
||||
>
|
||||
<div className="full-menu-container pdw-16">
|
||||
<div className="full-menu-header">
|
||||
<div className="full-menu-title center">{ t('transaction.detailTitle') }</div>
|
||||
<div className="full-menu-actions">
|
||||
<FullMenuClose
|
||||
addClass="full-menu-close"
|
||||
onClickToCallback={ onClickToClose }
|
||||
></FullMenuClose>
|
||||
</div>
|
||||
</div>
|
||||
<div className="tab-pane sub active">
|
||||
<div className="option-list">
|
||||
<div className="txn-detail">
|
||||
<AmountSection
|
||||
detail={ detail }
|
||||
></AmountSection>
|
||||
<div className="txn-divider minus"></div>
|
||||
<IssueSection
|
||||
detail={ detail }
|
||||
></IssueSection>
|
||||
<div className="txn-divider minus"></div>
|
||||
<ReceiverSection
|
||||
detail={ detail }
|
||||
></ReceiverSection>
|
||||
<div className="txn-divider"></div>
|
||||
<SupplierSection
|
||||
detail={ detail }
|
||||
></SupplierSection>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="apply-row">
|
||||
<button
|
||||
className="btn-50 btn-blue flex-1"
|
||||
onClick={ onClickToOpenBottomSheet }
|
||||
>{t('vatReturn.viewDetails')}</button>
|
||||
</div>
|
||||
</motion.div>
|
||||
{ !!bottomSheetOn &&
|
||||
<VatReturnListDetailBottomSheet
|
||||
bottomSheetOn={ bottomSheetOn }
|
||||
setBottomSheetOn={ setBottomSheetOn }
|
||||
breakdown={ breakdown }
|
||||
transactionAmount={ detail?.transactionAmount }
|
||||
supplyAmount={ detail?.supplyAmount }
|
||||
vatAmount={ detail?.vatAmount }
|
||||
totalAmount={ detail?.totalAmount }
|
||||
></VatReturnListDetailBottomSheet>
|
||||
}
|
||||
</>
|
||||
)
|
||||
};
|
||||
@@ -5,7 +5,8 @@ import { ListItem } from './list-item';
|
||||
|
||||
export const ListDateGroup = ({
|
||||
date,
|
||||
items
|
||||
items,
|
||||
setDetailData
|
||||
}: ListDateGroupProps) => {
|
||||
moment.locale('ko');
|
||||
const getStateDate = () => {
|
||||
@@ -21,12 +22,13 @@ export const ListDateGroup = ({
|
||||
rs.push(
|
||||
<ListItem
|
||||
key={ key }
|
||||
id={ items[i]?.id || 0 }
|
||||
taxInvoiceNumber={ items[i]?.taxInvoiceNumber || '' }
|
||||
companyName={ items[i]?.companyName || '' }
|
||||
mid={ items[i]?.mid || '' }
|
||||
issueDate={ items[i]?.issueDate || '' }
|
||||
paymentMethod={ items[i]?.paymentMethod || '' }
|
||||
amount={ items[i]?.amount || 0 }
|
||||
setDetailData={ setDetailData }
|
||||
></ListItem>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,27 +1,25 @@
|
||||
import { NumericFormat } from 'react-number-format';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
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 = ({
|
||||
id,
|
||||
taxInvoiceNumber,
|
||||
companyName,
|
||||
mid,
|
||||
issueDate,
|
||||
paymentMethod,
|
||||
amount
|
||||
amount,
|
||||
setDetailData
|
||||
}: ListItemProps) => {
|
||||
const { t, i18n } = useTranslation();
|
||||
const { navigate } = useNavigate();
|
||||
|
||||
const onClickToNavigate = () => {
|
||||
navigate(PATHS.vatReturn.detail, {
|
||||
state: {
|
||||
taxInvoiceNumber: id
|
||||
}
|
||||
});
|
||||
if(setDetailData && taxInvoiceNumber){
|
||||
setDetailData({
|
||||
taxInvoiceNumber: taxInvoiceNumber,
|
||||
detailOn: true
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -7,6 +7,7 @@ import { SortTypeBox } from '@/entities/common/ui/sort-type-box';
|
||||
import { DefaultRequestPagination, SortTypeKeys } from '@/entities/common/model/types';
|
||||
import { DEFAULT_PAGE_PARAM } from '@/entities/common/model/constant';
|
||||
import {
|
||||
DetailData,
|
||||
VatReturnListContent,
|
||||
VatReturnListParams,
|
||||
VatReturnListResponse,
|
||||
@@ -18,6 +19,7 @@ import { ListDateGroup } from './list-date-group';
|
||||
import { useStore } from '@/shared/model/store';
|
||||
import { EmailBottomSheet } from '@/entities/common/ui/email-bottom-sheet';
|
||||
import useIntersectionObserver from '@/widgets/intersection-observer';
|
||||
import { TaxInvoiceDetail } from './detail/tax-invoice-detail';
|
||||
|
||||
export const ListWrap = () => {
|
||||
const { t } = useTranslation();
|
||||
@@ -36,7 +38,10 @@ export const ListWrap = () => {
|
||||
|
||||
const [emailBottomSheetOn, setEmailBottomSheetOn] = useState<boolean>(false);
|
||||
|
||||
const [detailOn, setDetailOn] = useState<boolean>(false);
|
||||
const [detailTaxInvoiceNumber, setDetailTaxInvoiceNumber] = useState<string>('');
|
||||
const { mutateAsync: vatReturnList } = useVatReturnListMutation();
|
||||
|
||||
const onIntersect: IntersectionObserverCallback = (entries: Array<IntersectionObserverEntry>) => {
|
||||
entries.forEach((entry: IntersectionObserverEntry) => {
|
||||
if(entry.isIntersecting){
|
||||
@@ -122,6 +127,11 @@ export const ListWrap = () => {
|
||||
mid, startMonth, endMonth,
|
||||
receiptType, targetType, sortType
|
||||
]);
|
||||
const setDetailData = (detailData: DetailData) => {
|
||||
setDetailOn(detailData.detailOn);
|
||||
setDetailTaxInvoiceNumber(detailData.taxInvoiceNumber);
|
||||
};
|
||||
|
||||
|
||||
const getListDateGroup = () => {
|
||||
let rs = [];
|
||||
@@ -144,6 +154,7 @@ export const ListWrap = () => {
|
||||
key={ date + '-' + i }
|
||||
date={ date }
|
||||
items={ list }
|
||||
setDetailData={ setDetailData }
|
||||
></ListDateGroup>
|
||||
);
|
||||
}
|
||||
@@ -160,6 +171,7 @@ export const ListWrap = () => {
|
||||
key={ date + '-last' }
|
||||
date={ date }
|
||||
items={ list }
|
||||
setDetailData={ setDetailData }
|
||||
></ListDateGroup>
|
||||
);
|
||||
}
|
||||
@@ -220,6 +232,12 @@ export const ListWrap = () => {
|
||||
setReceiptType={ setReceiptType }
|
||||
setTargetType={ setTargetType }
|
||||
></ListFilter>
|
||||
<TaxInvoiceDetail
|
||||
detailOn={ detailOn }
|
||||
setDetailOn={ setDetailOn }
|
||||
taxInvoiceNumber={ detailTaxInvoiceNumber }
|
||||
>
|
||||
</TaxInvoiceDetail>
|
||||
{ !!emailBottomSheetOn &&
|
||||
<EmailBottomSheet
|
||||
bottomSheetOn={ emailBottomSheetOn }
|
||||
|
||||
Reference in New Issue
Block a user