如何在React Firebase中按时间展示交易历史记录
实现按提交日期分组展示交易历史的解决方案
1. 数据分组处理
首先需要将Firebase返回的交易数据按tglSetor字段进行分组,使用数组reduce方法可以高效完成这个操作:
// 工具函数:按提交日期分组交易数据 const groupTransactionsByDate = (transactions) => { return transactions.reduce((groupedData, item) => { // 根据Firebase中tglSetor的实际格式调整日期格式化逻辑 const formattedDate = new Date(item.tglSetor).toLocaleDateString('id-ID', { year: 'numeric', month: 'long', day: 'numeric' }); // 按格式化后的日期分组 if (!groupedData[formattedDate]) { groupedData[formattedDate] = []; } groupedData[formattedDate].push(item); return groupedData; }, {}); };
2. 创建分组展示组件(DataTableGrouped)
新建组件渲染分组后的交易数据,支持折叠/展开每组数据(匹配参考图的交互效果):
import { useState } from 'react'; const DataTableGrouped = ({ groupedTransactions }) => { // 控制每组折叠状态,默认全部展开 const [expandedDates, setExpandedDates] = useState( Object.keys(groupedTransactions) ); const toggleDateExpansion = (date) => { setExpandedDates(prev => prev.includes(date) ? prev.filter(d => d !== date) : [...prev, date] ); }; return ( <div className="grouped-transaction-container"> {Object.entries(groupedTransactions).map(([date, transactions]) => ( <div key={date} className="date-group"> {/* 日期标题栏,点击切换折叠状态 */} <div className="date-header" onClick={() => toggleDateExpansion(date)} style={{ cursor: 'pointer', padding: '8px 12px', backgroundColor: '#f5f5f5', borderBottom: '1px solid #ddd' }} > <span>{date}</span> <span style={{ float: 'right' }}> {expandedDates.includes(date) ? '▼' : '▶'} </span> </div> {/* 展开时显示该日期的交易列表 */} {expandedDates.includes(date) && ( <table style={{ width: '100%', borderCollapse: 'collapse', marginTop: '8px' }}> <thead> <tr style={{ backgroundColor: '#eee' }}> <th style={{ border: '1px solid #ddd', padding: '8px' }}>客户名称</th> <th style={{ border: '1px solid #ddd', padding: '8px' }}>垃圾类型</th> <th style={{ border: '1px solid #ddd', padding: '8px' }}>重量</th> <th style={{ border: '1px solid #ddd', padding: '8px' }}>金额</th> </tr> </thead> <tbody> {transactions.map((trans, index) => ( <tr key={index} style={{ borderBottom: '1px solid #ddd' }}> <td style={{ border: '1px solid #ddd', padding: '8px' }}>{trans.namaKonsumen}</td> <td style={{ border: '1px solid #ddd', padding: '8px' }}>{trans.jenisSampah}</td> <td style={{ border: '1px solid #ddd', padding: '8px' }}>{trans.berat} kg</td> <td style={{ border: '1px solid #ddd', padding: '8px' }}>Rp {trans.harga}</td> </tr> ))} {/* 每组小计行 */} <tr style={{ fontWeight: 'bold', backgroundColor: '#f9f9f9' }}> <td colSpan={2} style={{ border: '1px solid #ddd', padding: '8px', textAlign: 'right' }}>小计</td> <td style={{ border: '1px solid #ddd', padding: '8px' }}> {transactions.reduce((sum, item) => sum + parseFloat(item.berat), 0)} kg </td> <td style={{ border: '1px solid #ddd', padding: '8px' }}> Rp {transactions.reduce((sum, item) => sum + parseFloat(item.harga), 0)} </td> </tr> </tbody> </table> )} </div> ))} </div> ); }; export default DataTableGrouped;
3. 在Inventaris组件中集成分组功能
修改现有Inventaris组件,获取数据后完成分组并渲染新组件:
import { useEffect, useState } from 'react'; import { db } from './firebaseConfig'; // 你的Firebase配置文件 import { collection, getDocs } from 'firebase/firestore'; import DataTableTotal from './DataTableTotal'; import DataTableGrouped from './DataTableGrouped'; import { groupTransactionsByDate } from './utils'; // 引入分组工具函数 const Inventaris = () => { const [transactions, setTransactions] = useState([]); const [groupedTransactions, setGroupedTransactions] = useState({}); useEffect(() => { const fetchTransactions = async () => { const querySnapshot = await getDocs(collection(db, 'transactions')); const data = querySnapshot.docs.map(doc => ({ id: doc.id, ...doc.data() })); setTransactions(data); // 对数据进行分组 setGroupedTransactions(groupTransactionsByDate(data)); }; fetchTransactions(); }, []); return ( <div className="inventaris-container"> <h2>交易历史(按日期分组)</h2> <DataTableGrouped groupedTransactions={groupedTransactions} /> <h2>客户汇总数据</h2> <DataTableTotal transactions={transactions} /> </div> ); }; export default Inventaris;
关键说明
- 日期格式化:根据Firebase中
tglSetor的实际存储格式(时间戳/字符串日期)调整formattedDate的生成逻辑,确保分组日期格式统一。 - 样式自定义:可替换示例中的内联样式为项目的CSS类名,匹配系统UI风格。
- 折叠功能:若不需要折叠交互,直接移除
expandedDates相关逻辑即可。
内容的提问来源于stack exchange,提问作者Aya
相关产品推荐
相关产品推荐

