You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 13:05:39