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

[Spring Boot/React] 카드 사용 내역 페이지 만들기

dbfl9911 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 테이블 데이터

 

반응형