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

92.3% Statements 36/39
91.66% Branches 22/24
77.77% Functions 7/9
92.3% Lines 36/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                        609x 609x 609x 609x     609x               1132x         1132x   20x             1132x           1132x 1101x 31x           31x     609x       1139x 1132x     7x 15x 18x 2x   16x 3x   13x 2x   11x 2x   9x       1x   8x               609x       4643x 4643x 5142x 698x   4444x   4643x    
import {
  AgeGroup,
  Language,
  ProgramItem,
  Tag,
} from "shared/types/models/programItem";
import { isPreConventionWeekProgramItem } from "shared/utils/isPreConventionWeekProgramItem";
import {
  getUpcomingProgramItems,
  isMainEventProgramVisible,
} from "client/utils/getUpcomingProgramItems";
 
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>,
  timeNow: Date,
): 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(timeNow)
    ? fullnessFiltered
    : fullnessFiltered.filter((programItem) =>
        isPreConventionWeekProgramItem(programItem),
      );
 
  if (selectedView === StartingTimeOption.UPCOMING) {
    return getUpcomingProgramItems(phaseFilteredProgramItems, timeNow);
  } else Iif (selectedView === StartingTimeOption.REVOLVING_DOOR) {
    return getUpcomingProgramItems(phaseFilteredProgramItems, timeNow).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;
};