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;
};
|