From 7d22476b84026dd9d03118c34e338e0bf2627f0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=84=B1=EC=9A=B0?= Date: Fri, 13 Sep 2024 02:32:27 +0900 Subject: [PATCH 1/2] Delete .github/workflows/deploy.yml --- .github/workflows/deploy.yml | 59 ------------------------------------ 1 file changed, 59 deletions(-) delete mode 100644 .github/workflows/deploy.yml diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml deleted file mode 100644 index 72835a2..0000000 --- a/.github/workflows/deploy.yml +++ /dev/null @@ -1,59 +0,0 @@ -name: Frontend CI/CD - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - -jobs: - build-and-deploy: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: '20' - - - name: Cache dependencies - uses: actions/cache@v4 - with: - path: ~/.npm - key: ${{ runner.OS }}-node-${{ hashFiles('**/package-lock.json') }}-new-key - restore-keys: | - ${{ runner.OS }}-node- - - - name: Install dependencies - run: npm ci - continue-on-error: false - - - name: Run tests - run: npm test -- --passWithNoTests - continue-on-error: false - - - name: Build project - run: npm run build - env: - VITE_API_URL_MEMBER: ${{ secrets.API_URL_MEMBER }} - VITE_API_URL_PARTNER: ${{ secrets.API_URL_PARTNER }} - continue-on-error: false - - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v4 - with: - aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - aws-region: ap-northeast-2 - - - name: Deploy to S3 - run: | - aws s3 sync dist/ s3://${{ secrets.S3_BUCKET }} --delete - continue-on-error: false - - - name: Invalidate CloudFront cache - run: | - aws cloudfront create-invalidation --distribution-id ${{ secrets.CLOUDFRONT_DISTRIBUTION_ID }} --paths "/*" - continue-on-error: false From d244d911e0dca394724a5d66a4187492d48ff511 Mon Sep 17 00:00:00 2001 From: sw326 Date: Sat, 14 Sep 2024 17:34:24 +0900 Subject: [PATCH 2/2] fix : payment mock data --- src/pages/members/PaymentPage.tsx | 107 ++++++++++++------------------ src/types/portone.ts | 29 +++++++- src/utils/paymentAdapter.ts | 17 +++++ 3 files changed, 85 insertions(+), 68 deletions(-) create mode 100644 src/utils/paymentAdapter.ts diff --git a/src/pages/members/PaymentPage.tsx b/src/pages/members/PaymentPage.tsx index 992e40a..9516560 100644 --- a/src/pages/members/PaymentPage.tsx +++ b/src/pages/members/PaymentPage.tsx @@ -1,6 +1,15 @@ import React, { useState, useEffect } from 'react'; import { useNavigate, useLocation } from 'react-router-dom'; import { useCompletePayment } from '../../hooks/usePayment'; +import { adaptEstimateToPayment } from '../../utils/paymentAdapter'; +import { + PayMethod, + RequestPayParams, + RequestPayResponse, +} from '../../types/portone'; +import LoadingSpinner from '../../utils/LoadingSpinner'; +import { showErrorNotification } from '../../utils/errorHandler'; +import SimplePayButton from '../../components/members/SimplePayButton'; import { CreditCard, Building, @@ -8,53 +17,27 @@ import { Smartphone, CreditCard as SimplePayIcon, } from 'lucide-react'; -import { - handleApiError, - showErrorNotification, -} from '../../utils/errorHandler'; -import LoadingSpinner from '../../utils/LoadingSpinner'; -import { - PayMethod, - RequestPayParams, - RequestPayResponse, -} from '../../types/portone'; -import SimplePaySection from '../../components/members/SimplePayButton'; -import { getPaymentData } from '../../api/payment'; -import { v4 as uuidv4 } from 'uuid'; + +// Mockup data for testing without backend +const mockPaymentData = { + amount: 10000, + buyer_name: '홍길동', + buyer_tel: '010-1234-5678', + buyer_email: 'test@example.com', +}; const PaymentPage: React.FC = () => { const navigate = useNavigate(); const location = useLocation(); const { estimateId } = location.state as { estimateId: number }; - const completePaymentMutation = useCompletePayment(); - const [loading, setLoading] = useState(true); - const [paymentMethod, setPaymentMethod] = useState(''); + const [paymentMethod, setPaymentMethod] = useState('card'); const [simplePayMethod, setSimplePayMethod] = useState(''); - const [amount, setAmount] = useState(0); - const [buyerName, setBuyerName] = useState(''); - const [buyerTel, setBuyerTel] = useState(''); - const [buyerEmail, setBuyerEmail] = useState(''); - - useEffect(() => { - const fetchPaymentData = async () => { - try { - setLoading(true); - const data = await getPaymentData(estimateId); - setAmount(data.amount); - setBuyerName(data.buyer_name); - setBuyerTel(data.buyer_tel); - setBuyerEmail(data.buyer_email); - } catch (error) { - showErrorNotification(handleApiError(error)); - } finally { - setLoading(false); - } - }; + const [isLoading, setIsLoading] = useState(true); - fetchPaymentData(); + const completePaymentMutation = useCompletePayment(); - // IMP 초기화 + useEffect(() => { const jquery = document.createElement('script'); jquery.src = 'https://code.jquery.com/jquery-1.12.4.min.js'; const iamport = document.createElement('script'); @@ -62,18 +45,21 @@ const PaymentPage: React.FC = () => { document.head.appendChild(jquery); document.head.appendChild(iamport); + jquery.onload = () => { + if (iamport.readyState === 'complete') { + setIsLoading(false); + } else { + iamport.onload = () => setIsLoading(false); + } + }; + return () => { document.head.removeChild(jquery); document.head.removeChild(iamport); }; - }, [estimateId]); + }, []); - const getPayMethod = (): PayMethod => { - if (paymentMethod === 'SIMPLE_PAY') { - return simplePayMethod as PayMethod; - } - return paymentMethod as PayMethod; - }; + if (isLoading) return ; const onClickPayment = () => { if (!window.IMP) { @@ -84,15 +70,10 @@ const PaymentPage: React.FC = () => { const { IMP } = window; IMP.init(import.meta.env.VITE_IMP_KEY); - const data: RequestPayParams = { - pg: 'smartro.iamport01m', - pay_method: getPayMethod(), - merchant_uid: uuidv4().replace(/-/g, '').substring(0, 8), - amount: amount, - buyer_name: buyerName, - buyer_tel: buyerTel, - buyer_email: buyerEmail, - }; + const data: RequestPayParams = adaptEstimateToPayment( + mockPaymentData, + paymentMethod, + ); IMP.request_pay(data, callback); }; @@ -122,14 +103,6 @@ const PaymentPage: React.FC = () => { { id: 'SIMPLE_PAY', name: '간편 결제', icon: }, ]; - if (loading) { - return ( -
- -
- ); - } - return (
@@ -153,7 +126,7 @@ const PaymentPage: React.FC = () => { value={method.id} checked={paymentMethod === method.id} onChange={() => { - setPaymentMethod(method.id); + setPaymentMethod(method.id as PayMethod); if (method.id !== 'SIMPLE_PAY') { setSimplePayMethod(''); } @@ -168,7 +141,7 @@ const PaymentPage: React.FC = () => {
{paymentMethod === 'SIMPLE_PAY' && ( - @@ -181,7 +154,9 @@ const PaymentPage: React.FC = () => {
청소 서비스 금액 - {amount.toLocaleString()}원 + + {mockPaymentData.amount.toLocaleString()}원 +
@@ -206,7 +181,7 @@ const PaymentPage: React.FC = () => { } className="w-full bg-brand text-white py-3 px-4 rounded-lg hover:bg-brand-dark transition-colors disabled:opacity-50 disabled:cursor-not-allowed text-lg font-bold" > - {amount.toLocaleString()}원 결제하기 + {mockPaymentData.amount.toLocaleString()}원 결제하기 diff --git a/src/types/portone.ts b/src/types/portone.ts index b138ae7..1b281de 100644 --- a/src/types/portone.ts +++ b/src/types/portone.ts @@ -8,11 +8,36 @@ export type PayMethod = | 'samsungpay' | 'ssgpay'; +export interface EstimateDetail { + id: number; + commissionId: number; + partnerId: number; + price: number; + fixedDate: string; + statement: string; + status: string; + size: number; + desiredDate: string; + significant: string; + commissionStatus: string; + phoneNumber: string; + managerName: string; + companyName: string; +} + +export interface EstimateAndCommissionResponseDto { + estimate_id: number; + commission_id: number; + estimate_amount: number; + member_nick: string; + member_phone_number: string; + member_email: string; +} + export interface PaymentRequest { pg: string; - pay_method: string; + pay_method: PayMethod; merchant_uid: string; - name: string; amount: number; buyer_name: string; buyer_tel: string; diff --git a/src/utils/paymentAdapter.ts b/src/utils/paymentAdapter.ts new file mode 100644 index 0000000..0bd0605 --- /dev/null +++ b/src/utils/paymentAdapter.ts @@ -0,0 +1,17 @@ +import { PaymentRequest, PayMethod, RequestPayParams } from '../types/portone'; +import { v4 as uuidv4 } from 'uuid'; + +export const adaptEstimateToPayment = ( + paymentData: PaymentRequest, + selectedPayMethod: string, +): RequestPayParams => { + return { + pg: 'smartro.iamport01m', + pay_method: selectedPayMethod as PayMethod, + merchant_uid: `ORDER_${uuidv4().replace(/-/g, '')}`, + amount: paymentData.amount, + buyer_name: paymentData.buyer_name, + buyer_tel: paymentData.buyer_tel, + buyer_email: paymentData.buyer_email, + }; +};