상세 수정

This commit is contained in:
focp212@naver.com
2025-11-03 20:57:55 +09:00
parent 344e5c324a
commit d2b477e7bd
38 changed files with 1569 additions and 256 deletions

View 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>
</>
);
};