216 lines
6.1 KiB
TypeScript
216 lines
6.1 KiB
TypeScript
// selectors.ts - Redux selectors for application state
|
|
//
|
|
// Contains memoized selector functions that:
|
|
// - Derive computed data from the Redux store
|
|
// - Filter and transform state for UI components
|
|
// - Optimize performance by memoizing results
|
|
//
|
|
// Key selectors:
|
|
// - getFilteredSchedule: Filters sessions by track
|
|
// - getSearchedSchedule: Filters sessions by search text
|
|
// - getGroupedFavorites: Gets favorited sessions grouped by time
|
|
// - Various entity getters (getSession, getSpeaker, etc.)
|
|
|
|
import { createSelector } from 'reselect';
|
|
import { Schedule, Session, ScheduleGroup } from '../models/Schedule';
|
|
import { Speaker } from '../models/Speaker';
|
|
import { Location } from '../models/Location';
|
|
|
|
import { AppState } from './state';
|
|
import { IOrderItem } from '../models/Order';
|
|
import { Event } from '../models/Event';
|
|
|
|
const getSchedule = (state: AppState) => {
|
|
return state.data.schedule;
|
|
};
|
|
|
|
export const getSpeakers = (state: AppState) => state.data.speakers;
|
|
|
|
const getSessions = (state: AppState) => state.data.sessions;
|
|
const getFilteredTracks = (state: AppState) => state.data.filteredTracks;
|
|
const getFavoriteIds = (state: AppState) => state.data.favorites;
|
|
const getSearchText = (state: AppState) => state.data.searchText;
|
|
|
|
export const getEvents = (state: AppState) => {
|
|
return state.data.events;
|
|
};
|
|
|
|
export const getNearbyMembers = (state: AppState) => state.data.nearByMembers;
|
|
|
|
export const getOrders = (state: AppState) => {
|
|
return state.data.orders;
|
|
};
|
|
|
|
export const getFilteredSchedule = createSelector(
|
|
getSchedule,
|
|
getFilteredTracks,
|
|
(schedule, filteredTracks) => {
|
|
const groups: ScheduleGroup[] = [];
|
|
|
|
// Helper function to convert 12-hour time to 24-hour time for proper sorting
|
|
const convertTo24Hour = (timeStr: string) => {
|
|
const [time, period] = timeStr.toLowerCase().split(' ');
|
|
let [hours, minutes] = time.split(':').map(Number);
|
|
|
|
if (period === 'pm' && hours !== 12) {
|
|
hours += 12;
|
|
} else if (period === 'am' && hours === 12) {
|
|
hours = 0;
|
|
}
|
|
|
|
return `${hours.toString().padStart(2, '0')}:${minutes || '00'}`;
|
|
};
|
|
|
|
// Sort the groups by time
|
|
const sortedGroups = [...schedule.groups].sort((a, b) => {
|
|
const timeA = convertTo24Hour(a.time);
|
|
const timeB = convertTo24Hour(b.time);
|
|
return timeA.localeCompare(timeB);
|
|
});
|
|
|
|
sortedGroups.forEach((group: ScheduleGroup) => {
|
|
const sessions: Session[] = [];
|
|
group.sessions.forEach((session) => {
|
|
session.tracks.forEach((track) => {
|
|
if (filteredTracks.indexOf(track) > -1) {
|
|
sessions.push(session);
|
|
}
|
|
});
|
|
});
|
|
|
|
if (sessions.length) {
|
|
// Sort sessions within each group by start time
|
|
const sortedSessions = sessions.sort((a, b) => {
|
|
const timeA = convertTo24Hour(a.timeStart);
|
|
const timeB = convertTo24Hour(b.timeStart);
|
|
return timeA.localeCompare(timeB);
|
|
});
|
|
|
|
const groupToAdd: ScheduleGroup = {
|
|
time: group.time,
|
|
sessions: sortedSessions,
|
|
};
|
|
groups.push(groupToAdd);
|
|
}
|
|
});
|
|
|
|
return {
|
|
date: schedule.date,
|
|
groups,
|
|
} as Schedule;
|
|
}
|
|
);
|
|
|
|
export const getSearchedSchedule = createSelector(
|
|
getFilteredSchedule,
|
|
getSearchText,
|
|
(schedule, searchText) => {
|
|
if (!searchText) {
|
|
return schedule;
|
|
}
|
|
const groups: ScheduleGroup[] = [];
|
|
schedule.groups.forEach((group) => {
|
|
const sessions = group.sessions.filter(
|
|
(s) => s.name.toLowerCase().indexOf(searchText.toLowerCase()) > -1
|
|
);
|
|
if (sessions.length) {
|
|
const groupToAdd: ScheduleGroup = {
|
|
time: group.time,
|
|
sessions,
|
|
};
|
|
groups.push(groupToAdd);
|
|
}
|
|
});
|
|
return {
|
|
date: schedule.date,
|
|
groups,
|
|
} as Schedule;
|
|
}
|
|
);
|
|
|
|
export const getScheduleList = createSelector(getSearchedSchedule, (schedule) => schedule);
|
|
|
|
export const getGroupedFavorites = createSelector(
|
|
getScheduleList,
|
|
getFavoriteIds,
|
|
(schedule, favoriteIds) => {
|
|
const groups: ScheduleGroup[] = [];
|
|
schedule.groups.forEach((group) => {
|
|
const sessions = group.sessions.filter((s) => favoriteIds.indexOf(s.id) > -1);
|
|
if (sessions.length) {
|
|
const groupToAdd: ScheduleGroup = {
|
|
time: group.time,
|
|
sessions,
|
|
};
|
|
groups.push(groupToAdd);
|
|
}
|
|
});
|
|
return {
|
|
date: schedule.date,
|
|
groups,
|
|
} as Schedule;
|
|
}
|
|
);
|
|
|
|
const getIdParam = (_state: AppState, props: any) => {
|
|
return props.match.params['id'];
|
|
};
|
|
|
|
export const getSession = createSelector(getSessions, getIdParam, (sessions, id) => {
|
|
return sessions.find((s: Session) => s.id === id);
|
|
});
|
|
|
|
export const getSpeaker = createSelector(getSpeakers, getIdParam, (speakers, id) =>
|
|
speakers.find((x: Speaker) => x.id === id)
|
|
);
|
|
|
|
export const getEvent = createSelector(getEvents, getIdParam, (data_events, id) => {
|
|
const {
|
|
data: { events },
|
|
} = data_events;
|
|
|
|
return events.find((x: Event) => x.id === id);
|
|
});
|
|
|
|
export const getOrder = createSelector(getOrders, getIdParam, (data_orders, id) => {
|
|
const {
|
|
data: { orders },
|
|
} = data_orders;
|
|
|
|
return orders.find((x: IOrderItem) => x.id === id);
|
|
});
|
|
|
|
export const getSpeakerSessions = createSelector(getSessions, (sessions) => {
|
|
const speakerSessions: { [key: string]: Session[] } = {};
|
|
|
|
sessions.forEach((session: Session) => {
|
|
session.speakerNames &&
|
|
session.speakerNames.forEach((name) => {
|
|
if (speakerSessions[name]) {
|
|
speakerSessions[name].push(session);
|
|
} else {
|
|
speakerSessions[name] = [session];
|
|
}
|
|
});
|
|
});
|
|
return speakerSessions;
|
|
});
|
|
|
|
export const mapCenter = (state: AppState) => {
|
|
const item = state.data.locations.find((l: Location) => l.id === state.data.mapCenterId);
|
|
if (item == null) {
|
|
return {
|
|
id: 1,
|
|
name: 'Map Center',
|
|
lat: 43.071584,
|
|
lng: -89.38012,
|
|
};
|
|
}
|
|
return item;
|
|
};
|
|
|
|
export const getPartyUserUsername = (state: AppState) => state.user.username;
|
|
export const getPartyUserState = (state: AppState) => state.user;
|
|
|
|
export const getEventIdToJoin = (state: AppState) => state.dummy.eventIdToJoin;
|