- 수기발행,1:1문의 등록, 빌링 모바일 용 패딩 추가 로직 추가
This commit is contained in:
@@ -5,6 +5,7 @@ import { useSetOnBack } from '@/widgets/sub-layout/use-sub-layout';
|
|||||||
import { CashReceiptPurposeType } from '../model/types';
|
import { CashReceiptPurposeType } from '../model/types';
|
||||||
import { PatternFormat } from 'react-number-format';
|
import { PatternFormat } from 'react-number-format';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { useKeyboardAware } from '@/shared/lib/hooks/use-keyboard-aware';
|
||||||
|
|
||||||
export interface CashReceiptHandWrittenIssuanceStep1Props {
|
export interface CashReceiptHandWrittenIssuanceStep1Props {
|
||||||
businessNumber?: string;
|
businessNumber?: string;
|
||||||
@@ -41,6 +42,7 @@ export const CashReceiptHandWrittenIssuanceStep1 = ({
|
|||||||
}: CashReceiptHandWrittenIssuanceStep1Props) => {
|
}: CashReceiptHandWrittenIssuanceStep1Props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { navigate } = useNavigate();
|
const { navigate } = useNavigate();
|
||||||
|
const { handleInputFocus, keyboardAwarePadding } = useKeyboardAware();
|
||||||
|
|
||||||
useSetOnBack(() => {
|
useSetOnBack(() => {
|
||||||
navigate(PATHS.transaction.cashReceipt.list);
|
navigate(PATHS.transaction.cashReceipt.list);
|
||||||
@@ -55,8 +57,8 @@ export const CashReceiptHandWrittenIssuanceStep1 = ({
|
|||||||
<input
|
<input
|
||||||
className="error"
|
className="error"
|
||||||
type="text"
|
type="text"
|
||||||
value={ businessNumber }
|
value={businessNumber}
|
||||||
readOnly={ true }
|
readOnly={true}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -66,14 +68,14 @@ export const CashReceiptHandWrittenIssuanceStep1 = ({
|
|||||||
<div className="issue-field">
|
<div className="issue-field">
|
||||||
<div className="seg-buttons">
|
<div className="seg-buttons">
|
||||||
<button
|
<button
|
||||||
className={ `btn-40 ${(purposeType === CashReceiptPurposeType.INCOME_DEDUCTION)? 'btn-blue': 'btn-white'}` }
|
className={`btn-40 ${(purposeType === CashReceiptPurposeType.INCOME_DEDUCTION) ? 'btn-blue' : 'btn-white'}`}
|
||||||
type="button"
|
type="button"
|
||||||
onClick={ () => setPurposeType(CashReceiptPurposeType.INCOME_DEDUCTION) }
|
onClick={() => setPurposeType(CashReceiptPurposeType.INCOME_DEDUCTION)}
|
||||||
>{t('transaction.handWrittenIssuance.incomeDeduction')}</button>
|
>{t('transaction.handWrittenIssuance.incomeDeduction')}</button>
|
||||||
<button
|
<button
|
||||||
className={ `btn-40 ${(purposeType === CashReceiptPurposeType.EXPENSE_PROOF)? 'btn-blue': 'btn-white'}` }
|
className={`btn-40 ${(purposeType === CashReceiptPurposeType.EXPENSE_PROOF) ? 'btn-blue' : 'btn-white'}`}
|
||||||
type="button"
|
type="button"
|
||||||
onClick={ () => setPurposeType(CashReceiptPurposeType.EXPENSE_PROOF) }
|
onClick={() => setPurposeType(CashReceiptPurposeType.EXPENSE_PROOF)}
|
||||||
>{t('transaction.handWrittenIssuance.expenseProof')}</button>
|
>{t('transaction.handWrittenIssuance.expenseProof')}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -84,8 +86,9 @@ export const CashReceiptHandWrittenIssuanceStep1 = ({
|
|||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder={t('transaction.handWrittenIssuance.productNamePlaceholder')}
|
placeholder={t('transaction.handWrittenIssuance.productNamePlaceholder')}
|
||||||
value={ productName }
|
value={productName}
|
||||||
onChange={ (e: ChangeEvent<HTMLInputElement>) => setProductName(e.target.value) }
|
onChange={(e: ChangeEvent<HTMLInputElement>) => setProductName(e.target.value)}
|
||||||
|
onFocus={handleInputFocus}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -95,8 +98,9 @@ export const CashReceiptHandWrittenIssuanceStep1 = ({
|
|||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder={t('transaction.handWrittenIssuance.buyerNamePlaceholder')}
|
placeholder={t('transaction.handWrittenIssuance.buyerNamePlaceholder')}
|
||||||
value={ buyerName }
|
value={buyerName}
|
||||||
onChange={ (e: ChangeEvent<HTMLInputElement>) => setBuyerName(e.target.value) }
|
onChange={(e: ChangeEvent<HTMLInputElement>) => setBuyerName(e.target.value)}
|
||||||
|
onFocus={handleInputFocus}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -105,10 +109,11 @@ export const CashReceiptHandWrittenIssuanceStep1 = ({
|
|||||||
<div className="issue-field">
|
<div className="issue-field">
|
||||||
<PatternFormat
|
<PatternFormat
|
||||||
placeholder={t('transaction.handWrittenIssuance.issueNumberPlaceholder')}
|
placeholder={t('transaction.handWrittenIssuance.issueNumberPlaceholder')}
|
||||||
value={ issueNumber }
|
value={issueNumber}
|
||||||
valueIsNumericString
|
valueIsNumericString
|
||||||
format="###########"
|
format="###########"
|
||||||
onChange={ (e: ChangeEvent<HTMLInputElement>) => setIssueNumber(e.target.value) }
|
onChange={(e: ChangeEvent<HTMLInputElement>) => setIssueNumber(e.target.value)}
|
||||||
|
onFocus={handleInputFocus}
|
||||||
></PatternFormat>
|
></PatternFormat>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -118,20 +123,22 @@ export const CashReceiptHandWrittenIssuanceStep1 = ({
|
|||||||
<input
|
<input
|
||||||
type="email"
|
type="email"
|
||||||
placeholder={t('transaction.handWrittenIssuance.emailPlaceholder')}
|
placeholder={t('transaction.handWrittenIssuance.emailPlaceholder')}
|
||||||
value={ email }
|
value={email}
|
||||||
onChange={ (e: ChangeEvent<HTMLInputElement>) => setEmail(e.target.value) }
|
onChange={(e: ChangeEvent<HTMLInputElement>) => setEmail(e.target.value)}
|
||||||
|
onFocus={handleInputFocus}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="issue-row">
|
<div className="issue-row" style={keyboardAwarePadding}>
|
||||||
<div className="issue-label">{t('account.phoneNumber')}</div>
|
<div className="issue-label">{t('account.phoneNumber')}</div>
|
||||||
<div className="issue-field">
|
<div className="issue-field">
|
||||||
<PatternFormat
|
<PatternFormat
|
||||||
placeholder={t('transaction.handWrittenIssuance.phoneNumberPlaceholder')}
|
placeholder={t('transaction.handWrittenIssuance.phoneNumberPlaceholder')}
|
||||||
value={ phoneNumber }
|
value={phoneNumber}
|
||||||
valueIsNumericString
|
valueIsNumericString
|
||||||
format="###########"
|
format="###########"
|
||||||
onChange={ (e: ChangeEvent<HTMLInputElement>) => setPhoneNumber(e.target.value) }
|
onChange={(e: ChangeEvent<HTMLInputElement>) => setPhoneNumber(e.target.value)}
|
||||||
|
onFocus={handleInputFocus}
|
||||||
></PatternFormat>
|
></PatternFormat>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { useSetOnBack } from '@/widgets/sub-layout/use-sub-layout';
|
|||||||
import { ProcessStep } from '../model/types';
|
import { ProcessStep } from '../model/types';
|
||||||
import { NumericFormat } from 'react-number-format';
|
import { NumericFormat } from 'react-number-format';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { useKeyboardAware } from '@/shared/lib/hooks/use-keyboard-aware';
|
||||||
|
|
||||||
export interface CashReceiptHandWrittenIssuanceStep2Props {
|
export interface CashReceiptHandWrittenIssuanceStep2Props {
|
||||||
setProcessStep: (processStep: ProcessStep) => void;
|
setProcessStep: (processStep: ProcessStep) => void;
|
||||||
@@ -33,6 +34,7 @@ export const CashReceiptHandWrittenIssuanceStep2 = ({
|
|||||||
onClickToVatCalculate
|
onClickToVatCalculate
|
||||||
}: CashReceiptHandWrittenIssuanceStep2Props) => {
|
}: CashReceiptHandWrittenIssuanceStep2Props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { handleInputFocus, keyboardAwarePadding } = useKeyboardAware();
|
||||||
|
|
||||||
useSetOnBack(() => {
|
useSetOnBack(() => {
|
||||||
setProcessStep(ProcessStep.One);
|
setProcessStep(ProcessStep.One);
|
||||||
@@ -52,6 +54,7 @@ export const CashReceiptHandWrittenIssuanceStep2 = ({
|
|||||||
allowNegative={ false }
|
allowNegative={ false }
|
||||||
displayType="input"
|
displayType="input"
|
||||||
onChange={ (e: ChangeEvent<HTMLInputElement>) => setIssueAmount(parseInt(e.target.value)) }
|
onChange={ (e: ChangeEvent<HTMLInputElement>) => setIssueAmount(parseInt(e.target.value)) }
|
||||||
|
onFocus={handleInputFocus}
|
||||||
></NumericFormat>
|
></NumericFormat>
|
||||||
<button
|
<button
|
||||||
className="btn-40 btn-white"
|
className="btn-40 btn-white"
|
||||||
@@ -70,6 +73,7 @@ export const CashReceiptHandWrittenIssuanceStep2 = ({
|
|||||||
allowNegative={ false }
|
allowNegative={ false }
|
||||||
displayType="input"
|
displayType="input"
|
||||||
onChange={ (e: ChangeEvent<HTMLInputElement>) => setSupplyAmount(parseInt(e.target.value)) }
|
onChange={ (e: ChangeEvent<HTMLInputElement>) => setSupplyAmount(parseInt(e.target.value)) }
|
||||||
|
onFocus={handleInputFocus}
|
||||||
></NumericFormat>
|
></NumericFormat>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -81,6 +85,7 @@ export const CashReceiptHandWrittenIssuanceStep2 = ({
|
|||||||
allowNegative={ false }
|
allowNegative={ false }
|
||||||
displayType="input"
|
displayType="input"
|
||||||
onChange={ (e: ChangeEvent<HTMLInputElement>) => setVatAmount(parseInt(e.target.value)) }
|
onChange={ (e: ChangeEvent<HTMLInputElement>) => setVatAmount(parseInt(e.target.value)) }
|
||||||
|
onFocus={handleInputFocus}
|
||||||
></NumericFormat>
|
></NumericFormat>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -92,10 +97,11 @@ export const CashReceiptHandWrittenIssuanceStep2 = ({
|
|||||||
allowNegative={ false }
|
allowNegative={ false }
|
||||||
displayType="input"
|
displayType="input"
|
||||||
onChange={ (e: ChangeEvent<HTMLInputElement>) => setTaxFreeAmount(parseInt(e.target.value)) }
|
onChange={ (e: ChangeEvent<HTMLInputElement>) => setTaxFreeAmount(parseInt(e.target.value)) }
|
||||||
|
onFocus={handleInputFocus}
|
||||||
></NumericFormat>
|
></NumericFormat>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="issue-row">
|
<div className="issue-row" style={keyboardAwarePadding}>
|
||||||
<div className="issue-label">{t('transaction.fields.serviceAmount')}</div>
|
<div className="issue-label">{t('transaction.fields.serviceAmount')}</div>
|
||||||
<div className="issue-field">
|
<div className="issue-field">
|
||||||
<NumericFormat
|
<NumericFormat
|
||||||
@@ -103,6 +109,7 @@ export const CashReceiptHandWrittenIssuanceStep2 = ({
|
|||||||
allowNegative={ false }
|
allowNegative={ false }
|
||||||
displayType="input"
|
displayType="input"
|
||||||
onChange={ (e: ChangeEvent<HTMLInputElement>) => setServiceCharge(parseInt(e.target.value)) }
|
onChange={ (e: ChangeEvent<HTMLInputElement>) => setServiceCharge(parseInt(e.target.value)) }
|
||||||
|
onFocus={handleInputFocus}
|
||||||
></NumericFormat>
|
></NumericFormat>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import { useNavigate } from '@/shared/lib/hooks/use-navigate';
|
|||||||
import { useQnaSaveMutation } from '@/entities/support/api/use-qna-save-mutation';
|
import { useQnaSaveMutation } from '@/entities/support/api/use-qna-save-mutation';
|
||||||
import { HeaderType } from '@/entities/common/model/types';
|
import { HeaderType } from '@/entities/common/model/types';
|
||||||
import {
|
import {
|
||||||
useSetHeaderTitle,
|
useSetHeaderTitle,
|
||||||
useSetHeaderType,
|
useSetHeaderType,
|
||||||
useSetFooterMode,
|
useSetFooterMode,
|
||||||
useSetOnBack
|
useSetOnBack
|
||||||
} from '@/widgets/sub-layout/use-sub-layout';
|
} from '@/widgets/sub-layout/use-sub-layout';
|
||||||
import { useStore } from '@/shared/model/store';
|
import { useStore } from '@/shared/model/store';
|
||||||
@@ -16,6 +16,7 @@ import { overlay } from 'overlay-kit';
|
|||||||
import { Dialog } from '@/shared/ui/dialogs/dialog';
|
import { Dialog } from '@/shared/ui/dialogs/dialog';
|
||||||
import { QnaSaveParams, QnaSaveResponse } from '@/entities/support/model/types';
|
import { QnaSaveParams, QnaSaveResponse } from '@/entities/support/model/types';
|
||||||
import { checkGrant } from '@/shared/lib/check-grant';
|
import { checkGrant } from '@/shared/lib/check-grant';
|
||||||
|
import { useKeyboardAware } from '@/shared/lib/hooks/use-keyboard-aware';
|
||||||
|
|
||||||
export enum QnaRegisterPropsName {
|
export enum QnaRegisterPropsName {
|
||||||
Mid = 'Mid',
|
Mid = 'Mid',
|
||||||
@@ -39,6 +40,7 @@ export const QnaRegisterPage = () => {
|
|||||||
const [requestEmail, setRequestEmail] = useState<string>('');
|
const [requestEmail, setRequestEmail] = useState<string>('');
|
||||||
const [title, setTitle] = useState<string>('');
|
const [title, setTitle] = useState<string>('');
|
||||||
const [contents, setContents] = useState<string>('');
|
const [contents, setContents] = useState<string>('');
|
||||||
|
const { handleInputFocus, keyboardAwarePadding } = useKeyboardAware();
|
||||||
|
|
||||||
useSetHeaderTitle(t('support.qna.title'));
|
useSetHeaderTitle(t('support.qna.title'));
|
||||||
useSetHeaderType(HeaderType.LeftArrow);
|
useSetHeaderType(HeaderType.LeftArrow);
|
||||||
@@ -54,25 +56,25 @@ export const QnaRegisterPage = () => {
|
|||||||
key: string
|
key: string
|
||||||
) => {
|
) => {
|
||||||
let value = e.target.value;
|
let value = e.target.value;
|
||||||
if(key === QnaRegisterPropsName.Mid){
|
if (key === QnaRegisterPropsName.Mid) {
|
||||||
setMid(value);
|
setMid(value);
|
||||||
}
|
}
|
||||||
else if(key === QnaRegisterPropsName.RequestType){
|
else if (key === QnaRegisterPropsName.RequestType) {
|
||||||
setRequestType(value);
|
setRequestType(value);
|
||||||
}
|
}
|
||||||
else if(key === QnaRegisterPropsName.RequestName){
|
else if (key === QnaRegisterPropsName.RequestName) {
|
||||||
setRequestName(value);
|
setRequestName(value);
|
||||||
}
|
}
|
||||||
else if(key === QnaRegisterPropsName.RequestTel){
|
else if (key === QnaRegisterPropsName.RequestTel) {
|
||||||
setRequestTel(value);
|
setRequestTel(value);
|
||||||
}
|
}
|
||||||
else if(key === QnaRegisterPropsName.RequestEmail){
|
else if (key === QnaRegisterPropsName.RequestEmail) {
|
||||||
setRequestEmail(value);
|
setRequestEmail(value);
|
||||||
}
|
}
|
||||||
else if(key === QnaRegisterPropsName.Title){
|
else if (key === QnaRegisterPropsName.Title) {
|
||||||
setTitle(value);
|
setTitle(value);
|
||||||
}
|
}
|
||||||
else if(key === QnaRegisterPropsName.Contents){
|
else if (key === QnaRegisterPropsName.Contents) {
|
||||||
setContents(value);
|
setContents(value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -87,7 +89,7 @@ export const QnaRegisterPage = () => {
|
|||||||
afterLeave={unmount}
|
afterLeave={unmount}
|
||||||
open={isOpen}
|
open={isOpen}
|
||||||
onClose={close}
|
onClose={close}
|
||||||
message={ msg }
|
message={msg}
|
||||||
buttonLabel={[t('support.qna.confirmButton')]}
|
buttonLabel={[t('support.qna.confirmButton')]}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@@ -95,35 +97,35 @@ export const QnaRegisterPage = () => {
|
|||||||
}
|
}
|
||||||
const checkEmail = (email: string) => {
|
const checkEmail = (email: string) => {
|
||||||
var re = /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
else{
|
else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const callRegister = () => {
|
const callRegister = () => {
|
||||||
if(!title){
|
if (!title) {
|
||||||
showAlert(t('support.qna.validation.title'));
|
showAlert(t('support.qna.validation.title'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if(!requestType){
|
else if (!requestType) {
|
||||||
showAlert(t('support.qna.validation.requestType'));
|
showAlert(t('support.qna.validation.requestType'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if(!requestName){
|
else if (!requestName) {
|
||||||
showAlert(t('support.qna.validation.requestName'));
|
showAlert(t('support.qna.validation.requestName'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if(!requestTel){
|
else if (!requestTel) {
|
||||||
showAlert(t('support.qna.validation.requestTel'));
|
showAlert(t('support.qna.validation.requestTel'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if(requestEmail && !checkEmail(requestEmail)){
|
else if (requestEmail && !checkEmail(requestEmail)) {
|
||||||
showAlert(t('support.qna.validation.requestEmail'));
|
showAlert(t('support.qna.validation.requestEmail'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if(!contents){
|
else if (!contents) {
|
||||||
showAlert(t('support.qna.validation.contents'));
|
showAlert(t('support.qna.validation.contents'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -140,7 +142,7 @@ export const QnaRegisterPage = () => {
|
|||||||
alert(t('support.qna.successMessage'));
|
alert(t('support.qna.successMessage'));
|
||||||
navigate(PATHS.support.qna.list);
|
navigate(PATHS.support.qna.list);
|
||||||
}).catch((e: any) => {
|
}).catch((e: any) => {
|
||||||
if(e.response?.data?.error?.message){
|
if (e.response?.data?.error?.message) {
|
||||||
showAlert(e.response?.data?.error?.message);
|
showAlert(e.response?.data?.error?.message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -168,9 +170,10 @@ export const QnaRegisterPage = () => {
|
|||||||
<div className="inq-control">
|
<div className="inq-control">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={ title }
|
value={title}
|
||||||
required= { true }
|
required={true}
|
||||||
onChange={ (e: ChangeEvent<HTMLInputElement>) => setInputValue(e, QnaRegisterPropsName.Title) }
|
onChange={(e: ChangeEvent<HTMLInputElement>) => setInputValue(e, QnaRegisterPropsName.Title)}
|
||||||
|
onFocus={handleInputFocus}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -180,9 +183,9 @@ export const QnaRegisterPage = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="inq-control">
|
<div className="inq-control">
|
||||||
<select
|
<select
|
||||||
value={ requestType }
|
value={requestType}
|
||||||
required= { true }
|
required={true}
|
||||||
onChange={ (e: ChangeEvent<HTMLSelectElement>) => setInputValue(e, QnaRegisterPropsName.RequestType) }
|
onChange={(e: ChangeEvent<HTMLSelectElement>) => setInputValue(e, QnaRegisterPropsName.RequestType)}
|
||||||
>
|
>
|
||||||
<option value="">{t('support.qna.categories.choose')}</option>
|
<option value="">{t('support.qna.categories.choose')}</option>
|
||||||
<option value="01">{t('support.qna.categories.01')}</option>
|
<option value="01">{t('support.qna.categories.01')}</option>
|
||||||
@@ -202,9 +205,10 @@ export const QnaRegisterPage = () => {
|
|||||||
<div className="inq-control">
|
<div className="inq-control">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={ requestName }
|
value={requestName}
|
||||||
required= { true }
|
required={true}
|
||||||
onChange={ (e: ChangeEvent<HTMLInputElement>) => setInputValue(e, QnaRegisterPropsName.RequestName) }
|
onChange={(e: ChangeEvent<HTMLInputElement>) => setInputValue(e, QnaRegisterPropsName.RequestName)}
|
||||||
|
onFocus={handleInputFocus}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -215,10 +219,11 @@ export const QnaRegisterPage = () => {
|
|||||||
<div className="inq-control">
|
<div className="inq-control">
|
||||||
<PatternFormat
|
<PatternFormat
|
||||||
placeholder={t('support.qna.formLabels.phonePlaceholder')}
|
placeholder={t('support.qna.formLabels.phonePlaceholder')}
|
||||||
value={ requestTel }
|
value={requestTel}
|
||||||
valueIsNumericString
|
valueIsNumericString
|
||||||
format="###########"
|
format="###########"
|
||||||
onChange={ (e: ChangeEvent<HTMLInputElement>) => setInputValue(e, QnaRegisterPropsName.RequestTel) }
|
onChange={(e: ChangeEvent<HTMLInputElement>) => setInputValue(e, QnaRegisterPropsName.RequestTel)}
|
||||||
|
onFocus={handleInputFocus}
|
||||||
></PatternFormat>
|
></PatternFormat>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -228,20 +233,22 @@ export const QnaRegisterPage = () => {
|
|||||||
<input
|
<input
|
||||||
type="email"
|
type="email"
|
||||||
placeholder={t('support.qna.formLabels.emailPlaceholder')}
|
placeholder={t('support.qna.formLabels.emailPlaceholder')}
|
||||||
value={ requestEmail }
|
value={requestEmail}
|
||||||
onChange={ (e: ChangeEvent<HTMLInputElement>) => setInputValue(e, QnaRegisterPropsName.RequestEmail) }
|
onChange={(e: ChangeEvent<HTMLInputElement>) => setInputValue(e, QnaRegisterPropsName.RequestEmail)}
|
||||||
|
onFocus={handleInputFocus}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="inq-text">
|
<div className="inq-text" style={keyboardAwarePadding}>
|
||||||
<div className="inq-text-label">
|
<div className="inq-text-label">
|
||||||
{t('support.qna.formLabels.inquiryContents')} <span className="red">{t('support.qna.formLabels.required')}</span>
|
{t('support.qna.formLabels.inquiryContents')} <span className="red">{t('support.qna.formLabels.required')}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="inq-text-body">
|
<div className="inq-text-body">
|
||||||
<textarea
|
<textarea
|
||||||
value={ contents }
|
value={contents}
|
||||||
required= { true }
|
required={true}
|
||||||
onChange={ (e: ChangeEvent<HTMLTextAreaElement>) => setInputValue(e, QnaRegisterPropsName.Contents) }
|
onChange={(e: ChangeEvent<HTMLTextAreaElement>) => setInputValue(e, QnaRegisterPropsName.Contents)}
|
||||||
|
onFocus={handleInputFocus}
|
||||||
></textarea>
|
></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -249,7 +256,7 @@ export const QnaRegisterPage = () => {
|
|||||||
<div className="apply-row">
|
<div className="apply-row">
|
||||||
<button
|
<button
|
||||||
className="btn-50 btn-blue flex-1"
|
className="btn-50 btn-blue flex-1"
|
||||||
onClick={ () => onClickToRegisterQna() }
|
onClick={() => onClickToRegisterQna()}
|
||||||
>{t('support.qna.submitButton')}</button>
|
>{t('support.qna.submitButton')}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import moment from 'moment';
|
|||||||
import NiceCalendar from '@/shared/ui/calendar/nice-calendar';
|
import NiceCalendar from '@/shared/ui/calendar/nice-calendar';
|
||||||
import { notiBar, snackBar } from '@/shared/lib';
|
import { notiBar, snackBar } from '@/shared/lib';
|
||||||
import { BillingChargeParams, BillingChargeResponse } from '@/entities/transaction/model/types';
|
import { BillingChargeParams, BillingChargeResponse } from '@/entities/transaction/model/types';
|
||||||
|
import { useKeyboardAware } from '@/shared/lib/hooks/use-keyboard-aware';
|
||||||
|
|
||||||
export const BillingChargePage = () => {
|
export const BillingChargePage = () => {
|
||||||
const { navigate } = useNavigate();
|
const { navigate } = useNavigate();
|
||||||
@@ -31,7 +32,7 @@ export const BillingChargePage = () => {
|
|||||||
const [installmentMonth, setInstallmentMonth] = useState<string>('00');
|
const [installmentMonth, setInstallmentMonth] = useState<string>('00');
|
||||||
|
|
||||||
const [calendarOpen, setCalendarOpen] = useState<boolean>(false);
|
const [calendarOpen, setCalendarOpen] = useState<boolean>(false);
|
||||||
|
const { handleInputFocus, keyboardAwarePadding } = useKeyboardAware();
|
||||||
|
|
||||||
useSetHeaderTitle(t('billing.charge'));
|
useSetHeaderTitle(t('billing.charge'));
|
||||||
useSetHeaderType(HeaderType.RightClose);
|
useSetHeaderType(HeaderType.RightClose);
|
||||||
@@ -51,26 +52,26 @@ export const BillingChargePage = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onClickToBillingCharge = () => {
|
const onClickToBillingCharge = () => {
|
||||||
if(!billKey){
|
if (!billKey) {
|
||||||
showAlert('빌키는 필수 입력 항목입니다.');
|
showAlert('빌키는 필수 입력 항목입니다.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if(!productName){
|
else if (!productName) {
|
||||||
showAlert('상품명은 필수 입력 항목입니다.');
|
showAlert('상품명은 필수 입력 항목입니다.');
|
||||||
}
|
}
|
||||||
else if(!productAmount){
|
else if (!productAmount) {
|
||||||
showAlert('상품금액은 필수 입력 항목입니다.');
|
showAlert('상품금액은 필수 입력 항목입니다.');
|
||||||
}
|
}
|
||||||
else if(productAmount <= 0){
|
else if (productAmount <= 0) {
|
||||||
showAlert('상품금액은 0보다 커야 합니다.');
|
showAlert('상품금액은 0보다 커야 합니다.');
|
||||||
}
|
}
|
||||||
else if(!orderNumber){
|
else if (!orderNumber) {
|
||||||
showAlert('주문번호는 필수 입력 항목입니다.');
|
showAlert('주문번호는 필수 입력 항목입니다.');
|
||||||
}
|
}
|
||||||
else if(!buyerName){
|
else if (!buyerName) {
|
||||||
showAlert('구매자명은 필수 입력 항목입니다.');
|
showAlert('구매자명은 필수 입력 항목입니다.');
|
||||||
}
|
}
|
||||||
|
|
||||||
let params: BillingChargeParams = {
|
let params: BillingChargeParams = {
|
||||||
billKey: billKey,
|
billKey: billKey,
|
||||||
productName: productName,
|
productName: productName,
|
||||||
@@ -81,12 +82,12 @@ export const BillingChargePage = () => {
|
|||||||
installmentMonth: installmentMonth
|
installmentMonth: installmentMonth
|
||||||
};
|
};
|
||||||
billingCharge(params).then((rs: BillingChargeResponse) => {
|
billingCharge(params).then((rs: BillingChargeResponse) => {
|
||||||
snackBar('결제 신청을 성공하였습니다.', function(){
|
snackBar('결제 신청을 성공하였습니다.', function () {
|
||||||
navigate(PATHS.transaction.billing.list);
|
navigate(PATHS.transaction.billing.list);
|
||||||
}, 3000);
|
}, 3000);
|
||||||
|
|
||||||
}).catch((e: any) => {
|
}).catch((e: any) => {
|
||||||
if(e.response?.data?.error?.message){
|
if (e.response?.data?.error?.message) {
|
||||||
showAlert(e.response?.data?.error?.message);
|
showAlert(e.response?.data?.error?.message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -95,32 +96,32 @@ export const BillingChargePage = () => {
|
|||||||
|
|
||||||
const onChangeBillKey = (value: string) => {
|
const onChangeBillKey = (value: string) => {
|
||||||
const pattern = /^[A-Za-z0-9]+$/;
|
const pattern = /^[A-Za-z0-9]+$/;
|
||||||
if(pattern.test(value) || value === ''){
|
if (pattern.test(value) || value === '') {
|
||||||
setBillKey(value);
|
setBillKey(value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const makeInstallmentMonthSelect = () => {
|
const makeInstallmentMonthSelect = () => {
|
||||||
let rs = [];
|
let rs = [];
|
||||||
|
|
||||||
rs.push(
|
rs.push(
|
||||||
<option
|
<option
|
||||||
key={ `key-installment` }
|
key={`key-installment`}
|
||||||
value=''
|
value=''
|
||||||
>선택</option>
|
>선택</option>
|
||||||
);
|
);
|
||||||
rs.push(
|
rs.push(
|
||||||
<option
|
<option
|
||||||
key={ `key-installment-0` }
|
key={`key-installment-0`}
|
||||||
value='00'
|
value='00'
|
||||||
>일시불</option>
|
>일시불</option>
|
||||||
);
|
);
|
||||||
for(let i=2;i<=24;i++){
|
for (let i = 2; i <= 24; i++) {
|
||||||
let val = (i < 10)? '0'+i: ''+i;
|
let val = (i < 10) ? '0' + i : '' + i;
|
||||||
rs.push(
|
rs.push(
|
||||||
<option
|
<option
|
||||||
key={ `key-installment-${i}`}
|
key={`key-installment-${i}`}
|
||||||
value={ val }
|
value={val}
|
||||||
>{i}개월</option>
|
>{i}개월</option>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -138,20 +139,22 @@ export const BillingChargePage = () => {
|
|||||||
<div className="billing-row">
|
<div className="billing-row">
|
||||||
<div className="billing-label">빌키 <span>*</span></div>
|
<div className="billing-label">빌키 <span>*</span></div>
|
||||||
<div className="billing-field">
|
<div className="billing-field">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={ billKey }
|
value={billKey}
|
||||||
onChange={ (e: ChangeEvent<HTMLInputElement>) => onChangeBillKey(e.target.value) }
|
onChange={(e: ChangeEvent<HTMLInputElement>) => onChangeBillKey(e.target.value)}
|
||||||
|
onFocus={handleInputFocus}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="billing-row">
|
<div className="billing-row">
|
||||||
<div className="billing-label">상품명 <span>*</span></div>
|
<div className="billing-label">상품명 <span>*</span></div>
|
||||||
<div className="billing-field">
|
<div className="billing-field">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={ productName }
|
value={productName}
|
||||||
onChange={ (e: ChangeEvent<HTMLInputElement>) => setProductName(e.target.value) }
|
onChange={(e: ChangeEvent<HTMLInputElement>) => setProductName(e.target.value)}
|
||||||
|
onFocus={handleInputFocus}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -159,30 +162,33 @@ export const BillingChargePage = () => {
|
|||||||
<div className="billing-label">상품금액 <span>*</span></div>
|
<div className="billing-label">상품금액 <span>*</span></div>
|
||||||
<div className="billing-field">
|
<div className="billing-field">
|
||||||
<NumericFormat
|
<NumericFormat
|
||||||
value={ productAmount }
|
value={productAmount}
|
||||||
allowNegative={ false }
|
allowNegative={false}
|
||||||
displayType="input"
|
displayType="input"
|
||||||
onChange={ (e: ChangeEvent<HTMLInputElement>) => setProductAmount(parseInt(e.target.value)) }
|
onChange={(e: ChangeEvent<HTMLInputElement>) => setProductAmount(parseInt(e.target.value))}
|
||||||
|
onFocus={handleInputFocus}
|
||||||
></NumericFormat>
|
></NumericFormat>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="billing-row">
|
<div className="billing-row">
|
||||||
<div className="billing-label">주문번호 <span>*</span></div>
|
<div className="billing-label">주문번호 <span>*</span></div>
|
||||||
<div className="billing-field">
|
<div className="billing-field">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={ orderNumber }
|
value={orderNumber}
|
||||||
onChange={ (e: ChangeEvent<HTMLInputElement>) => setOrderNumber(e.target.value) }
|
onChange={(e: ChangeEvent<HTMLInputElement>) => setOrderNumber(e.target.value)}
|
||||||
|
onFocus={handleInputFocus}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="billing-row">
|
<div className="billing-row">
|
||||||
<div className="billing-label">구매자명 <span>*</span></div>
|
<div className="billing-label">구매자명 <span>*</span></div>
|
||||||
<div className="billing-field">
|
<div className="billing-field">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={ buyerName }
|
value={buyerName}
|
||||||
onChange={ (e: ChangeEvent<HTMLInputElement>) => setBuyerName(e.target.value) }
|
onChange={(e: ChangeEvent<HTMLInputElement>) => setBuyerName(e.target.value)}
|
||||||
|
onFocus={handleInputFocus}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -194,16 +200,16 @@ export const BillingChargePage = () => {
|
|||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="날짜 선택"
|
placeholder="날짜 선택"
|
||||||
value={ paymentRequestDate }
|
value={paymentRequestDate}
|
||||||
readOnly={ true }
|
readOnly={true}
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
className="date-btn"
|
className="date-btn"
|
||||||
type="button"
|
type="button"
|
||||||
onClick={ () => onClickToOpenCalendar() }
|
onClick={() => onClickToOpenCalendar()}
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
src={ IMAGE_ROOT + '/ico_date.svg' }
|
src={IMAGE_ROOT + '/ico_date.svg'}
|
||||||
alt="clear"
|
alt="clear"
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
@@ -211,33 +217,33 @@ export const BillingChargePage = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="billing-row">
|
<div className="billing-row" style={keyboardAwarePadding}>
|
||||||
<div className="billing-label">할부 개월</div>
|
<div className="billing-label">할부 개월</div>
|
||||||
<div className="billing-field">
|
<div className="billing-field">
|
||||||
<select
|
<select
|
||||||
value={ installmentMonth }
|
value={installmentMonth}
|
||||||
onChange={ (e: ChangeEvent<HTMLSelectElement>) => setBuyerName(e.target.value) }
|
onChange={(e: ChangeEvent<HTMLSelectElement>) => setBuyerName(e.target.value)}
|
||||||
>
|
>
|
||||||
{ makeInstallmentMonthSelect() }
|
{makeInstallmentMonthSelect()}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="apply-row">
|
<div className="apply-row">
|
||||||
<button
|
<button
|
||||||
className="btn-50 btn-blue flex-1"
|
className="btn-50 btn-blue flex-1"
|
||||||
onClick={ () => onClickToBillingCharge() }
|
onClick={() => onClickToBillingCharge()}
|
||||||
>결제 신청</button>
|
>결제 신청</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
<NiceCalendar
|
<NiceCalendar
|
||||||
calendarOpen={ calendarOpen }
|
calendarOpen={calendarOpen}
|
||||||
setCalendarOpen={ setCalendarOpen }
|
setCalendarOpen={setCalendarOpen}
|
||||||
calendarType={ CalendarType.Single }
|
calendarType={CalendarType.Single}
|
||||||
setNewDate={ setNewDate }
|
setNewDate={setNewDate}
|
||||||
></NiceCalendar>
|
></NiceCalendar>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export const useKeyboardAware = (options?: UseKeyboardAwareOptions) => {
|
|||||||
const [keyboardHeight, setKeyboardHeight] = useState<number>(0);
|
const [keyboardHeight, setKeyboardHeight] = useState<number>(0);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let focusedElement: HTMLInputElement | null = null;
|
let focusedElement: HTMLElement | null = null;
|
||||||
let isKeyboardOpen = false;
|
let isKeyboardOpen = false;
|
||||||
|
|
||||||
// 네이티브에서 호출할 전역 함수 등록
|
// 네이티브에서 호출할 전역 함수 등록
|
||||||
@@ -44,7 +44,7 @@ export const useKeyboardAware = (options?: UseKeyboardAwareOptions) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// focus된 요소를 추적하기 위한 함수
|
// focus된 요소를 추적하기 위한 함수
|
||||||
(window as any).setFocusedElement = (element: HTMLInputElement) => {
|
(window as any).setFocusedElement = (element: HTMLElement) => {
|
||||||
focusedElement = element;
|
focusedElement = element;
|
||||||
|
|
||||||
// 키보드가 이미 열려있으면 즉시 스크롤
|
// 키보드가 이미 열려있으면 즉시 스크롤
|
||||||
@@ -62,8 +62,8 @@ export const useKeyboardAware = (options?: UseKeyboardAwareOptions) => {
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// 모든 input에서 사용할 공통 핸들러
|
// input과 textarea 모두에서 사용할 공통 핸들러
|
||||||
const handleInputFocus = (e: React.FocusEvent<HTMLInputElement>) => {
|
const handleInputFocus = (e: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
||||||
// focus된 요소를 저장
|
// focus된 요소를 저장
|
||||||
(window as any).setFocusedElement?.(e.target);
|
(window as any).setFocusedElement?.(e.target);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user