HazardousWasteRecordsPage

 avatar
unknown
plain_text
10 months ago
6.5 kB
14
Indexable
import { useEffect, useState, useCallback, useMemo } from "react";
import { message, Tabs, Button, Space } from "antd";
import {
  UnorderedListOutlined,
  BarChartOutlined,
  PlusOutlined,
  ReloadOutlined,
} from "@ant-design/icons";
import {
  HazardousWasteRecordTable,
  HazardousWasteRecordFilters,
  HazardousWasteRecordModal,
  HazardousWasteRecordFormModal,
  HazardousWasteRecordStats,
} from "@/components/HazardousWasteRecord";
import useHazardousWasteRecords from "@/hooks/useHazardousWasteRecords";
import { useTranslation } from "react-i18next";

const HazardousWasteRecordsPage = () => {
  const {
    wasteRecords,
    loading,
    meta,
    filters,
    error,
    loadHazardousWasteRecords,
    removeHazardousWasteRecord,
    updateFilters,
    resetError,
  } = useHazardousWasteRecords();
  const { t } = useTranslation(["environment"]);
  const [viewModalVisible, setViewModalVisible] = useState(false);
  const [formModalVisible, setFormModalVisible] = useState(false);
  const [selectedRecord, setSelectedRecord] = useState(null);
  const [activeTab, setActiveTab] = useState("records");

  // Memoize handleLoadRecords to prevent infinite loops
  const handleLoadRecords = useCallback(
    (params = {}) => {
      const searchParams = {
        ...filters,
        ...params,
      };
      loadHazardousWasteRecords(searchParams);
    },
    [filters, loadHazardousWasteRecords]
  );

  useEffect(() => {
    handleLoadRecords();
  }, [handleLoadRecords]);

  useEffect(() => {
    if (error && !error.errors) {
      message.error(error.message || "Có lỗi xảy ra!");
      resetError();
    }
  }, [error, resetError]);

  const handleSearch = (searchFilters) => {
    handleLoadRecords(searchFilters);
  };

  const handleTableChange = (pagination, tableFilters, sorter) => {
    const params = {
      page: pagination.current,
      per_page: pagination.pageSize,
    };

    // Handle sorting
    if (sorter && sorter.field) {
      params.sort_by = sorter.field;
      params.sort_order = sorter.order === "ascend" ? "asc" : "desc";
    }

    updateFilters(params);
    handleLoadRecords(params);
  };

  const handleView = (record) => {
    setSelectedRecord(record);
    setViewModalVisible(true);
  };

  const handleEdit = (record) => {
    setSelectedRecord(record);
    setFormModalVisible(true);
  };

  const handleDelete = async (id) => {
    try {
      await removeHazardousWasteRecord(id).unwrap();
      message.success("Xóa bản ghi chất thải nguy hại thành công!");
      handleLoadRecords();
    } catch (error) {
      message.error(error.message || "Có lỗi xảy ra khi xóa bản ghi!");
    }
  };

  const handleAdd = () => {
    setSelectedRecord(null);
    setFormModalVisible(true);
  };

  const handleRefresh = useCallback(() => {
    handleLoadRecords();
  }, [handleLoadRecords]);

  const handleFormSuccess = useCallback(() => {
    handleLoadRecords();
  }, [handleLoadRecords]);

  // Memoize tab contents to prevent unnecessary re-renders
  const RecordsTabContent = useMemo(
    () => (
      <>
        {/* Page Header */}
        <div style={{ marginBottom: 16 }}>
          <div
            style={{
              display: "flex",
              justifyContent: "space-between",
              alignItems: "center",
              marginBottom: 16,
            }}
          >
            <h2 style={{ margin: 0 }}>
              {t("environment:hazardousWasteRecords")}
            </h2>
            <Space>
              <Button
                type="default"
                icon={<ReloadOutlined />}
                onClick={handleRefresh}
              >
                Làm mới
              </Button>
              <Button
                type="primary"
                icon={<PlusOutlined />}
                onClick={handleAdd}
              >
                Thêm mới
              </Button>
            </Space>
          </div>

          {/* Filters */}
          <HazardousWasteRecordFilters onSearch={handleSearch} />
        </div>

        {/* Table */}
        <HazardousWasteRecordTable
          data={wasteRecords}
          loading={loading}
          pagination={meta}
          onEdit={handleEdit}
          onDelete={handleDelete}
          onView={handleView}
          onTableChange={handleTableChange}
        />

        {/* Modals */}
        <HazardousWasteRecordModal
          visible={viewModalVisible}
          onClose={() => setViewModalVisible(false)}
          record={selectedRecord}
          onEdit={handleEdit}
        />

        <HazardousWasteRecordFormModal
          visible={formModalVisible}
          onClose={() => setFormModalVisible(false)}
          record={selectedRecord}
          onSuccess={handleFormSuccess}
        />
      </>
    ),
    [
      t,
      handleRefresh,
      handleAdd,
      handleSearch,
      wasteRecords,
      loading,
      meta,
      handleEdit,
      handleDelete,
      handleView,
      handleTableChange,
      viewModalVisible,
      selectedRecord,
      formModalVisible,
      handleFormSuccess,
    ]
  );

  // Statistics Tab Content - Only render when tab is active
  const StatisticsTabContent = useMemo(
    () => (
      <>
        <div style={{ marginBottom: 16 }}>
          <h2 style={{ margin: 0 }}>Thống kê chất thải nguy hại</h2>
        </div>
        {activeTab === "statistics" && <HazardousWasteRecordStats />}
      </>
    ),
    [activeTab]
  );

  const tabItems = useMemo(
    () => [
      {
        key: "records",
        label: (
          <span>
            <UnorderedListOutlined />
            Danh sách bản ghi
          </span>
        ),
        children: RecordsTabContent,
      },
      {
        key: "statistics",
        label: (
          <span>
            <BarChartOutlined />
            Thống kê
          </span>
        ),
        children: StatisticsTabContent,
      },
    ],
    [RecordsTabContent, StatisticsTabContent]
  );

  return (
    <div style={{ padding: "24px" }}>
      <Tabs
        items={tabItems}
        activeKey={activeTab}
        onChange={setActiveTab}
        size="large"
        type="card"
        tabBarStyle={{ marginBottom: 24 }}
      />
    </div>
  );
};

export default HazardousWasteRecordsPage;
Editor is loading...
Leave a Comment