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;
}
}
- 프론트
주요 기능
- 결제 내역 데이터 가져오기
- 총 결제 금액 계산
- 월별 데이터 필터링
- 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: 필터링된 결제 내역을 렌더링합니다.
- 결과 화면
반응형