import { ChangeEvent, useState } from 'react'; import { PATHS } from '@/shared/constants/paths'; import { useLocation } from 'react-router'; import { useNavigate } from '@/shared/lib/hooks/use-navigate'; import { HeaderType } from '@/entities/common/model/types'; import { useExtensionKeyinApplyMutation } from '@/entities/additional-service/api/use-extension-keyin-apply-mutation'; import { useSetHeaderTitle, useSetHeaderType, useSetFooterMode, useSetOnBack } from '@/widgets/sub-layout/use-sub-layout'; import { useStore } from '@/shared/model/store'; import { snackBar } from '@/shared/lib'; import { NumericFormat, PatternFormat } from 'react-number-format'; import { useTranslation } from 'react-i18next'; import { showAlert } from '@/widgets/show-alert'; import { useKeyboardAware } from '@/shared/lib/hooks/use-keyboard-aware'; export const KeyInPaymentRequestPage = () => { const { t } = useTranslation(); const { navigate } = useNavigate(); const location = useLocation(); const userMid = useStore.getState().UserStore.mid; const midOptions = useStore.getState().UserStore.selectOptionsMids const [mid, setMid] = useState(userMid || ''); const [productName, setProductName] = useState(''); const [amount, setAmount] = useState(0); const [customerName, setCustomerName] = useState(''); const [email, setEmail] = useState(''); const [phoneNumber, setPhoneNumber] = useState(''); const [cardNo1, setCardNo1] = useState(''); const [cardNo2, setCardNo2] = useState(''); const [cardNo3, setCardNo3] = useState(''); const [cardNo4, setCardNo4] = useState(''); const [expMon, setExpMon] = useState(''); const [expYear, setExpYear] = useState(''); const [instmnt, setInstmnt] = useState('00'); const [orderNumber, setOrderNumber] = useState(''); const { mutateAsync: keyInApply } = useExtensionKeyinApplyMutation(); const { handleInputFocus, keyboardAwarePadding } = useKeyboardAware(); useSetHeaderTitle(t('additionalService.keyIn.title')); useSetHeaderType(HeaderType.LeftArrow); useSetFooterMode(false); useSetOnBack(() => { navigate(PATHS.additionalService.keyInPayment.list); }); const resetForm = () => { setProductName(''); setAmount(0); setCustomerName(''); setEmail(''); setPhoneNumber(''); setCardNo1(''); setCardNo2(''); setCardNo3(''); setCardNo4(''); setExpMon(''); setExpYear(''); setInstmnt('00'); setOrderNumber(''); }; const callKeyInPaymentRequest = () => { const cardNo = `${cardNo1}${cardNo2}${cardNo3}${cardNo4}`; const cardExpire = `${expMon}${expYear}` let keyInApplyParams = { mid: mid, cardNo: cardNo, cardExpire: cardExpire, instmnt: instmnt, amount: amount, productName: productName, orderNumber: orderNumber, customerName: customerName, phoneNumber: phoneNumber, email: email, }; keyInApply(keyInApplyParams).then((rs) => { console.log('KEY-IN 결제 응답:', rs); console.log('rs.data:', rs.data); console.log('rs.data?.resultMessage:', rs.data?.resultMessage); if (rs.status && rs.data?.success) { // 성공: 화면 유지 & 입력 내용 초기화 snackBar(t('additionalService.keyIn.requestSuccess')) resetForm(); } else { // 실패: 화면 유지 & 입력 내용 유지 const errorMessage = rs.data?.resultMessage || rs.error?.message || rs.resultMessage || t('additionalService.keyIn.requestFailed'); console.log('최종 errorMessage:', errorMessage); // HTML 태그 제거 const cleanMessage = errorMessage.replace(//gi, ' ').trim(); snackBar(`[${t('common.failed')}] ${cleanMessage}`); } }).catch((error) => { console.error(error); const errorMessage = error?.response?.data?.data?.resultMessage || error?.response?.data?.error?.message || error?.message || t('additionalService.keyIn.requestError'); if (error.response?.data?.error?.root !== "SystemErrorCode") { snackBar(`[${t('common.failed')}] ${errorMessage}`); } else { showAlert(`[${t('common.failed')}] ${errorMessage}`) } }); }; const isValidPhoneNumber = (phone: string) => { const phoneRegex = /^01[0|1|6|7|8|9][0-9]{7,8}$/; return phoneRegex.test(phone); }; const isValidEmail = (email: string) => { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return emailRegex.test(email); }; const isValidCardNumber = () => { // 실제 숫자만 추출 (포맷팅 문자 제거) const cleanCardNo1 = cardNo1.replace(/\D/g, ''); const cleanCardNo2 = cardNo2.replace(/\D/g, ''); const cleanCardNo3 = cardNo3.replace(/\D/g, ''); const cleanCardNo4 = cardNo4.replace(/\D/g, ''); return cleanCardNo1.length === 4 && cleanCardNo2.length === 4 && cleanCardNo3.length === 4 && cleanCardNo4.length === 4; }; const isFormValid = () => { return ( mid.trim() !== '' && productName.trim() !== '' && amount > 0 && customerName.trim() !== '' && expMon.trim() !== '' && expYear.trim() !== '' && orderNumber.trim() !== '' && isValidEmail(email) && isValidPhoneNumber(phoneNumber) && isValidCardNumber() ); }; const onClickToRequest = () => { callKeyInPaymentRequest(); }; return ( <>
{t('additionalService.keyIn.merchant')} *
{t('additionalService.keyIn.productName')} *
) => setProductName(e.target.value)} onFocus={handleInputFocus} />
{t('additionalService.keyIn.productPrice')} *
{ const { floatValue } = values; setAmount(floatValue ?? 0); }} >
{t('additionalService.keyIn.buyerName')} *
) => setCustomerName(e.target.value)} onFocus={handleInputFocus} />
{t('additionalService.keyIn.buyerEmail')} *
) => setEmail(e.target.value)} className={email && !isValidEmail(email) ? 'error' : ''} onFocus={handleInputFocus} />
{t('additionalService.keyIn.buyerPhoneNumber')} *
) => { const onlyNumbers = e.target.value.replace(/[^0-9]/g, ''); setPhoneNumber(onlyNumbers); }} className={phoneNumber && !isValidPhoneNumber(phoneNumber) ? 'error' : ''} inputMode="numeric" pattern="[0-9]*" maxLength={11} onFocus={handleInputFocus} />
{t('additionalService.keyIn.cardNumber')} *
) => setCardNo1(e.target.value)} onFocus={handleInputFocus} >
) => setCardNo2(e.target.value)} onFocus={handleInputFocus} >
) => setCardNo3(e.target.value)} onFocus={handleInputFocus} >
) => setCardNo4(e.target.value)} onFocus={handleInputFocus} >
{t('additionalService.keyIn.expiryDate')}*
{ const { value } = values; if (!value) return true; const numValue = parseInt(value); return numValue >= 1 && numValue <= 12; }} onValueChange={(values) => { const { value } = values; setExpMon(value); }} onFocus={handleInputFocus} onBlur={() => { if (expMon.length === 1 && parseInt(expMon) >= 1 && parseInt(expMon) <= 9) { setExpMon(expMon.padStart(2, '0')); } }} style={{ flex: 1 }} inputMode="numeric" /> / { const { value } = values; setExpYear(value); }} onFocus={handleInputFocus} style={{ flex: 1 }} inputMode="numeric" />
{t('additionalService.keyIn.installmentPeriod')}*
{t('additionalService.keyIn.orderNumber')}*
) => setOrderNumber(e.target.value)} onFocus={handleInputFocus} />
) }