All files / client/src/views/all-program-items programListUtils.ts

94.87% Statements 37/39
95.83% Branches 23/24
88.88% Functions 8/9
94.87% Lines 37/39

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                          357x 357x 357x 357x     357x             758x         758x   2x             758x     46x     758x 735x 23x           23x     357x       765x 742x     23x 54x 71x 2x   69x 29x   40x 9x   31x 2x   29x       1x   28x               357x       3278x 3278x 3367x 152x   3215x   3278x    
import {
  AgeGroup,
  Language,
  ProgramItem,
  Tag,
} from "shared/types/models/programItem";
import { isPreConventionWeekProgramItem } from "shared/utils/isPreConventionWeekProgramItem";
import {
  getUpcomingProgramItems,
  isMainEventProgramVisible,
} from "client/utils/getUpcomingProgramItems";
import { getTimeNow } from "client/utils/getTimeNow";
 
export enum StartingTimeOption {
  UPCOMING = "upcoming",
  ALL = "all",
  REVOLVING_DOOR = "revolvingDoor",
}
 
export const getVisibleProgramItems = (
  programItems: readonly ProgramItem[],
  selectedView: StartingTimeOption,
  selectedTags: readonly string[],
  hideFull: boolean,
  fullProgramItemIds: ReadonlySet<string>,
): readonly ProgramItem[] => {
  const tagFilteredProgramItems = getTagFilteredProgramItems(
    programItems,
    selectedTags,
  );
 
  const fullnessFiltered = hideFull
    ? tagFilteredProgramItems.filter(
        (item) => !fullProgramItemIds.has(item.programItemId),
      )
    : tagFilteredProgramItems;
 
  // Before the main event program is visible, only show pre-convention week program.
  // After it is visible, pre-convention week program is in the past so it drops out of
  // the upcoming list on its own
  const phaseFilteredProgramItems = isMainEventProgramVisible(getTimeNow())
    ? fullnessFiltered
    : fullnessFiltered.filter((programItem) =>
        isPreConventionWeekProgramItem(programItem),
      );
 
  if (selectedView === StartingTimeOption.UPCOMING) {
    return getUpcomingProgramItems(phaseFilteredProgramItems);
  } else Iif (selectedView === StartingTimeOption.REVOLVING_DOOR) {
    return getUpcomingProgramItems(phaseFilteredProgramItems).filter(
      (programItem) => programItem.revolvingDoor,
    );
  }
 
  return phaseFilteredProgramItems;
};
 
export const getTagFilteredProgramItems = (
  programItems: readonly ProgramItem[],
  selectedTags: readonly string[],
): readonly ProgramItem[] => {
  if (selectedTags.length === 0) {
    return programItems;
  }
  // Show items matching all of the selected tags (AND)
  return programItems.filter((programItem) =>
    selectedTags.every((selectedTag) => {
      if (programItem.programType.includes(selectedTag)) {
        return true;
      }
      if (programItem.tags.includes(selectedTag as Tag)) {
        return true;
      }
      if (programItem.ageGroups.includes(selectedTag as AgeGroup)) {
        return true;
      }
      if (programItem.languages.includes(selectedTag as Language)) {
        return true;
      }
      if (
        programItem.languages.includes(Language.LANGUAGE_FREE) &&
        Object.values(Language).includes(selectedTag as Language)
      ) {
        return true;
      }
      return false;
    }),
  );
};
 
// The header of the group currently at (or scrolled past) the top of the visible
// range — pinned to the top while its group scrolls. `stickyHeaderIndexes` is
// ascending, so the last one at or before `rangeStartIndex` is the active header
export const getActiveStickyHeaderIndex = (
  stickyHeaderIndexes: readonly number[],
  rangeStartIndex: number,
): number => {
  let activeIndex = 0;
  for (const headerIndex of stickyHeaderIndexes) {
    if (headerIndex > rangeStartIndex) {
      break;
    }
    activeIndex = headerIndex;
  }
  return activeIndex;
};