부가 서비스 : 링크 결제 페이지

This commit is contained in:
HyeonJongKim
2025-09-08 17:52:03 +09:00
parent 065a4fd348
commit 5d37dfb253
4 changed files with 395 additions and 24 deletions

View File

@@ -0,0 +1,136 @@
import { useState } from 'react';
import { PATHS } from '@/shared/constants/paths';
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { useSetOnBack } from '@/widgets/sub-layout/use-sub-layout';
import { IMAGE_ROOT } from '@/shared/constants/common';
export const LinkPaymentStep1 = () => {
const { navigate } = useNavigate();
useSetOnBack(() => {
navigate(PATHS.additionalService.intro);
});
const [selectedPaymentMethod, setSelectedPaymentMethod] = useState('SMS');
const [formData, setFormData] = useState({
merchant: 'nictest001m',
productName: '',
productPrice: '',
orderNumber: '',
validDate: '2025.06.30'
});
const handlePaymentMethodChange = (method: string) => {
setSelectedPaymentMethod(method);
};
const handleInputChange = (field: string, value: string) => {
setFormData(prev => ({
...prev,
[field]: value
}));
};
return (
<>
<div className="issue-form">
<div className="issue-row gap-10">
<div className="issue-label"></div>
<div className="issue-field">
<select
className="wid-100"
value={formData.merchant}
onChange={(e) => handleInputChange('merchant', e.target.value)}
>
<option>nictest001m</option>
</select>
</div>
</div>
<div className="issue-row gap-10">
<div className="issue-label"> </div>
<div className="issue-field">
<div className="chip-row">
<span
className={`keyword-tag flex-1 ${selectedPaymentMethod === 'SMS' ? 'active' : ''}`}
onClick={() => handlePaymentMethodChange('SMS')}
>
SMS
</span>
<span
className={`keyword-tag flex-1 ${selectedPaymentMethod === '이메일' ? 'active' : ''}`}
onClick={() => handlePaymentMethodChange('이메일')}
>
</span>
<span
className={`keyword-tag flex-1 ${selectedPaymentMethod === '카카오' ? 'active' : ''}`}
onClick={() => handlePaymentMethodChange('카카오')}
>
</span>
</div>
</div>
</div>
<div className="issue-row gap-10">
<div className="issue-label"></div>
<div className="issue-field">
<input
type="text"
placeholder=""
value={formData.productName}
onChange={(e) => handleInputChange('productName', e.target.value)}
/>
</div>
</div>
<div className="issue-row gap-10">
<div className="issue-label"></div>
<div className="issue-field">
<input
type="text"
placeholder=""
value={formData.productPrice}
onChange={(e) => handleInputChange('productPrice', e.target.value)}
/>
</div>
</div>
<div className="issue-row gap-10">
<div className="issue-label"> </div>
<div className="issue-field">
<input
type="text"
placeholder=""
value={formData.orderNumber}
onChange={(e) => handleInputChange('orderNumber', e.target.value)}
/>
</div>
</div>
<div className="issue-row gap-10">
<div className="issue-label"> </div>
<div className="issue-field">
<div className="link-apply-date">
<div className="input-wrapper date">
<input
type="text"
value={formData.validDate}
className="date-input"
onChange={(e) => handleInputChange('validDate', e.target.value)}
/>
<button type="button" className="date-btn">
<img
src={IMAGE_ROOT + '/ico_date.svg'}
alt="날짜 선택"
/>
</button>
</div>
<span></span>
</div>
</div>
</div>
</div>
</>
);
};

View File

@@ -0,0 +1,164 @@
import {ProcessStep} from "@/entities/transaction/model/types";
import {useSetOnBack} from "@/widgets/sub-layout/use-sub-layout";
import {useState} from "react";
export interface LinkPaymentStep2Props {
setProcessStep: ((processStep: ProcessStep) => void);
}
export const LinkPaymentStep2 = ({
setProcessStep
}: LinkPaymentStep2Props) => {
useSetOnBack(() => {
setProcessStep(ProcessStep.One);
});
const handleInputChange = (field: string, value: string) => {
setFormData(prev => ({
...prev,
[field]: value
}));
};
const [selectedPurchaserType, setSelectedPurchaserType] = useState('개인');
const [selectedLanguage, setSelectedLanguage] = useState('국문')
const [selectedLinkContent, setSelectedLinkContent] = useState('기본');
const [formData, setFormData] = useState({
purchaser: '',
purchaserEmail: '',
purchaserPhone: '',
purchaserBirth: ''
});
const handlePurchaserTypeChange = (type: string) => {
setSelectedPurchaserType(type)
}
const handleLanguageType = (type: string) => {
setSelectedLanguage(type)
}
const handleLinkContent = (content: string) => {
setSelectedLinkContent(content)
}
return (
<>
<div className="issue-form">
<div className="issue-row gap-10">
<div className="issue-label wid-105"></div>
<div className="issue-field">
<input
type="text"
placeholder=""
value={formData.purchaser}
onChange={(e) => handleInputChange('purchaser', e.target.value)}
/>
</div>
</div>
<div className="issue-row gap-10">
<div className="issue-label wid-105"> </div>
<div className="issue-field">
<input
type="text"
placeholder="test@nicepay.co.kr"
value={formData.purchaserEmail}
onChange={(e) => handleInputChange('purchaserEmail', e.target.value)}
/>
</div>
</div>
<div className="issue-row gap-10">
<div className="issue-label wid-105"><br/> </div>
<div className="issue-field">
<input
type="text"
placeholder="01012345678"
value={formData.purchaserPhone}
onChange={(e) => handleInputChange('purchaserPhone', e.target.value)}
/>
</div>
</div>
<div className="issue-row gap-10 beetween">
<div className="issue-label wid-105"> </div>
<label className="settings-switch">
<input type="checkbox"/>
<span className="slider"></span>
</label>
</div>
<div className="issue-row gap-10">
<div className="issue-label wid-105"></div>
<div className="issue-field">
<div className="chip-row">
<span
className={`keyword-tag flex-1 ${selectedPurchaserType === '개인' ? 'active' : ''}`}
onClick={() => handlePurchaserTypeChange('개인')}
>
</span>
<span
className={`keyword-tag flex-1 ${selectedPurchaserType === '법인' ? 'active' : ''}`}
onClick={() => handlePurchaserTypeChange('법인')}
>
</span>
</div>
</div>
</div>
<div className="issue-row gap-10">
<div className="issue-label wid-105"></div>
<div className='issue-field'>
<input
type="text"
placeholder="생년월일 6자리"
value={formData.purchaserBirth}
onChange={(e) => handleInputChange('purchaserPhone', e.target.value)}
/>
</div>
</div>
<div className="issue-row gap-10">
<div className="issue-label wid-105"></div>
<div className="issue-field">
<div className="chip-row">
<span
className={`keyword-tag flex-1 ${selectedLanguage === '국문' ? 'active' : ''}`}
onClick={() => handleLanguageType('국문')}
>
</span>
<span
className={`keyword-tag flex-1 ${selectedLanguage === '영문' ? 'active' : ''}`}
onClick={() => handleLanguageType('영문')}
>
</span>
</div>
</div>
</div>
<div className="issue-row gap-10">
<div className="issue-label wid-105"></div>
<div className="issue-field">
<div className="chip-row">
<span
className={`keyword-tag flex-1 ${selectedLinkContent === '기본' ? 'active' : ''}`}
onClick={() => handleLinkContent('기본')}
>
</span>
<span
className={`keyword-tag flex-1 ${selectedLinkContent === '추가' ? 'active' : ''}`}
onClick={() => handleLinkContent('추가')}
>
</span>
</div>
</div>
</div>
</div>
</>
)
}

View File

@@ -1,18 +1,85 @@
import { HeaderType } from '@/entities/common/model/types';
import {
useSetHeaderTitle,
useSetHeaderType,
useSetFooterMode
} from '@/widgets/sub-layout/use-sub-layout';
import {useState} from 'react';
import {LinkPaymentStep1} from '@/entities/additional-service/ui/link-payment-step1';
import {LinkPaymentStep2} from '@/entities/additional-service/ui/link-payment-step2';
import {HeaderType} from '@/entities/common/model/types';
import {ProcessStep} from '@/entities/transaction/model/types';
import {useSetFooterMode, useSetHeaderTitle, useSetHeaderType} from '@/widgets/sub-layout/use-sub-layout';
import {useNavigate} from '@/shared/lib/hooks/use-navigate';
import {PATHS} from "@/shared/constants/paths";
export const LinkPaymentPage = () => {
useSetHeaderTitle('링크결제');
const { navigate } = useNavigate();
const [processStep, setProcessStep] = useState<ProcessStep>(ProcessStep.One);
useSetHeaderTitle('링크결제 신청');
useSetHeaderType(HeaderType.LeftArrow);
useSetFooterMode(true);
useSetFooterMode(false);
const onClickToChangeTab = () => {
if(processStep === ProcessStep.One) {
setProcessStep(ProcessStep.Two);
}
else if(processStep === ProcessStep.Two) {
alert('완료')
navigate(PATHS.home)
}
};
return (
<>
<main>
<div className="tab-content">
<div className="tab-pane sub active">
<div className="option-list">
<div className="issue-progress">
<div className="bar">
{(processStep === ProcessStep.One) &&
<div
className="fill"
style={{ width: '50%' }}
></div>
}
{(processStep === ProcessStep.Two) &&
<div
className="fill"
style={{ width: '100%' }}
></div>
}
</div>
</div>
{(processStep === ProcessStep.One) &&
<LinkPaymentStep1 ></LinkPaymentStep1>
}
{ (processStep === ProcessStep.Two) &&
<LinkPaymentStep2
setProcessStep={ setProcessStep }
></LinkPaymentStep2>
}
</div>
{(processStep === ProcessStep.One) &&
<div className="apply-row">
<button
className="btn-50 btn-blue flex-1"
onClick={() => onClickToChangeTab() }
></button>
</div>
}
{(processStep === ProcessStep.Two) &&
<div className="apply-row two-button">
<button
className="btn-50 btn-darkgray flex-1">
</button>
<button
className="btn-50 btn-blue flex-3"
onClick={() => onClickToChangeTab() }
> </button>
</div>
}
</div>
</div>
</main>
</>
);
};

View File

@@ -1,15 +1,11 @@
import { useState } from 'react';
import { PATHS } from '@/shared/constants/paths';
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { CashReceitHandWrittenIssuanceStep1 } from '@/entities/transaction/ui/cash-receit-hand-written-issuance-step1';
import { CashReceitHandWrittenIssuanceStep2 } from '@/entities/transaction/ui/cash-receit-hand-written-issuance-step2';
import { ProcessStep } from '@/entities/transaction/model/types';
import { HeaderType } from '@/entities/common/model/types';
import {
useSetHeaderTitle,
useSetHeaderType,
useSetFooterMode
} from '@/widgets/sub-layout/use-sub-layout';
import {useState} from 'react';
import {PATHS} from '@/shared/constants/paths';
import {useNavigate} from '@/shared/lib/hooks/use-navigate';
import {CashReceitHandWrittenIssuanceStep1} from '@/entities/transaction/ui/cash-receit-hand-written-issuance-step1';
import {CashReceitHandWrittenIssuanceStep2} from '@/entities/transaction/ui/cash-receit-hand-written-issuance-step2';
import {ProcessStep} from '@/entities/transaction/model/types';
import {HeaderType} from '@/entities/common/model/types';
import {useSetFooterMode, useSetHeaderTitle, useSetHeaderType} from '@/widgets/sub-layout/use-sub-layout';
export const CashReceitHandWrittenIssuancePage = () => {
const { navigate } = useNavigate();
@@ -40,10 +36,18 @@ export const CashReceitHandWrittenIssuancePage = () => {
<div className="option-list">
<div className="issue-progress">
<div className="bar">
{(processStep === ProcessStep.One) &&
<div
className="fill"
style={{ width: '50%' }}
></div>
}
{(processStep === ProcessStep.Two) &&
<div
className="fill"
style={{ width: '100%' }}
></div>
}
</div>
{ (processStep === ProcessStep.One) &&
<CashReceitHandWrittenIssuanceStep1></CashReceitHandWrittenIssuanceStep1>