-
+ {t('home.money', { value: new Intl.NumberFormat('en-US').format(detail?.amount || 0) })}
{ detail?.corpName }
diff --git a/src/pages/additional-service/fund-account/result-detail-page.tsx b/src/pages/additional-service/fund-account/result-detail-page.tsx
index 0eb880d..5c2491b 100644
--- a/src/pages/additional-service/fund-account/result-detail-page.tsx
+++ b/src/pages/additional-service/fund-account/result-detail-page.tsx
@@ -86,13 +86,7 @@ export const FundAccountResultDetailPage = () => {
-
+ {t('home.money', { value: new Intl.NumberFormat('en-US').format(detail?.amount || 0) })}
{detail?.accountName}({detail?.accountNo})
diff --git a/src/pages/additional-service/fund-account/transfer-detail-page.tsx b/src/pages/additional-service/fund-account/transfer-detail-page.tsx
index 30534ab..e1bc605 100644
--- a/src/pages/additional-service/fund-account/transfer-detail-page.tsx
+++ b/src/pages/additional-service/fund-account/transfer-detail-page.tsx
@@ -79,13 +79,7 @@ export const FundAccountTransferDetailPage = () => {
-
+ {t('home.money', { value: new Intl.NumberFormat('en-US').format(detail?.amount || 0) })}
{detail?.accountName}({detail?.accountNo})
diff --git a/src/pages/additional-service/link-payment/apply/link-payment-apply-confirm-page.tsx b/src/pages/additional-service/link-payment/apply/link-payment-apply-confirm-page.tsx
index e6e011d..4381a08 100644
--- a/src/pages/additional-service/link-payment/apply/link-payment-apply-confirm-page.tsx
+++ b/src/pages/additional-service/link-payment/apply/link-payment-apply-confirm-page.tsx
@@ -52,17 +52,9 @@ export const LinkPaymentApplyConfirmPage = () => {
if (rs.status) {
navigate(PATHS.additionalService.linkPayment.confirmSuccess);
} else {
- // 응답은 성공했지만 status가 false인 경우
- const validationErrors = rs.error?.details?.validationErrors;
- if (validationErrors) {
- // validation 에러 메시지들을 수집
- const errorMessages = Object.values(validationErrors).join('\n');
- snackBar(`[실패] ${errorMessages}`);
- } else {
- // 일반 에러 메시지
- const errorMessage = rs.error?.message || '요청을 처리할 수 없습니다.';
- snackBar(`[실패] ${errorMessage}`);
- }
+ // 일반 에러 메시지
+ const errorMessage = rs.error?.message || '요청을 처리할 수 없습니다.';
+ snackBar(`[실패] ${errorMessage}`);
}
})
.catch((error) => {
diff --git a/src/pages/additional-service/link-payment/link-payment-detail-page.tsx b/src/pages/additional-service/link-payment/link-payment-detail-page.tsx
index 61c66a9..e67cf12 100644
--- a/src/pages/additional-service/link-payment/link-payment-detail-page.tsx
+++ b/src/pages/additional-service/link-payment/link-payment-detail-page.tsx
@@ -157,7 +157,7 @@ export const LinkPaymentDetailPage = () => {
diff --git a/src/pages/additional-service/link-payment/separate-approval/link-payment-separate-approval-page.tsx b/src/pages/additional-service/link-payment/separate-approval/link-payment-separate-approval-page.tsx
index 57d96ad..6bb1e67 100644
--- a/src/pages/additional-service/link-payment/separate-approval/link-payment-separate-approval-page.tsx
+++ b/src/pages/additional-service/link-payment/separate-approval/link-payment-separate-approval-page.tsx
@@ -52,11 +52,63 @@ export const LinkPaymentSeparateApprovalPage = () => {
const handleCheckboxChange = (subRequestId: string) => {
setSelectedItems(prev => {
- if (prev.includes(subRequestId)) {
- return prev.filter(id => id !== subRequestId);
- } else {
- return [...prev, subRequestId];
+ // 현재 클릭한 item 찾기
+ const target = items.find(i => i.subRequestId === subRequestId)
+ || items.find((_, idx) => `item-${idx}` === subRequestId);
+ if (!target) return prev;
+
+ // 동일한 requestId를 가진 MAIN, SUB 그룹 가져오기
+ const sameRequestIdItems = items.filter(i => i.requestId === target.requestId);
+ const mainItem = sameRequestIdItems.find(i => i.type === LinkPaymentSeparateType.MAIN);
+ // PENDING 상태인 SUB만 필터링
+ const subItems = sameRequestIdItems.filter(i =>
+ i.type === LinkPaymentSeparateType.SUB && i.paymentStatus === 'PENDING'
+ );
+
+ const mainId = mainItem?.subRequestId || (mainItem ? `item-${items.indexOf(mainItem)}` : '');
+ const subIds = subItems.map(i => i.subRequestId || `item-${items.indexOf(i)}`);
+
+ // -----------------------------
+ // MAIN 클릭 시
+ // -----------------------------
+ if (target.type === LinkPaymentSeparateType.MAIN) {
+ const isMainChecked = prev.includes(mainId);
+ if (isMainChecked) {
+ // MAIN 해제 → PENDING인 SUB만 해제
+ return prev.filter(id => ![mainId, ...subIds].includes(id));
+ } else {
+ // MAIN 체크 → PENDING인 SUB만 추가
+ return [...new Set([...prev, mainId, ...subIds])];
+ }
}
+
+ // -----------------------------
+ // SUB 클릭 시
+ // -----------------------------
+ const isChecked = prev.includes(subRequestId);
+ let updated: string[] = [];
+
+ if (isChecked) {
+ // SUB 해제
+ updated = prev.filter(id => id !== subRequestId);
+
+ // 해제 후 남은 PENDING SUB 중 하나라도 빠져 있으면 MAIN도 해제
+ const allPendingSubsChecked = subIds.every(id => updated.includes(id));
+ if (!allPendingSubsChecked && mainId) {
+ updated = updated.filter(id => id !== mainId);
+ }
+ } else {
+ // SUB 체크
+ updated = [...prev, subRequestId];
+
+ // 모든 PENDING SUB 체크되면 MAIN도 자동 체크
+ const allPendingSubsChecked = subIds.every(id => updated.includes(id));
+ if (allPendingSubsChecked && mainId) {
+ updated = [...new Set([...updated, mainId])];
+ }
+ }
+
+ return updated;
});
};
@@ -67,12 +119,60 @@ export const LinkPaymentSeparateApprovalPage = () => {
}));
};
- // 기간연장 버튼 활성화 조건: 선택된 항목이 있고, 모든 선택된 항목의 연장기간이 설정됨
- const isExtendButtonEnabled = () => {
- if (selectedItems.length === 0) return false;
- return selectedItems.every(id => extendPeriods[id] && extendPeriods[id] !== '');
+ // 각 SUB 항목이 연장기간 설정 가능한지 체크
+ const canExtendPeriod = (item: ExtensionLinkPaySeparateDetailItem) => {
+ const today = moment().format('YYYYMMDD');
+ const paymentLimitDate = item.paymentLimitDate || '';
+ const paymentLimitCount = item.paymentLimitCount || 0;
+
+ // 연장횟수 < 3 이고 유효일자 >= 조회일자
+ return paymentLimitCount < 3 && paymentLimitDate >= today;
};
+ // 각 SUB 항목이 링크중단 가능한지 체크
+ const canLinkBreak = (item: ExtensionLinkPaySeparateDetailItem) => {
+ const today = moment().format('YYYYMMDD');
+ const paymentLimitDate = item.paymentLimitDate || '';
+
+ // 유효일자 >= 조회일자
+ return paymentLimitDate >= today;
+ };
+
+ const isExtendButtonEnabled = () => {
+ // MAIN 제외, 체크된 SUB 중에서
+ const checkedSubs = items.filter((i, index) => {
+ const itemId = i.subRequestId || `item-${index}`;
+ return i.type === LinkPaymentSeparateType.SUB &&
+ selectedItems.includes(itemId) &&
+ i.paymentStatus === 'PENDING';
+ });
+
+ // 체크된 SUB가 없으면 비활성화
+ if (checkedSubs.length === 0) return false;
+
+ // 모든 체크된 SUB가 연장 가능하고, 연장기간이 설정되어 있어야 함
+ return checkedSubs.every((sub) => {
+ const itemId = sub.subRequestId || `item-${items.indexOf(sub)}`;
+ return canExtendPeriod(sub) && extendPeriods[itemId] && extendPeriods[itemId] !== '';
+ });
+ };
+
+ const isLinkBreadkEnabled = () => {
+ // MAIN 제외, 체크된 SUB 중에서
+ const checkedSubs = items.filter((i, index) => {
+ const itemId = i.subRequestId || `item-${index}`;
+ return i.type === LinkPaymentSeparateType.SUB &&
+ selectedItems.includes(itemId) &&
+ i.paymentStatus === 'PENDING';
+ });
+
+ // 체크된 SUB가 없으면 비활성화
+ if (checkedSubs.length === 0) return false;
+
+ // 모든 체크된 SUB가 링크중단 가능해야 함
+ return checkedSubs.every(sub => canLinkBreak(sub));
+ }
+
const onClickToValidityPeriod = () => {
// 기간연장 바텀시트 열기
setExtendedPeriodBottomSheetOn(true);
@@ -94,8 +194,13 @@ export const LinkPaymentSeparateApprovalPage = () => {
return;
}
- // 모든 선택된 항목들의 연장 기간이 설정되었는지 확인
- const allHaveExtendPeriod = selectedItems.every(id => extendPeriods[id]);
+ // MAIN을 제외한 선택된 SUB 항목들의 연장 기간이 설정되었는지 확인
+ const selectedSubItems = selectedItems.filter(id => {
+ const item = items.find(i => (i.subRequestId || `item-${items.indexOf(i)}`) === id);
+ return item && item.type === LinkPaymentSeparateType.SUB;
+ });
+
+ const allHaveExtendPeriod = selectedSubItems.every(id => extendPeriods[id]);
if (!allHaveExtendPeriod) {
setErrorMessage('모든 선택된 항목의 연장 기간을 선택해주세요.');
@@ -103,15 +208,15 @@ export const LinkPaymentSeparateApprovalPage = () => {
return;
}
- // 첫 번째 선택된 항목의 연장 기간 사용 (모든 항목이 같은 기간으로 연장)
- const firstSelectedId = selectedItems[0] as string;
- const extendDays = extendPeriods[firstSelectedId] as string;
+ // 첫 번째 선택된 SUB 항목의 연장 기간 사용 (모든 항목이 같은 기간으로 연장)
+ const firstSelectedSubId = selectedSubItems[0] as string;
+ const extendDays = extendPeriods[firstSelectedSubId] as string;
// 연장 날짜 계산 (오늘 날짜 + 연장일수)
const extendDate = moment().add(parseInt(extendDays), 'days').format('YYYYMMDD');
- // selectedItems를 API 형식으로 변환
- const selectedItemsData = selectedItems.map(itemId => {
+ // MAIN을 제외한 SUB 항목만 API 형식으로 변환
+ const selectedItemsData = selectedSubItems.map(itemId => {
const item = items.find(i => (i.subRequestId || `item-${items.indexOf(i)}`) === itemId);
return {
type: item?.type || '',
@@ -157,7 +262,13 @@ export const LinkPaymentSeparateApprovalPage = () => {
return;
}
- const selectedItemsData = selectedItems.map(itemId => {
+ // MAIN을 제외한 SUB 항목만 필터링
+ const selectedSubItems = selectedItems.filter(id => {
+ const item = items.find(i => (i.subRequestId || `item-${items.indexOf(i)}`) === id);
+ return item && item.type === LinkPaymentSeparateType.SUB;
+ });
+
+ const selectedItemsData = selectedSubItems.map(itemId => {
const item = items.find(i => (i.subRequestId || `item-${items.indexOf(i)}`) === itemId);
return {
type: item?.type || '',
@@ -230,67 +341,75 @@ export const LinkPaymentSeparateApprovalPage = () => {
{items.map((item, index) => {
const itemId = item.subRequestId || `item-${index}`;
+ const isDisabled = item.paymentStatus !== 'PENDING';
return (
-
-
- handleCheckboxChange(itemId)}
- className="card-checkbox"
- />
- [{item.type}]
- {item.moid}
-
-
-
- -
- • 거래금액:
- {item.amount.toLocaleString()}
-
- -
- • 결제상태:
- {item.paymentStatusName}
-
- {item.type !== LinkPaymentSeparateType.MAIN && (
- <>
- -
- • 유효기간:
-
- {item.paymentLimitDate
- ? moment(item.paymentLimitDate, 'YYYYMMDD').format('YYYY/MM/DD')
- : '-'
- }
-
-
- -
- • 연장횟수:
- {item.paymentLimitCount}
-
- >
- )}
-
-
-
-
-
-
+
+
+ handleCheckboxChange(itemId)}
+ className="card-checkbox"
+ disabled={item.paymentStatus !== 'PENDING'}
+ />
+ [{item.type}]
+ {item.moid}
+
+
+
+ -
+ • 거래금액:
+ {item.amount.toLocaleString()}
+
+ -
+ • 결제상태:
+ {item.paymentStatusName}
+
+ {item.type !== LinkPaymentSeparateType.MAIN && (
+ <>
+ -
+ • 유효기간:
+
+ {item.paymentLimitDate
+ ? moment(item.paymentLimitDate, 'YYYYMMDD').format('YYYY/MM/DD')
+ : '-'
+ }
+
+
+ -
+ • 연장횟수:
+ {item.paymentLimitCount}
+
+ >
+ )}
+
+
+
+
+
+
+
-
);
})}
@@ -306,7 +425,7 @@ export const LinkPaymentSeparateApprovalPage = () => {
diff --git a/src/pages/additional-service/link-payment/separate-approval/link-payment-separate-approval-success-page.tsx b/src/pages/additional-service/link-payment/separate-approval/link-payment-separate-approval-success-page.tsx
index d5d5711..3699a61 100644
--- a/src/pages/additional-service/link-payment/separate-approval/link-payment-separate-approval-success-page.tsx
+++ b/src/pages/additional-service/link-payment/separate-approval/link-payment-separate-approval-success-page.tsx
@@ -1,6 +1,4 @@
import { motion } from 'framer-motion';
-import { useNavigate } from '@/shared/lib/hooks/use-navigate';
-import { PATHS } from "@/shared/constants/paths";
import {
FilterMotionDuration,
FilterMotionStyle,
diff --git a/src/pages/additional-service/payout/detail-page.tsx b/src/pages/additional-service/payout/detail-page.tsx
index 2a7b57e..2083760 100644
--- a/src/pages/additional-service/payout/detail-page.tsx
+++ b/src/pages/additional-service/payout/detail-page.tsx
@@ -108,13 +108,7 @@ export const PayoutDetailPage = () => {
-
+ {t('home.money', { value: new Intl.NumberFormat('en-US').format(detail?.disbursementAmount || 0) })}
{detail?.companyName}
diff --git a/src/pages/transaction/all-transaction/list-page.tsx b/src/pages/transaction/all-transaction/list-page.tsx
index 0aab01a..57167fc 100644
--- a/src/pages/transaction/all-transaction/list-page.tsx
+++ b/src/pages/transaction/all-transaction/list-page.tsx
@@ -231,13 +231,7 @@ export const AllTransactionListPage = () => {
{t('transaction.searchAmount')}
-
+ {t('home.money', { value: new Intl.NumberFormat('en-US').format(totalAmount || 0) })}
diff --git a/src/pages/vat-return/list-page.tsx b/src/pages/vat-return/list-page.tsx
index 693f27e..99273d6 100644
--- a/src/pages/vat-return/list-page.tsx
+++ b/src/pages/vat-return/list-page.tsx
@@ -1,11 +1,12 @@
import { useState } from 'react';
+import { useTranslation } from 'react-i18next';
import { PATHS } from '@/shared/constants/paths';
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { VatReturnTab } from '@/entities/vat-return/ui/vat-return-tab';
import { ListWrap } from '@/entities/vat-return/ui/list-wrap';
import { VatReturnTabKeys } from '@/entities/vat-return/model/types';
import { HeaderType } from '@/entities/common/model/types';
-import {
+import {
useSetHeaderTitle,
useSetHeaderType,
useSetFooterMode,
@@ -13,11 +14,12 @@ import {
} from '@/widgets/sub-layout/use-sub-layout';
export const ListPage = () => {
+ const { t } = useTranslation();
const { navigate } = useNavigate();
const [activeTab, setActiveTab] = useState
(VatReturnTabKeys.List);
-
- useSetHeaderTitle('부가세 신고 자료');
+
+ useSetHeaderTitle(t('vatReturn.title'));
useSetHeaderType(HeaderType.LeftArrow);
useSetFooterMode(false);
useSetOnBack(() => {
diff --git a/src/pages/vat-return/reference-page.tsx b/src/pages/vat-return/reference-page.tsx
index c0f90ec..b1e289c 100644
--- a/src/pages/vat-return/reference-page.tsx
+++ b/src/pages/vat-return/reference-page.tsx
@@ -1,11 +1,12 @@
import { useState } from 'react';
+import { useTranslation } from 'react-i18next';
import { PATHS } from '@/shared/constants/paths';
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { VatReturnTab } from '@/entities/vat-return/ui/vat-return-tab';
import { ReferenceWrap } from '@/entities/vat-return/ui/reference-wrap';
import { VatReturnTabKeys } from '@/entities/vat-return/model/types';
import { HeaderType } from '@/entities/common/model/types';
-import {
+import {
useSetHeaderTitle,
useSetHeaderType,
useSetFooterMode,
@@ -13,11 +14,12 @@ import {
} from '@/widgets/sub-layout/use-sub-layout';
export const ReferencePage = () => {
+ const { t } = useTranslation();
const { navigate } = useNavigate();
const [activeTab, setActiveTab] = useState(VatReturnTabKeys.VatReference);
-
- useSetHeaderTitle('부가세 신고 자료');
+
+ useSetHeaderTitle(t('vatReturn.title'));
useSetHeaderType(HeaderType.LeftArrow);
useSetFooterMode(false);
useSetOnBack(() => {
diff --git a/src/shared/ui/assets/css/style-fix.css b/src/shared/ui/assets/css/style-fix.css
index 9b4648e..3e865ee 100644
--- a/src/shared/ui/assets/css/style-fix.css
+++ b/src/shared/ui/assets/css/style-fix.css
@@ -233,6 +233,29 @@ main.home-main{
box-shadow: 0 4px 12px rgba(62, 106, 252, 0.2);
}
+/* PENDING이 아닌 항목 비활성화 스타일 */
+.approval-card.disabled {
+ opacity: 0.5;
+ background: var(--color-F9F9F9);
+ pointer-events: none;
+}
+
+.approval-card.disabled .card-checkbox {
+ cursor: not-allowed;
+ background-color: var(--color-E6E6E6);
+ border-color: var(--color-CCCCCC);
+}
+
+.approval-card.disabled .card-tid,
+.approval-card.disabled .info-list .value {
+ color: var(--color-999999);
+}
+
+.approval-card.disabled .period-selector select {
+ background-color: var(--color-F3F3F3);
+ cursor: not-allowed;
+}
+
.approval-card .card-checkbox {
display: block !important;
position: absolute;