250 lines
8.9 KiB
TypeScript
250 lines
8.9 KiB
TypeScript
import { ChangeEvent, useState } from 'react';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { PATHS } from '@/shared/constants/paths';
|
|
import { IMAGE_ROOT } from '@/shared/constants/common';
|
|
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
|
|
import { CalendarType, HeaderType } from '@/entities/common/model/types';
|
|
import { useBillingChargeMutation } from '@/entities/transaction/api/use-billing-charge-mutation';
|
|
import {
|
|
useSetOnBack,
|
|
useSetHeaderTitle,
|
|
useSetHeaderType,
|
|
useSetFooterMode
|
|
} from '@/widgets/sub-layout/use-sub-layout';
|
|
import { NumericFormat, PatternFormat } from 'react-number-format';
|
|
import { showAlert } from '@/widgets/show-alert';
|
|
import moment from 'moment';
|
|
import NiceCalendar from '@/shared/ui/calendar/nice-calendar';
|
|
import { notiBar, snackBar } from '@/shared/lib';
|
|
import { BillingChargeParams, BillingChargeResponse } from '@/entities/transaction/model/types';
|
|
import { useKeyboardAware } from '@/shared/lib/hooks/use-keyboard-aware';
|
|
|
|
export const BillingChargePage = () => {
|
|
const { navigate } = useNavigate();
|
|
const { t } = useTranslation();
|
|
|
|
const [billKey, setBillKey] = useState<string>('');
|
|
const [productName, setProductName] = useState<string>('');
|
|
const [productAmount, setProductAmount] = useState<number>(0);
|
|
const [orderNumber, setOrderNumber] = useState<string>('');
|
|
const [buyerName, setBuyerName] = useState<string>('');
|
|
const [paymentRequestDate, setPaymentRequestDate] = useState<string>(moment().format('YYYY.MM.DD'));
|
|
const [installmentMonth, setInstallmentMonth] = useState<string>('00');
|
|
|
|
const [calendarOpen, setCalendarOpen] = useState<boolean>(false);
|
|
const { handleInputFocus, keyboardAwarePadding } = useKeyboardAware();
|
|
|
|
useSetHeaderTitle(t('billing.charge'));
|
|
useSetHeaderType(HeaderType.RightClose);
|
|
useSetOnBack(() => {
|
|
navigate(PATHS.transaction.billing.list);
|
|
});
|
|
useSetFooterMode(false);
|
|
|
|
const { mutateAsync: billingCharge } = useBillingChargeMutation();
|
|
|
|
const setNewDate = (date: string) => {
|
|
setPaymentRequestDate(moment(date).format('YYYY.MM.DD'));
|
|
setCalendarOpen(false);
|
|
};
|
|
const onClickToOpenCalendar = () => {
|
|
setCalendarOpen(true);
|
|
};
|
|
|
|
const onClickToBillingCharge = () => {
|
|
if (!billKey) {
|
|
showAlert('빌키는 필수 입력 항목입니다.');
|
|
return;
|
|
}
|
|
else if (!productName) {
|
|
showAlert('상품명은 필수 입력 항목입니다.');
|
|
}
|
|
else if (!productAmount) {
|
|
showAlert('상품금액은 필수 입력 항목입니다.');
|
|
}
|
|
else if (productAmount <= 0) {
|
|
showAlert('상품금액은 0보다 커야 합니다.');
|
|
}
|
|
else if (!orderNumber) {
|
|
showAlert('주문번호는 필수 입력 항목입니다.');
|
|
}
|
|
else if (!buyerName) {
|
|
showAlert('구매자명은 필수 입력 항목입니다.');
|
|
}
|
|
|
|
let params: BillingChargeParams = {
|
|
billKey: billKey,
|
|
productName: productName,
|
|
productAmount: productAmount,
|
|
orderNumber: orderNumber,
|
|
buyerName: buyerName,
|
|
paymentRequestDate: moment(paymentRequestDate).format('YYYYMMDD'),
|
|
installmentMonth: installmentMonth
|
|
};
|
|
billingCharge(params).then((rs: BillingChargeResponse) => {
|
|
snackBar('결제 신청을 성공하였습니다.', function () {
|
|
navigate(PATHS.transaction.billing.list);
|
|
}, 3000);
|
|
|
|
}).catch((e: any) => {
|
|
if (e.response?.data?.error?.message) {
|
|
snackBar(e.response?.data?.error?.message);
|
|
return;
|
|
}
|
|
});
|
|
};
|
|
|
|
const onChangeBillKey = (value: string) => {
|
|
const pattern = /^[A-Za-z0-9]+$/;
|
|
if (pattern.test(value) || value === '') {
|
|
setBillKey(value);
|
|
}
|
|
};
|
|
|
|
const makeInstallmentMonthSelect = () => {
|
|
let rs = [];
|
|
|
|
rs.push(
|
|
<option
|
|
key={`key-installment`}
|
|
value=''
|
|
>선택</option>
|
|
);
|
|
rs.push(
|
|
<option
|
|
key={`key-installment-0`}
|
|
value='00'
|
|
>일시불</option>
|
|
);
|
|
for (let i = 2; i <= 24; i++) {
|
|
let val = (i < 10) ? '0' + i : '' + i;
|
|
rs.push(
|
|
<option
|
|
key={`key-installment-${i}`}
|
|
value={val}
|
|
>{i}개월</option>
|
|
);
|
|
};
|
|
return rs;
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<main>
|
|
<div className="tab-content">
|
|
<div className="tab-pane sub active">
|
|
<div className="option-list">
|
|
<div className="billing-title">결제 정보 입력</div>
|
|
<div className="billing-form">
|
|
<div className="billing-row">
|
|
<div className="billing-label">빌키 <span>*</span></div>
|
|
<div className="billing-field">
|
|
<input
|
|
type="text"
|
|
value={billKey}
|
|
onChange={(e: ChangeEvent<HTMLInputElement>) => onChangeBillKey(e.target.value)}
|
|
onFocus={handleInputFocus}
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div className="billing-row">
|
|
<div className="billing-label">상품명 <span>*</span></div>
|
|
<div className="billing-field">
|
|
<input
|
|
type="text"
|
|
value={productName}
|
|
onChange={(e: ChangeEvent<HTMLInputElement>) => setProductName(e.target.value)}
|
|
onFocus={handleInputFocus}
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div className="billing-row">
|
|
<div className="billing-label">상품금액 <span>*</span></div>
|
|
<div className="billing-field">
|
|
<NumericFormat
|
|
value={productAmount}
|
|
allowNegative={false}
|
|
displayType="input"
|
|
onChange={(e: ChangeEvent<HTMLInputElement>) => setProductAmount(parseInt(e.target.value))}
|
|
onFocus={handleInputFocus}
|
|
></NumericFormat>
|
|
</div>
|
|
</div>
|
|
<div className="billing-row">
|
|
<div className="billing-label">주문번호 <span>*</span></div>
|
|
<div className="billing-field">
|
|
<input
|
|
type="text"
|
|
value={orderNumber}
|
|
onChange={(e: ChangeEvent<HTMLInputElement>) => setOrderNumber(e.target.value)}
|
|
onFocus={handleInputFocus}
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div className="billing-row">
|
|
<div className="billing-label">구매자명 <span>*</span></div>
|
|
<div className="billing-field">
|
|
<input
|
|
type="text"
|
|
value={buyerName}
|
|
onChange={(e: ChangeEvent<HTMLInputElement>) => setBuyerName(e.target.value)}
|
|
onFocus={handleInputFocus}
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="billing-row">
|
|
<div className="billing-label">결제 요청일자</div>
|
|
<div className="billing-field">
|
|
<div className="input-wrapper date wid-100">
|
|
<input
|
|
type="text"
|
|
placeholder="날짜 선택"
|
|
value={paymentRequestDate}
|
|
readOnly={true}
|
|
/>
|
|
<button
|
|
className="date-btn"
|
|
type="button"
|
|
onClick={() => onClickToOpenCalendar()}
|
|
>
|
|
<img
|
|
src={IMAGE_ROOT + '/ico_date.svg'}
|
|
alt="clear"
|
|
/>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="billing-row" style={keyboardAwarePadding}>
|
|
<div className="billing-label">할부 개월</div>
|
|
<div className="billing-field">
|
|
<select
|
|
value={installmentMonth}
|
|
onChange={(e: ChangeEvent<HTMLSelectElement>) => setBuyerName(e.target.value)}
|
|
>
|
|
{makeInstallmentMonthSelect()}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="apply-row">
|
|
<button
|
|
className="btn-50 btn-blue flex-1"
|
|
onClick={() => onClickToBillingCharge()}
|
|
>결제 신청</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
<NiceCalendar
|
|
calendarOpen={calendarOpen}
|
|
setCalendarOpen={setCalendarOpen}
|
|
calendarType={CalendarType.Single}
|
|
setNewDate={setNewDate}
|
|
></NiceCalendar>
|
|
</>
|
|
);
|
|
}; |