Skip to content

Data Table with Tender Management and Review Workflow

Key Features:

  1. Data Table Display: The core feature is a data table that displays tenders fetched from the backend. Each row represents a tender with details such as title, procurement process, activity, industry, start and end dates, status, and reviewers.

  2. Sorting and Pagination: The table supports sorting of data by various columns (e.g., title, procurement process) and pagination (i.e., rows per page and navigating through pages). This is handled via state hooks and event handlers like handleRequestSort and handleChangePage.

  3. Popover for Tender Actions: There are popovers that provide additional options for each tender, including actions like reviewing or viewing more details. This is controlled through Popover components and state hooks for toggling visibility.

  4. Filtering and Searching: Users can filter tenders based on status (e.g., Approved, Pending, etc.), search by name, and filter by date or other attributes. The filtering logic is implemented using state hooks like tenderFilter, searchName, and selectedDate.

  5. Dynamic Action Routing: Based on the user’s role (e.g., procurement officer), the actions taken on a tender vary. For instance, reviewing or drafting tenders triggers routing to different pages with specific query parameters, managed via useRouter.

  6. Loading State: A Loader component is used to indicate that data is being fetched from the backend, making the UI responsive and preventing user interaction during loading.

  7. State Management with Redux: The user information (like role and organization) is retrieved from the Redux store, which helps in managing user-specific logic such as routing and filtering based on the role.

Key Functionalities:

  1. Data Fetching (fetchTenders):

    • The useEffect hook triggers an asynchronous function to fetch tender data from the backend.
    • Filters are applied based on the selected status, search name, and the logged-in user’s ID.
    • The tenderService.getAllTendersByOrgId method is used to retrieve the data, which is then set to the tenderData state for rendering in the table.
    const fetchTenders = async () => {
    setIsLoading(true); // Start loading
    try {
    const response = await tenderService.getAllTendersByOrgId(page + 1, rowsPerPage, searchName, tenderFilter, organization_id, userId);
    setTenderData(response.tenders);
    setTotalTenders(response.total_count);
    } catch (error) {
    console.error('Error fetching tenders:', error);
    } finally {
    setIsLoading(false); // Stop loading
    }
    };
  2. Sorting (handleRequestSort):

    • The table can be sorted based on columns, changing the sorting order (ascending or descending).
    • This is achieved by updating the order and orderBy state hooks when a column header is clicked.
    const handleRequestSort = (property: keyof Data) => {
    const isAsc = orderBy === property && order === 'asc';
    setOrder(isAsc ? 'desc' : 'asc');
    setOrderBy(property);
    };
  3. Popover Toggle for Row Actions (togglePopover):

    • A popover displays additional options (e.g., view, review, draft) when a user clicks on a row.
    • This is managed by toggling the openPopoverId state, which tracks which row’s popover is open.
    const togglePopover = (event: React.MouseEvent<HTMLElement>, serialId: string) => {
    if (openPopoverId === serialId) {
    setAnchorEl(null);
    setOpenPopoverId(null);
    } else {
    setAnchorEl(event.currentTarget);
    setOpenPopoverId(serialId);
    }
    };
  4. Handling Filter Change (handleChangeFilter):

    • The filter state (tenderFilter) is updated when the user selects a different status from a dropdown.
    • The filter is used to refine which tenders are fetched from the backend.
    const handleChangeFilter = (event: any) => {
    const selectedFilter = event.target.value as string;
    const selectedStatus = buttonColorDecider.find(item => item.status === selectedFilter);
    setTenderFilter(selectedStatus.status);
    };
  5. Review and Action Routing (handleClickReview, handleClickDraft):

    • These functions manage routing based on the role and action. For example, when reviewing a tender, the user is routed to a page with a specific query string depending on the tender’s activity type.
    const handleClickReview = (event: React.MouseEvent<HTMLElement>, tender: any) => {
    const routePath = user?.role === 'procurement_officer'
    ? `/review-tender?tender-id=${tender.serial_id}`
    : `/my-request?review-tender=${tender.serial_id}`;
    router.push(routePath);
    };

Data Fetching and Step Handling:

  • Data Fetching:

    • The code fetches tenders using an API call made by tenderService.getAllTendersByOrgId, with filters applied for pagination, search, and status. This function is invoked whenever the relevant state (page, rowsPerPage, searchName, selectedDate, tenderFilter) changes.
    • It uses setIsLoading to display a loading indicator while the data is being fetched.
  • Step Handling:

    • The tender’s status and step are integral to routing and the available actions for each tender.
    • Based on the tender’s current step (e.g., draft, evaluation), specific paths are provided for users to either review or edit tenders. For instance, when handling a draft, the handleClickDraft function considers both the tender’s step and type to determine the next action.
const handleClickDraft = (event: React.MouseEvent<HTMLElement>, tender: any) => {
if (user && user.role === 'procurement_officer')
router.push(`/create-request?draft-id=${tender.serial_id}&step=${tender.step}&type=${tender.activity_type}`);
else
router.push(`/my-request?review-tender=${tender.serial_id}`);
};

In summary, this code primarily handles the dynamic fetching, sorting, filtering, and action routing of tender data in a user-friendly interface. It integrates state management, popover actions, and dynamic routing to ensure that users can manage tenders efficiently based on their roles and the current state of the tender.