부가서비스
- 링크결제 결제신청 API 연결
This commit is contained in:
@@ -0,0 +1,26 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
import { API_URL_ADDITIONAL_SERVICE } from '@/shared/api/api-url-additional-service';
|
||||||
|
import { resultify } from '@/shared/lib/resultify';
|
||||||
|
import { CBDCAxiosError } from '@/shared/@types/error';
|
||||||
|
import {
|
||||||
|
useMutation,
|
||||||
|
UseMutationOptions
|
||||||
|
} from '@tanstack/react-query';
|
||||||
|
import { ExtensionLinkPayRequestParams, ExtensionLinkPayRequestResponse } from '../../model/types';
|
||||||
|
|
||||||
|
export const extensionLinkPayRequest = (params: ExtensionLinkPayRequestParams) => {
|
||||||
|
return resultify(
|
||||||
|
axios.post<ExtensionLinkPayRequestResponse>(API_URL_ADDITIONAL_SERVICE.extensionLinkPaymentRequest(), params),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useExtensionLinkPayRequestMutation = (options?: UseMutationOptions<ExtensionLinkPayRequestResponse, CBDCAxiosError, ExtensionLinkPayRequestParams>) => {
|
||||||
|
const mutation = useMutation<ExtensionLinkPayRequestResponse, CBDCAxiosError, ExtensionLinkPayRequestParams>({
|
||||||
|
...options,
|
||||||
|
mutationFn: (params: ExtensionLinkPayRequestParams) => extensionLinkPayRequest(params),
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
...mutation,
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -13,7 +13,7 @@ import { ExtensionLinkPayWaitDeleteParams } from '../../model/types';
|
|||||||
|
|
||||||
export const extensionLinkPayWaitDelete = async (params: ExtensionLinkPayWaitDeleteParams)=> {
|
export const extensionLinkPayWaitDelete = async (params: ExtensionLinkPayWaitDeleteParams)=> {
|
||||||
return resultify(
|
return resultify(
|
||||||
axios.post<ExtensionLinkPayWaitDeleteRespone>(API_URL_ADDITIONAL_SERVICE.extensionLinkPayMentWaitDelete(), params)
|
axios.post<ExtensionLinkPayWaitDeleteRespone>(API_URL_ADDITIONAL_SERVICE.extensionLinkPaymentWaitDelete(), params)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -215,6 +215,21 @@ export enum LinkPaymentSendingStatus {
|
|||||||
SEND_CANCEL = "SEND_CANCEL"
|
SEND_CANCEL = "SEND_CANCEL"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum IdentityType {
|
||||||
|
INDIVIDUAL = "INDIVIDUAL",
|
||||||
|
CORPORATE = "CORPORATE"
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum Language {
|
||||||
|
KR = "KR",
|
||||||
|
EN = "EN"
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum LinkContentType {
|
||||||
|
BASIC = "BASIC",
|
||||||
|
ADDITIONAL = "ADDITIONAL"
|
||||||
|
}
|
||||||
|
|
||||||
export interface LinkPaymentHistoryListItem {
|
export interface LinkPaymentHistoryListItem {
|
||||||
tid?: string;
|
tid?: string;
|
||||||
// TODO : buyerName 필요
|
// TODO : buyerName 필요
|
||||||
@@ -396,6 +411,45 @@ export interface ExtensionLinkPayHistoryDownloadExcelRespone {
|
|||||||
status: boolean;
|
status: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ExtensionLinkPayRequestParams extends ExtensionRequestParams {
|
||||||
|
sendMethod: string;
|
||||||
|
goodsName: string;
|
||||||
|
amount: number;
|
||||||
|
moid: string;
|
||||||
|
paymentExpiryDate: string;
|
||||||
|
buyerName: string;
|
||||||
|
email: string;
|
||||||
|
phoneNumber: string;
|
||||||
|
isIdentity: boolean;
|
||||||
|
identityType: IdentityType;
|
||||||
|
identityValue: string;
|
||||||
|
language: Language;
|
||||||
|
linkContentType: LinkContentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ExtensionLinkPayRequestResponse {
|
||||||
|
status: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LinkPaymentFormData {
|
||||||
|
// Step 1
|
||||||
|
mid: string;
|
||||||
|
sendMethod: LinkPaymentSendMethod;
|
||||||
|
goodsName: string;
|
||||||
|
amount: number;
|
||||||
|
moid: string;
|
||||||
|
paymentExpiryDate: string;
|
||||||
|
// Step 2
|
||||||
|
buyerName: string;
|
||||||
|
email: string;
|
||||||
|
phoneNumber: string;
|
||||||
|
isIdentity: boolean;
|
||||||
|
identityType: IdentityType;
|
||||||
|
identityValue: string;
|
||||||
|
language: Language;
|
||||||
|
linkContentType: LinkContentType;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ExtensionLinkPayHistoryDetailParams extends ExtensionRequestParams {
|
export interface ExtensionLinkPayHistoryDetailParams extends ExtensionRequestParams {
|
||||||
tid: string;
|
tid: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +1,31 @@
|
|||||||
import { useState } from 'react';
|
|
||||||
import { PATHS } from '@/shared/constants/paths';
|
import { PATHS } from '@/shared/constants/paths';
|
||||||
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
|
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
|
||||||
import { useSetOnBack } from '@/widgets/sub-layout/use-sub-layout';
|
import { useSetOnBack } from '@/widgets/sub-layout/use-sub-layout';
|
||||||
import { IMAGE_ROOT } from '@/shared/constants/common';
|
import { LinkPaymentFormData, LinkPaymentSendMethod } from '@/entities/additional-service/model/types';
|
||||||
|
import { SingleDatePicker } from '@/shared/ui/filter/single-date-picker';
|
||||||
|
|
||||||
export const LinkPaymentStep1 = () => {
|
interface LinkPaymentStep1Props {
|
||||||
|
formData: LinkPaymentFormData;
|
||||||
|
setFormData: (formData: LinkPaymentFormData) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const LinkPaymentStep1 = ({ formData, setFormData }: LinkPaymentStep1Props) => {
|
||||||
const { navigate } = useNavigate();
|
const { navigate } = useNavigate();
|
||||||
|
|
||||||
useSetOnBack(() => {
|
useSetOnBack(() => {
|
||||||
navigate(PATHS.additionalService.intro);
|
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) => {
|
const handlePaymentMethodChange = (method: LinkPaymentSendMethod) => {
|
||||||
setSelectedPaymentMethod(method);
|
setFormData({ ...formData, sendMethod: method });
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleInputChange = (field: string, value: string) => {
|
const handleInputChange = (field: string, value: string) => {
|
||||||
setFormData(prev => ({
|
setFormData({ ...formData, [field]: value });
|
||||||
...prev,
|
};
|
||||||
[field]: value
|
|
||||||
}));
|
const handleDateChange = (date: string) => {
|
||||||
|
setFormData({ ...formData, paymentExpiryDate: date });
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -38,8 +36,8 @@ export const LinkPaymentStep1 = () => {
|
|||||||
<div className="issue-field">
|
<div className="issue-field">
|
||||||
<select
|
<select
|
||||||
className="wid-100"
|
className="wid-100"
|
||||||
value={formData.merchant}
|
value={formData.mid}
|
||||||
onChange={(e) => handleInputChange('merchant', e.target.value)}
|
onChange={(e) => handleInputChange('mid', e.target.value)}
|
||||||
>
|
>
|
||||||
<option>nictest001m</option>
|
<option>nictest001m</option>
|
||||||
</select>
|
</select>
|
||||||
@@ -51,20 +49,20 @@ export const LinkPaymentStep1 = () => {
|
|||||||
<div className="issue-field">
|
<div className="issue-field">
|
||||||
<div className="chip-row">
|
<div className="chip-row">
|
||||||
<span
|
<span
|
||||||
className={`keyword-tag flex-1 ${selectedPaymentMethod === 'SMS' ? 'active' : ''}`}
|
className={`keyword-tag flex-1 ${formData.sendMethod === 'SMS' ? 'active' : ''}`}
|
||||||
onClick={() => handlePaymentMethodChange('SMS')}
|
onClick={() => handlePaymentMethodChange(LinkPaymentSendMethod.SMS)}
|
||||||
>
|
>
|
||||||
SMS
|
SMS
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className={`keyword-tag flex-1 ${selectedPaymentMethod === '이메일' ? 'active' : ''}`}
|
className={`keyword-tag flex-1 ${formData.sendMethod === 'EMAIL' ? 'active' : ''}`}
|
||||||
onClick={() => handlePaymentMethodChange('이메일')}
|
onClick={() => handlePaymentMethodChange(LinkPaymentSendMethod.EMAIL)}
|
||||||
>
|
>
|
||||||
이메일
|
이메일
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className={`keyword-tag flex-1 ${selectedPaymentMethod === '카카오' ? 'active' : ''}`}
|
className={`keyword-tag flex-1 ${formData.sendMethod === 'KAKAO' ? 'active' : ''}`}
|
||||||
onClick={() => handlePaymentMethodChange('카카오')}
|
onClick={() => handlePaymentMethodChange(LinkPaymentSendMethod.KAKAO)}
|
||||||
>
|
>
|
||||||
카카오
|
카카오
|
||||||
</span>
|
</span>
|
||||||
@@ -78,8 +76,8 @@ export const LinkPaymentStep1 = () => {
|
|||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder=""
|
placeholder=""
|
||||||
value={formData.productName}
|
value={formData.goodsName}
|
||||||
onChange={(e) => handleInputChange('productName', e.target.value)}
|
onChange={(e) => handleInputChange('goodsName', e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -90,8 +88,8 @@ export const LinkPaymentStep1 = () => {
|
|||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder=""
|
placeholder=""
|
||||||
value={formData.productPrice}
|
value={formData.amount}
|
||||||
onChange={(e) => handleInputChange('productPrice', e.target.value)}
|
onChange={(e) => handleInputChange('amount', e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -102,8 +100,8 @@ export const LinkPaymentStep1 = () => {
|
|||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder=""
|
placeholder=""
|
||||||
value={formData.orderNumber}
|
value={formData.moid}
|
||||||
onChange={(e) => handleInputChange('orderNumber', e.target.value)}
|
onChange={(e) => handleInputChange('moid', e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -112,20 +110,11 @@ export const LinkPaymentStep1 = () => {
|
|||||||
<div className="issue-label">결제 유효일</div>
|
<div className="issue-label">결제 유효일</div>
|
||||||
<div className="issue-field">
|
<div className="issue-field">
|
||||||
<div className="link-apply-date">
|
<div className="link-apply-date">
|
||||||
<div className="input-wrapper date">
|
<SingleDatePicker
|
||||||
<input
|
date={formData.paymentExpiryDate}
|
||||||
type="text"
|
setDate={handleDateChange}
|
||||||
value={formData.validDate}
|
placeholder="날짜 선택"
|
||||||
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>
|
<span>까지</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,45 +1,40 @@
|
|||||||
import {ProcessStep} from "@/entities/transaction/model/types";
|
import {ProcessStep} from "@/entities/transaction/model/types";
|
||||||
import {useSetOnBack} from "@/widgets/sub-layout/use-sub-layout";
|
import {useSetOnBack} from "@/widgets/sub-layout/use-sub-layout";
|
||||||
import {useState} from "react";
|
import { LinkPaymentFormData, IdentityType, Language, LinkContentType } from '@/entities/additional-service/model/types'
|
||||||
|
|
||||||
export interface LinkPaymentStep2Props {
|
export interface LinkPaymentStep2Props {
|
||||||
setProcessStep: ((processStep: ProcessStep) => void);
|
setProcessStep: ((processStep: ProcessStep) => void);
|
||||||
|
formData: LinkPaymentFormData;
|
||||||
|
setFormData: (formData: LinkPaymentFormData) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const LinkPaymentStep2 = ({
|
export const LinkPaymentStep2 = ({
|
||||||
setProcessStep
|
setProcessStep,
|
||||||
|
formData,
|
||||||
|
setFormData
|
||||||
}: LinkPaymentStep2Props) => {
|
}: LinkPaymentStep2Props) => {
|
||||||
useSetOnBack(() => {
|
useSetOnBack(() => {
|
||||||
setProcessStep(ProcessStep.One);
|
setProcessStep(ProcessStep.One);
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleInputChange = (field: string, value: string) => {
|
const handleInputChange = (field: string, value: string) => {
|
||||||
setFormData(prev => ({
|
setFormData({ ...formData, [field]: value });
|
||||||
...prev,
|
|
||||||
[field]: value
|
|
||||||
}));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const [selectedPurchaserType, setSelectedPurchaserType] = useState('개인');
|
const handleIdendityTypeChange = (type: IdentityType) => {
|
||||||
const [selectedLanguage, setSelectedLanguage] = useState('국문')
|
setFormData({ ...formData, identityType: type });
|
||||||
const [selectedLinkContent, setSelectedLinkContent] = useState('기본');
|
|
||||||
const [formData, setFormData] = useState({
|
|
||||||
purchaser: '',
|
|
||||||
purchaserEmail: '',
|
|
||||||
purchaserPhone: '',
|
|
||||||
purchaserBirth: ''
|
|
||||||
});
|
|
||||||
|
|
||||||
const handlePurchaserTypeChange = (type: string) => {
|
|
||||||
setSelectedPurchaserType(type)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleLanguageType = (type: string) => {
|
const handleLanguageType = (type: Language) => {
|
||||||
setSelectedLanguage(type)
|
setFormData({ ...formData, language: type });
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleLinkContent = (content: string) => {
|
const handleLinkContent = (content: LinkContentType) => {
|
||||||
setSelectedLinkContent(content)
|
setFormData({ ...formData, linkContentType: content });
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleIdentityToggle = (isChecked: boolean) => {
|
||||||
|
setFormData({ ...formData, isIdentity: isChecked });
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -51,8 +46,8 @@ export const LinkPaymentStep2 = ({
|
|||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder=""
|
placeholder=""
|
||||||
value={formData.purchaser}
|
value={formData.buyerName}
|
||||||
onChange={(e) => handleInputChange('purchaser', e.target.value)}
|
onChange={(e) => handleInputChange('buyerName', e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -63,8 +58,8 @@ export const LinkPaymentStep2 = ({
|
|||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="test@nicepay.co.kr"
|
placeholder="test@nicepay.co.kr"
|
||||||
value={formData.purchaserEmail}
|
value={formData.email}
|
||||||
onChange={(e) => handleInputChange('purchaserEmail', e.target.value)}
|
onChange={(e) => handleInputChange('email', e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -75,8 +70,8 @@ export const LinkPaymentStep2 = ({
|
|||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="01012345678"
|
placeholder="01012345678"
|
||||||
value={formData.purchaserPhone}
|
value={formData.phoneNumber}
|
||||||
onChange={(e) => handleInputChange('purchaserPhone', e.target.value)}
|
onChange={(e) => handleInputChange('phoneNumber', e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -84,7 +79,7 @@ export const LinkPaymentStep2 = ({
|
|||||||
<div className="issue-row gap-10 beetween">
|
<div className="issue-row gap-10 beetween">
|
||||||
<div className="issue-label wid-105">구매자 정보 대조</div>
|
<div className="issue-label wid-105">구매자 정보 대조</div>
|
||||||
<label className="settings-switch">
|
<label className="settings-switch">
|
||||||
<input type="checkbox"/>
|
<input type="checkbox" checked={formData.isIdentity} onChange={(e) => handleIdentityToggle(e.target.checked)}/>
|
||||||
<span className="slider"></span>
|
<span className="slider"></span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -93,14 +88,14 @@ export const LinkPaymentStep2 = ({
|
|||||||
<div className="issue-field">
|
<div className="issue-field">
|
||||||
<div className="chip-row">
|
<div className="chip-row">
|
||||||
<span
|
<span
|
||||||
className={`keyword-tag flex-1 ${selectedPurchaserType === '개인' ? 'active' : ''}`}
|
className={`keyword-tag flex-1 ${formData.identityType === IdentityType.INDIVIDUAL ? 'active' : ''}`}
|
||||||
onClick={() => handlePurchaserTypeChange('개인')}
|
onClick={() => handleIdendityTypeChange(IdentityType.INDIVIDUAL)}
|
||||||
>
|
>
|
||||||
개인
|
개인
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className={`keyword-tag flex-1 ${selectedPurchaserType === '법인' ? 'active' : ''}`}
|
className={`keyword-tag flex-1 ${formData.identityType === IdentityType.CORPORATE ? 'active' : ''}`}
|
||||||
onClick={() => handlePurchaserTypeChange('법인')}
|
onClick={() => handleIdendityTypeChange(IdentityType.CORPORATE)}
|
||||||
>
|
>
|
||||||
법인
|
법인
|
||||||
</span>
|
</span>
|
||||||
@@ -112,10 +107,10 @@ export const LinkPaymentStep2 = ({
|
|||||||
<div className="issue-label wid-105"></div>
|
<div className="issue-label wid-105"></div>
|
||||||
<div className='issue-field'>
|
<div className='issue-field'>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="number"
|
||||||
placeholder="생년월일 6자리"
|
placeholder="생년월일 6자리"
|
||||||
value={formData.purchaserBirth}
|
value={formData.identityValue}
|
||||||
onChange={(e) => handleInputChange('purchaserPhone', e.target.value)}
|
onChange={(e) => handleInputChange('identityValue', e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -125,14 +120,14 @@ export const LinkPaymentStep2 = ({
|
|||||||
<div className="issue-field">
|
<div className="issue-field">
|
||||||
<div className="chip-row">
|
<div className="chip-row">
|
||||||
<span
|
<span
|
||||||
className={`keyword-tag flex-1 ${selectedLanguage === '국문' ? 'active' : ''}`}
|
className={`keyword-tag flex-1 ${formData.language === Language.KR ? 'active' : ''}`}
|
||||||
onClick={() => handleLanguageType('국문')}
|
onClick={() => handleLanguageType(Language.KR)}
|
||||||
>
|
>
|
||||||
국문
|
국문
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className={`keyword-tag flex-1 ${selectedLanguage === '영문' ? 'active' : ''}`}
|
className={`keyword-tag flex-1 ${formData.language === Language.EN ? 'active' : ''}`}
|
||||||
onClick={() => handleLanguageType('영문')}
|
onClick={() => handleLanguageType(Language.EN)}
|
||||||
>
|
>
|
||||||
영문
|
영문
|
||||||
</span>
|
</span>
|
||||||
@@ -144,14 +139,14 @@ export const LinkPaymentStep2 = ({
|
|||||||
<div className="issue-field">
|
<div className="issue-field">
|
||||||
<div className="chip-row">
|
<div className="chip-row">
|
||||||
<span
|
<span
|
||||||
className={`keyword-tag flex-1 ${selectedLinkContent === '기본' ? 'active' : ''}`}
|
className={`keyword-tag flex-1 ${formData.linkContentType === LinkContentType.BASIC ? 'active' : ''}`}
|
||||||
onClick={() => handleLinkContent('기본')}
|
onClick={() => handleLinkContent(LinkContentType.BASIC)}
|
||||||
>
|
>
|
||||||
기본
|
기본
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className={`keyword-tag flex-1 ${selectedLinkContent === '추가' ? 'active' : ''}`}
|
className={`keyword-tag flex-1 ${formData.linkContentType === LinkContentType.ADDITIONAL ? 'active' : ''}`}
|
||||||
onClick={() => handleLinkContent('추가')}
|
onClick={() => handleLinkContent(LinkContentType.ADDITIONAL)}
|
||||||
>
|
>
|
||||||
추가
|
추가
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -1,18 +1,58 @@
|
|||||||
import { HeaderType } from '@/entities/common/model/types';
|
import { HeaderType } from '@/entities/common/model/types';
|
||||||
import { useSetFooterMode, useSetHeaderTitle, useSetHeaderType } from '@/widgets/sub-layout/use-sub-layout';
|
import { useSetFooterMode, useSetHeaderTitle, useSetHeaderType } from '@/widgets/sub-layout/use-sub-layout';
|
||||||
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
|
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
|
||||||
|
import { useLocation } from 'react-router';
|
||||||
import { IMAGE_ROOT } from "@/shared/constants/common";
|
import { IMAGE_ROOT } from "@/shared/constants/common";
|
||||||
import { PATHS } from '@/shared/constants/paths';
|
import { PATHS } from '@/shared/constants/paths';
|
||||||
|
import { LinkPaymentFormData } from '@/entities/additional-service/model/types'
|
||||||
|
import { useExtensionLinkPayRequestMutation } from '@/entities/additional-service/api/link-payment/use-extension-link-pay-request-mutation';
|
||||||
|
import { ExtensionLinkPayRequestParams } from '@/entities/additional-service/model/types';
|
||||||
|
|
||||||
export const LinkPaymentApplyConfirmPage = () => {
|
export const LinkPaymentApplyConfirmPage = () => {
|
||||||
const { navigate } = useNavigate();
|
const { navigate } = useNavigate();
|
||||||
|
const location = useLocation();
|
||||||
|
|
||||||
|
const formData: LinkPaymentFormData = location.state?.formData;
|
||||||
|
const { mutateAsync: linkPayRequest } = useExtensionLinkPayRequestMutation();
|
||||||
|
|
||||||
useSetHeaderTitle('메시지 미리보기');
|
useSetHeaderTitle('메시지 미리보기');
|
||||||
useSetHeaderType(HeaderType.LeftArrow);
|
useSetHeaderType(HeaderType.LeftArrow);
|
||||||
useSetFooterMode(false);
|
useSetFooterMode(false);
|
||||||
|
|
||||||
const onClickToConfirm = () => {
|
const onClickToConfirm = () => {
|
||||||
navigate(PATHS.additionalService.linkPayment.confirmSuccess);
|
if (!formData) {
|
||||||
|
console.error('Form data is missing');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const requestParams: ExtensionLinkPayRequestParams = {
|
||||||
|
mid: formData.mid,
|
||||||
|
sendMethod: formData.sendMethod,
|
||||||
|
goodsName: formData.goodsName,
|
||||||
|
amount: formData.amount,
|
||||||
|
moid: formData.moid,
|
||||||
|
paymentExpiryDate: formData.paymentExpiryDate.replace(/\./g, ''),
|
||||||
|
buyerName: formData.buyerName,
|
||||||
|
email: formData.email,
|
||||||
|
phoneNumber: formData.phoneNumber,
|
||||||
|
isIdentity: formData.isIdentity,
|
||||||
|
identityType: formData.identityType,
|
||||||
|
identityValue: formData.identityValue,
|
||||||
|
language: formData.language,
|
||||||
|
linkContentType: formData.linkContentType
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log("Link Payment 요청 파라미터: ", requestParams);
|
||||||
|
|
||||||
|
linkPayRequest(requestParams)
|
||||||
|
.then((response) => {
|
||||||
|
console.log("Link Payment 성공 응답: ", response);
|
||||||
|
navigate(PATHS.additionalService.linkPayment.confirmSuccess);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error("Link Payment 실패: ", error);
|
||||||
|
// 에러 처리 로직 추가 가능
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const onClickToBack = () => {
|
const onClickToBack = () => {
|
||||||
@@ -37,8 +77,8 @@ export const LinkPaymentApplyConfirmPage = () => {
|
|||||||
!${pay_url}<br/><br/>
|
!${pay_url}<br/><br/>
|
||||||
<b>
|
<b>
|
||||||
가맹점 상호 : 나이스페이먼츠 주식회사<br/>
|
가맹점 상호 : 나이스페이먼츠 주식회사<br/>
|
||||||
상품명 : TEST<br/>
|
상품명 : {formData.goodsName}<br/>
|
||||||
금액 : 123,123원
|
금액 : {formData.amount}원
|
||||||
</b>
|
</b>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -6,22 +6,47 @@ import {ProcessStep} from '@/entities/transaction/model/types';
|
|||||||
import {useSetFooterMode, useSetHeaderTitle, useSetHeaderType} from '@/widgets/sub-layout/use-sub-layout';
|
import {useSetFooterMode, useSetHeaderTitle, useSetHeaderType} from '@/widgets/sub-layout/use-sub-layout';
|
||||||
import {useNavigate} from '@/shared/lib/hooks/use-navigate';
|
import {useNavigate} from '@/shared/lib/hooks/use-navigate';
|
||||||
import {PATHS} from "@/shared/constants/paths";
|
import {PATHS} from "@/shared/constants/paths";
|
||||||
|
import { LinkPaymentFormData, IdentityType, Language, LinkContentType, LinkPaymentSendMethod } from '@/entities/additional-service/model/types';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const LinkPaymentApplyPage = () => {
|
export const LinkPaymentApplyPage = () => {
|
||||||
const { navigate } = useNavigate();
|
const { navigate } = useNavigate();
|
||||||
|
|
||||||
const [processStep, setProcessStep] = useState<ProcessStep>(ProcessStep.One);
|
const [processStep, setProcessStep] = useState<ProcessStep>(ProcessStep.One);
|
||||||
|
const [formData, setFormData] = useState<LinkPaymentFormData>({
|
||||||
|
mid: 'nictest001m',
|
||||||
|
sendMethod: LinkPaymentSendMethod.SMS,
|
||||||
|
goodsName: '',
|
||||||
|
amount: 0,
|
||||||
|
moid: '',
|
||||||
|
paymentExpiryDate: '',
|
||||||
|
buyerName: '',
|
||||||
|
email: '',
|
||||||
|
phoneNumber: '',
|
||||||
|
isIdentity: false,
|
||||||
|
identityType: IdentityType.INDIVIDUAL,
|
||||||
|
identityValue: '',
|
||||||
|
language: Language.KR,
|
||||||
|
linkContentType: LinkContentType.BASIC
|
||||||
|
});
|
||||||
|
|
||||||
useSetHeaderTitle('링크결제 신청');
|
useSetHeaderTitle('링크결제 신청');
|
||||||
useSetHeaderType(HeaderType.LeftArrow);
|
useSetHeaderType(HeaderType.LeftArrow);
|
||||||
useSetFooterMode(false);
|
useSetFooterMode(false);
|
||||||
|
|
||||||
|
const onClickToBack = () => {
|
||||||
|
navigate(-1);
|
||||||
|
};
|
||||||
|
|
||||||
const onClickToChangeTab = () => {
|
const onClickToChangeTab = () => {
|
||||||
if(processStep === ProcessStep.One) {
|
if(processStep === ProcessStep.One) {
|
||||||
setProcessStep(ProcessStep.Two);
|
setProcessStep(ProcessStep.Two);
|
||||||
}
|
}
|
||||||
else if(processStep === ProcessStep.Two) {
|
else if(processStep === ProcessStep.Two) {
|
||||||
navigate(PATHS.additionalService.linkPayment.requestConfirm)
|
navigate(PATHS.additionalService.linkPayment.requestConfirm, {
|
||||||
|
state: { formData }
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -49,11 +74,16 @@ export const LinkPaymentApplyPage = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{(processStep === ProcessStep.One) &&
|
{(processStep === ProcessStep.One) &&
|
||||||
<LinkPaymentStep1 ></LinkPaymentStep1>
|
<LinkPaymentStep1
|
||||||
|
formData={formData}
|
||||||
|
setFormData={setFormData}
|
||||||
|
></LinkPaymentStep1>
|
||||||
}
|
}
|
||||||
{ (processStep === ProcessStep.Two) &&
|
{ (processStep === ProcessStep.Two) &&
|
||||||
<LinkPaymentStep2
|
<LinkPaymentStep2
|
||||||
setProcessStep={ setProcessStep }
|
setProcessStep={ setProcessStep }
|
||||||
|
formData={formData}
|
||||||
|
setFormData={setFormData}
|
||||||
></LinkPaymentStep2>
|
></LinkPaymentStep2>
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,8 +99,9 @@ export const LinkPaymentApplyPage = () => {
|
|||||||
{(processStep === ProcessStep.Two) &&
|
{(processStep === ProcessStep.Two) &&
|
||||||
<div className="apply-row two-button">
|
<div className="apply-row two-button">
|
||||||
<button
|
<button
|
||||||
className="btn-50 btn-darkgray flex-1">
|
className="btn-50 btn-darkgray flex-1"
|
||||||
이전</button>
|
onClick={() => onClickToBack() }
|
||||||
|
>이전</button>
|
||||||
<button
|
<button
|
||||||
className="btn-50 btn-blue flex-3"
|
className="btn-50 btn-blue flex-3"
|
||||||
onClick={() => onClickToChangeTab() }
|
onClick={() => onClickToChangeTab() }
|
||||||
|
|||||||
@@ -25,6 +25,10 @@ export const API_URL_ADDITIONAL_SERVICE = {
|
|||||||
// POST: 링크결제 - 발송내역 엑셀 다운
|
// POST: 링크결제 - 발송내역 엑셀 다운
|
||||||
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/extension/linkpay/history/excel`;
|
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/extension/linkpay/history/excel`;
|
||||||
},
|
},
|
||||||
|
extensionLinkPaymentRequest: () => {
|
||||||
|
// POST: 링크결제 - 결제 신청
|
||||||
|
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/extension/linkpay/request`;
|
||||||
|
},
|
||||||
extensionLinkPaymentHistoryDetail: () => {
|
extensionLinkPaymentHistoryDetail: () => {
|
||||||
// POST: 링크결제 - 발송내역 상세 조회
|
// POST: 링크결제 - 발송내역 상세 조회
|
||||||
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/extension/linkpay/history/detail`;
|
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/extension/linkpay/history/detail`;
|
||||||
@@ -45,7 +49,7 @@ export const API_URL_ADDITIONAL_SERVICE = {
|
|||||||
// POST: 링크결제 - 발송대기 상세 내역 조회
|
// POST: 링크결제 - 발송대기 상세 내역 조회
|
||||||
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/extension/linkpay/wait/detail`;
|
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/extension/linkpay/wait/detail`;
|
||||||
},
|
},
|
||||||
extensionLinkPayMentWaitDelete: () => {
|
extensionLinkPaymentWaitDelete: () => {
|
||||||
// POST: 링크결제 - 발송대기 삭제
|
// POST: 링크결제 - 발송대기 삭제
|
||||||
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/extension/linkpay/wait/delete`;
|
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/extension/linkpay/wait/delete`;
|
||||||
},
|
},
|
||||||
|
|||||||
90
src/shared/ui/filter/single-date-picker.tsx
Normal file
90
src/shared/ui/filter/single-date-picker.tsx
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
import { useState } from 'react';
|
||||||
|
import { CalendarType } from '@/entities/common/model/types';
|
||||||
|
import { IMAGE_ROOT } from '@/shared/constants/common';
|
||||||
|
import NiceCalendar from '../calendar/nice-calendar';
|
||||||
|
|
||||||
|
interface SingleDatePickerProps {
|
||||||
|
title?: string;
|
||||||
|
date: string;
|
||||||
|
setDate: (date: string) => void;
|
||||||
|
placeholder?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SingleDatePicker = ({
|
||||||
|
title,
|
||||||
|
date,
|
||||||
|
setDate,
|
||||||
|
placeholder = '날짜 선택'
|
||||||
|
}: SingleDatePickerProps) => {
|
||||||
|
const [calendarOpen, setCalendarOpen] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const onClickToOpenCalendar = () => {
|
||||||
|
setCalendarOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const setNewDate = (newDate: string) => {
|
||||||
|
setDate(newDate);
|
||||||
|
setCalendarOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{title && (
|
||||||
|
<div className="issue-row gap-10">
|
||||||
|
<div className="issue-label">{title}</div>
|
||||||
|
<div className="issue-field">
|
||||||
|
<div className="input-wrapper date">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={date}
|
||||||
|
className="date-input"
|
||||||
|
placeholder={placeholder}
|
||||||
|
readOnly
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="date-btn"
|
||||||
|
onClick={onClickToOpenCalendar}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={IMAGE_ROOT + '/ico_date.svg'}
|
||||||
|
alt="날짜 선택"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{!title && (
|
||||||
|
<div className="input-wrapper date">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={date}
|
||||||
|
className="date-input"
|
||||||
|
placeholder={placeholder}
|
||||||
|
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="date-btn"
|
||||||
|
onClick={onClickToOpenCalendar}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={IMAGE_ROOT + '/ico_date.svg'}
|
||||||
|
alt="날짜 선택"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<NiceCalendar
|
||||||
|
calendarOpen={calendarOpen}
|
||||||
|
setCalendarOpen={setCalendarOpen}
|
||||||
|
singleDate={date}
|
||||||
|
calendarType={CalendarType.Single}
|
||||||
|
setNewDate={setNewDate}
|
||||||
|
></NiceCalendar>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user