diff --git a/src/entities/transaction/ui/cash-receipt-hand-written-issuance-step1.tsx b/src/entities/transaction/ui/cash-receipt-hand-written-issuance-step1.tsx index 46f7f3f..fea081d 100644 --- a/src/entities/transaction/ui/cash-receipt-hand-written-issuance-step1.tsx +++ b/src/entities/transaction/ui/cash-receipt-hand-written-issuance-step1.tsx @@ -5,6 +5,7 @@ import { useSetOnBack } from '@/widgets/sub-layout/use-sub-layout'; import { CashReceiptPurposeType } from '../model/types'; import { PatternFormat } from 'react-number-format'; import { useTranslation } from 'react-i18next'; +import { useKeyboardAware } from '@/shared/lib/hooks/use-keyboard-aware'; export interface CashReceiptHandWrittenIssuanceStep1Props { businessNumber?: string; @@ -41,6 +42,7 @@ export const CashReceiptHandWrittenIssuanceStep1 = ({ }: CashReceiptHandWrittenIssuanceStep1Props) => { const { t } = useTranslation(); const { navigate } = useNavigate(); + const { handleInputFocus, keyboardAwarePadding } = useKeyboardAware(); useSetOnBack(() => { navigate(PATHS.transaction.cashReceipt.list); @@ -55,8 +57,8 @@ export const CashReceiptHandWrittenIssuanceStep1 = ({ @@ -66,14 +68,14 @@ export const CashReceiptHandWrittenIssuanceStep1 = ({
@@ -84,8 +86,9 @@ export const CashReceiptHandWrittenIssuanceStep1 = ({ ) => setProductName(e.target.value) } + value={productName} + onChange={(e: ChangeEvent) => setProductName(e.target.value)} + onFocus={handleInputFocus} /> @@ -95,8 +98,9 @@ export const CashReceiptHandWrittenIssuanceStep1 = ({ ) => setBuyerName(e.target.value) } + value={buyerName} + onChange={(e: ChangeEvent) => setBuyerName(e.target.value)} + onFocus={handleInputFocus} /> @@ -105,10 +109,11 @@ export const CashReceiptHandWrittenIssuanceStep1 = ({
) => setIssueNumber(e.target.value) } + onChange={(e: ChangeEvent) => setIssueNumber(e.target.value)} + onFocus={handleInputFocus} >
@@ -118,20 +123,22 @@ export const CashReceiptHandWrittenIssuanceStep1 = ({ ) => setEmail(e.target.value) } + value={email} + onChange={(e: ChangeEvent) => setEmail(e.target.value)} + onFocus={handleInputFocus} /> -
+
{t('account.phoneNumber')}
) => setPhoneNumber(e.target.value) } + onChange={(e: ChangeEvent) => setPhoneNumber(e.target.value)} + onFocus={handleInputFocus} >
diff --git a/src/entities/transaction/ui/cash-receipt-hand-written-issuance-step2.tsx b/src/entities/transaction/ui/cash-receipt-hand-written-issuance-step2.tsx index cdf7b95..afc2ffd 100644 --- a/src/entities/transaction/ui/cash-receipt-hand-written-issuance-step2.tsx +++ b/src/entities/transaction/ui/cash-receipt-hand-written-issuance-step2.tsx @@ -3,6 +3,7 @@ import { useSetOnBack } from '@/widgets/sub-layout/use-sub-layout'; import { ProcessStep } from '../model/types'; import { NumericFormat } from 'react-number-format'; import { useTranslation } from 'react-i18next'; +import { useKeyboardAware } from '@/shared/lib/hooks/use-keyboard-aware'; export interface CashReceiptHandWrittenIssuanceStep2Props { setProcessStep: (processStep: ProcessStep) => void; @@ -33,6 +34,7 @@ export const CashReceiptHandWrittenIssuanceStep2 = ({ onClickToVatCalculate }: CashReceiptHandWrittenIssuanceStep2Props) => { const { t } = useTranslation(); + const { handleInputFocus, keyboardAwarePadding } = useKeyboardAware(); useSetOnBack(() => { setProcessStep(ProcessStep.One); @@ -52,6 +54,7 @@ export const CashReceiptHandWrittenIssuanceStep2 = ({ allowNegative={ false } displayType="input" onChange={ (e: ChangeEvent) => setIssueAmount(parseInt(e.target.value)) } + onFocus={handleInputFocus} >
@@ -81,6 +85,7 @@ export const CashReceiptHandWrittenIssuanceStep2 = ({ allowNegative={ false } displayType="input" onChange={ (e: ChangeEvent) => setVatAmount(parseInt(e.target.value)) } + onFocus={handleInputFocus} > @@ -92,10 +97,11 @@ export const CashReceiptHandWrittenIssuanceStep2 = ({ allowNegative={ false } displayType="input" onChange={ (e: ChangeEvent) => setTaxFreeAmount(parseInt(e.target.value)) } + onFocus={handleInputFocus} > -
+
{t('transaction.fields.serviceAmount')}
) => setServiceCharge(parseInt(e.target.value)) } + onFocus={handleInputFocus} >
diff --git a/src/pages/support/qna/register-page.tsx b/src/pages/support/qna/register-page.tsx index b0374e0..378fc4f 100644 --- a/src/pages/support/qna/register-page.tsx +++ b/src/pages/support/qna/register-page.tsx @@ -4,9 +4,9 @@ import { useNavigate } from '@/shared/lib/hooks/use-navigate'; import { useQnaSaveMutation } from '@/entities/support/api/use-qna-save-mutation'; import { HeaderType } from '@/entities/common/model/types'; import { - useSetHeaderTitle, - useSetHeaderType, - useSetFooterMode, + useSetHeaderTitle, + useSetHeaderType, + useSetFooterMode, useSetOnBack } from '@/widgets/sub-layout/use-sub-layout'; import { useStore } from '@/shared/model/store'; @@ -16,6 +16,7 @@ import { overlay } from 'overlay-kit'; import { Dialog } from '@/shared/ui/dialogs/dialog'; import { QnaSaveParams, QnaSaveResponse } from '@/entities/support/model/types'; import { checkGrant } from '@/shared/lib/check-grant'; +import { useKeyboardAware } from '@/shared/lib/hooks/use-keyboard-aware'; export enum QnaRegisterPropsName { Mid = 'Mid', @@ -39,6 +40,7 @@ export const QnaRegisterPage = () => { const [requestEmail, setRequestEmail] = useState(''); const [title, setTitle] = useState(''); const [contents, setContents] = useState(''); + const { handleInputFocus, keyboardAwarePadding } = useKeyboardAware(); useSetHeaderTitle(t('support.qna.title')); useSetHeaderType(HeaderType.LeftArrow); @@ -54,25 +56,25 @@ export const QnaRegisterPage = () => { key: string ) => { let value = e.target.value; - if(key === QnaRegisterPropsName.Mid){ + if (key === QnaRegisterPropsName.Mid) { setMid(value); } - else if(key === QnaRegisterPropsName.RequestType){ + else if (key === QnaRegisterPropsName.RequestType) { setRequestType(value); } - else if(key === QnaRegisterPropsName.RequestName){ + else if (key === QnaRegisterPropsName.RequestName) { setRequestName(value); } - else if(key === QnaRegisterPropsName.RequestTel){ + else if (key === QnaRegisterPropsName.RequestTel) { setRequestTel(value); } - else if(key === QnaRegisterPropsName.RequestEmail){ + else if (key === QnaRegisterPropsName.RequestEmail) { setRequestEmail(value); } - else if(key === QnaRegisterPropsName.Title){ + else if (key === QnaRegisterPropsName.Title) { setTitle(value); } - else if(key === QnaRegisterPropsName.Contents){ + else if (key === QnaRegisterPropsName.Contents) { setContents(value); } }; @@ -87,7 +89,7 @@ export const QnaRegisterPage = () => { afterLeave={unmount} open={isOpen} onClose={close} - message={ msg } + message={msg} buttonLabel={[t('support.qna.confirmButton')]} /> ); @@ -95,35 +97,35 @@ export const QnaRegisterPage = () => { } const checkEmail = (email: string) => { var re = /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i; - if(email != '' && email != 'undefined' && re.test(email)){ + if (email != '' && email != 'undefined' && re.test(email)) { return true; } - else{ + else { return false; } }; const callRegister = () => { - if(!title){ + if (!title) { showAlert(t('support.qna.validation.title')); return; } - else if(!requestType){ + else if (!requestType) { showAlert(t('support.qna.validation.requestType')); return; } - else if(!requestName){ + else if (!requestName) { showAlert(t('support.qna.validation.requestName')); return; } - else if(!requestTel){ + else if (!requestTel) { showAlert(t('support.qna.validation.requestTel')); return; } - else if(requestEmail && !checkEmail(requestEmail)){ + else if (requestEmail && !checkEmail(requestEmail)) { showAlert(t('support.qna.validation.requestEmail')); return; } - else if(!contents){ + else if (!contents) { showAlert(t('support.qna.validation.contents')); return; } @@ -140,7 +142,7 @@ export const QnaRegisterPage = () => { alert(t('support.qna.successMessage')); navigate(PATHS.support.qna.list); }).catch((e: any) => { - if(e.response?.data?.error?.message){ + if (e.response?.data?.error?.message) { showAlert(e.response?.data?.error?.message); return; } @@ -168,9 +170,10 @@ export const QnaRegisterPage = () => {
) => setInputValue(e, QnaRegisterPropsName.Title) } + value={title} + required={true} + onChange={(e: ChangeEvent) => setInputValue(e, QnaRegisterPropsName.Title)} + onFocus={handleInputFocus} />
@@ -180,9 +183,9 @@ export const QnaRegisterPage = () => {
) => setInputValue(e, QnaRegisterPropsName.RequestName) } + value={requestName} + required={true} + onChange={(e: ChangeEvent) => setInputValue(e, QnaRegisterPropsName.RequestName)} + onFocus={handleInputFocus} />
@@ -215,10 +219,11 @@ export const QnaRegisterPage = () => {
) => setInputValue(e, QnaRegisterPropsName.RequestTel) } + onChange={(e: ChangeEvent) => setInputValue(e, QnaRegisterPropsName.RequestTel)} + onFocus={handleInputFocus} >
@@ -228,20 +233,22 @@ export const QnaRegisterPage = () => { ) => setInputValue(e, QnaRegisterPropsName.RequestEmail) } + value={requestEmail} + onChange={(e: ChangeEvent) => setInputValue(e, QnaRegisterPropsName.RequestEmail)} + onFocus={handleInputFocus} /> -
+
{t('support.qna.formLabels.inquiryContents')} {t('support.qna.formLabels.required')}
@@ -249,7 +256,7 @@ export const QnaRegisterPage = () => {
diff --git a/src/pages/transaction/billing/charge-page.tsx b/src/pages/transaction/billing/charge-page.tsx index 12e4972..82dfe60 100644 --- a/src/pages/transaction/billing/charge-page.tsx +++ b/src/pages/transaction/billing/charge-page.tsx @@ -17,6 +17,7 @@ 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(); @@ -31,7 +32,7 @@ export const BillingChargePage = () => { const [installmentMonth, setInstallmentMonth] = useState('00'); const [calendarOpen, setCalendarOpen] = useState(false); - + const { handleInputFocus, keyboardAwarePadding } = useKeyboardAware(); useSetHeaderTitle(t('billing.charge')); useSetHeaderType(HeaderType.RightClose); @@ -51,26 +52,26 @@ export const BillingChargePage = () => { }; const onClickToBillingCharge = () => { - if(!billKey){ + if (!billKey) { showAlert('빌키는 필수 입력 항목입니다.'); return; } - else if(!productName){ + else if (!productName) { showAlert('상품명은 필수 입력 항목입니다.'); } - else if(!productAmount){ + else if (!productAmount) { showAlert('상품금액은 필수 입력 항목입니다.'); } - else if(productAmount <= 0){ + else if (productAmount <= 0) { showAlert('상품금액은 0보다 커야 합니다.'); } - else if(!orderNumber){ + else if (!orderNumber) { showAlert('주문번호는 필수 입력 항목입니다.'); } - else if(!buyerName){ + else if (!buyerName) { showAlert('구매자명은 필수 입력 항목입니다.'); } - + let params: BillingChargeParams = { billKey: billKey, productName: productName, @@ -81,12 +82,12 @@ export const BillingChargePage = () => { installmentMonth: installmentMonth }; billingCharge(params).then((rs: BillingChargeResponse) => { - snackBar('결제 신청을 성공하였습니다.', function(){ + snackBar('결제 신청을 성공하였습니다.', function () { navigate(PATHS.transaction.billing.list); }, 3000); - + }).catch((e: any) => { - if(e.response?.data?.error?.message){ + if (e.response?.data?.error?.message) { showAlert(e.response?.data?.error?.message); return; } @@ -95,32 +96,32 @@ export const BillingChargePage = () => { const onChangeBillKey = (value: string) => { const pattern = /^[A-Za-z0-9]+$/; - if(pattern.test(value) || value === ''){ + if (pattern.test(value) || value === '') { setBillKey(value); } }; const makeInstallmentMonthSelect = () => { let rs = []; - + rs.push( - ); rs.push( - ); - for(let i=2;i<=24;i++){ - let val = (i < 10)? '0'+i: ''+i; + for (let i = 2; i <= 24; i++) { + let val = (i < 10) ? '0' + i : '' + i; rs.push( - ); }; @@ -138,20 +139,22 @@ export const BillingChargePage = () => {
빌키 *
- ) => onChangeBillKey(e.target.value) } + ) => onChangeBillKey(e.target.value)} + onFocus={handleInputFocus} />
상품명 *
- ) => setProductName(e.target.value) } + ) => setProductName(e.target.value)} + onFocus={handleInputFocus} />
@@ -159,30 +162,33 @@ export const BillingChargePage = () => {
상품금액 *
) => setProductAmount(parseInt(e.target.value)) } + onChange={(e: ChangeEvent) => setProductAmount(parseInt(e.target.value))} + onFocus={handleInputFocus} >
주문번호 *
- ) => setOrderNumber(e.target.value) } + ) => setOrderNumber(e.target.value)} + onFocus={handleInputFocus} />
구매자명 *
- ) => setBuyerName(e.target.value) } + ) => setBuyerName(e.target.value)} + onFocus={handleInputFocus} />
@@ -194,16 +200,16 @@ export const BillingChargePage = () => { @@ -211,33 +217,33 @@ export const BillingChargePage = () => { -
+
할부 개월
-
); diff --git a/src/shared/lib/hooks/use-keyboard-aware.ts b/src/shared/lib/hooks/use-keyboard-aware.ts index 771950b..f3139e6 100644 --- a/src/shared/lib/hooks/use-keyboard-aware.ts +++ b/src/shared/lib/hooks/use-keyboard-aware.ts @@ -18,7 +18,7 @@ export const useKeyboardAware = (options?: UseKeyboardAwareOptions) => { const [keyboardHeight, setKeyboardHeight] = useState(0); useEffect(() => { - let focusedElement: HTMLInputElement | null = null; + let focusedElement: HTMLElement | null = null; let isKeyboardOpen = false; // 네이티브에서 호출할 전역 함수 등록 @@ -44,7 +44,7 @@ export const useKeyboardAware = (options?: UseKeyboardAwareOptions) => { }; // focus된 요소를 추적하기 위한 함수 - (window as any).setFocusedElement = (element: HTMLInputElement) => { + (window as any).setFocusedElement = (element: HTMLElement) => { focusedElement = element; // 키보드가 이미 열려있으면 즉시 스크롤 @@ -62,8 +62,8 @@ export const useKeyboardAware = (options?: UseKeyboardAwareOptions) => { }; }, []); - // 모든 input에서 사용할 공통 핸들러 - const handleInputFocus = (e: React.FocusEvent) => { + // input과 textarea 모두에서 사용할 공통 핸들러 + const handleInputFocus = (e: React.FocusEvent) => { // focus된 요소를 저장 (window as any).setFocusedElement?.(e.target); };