Project/[Team]외국인 관광객을 위한 카드 플랫폼

[Spring Boot/React] 카드 신청 페이지 제작

dbfl9911 2024. 8. 10. 23:03
반응형

- 카드 신청 폼 만들기

자료 참고 

https://velog.io/@jiaegong/%EC%A3%BC%EB%AF%BC%EB%93%B1%EB%A1%9D%EB%B2%88%ED%98%B8-%EC%9E%90%EB%8F%99-%ED%95%98%EC%9D%B4%ED%94%88-%EB%84%A3%EA%B8%B0-%EB%92%B7%EC%9E%90%EB%A6%AC-%EB%A1%9C-%EB%A7%88%EC%8A%A4%ED%82%B9-%ED%95%98%EA%B8%B0

 

주민등록번호 자동 하이픈 넣기, 뒷자리 *로 마스킹 하기

가입 폼을 만들다보면 핸드폰 번호나 주민등록번호에 자동 하이픈이 생기게 해야 할 때가 있다. 열심히 해놨는데 기획 변경으로 이 부분을 다 날려야 하는 일이 생겨 필요한 코드만 정리해놓기

velog.io

 

 

 

카드 신청 프로세스 피그마 디자인

 

- 문제 : 카드 신청할 때 입력된 카드 정보 데이터들 card 테이블에 insert하고 싶은데 단계별로 넣을 때마다 실시간으로 정보 하나씩 insert해서 db에 들어갔다가 나오는 과정으로 설계하려했지만 더 효율적인 방법이 있을 거 같아 고민

 

- 해결: 리액트의 useContext사용해 프론트 단에서 데이터 모아서 마지막에 한꺼번에 입력시키고 백으로 insert하기로 함

 

 

https://ko.react.dev/reference/react/useContext

 

useContext – React

The library for web and native user interfaces

ko.react.dev

useContext는 React의 훅(hook) 중 하나로, 컨텍스트(Context) 객체의 현재 값을 가져오기 위해 사용됩니다. 컨텍스트는 컴포넌트 트리 전체에 걸쳐 데이터를 전역적으로 전달할 수 있는 방법을 제공합니다. 이는 props를 통해 데이터를 전달해야 하는 필요성을 줄여줍니다

 

 


 

 

1. Context 생성 및 제공

import React, { createContext, useContext, useState } from 'react';

const CardContext = createContext(); // 컨텍스트 객체를 생성

//  useContext를 사용하여 CardContext의 현재 값을 반환
export const useCardContext = () => {
    return useContext(CardContext);
};

export const CardProvider = ({children}) => {
    const [produceCardOffer, setProduceCardOffer] = useState({
        "card_id":"",
        "card_account":"",
        "card_balance" : "",
        "card_number":"",
        "card_password":"",
        "card_pickup":"",
        "card_status":"",
        "cvv_code":"",
        "expiration_date":"",
        "issue_date":"",
        "payment_bank":"",
        "payment_date":"",
        "pickup_date":"",
        "transportation":"",
        "card_type_id":"",
        "member_id":""
    });

    return (
        <CardContext.Provider value={{produceCardOffer, setProduceCardOffer}}>
            {children}
        </CardContext.Provider>
    )
}

 

  • CardContext를 생성합니다.
  • useCardContext는 useContext를 사용하여 CardContext의 현재 값을 반환하는 커스텀 훅입니다.
  • CardProvider 컴포넌트는 produceCardOffer 상태와 그 상태를 업데이트하는 setProduceCardOffer 함수를 CardContext.Provider를 통해 하위 컴포넌트에 제공합니다.

 

 

 

2. CardProvider로 Context 감싸기

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { CardProvider } from './CardContext';

ReactDOM.render(
    <CardProvider>
        <App />
    </CardProvider>,
    document.getElementById('root')
);

 

CardProvider로 App을 감싸서 CardContext를 앱 전체에 제공할 수 있도록 합니다.

 

 

 

 

3. Context 사용하기 (예시: Card1 컴포넌트)

import React, { useState, useEffect } from 'react';
import '../../assets/Card.css';
import Flickity from 'react-flickity-component';
import axios from 'axios';
import { useCardContext } from './CardContext';
import { useNavigate } from 'react-router-dom';

function Card1() {
    const [selectedCard, setSelectedCard] = useState(null);
    const [cards, setCards] = useState([]);
    const [isLoading, setIsLoading] = useState(true);

    const {produceCardOffer, setProduceCardOffer} = useCardContext();

    let navigate = useNavigate();

    const flickityOptions = {
        cellAlign: 'right',
        pageDots: false,
        groupCells: '20%',
        selectedAttraction: 0.03,
        friction: 0.15,
    };

    useEffect(() => {
        axios.get('/api/cards')
            .then(response => {
                console.log('Fetched cards:', response.data);
                setCards(response.data);
                if (response.data.length > 0) {
                    setSelectedCard(response.data[0]);
                }
                setIsLoading(false);  // 데이터 로드 완료
            })
            .catch(error => {
                console.error('There was an error fetching the cards!', error);
                setIsLoading(false);  // 데이터 로드 실패
            });
    }, []);

    const handleChange = (index) => {
        if (cards.length > 0 && index < cards.length) {
            setSelectedCard(cards[index]);
            // console.log('Selected card:', cards[index]);
        } else {
            console.log("카드 데이터가 아직 로드되지 않았습니다.");
        }
    };

    return (
        <div className='container'>
            <div className='header'>
                <div>카드 신청</div>
            </div>

            <div className='content'>

                <div className='carousel-container'>
                    {isLoading ? (
                        <div>카드 불러오는 중...</div>
                    ) : (
                        <Flickity
                            className='carousel'
                            options={flickityOptions}
                            flickityRef={(c) => {
                                if (c) {
                                    c.on('change', (index) => handleChange(index));
                                }
                            }}
                        >
                            {cards.map((card, index) => (
                                <div className="carousel-cell" key={card.cardTypeId}>
                                    <img src={card.cardImg} className="p" alt={card.cardName} />
                                    <div className='card-info'>
                                        <div>카드이름: {card.cardName}</div>
                                        <div>카드사용목적: {card.cardUsage}</div>
                                        <div>카드한도: {card.cardLimit}</div>
                                        <div>연회비: {card.annualFee}</div>
                                    </div>
                                </div>
                            ))}
                        </Flickity>
                    )}
                </div>

                {selectedCard && (
                    <div className='selected-card'>
                        <div>선택한 카드이름: {selectedCard.cardName}</div>
                        <div>카드사용목적: {selectedCard.cardUsage}</div>
                        <div>카드한도: {selectedCard.cardLimit}</div>
                        <div>연회비: {selectedCard.annualFee}</div>
                    </div>
                )}
            </div>
            
            <button onClick={() => {
                if(selectedCard) {
                    setProduceCardOffer(prevState => ({
                        ...prevState,
                        card_type_id:selectedCard.cardTypeId // 선택된 카드 타입 
                    }));
                    setTimeout(() => navigate('/card2'), 300);
                }else{
                    console.log('카드가 선택되지 않았습니다.');
                }
                 }}>신청하기</button>
            <div className='menubar'></div>
        </div>
    );
}

export default Card1;

 

  • Card1 컴포넌트에서 useCardContext를 사용하여 produceCardOffer와 setProduceCardOffer를 가져옵니다.
  • 사용자가 카드 신청 버튼을 클릭하면 selectedCard의 cardTypeId를 produceCardOffer 상태에 업데이트하고, 다음 페이지로 이동합니다.

 

이와 같은 방식으로 다른 컴포넌트 (Card2, Card3, CardForm, Card5)에서도 useCardContext를 사용하여 produceCardOffer 상태를 가져오고 업데이트합니다. 각 컴포넌트는 필요에 따라 produceCardOffer의 특정 필드를 업데이트하고, 폼 제출 시 해당 데이터를 다음 단계로 전달합니다.

 

 

4. 제출 

import React from 'react';
import { useCardContext } from './CardContext';
function Card6(props) {
    const { produceCardOffer } = useCardContext();
    return (
        <div>
            <h3>카드 발급이 완료되었습니다.</h3>
            <pre>{JSON.stringify(produceCardOffer, null, 2)}</pre> {/* 데이터 확인 */}
        </div>
    );
}

export default Card6;

 

  • <pre> 태그 내에 produceCardOffer 객체를 JSON 형식으로 변환하여 출력합니다. JSON.stringify(produceCardOffer, null, 2)는 produceCardOffer 객체를 JSON 문자열로 변환하며, 두 번째 인자는 들여쓰기(indentation)를 위해 사용됩니다.
  • 이렇게 하면 produceCardOffer의 내용을 포맷팅된 JSON 형식으로 화면에 표시할 수 있습니다.

 

 

카드 정보 다 선택 후 결과 화면

 

반응형