All files / src/components/VirtualList/hooks index.ts

51.72% Statements 45/87
48.48% Branches 16/33
54.54% Functions 12/22
51.76% Lines 44/85

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204                                        67x             67x             67x 493x 493x 493x         67x 574x 574x 574x   574x 547x     574x 574x         574x 475x   99x 99x         574x 191x     383x 383x 15x     15x           15x     67x                                                   67x 532x 532x 188x       532x           67x 532x 532x   532x                 67x 228x   228x 228x 47x 47x 47x       228x     67x                                                                                                          
import { TableColumnType } from "@common/Table";
import {
  QKEY_ACQUIRER_MANAGE_MONEY_TRANSACTIONS_LIST,
  QKEY_MANAGE_MONEY_TRANSACTIONS_LIST,
  QKEY_PROVIDER_PROCESSING,
} from "@constants/queryKeys";
import { useAppDispatch, useAppSelector } from "@redux/hooks";
import { setDynamicSortByKey, updateSorting } from "@redux/slices/fundraisers";
import { selectDateFilter } from "@redux/slices/merchantFilters";
import {
  clearFilters,
  resetStatusFilter,
  selectQueryFilters,
  selectTableFilter,
} from "@redux/slices/transactions";
import { encodedQueryFilterMap } from "@services/filtering";
import moment from "moment";
import { useEffect, useMemo, useState } from "react";
import { useDispatch } from "react-redux";
 
const NEGATIVE_FILTER_QUERY_KEYS = [
  "acquirer-processing-transactions",
  QKEY_PROVIDER_PROCESSING,
  QKEY_MANAGE_MONEY_TRANSACTIONS_LIST,
  QKEY_ACQUIRER_MANAGE_MONEY_TRANSACTIONS_LIST,
];
 
const PENDING_FILTER_QUERY_KEYS = [
  "acquirer-processing-transactions",
  QKEY_PROVIDER_PROCESSING,
  QKEY_MANAGE_MONEY_TRANSACTIONS_LIST,
  QKEY_ACQUIRER_MANAGE_MONEY_TRANSACTIONS_LIST,
];
 
const formatFilterItem = (item: { type: string; value: string }): string => {
  const isNegativeFilter = item.value?.startsWith("!");
  const value = isNegativeFilter ? item.value?.slice(1) : item.value;
  return encodeURIComponent(
    `${item.type}:${isNegativeFilter ? "!" : ""}"${value}"`,
  );
};
 
export const useFilters = (queryKey: string) => {
  const filters = useAppSelector(selectTableFilter);
  const isNegativeFilterKey = NEGATIVE_FILTER_QUERY_KEYS.includes(queryKey);
  const allowPendingFilter = PENDING_FILTER_QUERY_KEYS.includes(queryKey);
 
  const hasPendingPurchasesFilter = filters.some(
    (item: any) => item.value === "pending",
  );
 
  const fFilters = (() => {
    Iif (hasPendingPurchasesFilter && !allowPendingFilter) {
      return filters.filter(
        ({ value }: { value: string }) => value !== "pending",
      );
    }
    if (isNegativeFilterKey) {
      return filters;
    } else {
      return filters.filter(
        ({ value }: { value: string }) => !value?.startsWith("!"),
      );
    }
  })();
 
  if (fFilters.length === 0) {
    return "";
  }
 
  const formattedFilter = fFilters.map(formatFilterItem).join(",");
  if (!hasPendingPurchasesFilter) return `(${formattedFilter})`;
  const formattedTypePendingPurchases = encodeURIComponent(
    `type:!"chargeback";type:!"pre_chargeback_refund"`,
  );
  return customEncodeURIComponent(
    `(${formattedTypePendingPurchases})%3B(${formattedFilter})`,
  );
};
 
function customEncodeURIComponent(str: string) {
  return str.replace(/%3A/g, ":"); // keep colons
}
 
export const useSettlementFiltersRepository = () => {
  const dispatch = useDispatch();
  const settlementDate = useAppSelector((state) =>
    selectDateFilter(state, "settlement-date"),
  );
  const queryString = "";
  let filterString = "";
  let filterStringFBO = "";
 
  if (settlementDate) {
    filterString = `?filter=settlementDate:"${settlementDate}"`;
    filterStringFBO = `?settlement_date=${moment(settlementDate).format(
      "YYYY-MM-DD",
    )}`;
  }
 
  useEffect(() => {
    return () => {
      dispatch(resetStatusFilter());
      dispatch(clearFilters());
    };
  }, []);
 
  return { settlementDate, filterString, filterStringFBO, queryString };
};
 
const useQuerySearchFilter = () => {
  const queryFilters = useAppSelector(selectQueryFilters);
  const queryFilter = useMemo(
    () => encodedQueryFilterMap(queryFilters),
    [queryFilters],
  );
 
  return queryFilter.transactions || "";
};
 
// Read-only access to the current transaction filters. Safe to call from
// components that mount/unmount during the page lifecycle (e.g. the compact
// scroll banner) — unlike useFiltersRepository, it has NO unmount cleanup.
export const useFiltersState = (queryKey = "") => {
  const queryString = useQuerySearchFilter();
  const formattedFilter = useFilters(queryKey);
 
  return { queryString, formattedFilter };
};
 
// Page-level owner of the transaction filters: same values as
// useFiltersState, plus a cleanup that resets the filters when the PAGE
// unmounts. Only call this from a component that lives for the whole page
// lifecycle — calling it from a component that unmounts on scroll/resize
// silently wipes the active tab's status filter (GB bug: tab stayed
// highlighted but the list reset to all statuses).
export const useFiltersRepository = (queryKey = "") => {
  const dispatch = useDispatch();
 
  const filtersState = useFiltersState(queryKey);
  useEffect(() => {
    return () => {
      dispatch(resetStatusFilter());
      dispatch(clearFilters());
    };
  }, []);
 
  return filtersState;
};
 
export const useSorting = (
  setSort: any,
  defaultSortKey = "createdAt",
  sortReduxKey = "",
  tab = "",
) => {
  const [sortKey, setSortKey] = useState<any>(null);
  const [order, setOrder] = useState<any>("desc");
 
  const getNewOrder = (columnKey: any) => {
    let newOrder: any = "asc";
 
    if (sortKey === null) {
      newOrder = "asc";
    } else {
      if (sortKey !== columnKey) {
        newOrder = "asc";
      } else {
        newOrder = order === "asc" ? "desc" : "asc";
      }
    }
 
    return newOrder;
  };
 
  useEffect(() => {
    setSortKey(defaultSortKey);
    setOrder("desc");
  }, [tab]);
 
  const dispatch = useAppDispatch();
 
  const onSort =
    (column: TableColumnType) => (_: React.MouseEvent<HTMLElement>) => {
      setSortKey(column.key);
      const newOrder = getNewOrder(column.key);
      const ascOrder = column.key?.replace("-", "");
      const newSorting = newOrder === "asc" ? ascOrder : `-${column.key}`;
 
      setOrder(newOrder);
 
      if (sortReduxKey) {
        dispatch(
          setDynamicSortByKey({ key: sortReduxKey, params: newSorting }),
        );
      } else {
        dispatch(updateSorting(newSorting));
      }
      setSort(newSorting);
    };
 
  return { sortKey, order, onSort };
};