- 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>
151 lines
5.5 KiB
TypeScript
151 lines
5.5 KiB
TypeScript
import { IMAGE_ROOT } from "@/shared/constants/common";
|
|
import { PATHS } from '@/shared/constants/paths';
|
|
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
|
|
import { CalendarType, HeaderType } from '@/entities/common/model/types';
|
|
import {
|
|
useSetHeaderTitle,
|
|
useSetHeaderType,
|
|
useSetFooterMode,
|
|
useSetOnBack
|
|
} from '@/widgets/sub-layout/use-sub-layout';
|
|
import { ChangeEvent, useState } from "react";
|
|
import { useExtensionPayoutRequestMutation } from "@/entities/additional-service/api/payout/use-extension-payout-request-mutation";
|
|
import { ExtensionPayoutRequestParams, ExtensionPayoutRequestResponse } from "@/entities/additional-service/model/payout/types";
|
|
import NiceCalendar from "@/shared/ui/calendar/nice-calendar";
|
|
import { useStore } from "@/shared/model/store";
|
|
import moment from 'moment';
|
|
import { NumericFormat } from "react-number-format";
|
|
import { snackBar } from "@/shared/lib";
|
|
import { useTranslation } from 'react-i18next';
|
|
|
|
export const PayoutRequestPage = () => {
|
|
const { t } = useTranslation();
|
|
const { navigate } = useNavigate();
|
|
const userMid = useStore.getState().UserStore.mid;
|
|
|
|
const [calendarOpen, setCalendarOpen] = useState<boolean>(false);
|
|
const [mid, setMid] = useState<string>(userMid);
|
|
const [submallId, setSubmallId] = useState<string>('');
|
|
const [disbursementAmount, setDisbursementAmount] = useState<number>(0);
|
|
const [settlementDate, setSettlementDate] = useState<string>('');
|
|
|
|
const { mutateAsync: extensionPayoutRequest } = useExtensionPayoutRequestMutation();
|
|
|
|
useSetHeaderTitle(t('additionalService.payout.requestTitle'));
|
|
useSetHeaderType(HeaderType.RightClose);
|
|
useSetFooterMode(false);
|
|
useSetOnBack(() => {
|
|
navigate(PATHS.additionalService.payout.list);
|
|
});
|
|
|
|
const callExtensionPayoutRequest = () => {
|
|
let params: ExtensionPayoutRequestParams = {
|
|
mid: mid,
|
|
submallId: submallId,
|
|
disbursementAmount: disbursementAmount,
|
|
settlementDate: settlementDate,
|
|
};
|
|
extensionPayoutRequest(params)
|
|
.then((rs) => {
|
|
if (rs.status) {
|
|
snackBar(t('additionalService.payout.requestSuccess'))
|
|
} else {
|
|
snackBar(`[${t('common.failed')}] ${rs.error?.message}`)
|
|
}
|
|
})
|
|
.catch((error) => {
|
|
snackBar(`[${t('common.failed')}] ${error?.response?.data?.message} ` || `[${t('common.failed')}] ${t('additionalService.payout.requestFailed')}`)
|
|
})
|
|
;
|
|
};
|
|
|
|
const isFormValid = () => {
|
|
return (
|
|
submallId.trim() !== '' &&
|
|
disbursementAmount > 0 &&
|
|
settlementDate.trim() !== ''
|
|
);
|
|
};
|
|
|
|
const setNewDate = (date: string) => {
|
|
setSettlementDate(moment(date).format('YYYYMMDD'));
|
|
setCalendarOpen(false);
|
|
};
|
|
|
|
|
|
return (
|
|
<>
|
|
<main>
|
|
<div className="tab-content">
|
|
<div className="tab-pane sub active">
|
|
<div className="ing-list">
|
|
<div className="billing-form gap-30">
|
|
<div className="billing-row">
|
|
<div className="billing-label">{t('additionalService.payout.subId')}</div>
|
|
<div className="billing-field">
|
|
<input
|
|
type="text"
|
|
value={submallId}
|
|
onChange={(e: ChangeEvent<HTMLInputElement>) => setSubmallId(e.target.value)}
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div className="billing-row">
|
|
<div className="billing-label">{t('additionalService.payout.disbursementAmount')}</div>
|
|
<div className="billing-field">
|
|
<NumericFormat
|
|
value={disbursementAmount}
|
|
allowNegative={false}
|
|
thousandSeparator={true}
|
|
displayType="input"
|
|
onValueChange={(values) => {
|
|
const { floatValue } = values;
|
|
setDisbursementAmount(floatValue ?? 0);
|
|
}}
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div className="billing-row">
|
|
<div className="billing-label">{t('additionalService.payout.disbursementDate')}</div>
|
|
<div className="billing-field">
|
|
<div className="input-wrapper date wid-100">
|
|
<input
|
|
type="text"
|
|
placeholder={t('additionalService.payout.dateSelectPlaceholder')}
|
|
value={settlementDate ? moment(settlementDate).format('YYYY.MM.DD') : ''}
|
|
/>
|
|
<button
|
|
className="date-btn"
|
|
type="button"
|
|
onClick={() => setCalendarOpen(true)}
|
|
>
|
|
<img
|
|
src={IMAGE_ROOT + '/ico_date.svg'}
|
|
alt={t('common.clear')}
|
|
/>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
<div className="apply-row">
|
|
<button
|
|
className="btn-50 btn-blue flex-1"
|
|
onClick={callExtensionPayoutRequest}
|
|
disabled={!isFormValid()}
|
|
>{t('common.request')}</button>
|
|
</div>
|
|
<NiceCalendar
|
|
calendarOpen={calendarOpen}
|
|
setCalendarOpen={setCalendarOpen}
|
|
calendarType={CalendarType.Single}
|
|
setNewDate={setNewDate}
|
|
minDate={new Date()}
|
|
></NiceCalendar>
|
|
</>
|
|
);
|
|
}; |