ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Spring Boot/React] 카드 사용 내역 페이지 만들기
    Project/외국인 관광객을 위한 카드 플랫폼 2024. 8. 8. 09:03

    - 카드 사용 내역 페이지 (백이랑 연동o /  ui 아직 신경 안씀)

    - 백 : store 테이블 crud 테스트용으로 만들기 

    - 프론트: 


    - 백 

    store 테이블 crud 만들고 payment entity에 조인 관계 추가 

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Builder
    @Entity
    @Table(name = "payment")
    public class PaymentEntity {
    	@Id
    	@GeneratedValue(strategy = GenerationType.IDENTITY)
    	Long paymentId;
    
    	@Column(nullable = false)
    	Double paymentPrice;
    	@Column(nullable = false)
    	LocalDateTime paymentDate;
    
    // 조인 관계 추가
    	@ManyToOne
    	@JoinColumn(name = "store_id", nullable = false)
    	StoreEntity store;
    
    	@ManyToOne
    	@JoinColumn(name = "card_id", nullable = false)
    	CardEntity card;
    
    }
    @NoArgsConstructor
    @Builder
    @AllArgsConstructor
    @Data
    public class PaymentDTO {
    	Long paymentId;
    	Double paymentPrice;
    	LocalDateTime paymentDate;
    	
    	Long storeId; // 추가된 부분
        Long cardId;
        String storeName;  // 추가된 부분
    }

     

    - payment repository, service에 아래 코드 추가

    public interface PaymentRepository extends JpaRepository<PaymentEntity, Long>{
    	@Query("SELECT new com.urcarcher.be.kimyuri.PaymentDTO(p.paymentId, p.paymentPrice, p.paymentDate, s.storeId, p.card.cardId, s.storeName) " +
    	           "FROM PaymentEntity p JOIN p.store s")
    	    List<PaymentDTO> findAllPaymentsWithStoreName();
    }
    @Service
    @RequiredArgsConstructor 
    public class PaymentServiceImpl implements PaymentService{
    	
    	final PaymentRepository paymentRepo;
    	
    	@Override
    	public void insert(PaymentDTO dto) {
    		PaymentEntity entity = dtoToEntity(dto);
    		paymentRepo.save(entity);
    	}
    	
    	@Override
    	public List<PaymentDTO> readAll() {
    //		List<PaymentEntity> entityList = (List<PaymentEntity>) paymentRepo.findAll();
    //		
    //		List<PaymentDTO> dtoList = entityList.stream().map(entity -> entityToDTO(entity))
    //				.collect(Collectors.toList());
    //		return dtoList;
    		 // 기존 findAll() 대신 findAllPaymentsWithStoreName() 사용
            return paymentRepo.findAllPaymentsWithStoreName();
    	}
    	
    }
    public interface PaymentService {
    	
    	void insert(PaymentDTO dto);
    	
    	List<PaymentDTO> readAll();
    	
    	PaymentDTO readById(Long paymentId);
    	
    	void delete(Long paymentId);
    	
    	// Entity -> DTO
    	default PaymentDTO entityToDTO(PaymentEntity entity) {
    		PaymentDTO dto = PaymentDTO.builder()
    				.paymentId(entity.getPaymentId())
    				.paymentPrice(entity.getPaymentPrice())
    				.paymentDate(entity.getPaymentDate())
    				.storeId(entity.getStore().getStoreId()) // 추가된부분
                    .cardId(entity.getCard().getCardId())
                    .storeName(entity.getStore().getStoreName())// 추가된부분
    				.build();
    		return dto;
    	}
    	
    	
    	// DTO -> Entity
    	default PaymentEntity dtoToEntity(PaymentDTO dto) {
    		
    		PaymentEntity entity = PaymentEntity.builder()
    				.paymentId(dto.getPaymentId())
    				.paymentPrice(dto.getPaymentPrice())
    				.paymentDate(dto.getPaymentDate())
    				.store(StoreEntity.builder().storeId(dto.getStoreId()).build())// 추가된부분
    	            .card(CardEntity.builder().cardId(dto.getCardId()).build())// 추가된부분
    				.build();
    		return entity;
    	}
    	
    	
    	
    }

     


    - 프론트

     

    주요 기능

    1. 결제 내역 데이터 가져오기
    2. 총 결제 금액 계산
    3. 월별 데이터 필터링
    4. UI를 통해 선택한 월의 데이터를 표시

     

     

    [ 컴포넌트 구조와 주요 부분 설명 ]

    import axios from 'axios';
    import React, { useEffect, useState } from 'react';
    
    function UsageHistory(props) {
        const [usage, setUsage] = useState([]); // 결제 내역 데이터를 저장할 상태
        const [totalPrice, setTotalPrice] = useState(0); // 총 결제 금액을 저장할 상태
        const [selectedMonth, setSelectedMonth] = useState(() => {
            const today = new Date();
            return `${today.getFullYear()}-${(today.getMonth() + 1).toString().padStart(2, '0')}`; // 기본값으로 현재 년월 설정
        });
        const [filteredUsage, setFilteredUsage] = useState([]); // 필터링된 결제 내역 데이터를 저장할 상태

     

     

    1. 데이터 가져오기와 총 금액 계산

        useEffect(() => {
            axios.get('/api/payment/list')
                .then(response => {
                    console.log(response.data);
                    setUsage(response.data); // 결제 내역 데이터를 상태에 저장
    
                    // 총금액 계산
                    const total = response.data.reduce((acc, curr) => acc + curr.paymentPrice, 0);
                    setTotalPrice(total); // 총 금액을 상태에 저장
                })
                .catch(error => {
                    console.log('에러에러', error);
                });
        }, []); // 컴포넌트가 처음 마운트될 때 한 번 실행

     

    • axios.get('/api/payment/list'): 서버에서 결제 내역 데이터를 가져옵니다.
    • setUsage(response.data): 가져온 데이터를 usage 상태에 저장합니다.
    • setTotalPrice(total): 가져온 데이터를 기반으로 총 결제 금액을 계산하여 totalPrice 상태에 저장합니다.

     

    2. 월별 데이터 필터링

        useEffect(() => {
            // 선택한 월의 데이터 필터링
            const filteredData = usage.filter(item => {
                const date = new Date(item.paymentDate);
                const month = `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}`;
                return month === selectedMonth;
            });
    
            setFilteredUsage(filteredData); // 필터링된 데이터를 설정
        }, [selectedMonth, usage]); // selectedMonth 또는 usage가 변경될 때마다 실행

     

     

    • selectedMonth와 usage가 변경될 때마다 실행됩니다.
    • usage 데이터를 selectedMonth에 맞게 필터링하여 filteredUsage 상태에 저장합니다.

     

    3. 월 선택 옵션 생성

        // 2024년 1월부터 현재 월까지의 옵션 생성
        const generateMonthOptions = () => {
            const options = [];
            const currentDate = new Date();
            const currentYear = currentDate.getFullYear();
            if (currentYear !== 2024) return options;
            const currentMonth = currentDate.getMonth() + 1;
            for (let month = currentMonth; month >= 1; month--) {
                const value = `2024-${month.toString().padStart(2, '0')}`;
                options.push(<option key={value} value={value}>2024년 {month}월</option>);
            }
            return options;
        };

     

    • generateMonthOptions 함수는 2024년 1월부터 현재 월까지의 월 옵션을 생성합니다.
    • 드롭다운 메뉴에 표시될 옵션들을 동적으로 생성합니다.

     

    4. 렌더링

        return (
            <div>
                <div>총 금액: {totalPrice.toLocaleString()}원</div> {/* 총금액 표시 */}
                <h4>{selectedMonth.replace('-', '년 ')}월</h4> {/* 선택한 년도와 월 표시 */}
                <div>
                    <select value={selectedMonth} onChange={(e) => setSelectedMonth(e.target.value)}>
                        {generateMonthOptions()}
                    </select>
                </div>
                <div>
                    {
                        filteredUsage.map((usage, index) => {
                            return (
                                <div key={index}>
                                    <div>가맹점이름: {usage.storeName}</div>
                                    <div>결제금액 : {usage.paymentPrice}</div>
                                    <div>결제날짜 : {new Date(usage.paymentDate).toLocaleString()}</div>
                                    <p></p>
                                    <br/>
                                </div>
                            );
                        })
                    }
                </div>
            </div>
        );
    }
    
    export default UsageHistory;

     

    • totalPrice: 총 결제 금액을 표시합니다.
    • selectedMonth: 사용자가 선택한 월을 표시합니다.
    • generateMonthOptions(): 드롭다운 메뉴를 생성합니다.
    • filteredUsage.map: 필터링된 결제 내역을 렌더링합니다.

     


     

    - 결과 화면

    드롭다운 메뉴에서 8월 선택시

     

    드롭다운 메뉴에서 7월 선택시
    payment 테이블 데이터
    store 테이블 데이터

     

Designed by Tistory.