All files / src/features/Events/EventDetail/inventory useEventInventory.ts

100% Statements 11/11
87.5% Branches 7/8
100% Functions 3/3
100% Lines 10/10

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              5x 10x 10x 10x   10x                                                       5x 24x 24x         24x   24x    
import { useMemo } from "react";
import { useGetCurrentMerchantId } from "@hooks/common";
import { CURRENCY } from "@constants/constants";
import { toEnFormat } from "@utils/index";
import { useGetEventInventory } from "@services/api/products/inventory";
import { EventInventoryRow, EventVariantApiRow } from "./inventory.types";
 
const parseInventoryRow = (variant: EventVariantApiRow): EventInventoryRow => {
  const isUnlimited = variant.inventory === null;
  const available = variant.inventory ?? 0;
  const sold = variant.numSold ?? 0;
 
  return {
    id: variant.id,
    name: variant.name,
    // Prices are minor units. `toEnFormat` is what the sibling transactions
    // table on this page already uses, so the two tabs agree on grouping and
    // decimals. There is no per-product currency on the API, so the portal's
    // single CURRENCY constant stands in — the same assumption the rest of the
    // app makes.
    priceLabel: `${toEnFormat(variant.price / 100)} ${CURRENCY}`,
    sold,
    // The card states sold, total and available together, so total is derived
    // as sold + remaining rather than read from `initialInventory`: the latter
    // is re-set whenever the merchant edits capacity, which would let the card
    // print three numbers that don't add up.
    total: sold + available,
    available,
    isSoldOut: !isUnlimited && available === 0,
    isUnlimited,
  };
};
 
/**
 * The Inventory tab's data: an event's ticket types with their capacity.
 *
 * Everything the cards need is already on the variant view, so this is one
 * read — the ticket-stats endpoint counts issued tickets by status, which is a
 * different question from how many are left to sell.
 */
export const useEventInventory = (eventId?: string) => {
  const { merchantId } = useGetCurrentMerchantId();
  const { data, isLoading, isError } = useGetEventInventory(
    merchantId,
    eventId,
  );
 
  const rows = useMemo(() => (data?.data ?? []).map(parseInventoryRow), [data]);
 
  return { rows, isLoading, isError };
};