Localize payout pages (detail, list, request)

- Added payout-specific translation keys to en.json:
  - depositBalance, subId, disbursementAmount, requestFailed
- Added common translation keys: filter, download, searchOptions, failed, clear, currency.krw
- Localized detail-page.tsx:
  - Header title, button text, detail section title
  - All KV labels (disbursementStatus, transactionType, etc.)
  - Updated code comments from Korean to English
- Localized list-page.tsx:
  - Header title, aria-labels, alt texts
  - Deposit balance label and currency unit
  - Request button text
- Localized request-page.tsx:
  - Header title, form labels, placeholder text
  - Success/error messages in snackBar calls
  - Added useTranslation hook import

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Jay Sheen
2025-10-31 13:06:28 +09:00
parent 52717206db
commit c2e8da956a
4 changed files with 67 additions and 36 deletions

View File

@@ -35,7 +35,16 @@
"image": "Image", "image": "Image",
"request": "Request", "request": "Request",
"imageRequested": "Image has been requested.", "imageRequested": "Image has been requested.",
"selectDownloadMethod": "Select Download Method" "selectDownloadMethod": "Select Download Method",
"filter": "Filter",
"download": "Download",
"searchOptions": "Search Options",
"requestDate": "Request Date",
"failed": "Failed",
"clear": "Clear",
"currency": {
"krw": "KRW"
}
}, },
"menu": { "menu": {
"home": "Home", "home": "Home",
@@ -964,9 +973,29 @@
"sendCategory": "Send Category" "sendCategory": "Send Category"
}, },
"payout": { "payout": {
"title": "Payout",
"detailTitle": "Payout Detail",
"requestTitle": "Payout Request",
"requestDate": "Request Date", "requestDate": "Request Date",
"disbursementDate": "Disbursement Date", "disbursementDate": "Disbursement Date",
"paymentStatus": "Payment Status" "paymentStatus": "Payment Status",
"depositCertificate": "Deposit Certificate",
"detailInfo": "Detail Information",
"disbursementStatus": "Disbursement Status",
"transactionType": "Transaction Type",
"disbursementDateTime": "Disbursement Date Time",
"businessNumber": "Business Number",
"accountHolder": "Account Holder",
"bank": "Bank",
"accountNumber": "Account Number",
"depositor": "Depositor",
"failureReason": "Failure Reason",
"requestSuccess": "Request submitted successfully.",
"dateSelectPlaceholder": "Select Date",
"depositBalance": "Deposit Balance",
"subId": "Sub ID",
"disbursementAmount": "Disbursement Amount",
"requestFailed": "Request failed."
}, },
"keyIn": { "keyIn": {
"fullCancel": "Full Cancel", "fullCancel": "Full Cancel",

View File

@@ -44,7 +44,7 @@ export const PayoutDetailPage = () => {
}); });
}; };
useSetHeaderTitle('지급대행 상세'); useSetHeaderTitle(t('additionalService.payout.detailTitle'));
useSetHeaderType(HeaderType.LeftArrow); useSetHeaderType(HeaderType.LeftArrow);
useSetFooterMode(false); useSetFooterMode(false);
useSetOnBack(() => { useSetOnBack(() => {
@@ -57,7 +57,7 @@ export const PayoutDetailPage = () => {
const onSelectDownloadType = (type: 'IMAGE' | 'EMAIL') => { const onSelectDownloadType = (type: 'IMAGE' | 'EMAIL') => {
if (type === 'IMAGE') { if (type === 'IMAGE') {
// 이미지 저장은 바로 실행 // Save image directly
const params: ExtensionPayoutDetailDownloadCertificateParams = { const params: ExtensionPayoutDetailDownloadCertificateParams = {
mid: mid, mid: mid,
tid: tid, tid: tid,
@@ -72,7 +72,7 @@ export const PayoutDetailPage = () => {
console.error('Certificate Download Failed:', error); console.error('Certificate Download Failed:', error);
}); });
} else { } else {
// 이메일은 EmailBottomSheet 열기 // Open EmailBottomSheet for email option
setEmailBottomSheetOn(true); setEmailBottomSheetOn(true);
} }
}; };
@@ -120,52 +120,52 @@ export const PayoutDetailPage = () => {
onClick={ onClickToDownload } onClick={ onClickToDownload }
> >
<span className="icon-24 download"></span> <span className="icon-24 download"></span>
<span> </span> <span>{t('additionalService.payout.depositCertificate')}</span>
</button> </button>
</div> </div>
</div> </div>
<div className="detail-divider"></div> <div className="detail-divider"></div>
<div className="pay-detail"> <div className="pay-detail">
<div className="detail-title"> </div> <div className="detail-title">{t('additionalService.payout.detailInfo')}</div>
<ul className="kv-list"> <ul className="kv-list">
<li className="kv-row"> <li className="kv-row">
<span className="k"></span> <span className="k">{t('additionalService.payout.disbursementStatus')}</span>
<span className="v">{ detail?.disbursementStatus }</span> <span className="v">{ detail?.disbursementStatus }</span>
</li> </li>
<li className="kv-row"> <li className="kv-row">
<span className="k"></span> <span className="k">{t('additionalService.payout.transactionType')}</span>
<span className="v">{ detail?.transTypeName }</span> <span className="v">{ detail?.transTypeName }</span>
</li> </li>
<li className="kv-row"> <li className="kv-row">
<span className="k"></span> <span className="k">{t('common.requestDate')}</span>
<span className="v">{ moment(detail?.requestDate).format('YYYY.MM.DD') }</span> <span className="v">{ moment(detail?.requestDate).format('YYYY.MM.DD') }</span>
</li> </li>
<li className="kv-row"> <li className="kv-row">
<span className="k"></span> <span className="k">{t('additionalService.payout.disbursementDateTime')}</span>
<span className="v">{moment(detail?.settlementDateTime,'YYYYMMDDHHmmss').format('YYYY.MM.DD HH:mm:ss')}</span> <span className="v">{moment(detail?.settlementDateTime,'YYYYMMDDHHmmss').format('YYYY.MM.DD HH:mm:ss')}</span>
</li> </li>
<li className="kv-row"> <li className="kv-row">
<span className="k"></span> <span className="k">{t('additionalService.payout.businessNumber')}</span>
<span className="v">{ detail?.companyNo }</span> <span className="v">{ detail?.companyNo }</span>
</li> </li>
<li className="kv-row"> <li className="kv-row">
<span className="k"></span> <span className="k">{t('additionalService.payout.accountHolder')}</span>
<span className="v">{ detail?.accountName }</span> <span className="v">{ detail?.accountName }</span>
</li> </li>
<li className="kv-row"> <li className="kv-row">
<span className="k"></span> <span className="k">{t('additionalService.payout.bank')}</span>
<span className="v">{ detail?.bankName }</span> <span className="v">{ detail?.bankName }</span>
</li> </li>
<li className="kv-row"> <li className="kv-row">
<span className="k"></span> <span className="k">{t('additionalService.payout.accountNumber')}</span>
<span className="v">{ detail?.accountNo }</span> <span className="v">{ detail?.accountNo }</span>
</li> </li>
<li className="kv-row"> <li className="kv-row">
<span className="k"></span> <span className="k">{t('additionalService.payout.depositor')}</span>
<span className="v">{ detail?.depositName }</span> <span className="v">{ detail?.depositName }</span>
</li> </li>
<li className="kv-row"> <li className="kv-row">
<span className="k"></span> <span className="k">{t('additionalService.payout.failureReason')}</span>
<span className="v">{ detail?.failReason }</span> <span className="v">{ detail?.failReason }</span>
</li> </li>
</ul> </ul>

View File

@@ -34,7 +34,7 @@ import { useExtensionAccessCheck } from '@/shared/lib/hooks/use-extension-access
import useIntersectionObserver from '@/widgets/intersection-observer'; import useIntersectionObserver from '@/widgets/intersection-observer';
export const PayoutListPage = () => { export const PayoutListPage = () => {
// 권한 체크 // Access check
const { hasAccess, AccessDeniedDialog } = useExtensionAccessCheck({ const { hasAccess, AccessDeniedDialog } = useExtensionAccessCheck({
extensionCode: 'PAYOUT' extensionCode: 'PAYOUT'
}); });
@@ -74,7 +74,7 @@ export const PayoutListPage = () => {
onIntersect onIntersect
}); });
useSetHeaderTitle('지급대행'); useSetHeaderTitle(t('additionalService.payout.title'));
useSetHeaderType(HeaderType.LeftArrow); useSetHeaderType(HeaderType.LeftArrow);
useSetFooterMode(false); useSetFooterMode(false);
useSetOnBack(() => { useSetOnBack(() => {
@@ -244,32 +244,32 @@ export const PayoutListPage = () => {
/> />
<button <button
className="filter-btn" className="filter-btn"
aria-label="필터" aria-label={t('common.filter')}
onClick={() => onClickToOpenFilter()} onClick={() => onClickToOpenFilter()}
> >
<img <img
src={IMAGE_ROOT + '/ico_setting.svg'} src={IMAGE_ROOT + '/ico_setting.svg'}
alt="검색옵션" alt={t('common.searchOptions')}
/> />
</button> </button>
</div> </div>
<button <button
className="download-btn" className="download-btn"
aria-label="다운로드" aria-label={t('common.download')}
onClick={() => onClickToOpenEmailBottomSheet()} onClick={() => onClickToOpenEmailBottomSheet()}
> >
<img <img
src={IMAGE_ROOT + '/ico_download.svg'} src={IMAGE_ROOT + '/ico_download.svg'}
alt="다운로드" alt={t('common.download')}
/> />
</button> </button>
</div> </div>
<div className="account-frame"> <div className="account-frame">
<div className="credit-summary"> <div className="credit-summary">
<div className="row"> <div className="row">
<span className="label"> </span> <span className="label">{t('additionalService.payout.depositBalance')}</span>
<span className="amount22"> <span className="amount22">
50,000,000<span className="unit"></span> 50,000,000<span className="unit">{t('common.currency.krw')}</span>
</span> </span>
</div> </div>
</div> </div>
@@ -303,7 +303,7 @@ export const PayoutListPage = () => {
<button <button
className="btn-50 btn-blue flex-1" className="btn-50 btn-blue flex-1"
onClick={() => onClickToNavigation()} onClick={() => onClickToNavigation()}
> </button> >{t('additionalService.payout.requestTitle')}</button>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -16,8 +16,10 @@ import { useStore } from "@/shared/model/store";
import moment from 'moment'; import moment from 'moment';
import { NumericFormat } from "react-number-format"; import { NumericFormat } from "react-number-format";
import { snackBar } from "@/shared/lib"; import { snackBar } from "@/shared/lib";
import { useTranslation } from 'react-i18next';
export const PayoutRequestPage = () => { export const PayoutRequestPage = () => {
const { t } = useTranslation();
const { navigate } = useNavigate(); const { navigate } = useNavigate();
const userMid = useStore.getState().UserStore.mid; const userMid = useStore.getState().UserStore.mid;
@@ -29,7 +31,7 @@ export const PayoutRequestPage = () => {
const { mutateAsync: extensionPayoutRequest } = useExtensionPayoutRequestMutation(); const { mutateAsync: extensionPayoutRequest } = useExtensionPayoutRequestMutation();
useSetHeaderTitle('지급대행 신청'); useSetHeaderTitle(t('additionalService.payout.requestTitle'));
useSetHeaderType(HeaderType.RightClose); useSetHeaderType(HeaderType.RightClose);
useSetFooterMode(false); useSetFooterMode(false);
useSetOnBack(() => { useSetOnBack(() => {
@@ -46,13 +48,13 @@ export const PayoutRequestPage = () => {
extensionPayoutRequest(params) extensionPayoutRequest(params)
.then((rs) => { .then((rs) => {
if (rs.status) { if (rs.status) {
snackBar("신청을 성공하였습니다.") snackBar(t('additionalService.payout.requestSuccess'))
} else { } else {
snackBar(`[실패] ${rs.error?.message}`) snackBar(`[${t('common.failed')}] ${rs.error?.message}`)
} }
}) })
.catch((error) => { .catch((error) => {
snackBar(`[실패] ${error?.response?.data?.message} ` || '[실패] 신청을 실패하였습니다.') snackBar(`[${t('common.failed')}] ${error?.response?.data?.message} ` || `[${t('common.failed')}] ${t('additionalService.payout.requestFailed')}`)
}) })
; ;
}; };
@@ -79,7 +81,7 @@ export const PayoutRequestPage = () => {
<div className="ing-list"> <div className="ing-list">
<div className="billing-form gap-30"> <div className="billing-form gap-30">
<div className="billing-row"> <div className="billing-row">
<div className="billing-label">ID</div> <div className="billing-label">{t('additionalService.payout.subId')}</div>
<div className="billing-field"> <div className="billing-field">
<input <input
type="text" type="text"
@@ -89,7 +91,7 @@ export const PayoutRequestPage = () => {
</div> </div>
</div> </div>
<div className="billing-row"> <div className="billing-row">
<div className="billing-label"></div> <div className="billing-label">{t('additionalService.payout.disbursementAmount')}</div>
<div className="billing-field"> <div className="billing-field">
<NumericFormat <NumericFormat
value={disbursementAmount} value={disbursementAmount}
@@ -104,12 +106,12 @@ export const PayoutRequestPage = () => {
</div> </div>
</div> </div>
<div className="billing-row"> <div className="billing-row">
<div className="billing-label"></div> <div className="billing-label">{t('additionalService.payout.disbursementDate')}</div>
<div className="billing-field"> <div className="billing-field">
<div className="input-wrapper date wid-100"> <div className="input-wrapper date wid-100">
<input <input
type="text" type="text"
placeholder="날짜 선택" placeholder={t('additionalService.payout.dateSelectPlaceholder')}
value={settlementDate ? moment(settlementDate).format('YYYY.MM.DD') : ''} value={settlementDate ? moment(settlementDate).format('YYYY.MM.DD') : ''}
/> />
<button <button
@@ -119,7 +121,7 @@ export const PayoutRequestPage = () => {
> >
<img <img
src={IMAGE_ROOT + '/ico_date.svg'} src={IMAGE_ROOT + '/ico_date.svg'}
alt="clear" alt={t('common.clear')}
/> />
</button> </button>
</div> </div>
@@ -135,7 +137,7 @@ export const PayoutRequestPage = () => {
className="btn-50 btn-blue flex-1" className="btn-50 btn-blue flex-1"
onClick={callExtensionPayoutRequest} onClick={callExtensionPayoutRequest}
disabled={!isFormValid()} disabled={!isFormValid()}
></button> >{t('common.request')}</button>
</div> </div>
<NiceCalendar <NiceCalendar
calendarOpen={calendarOpen} calendarOpen={calendarOpen}