Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 127 additions & 38 deletions apps/antalmanac/src/actions/AppStoreActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ import { TRPCError } from '@trpc/server';
import { SnackbarOrigin, VariantType } from 'notistack';
import { PostHog } from 'posthog-js/react';

import analyticsEnum, { logAnalytics, courseNumAsDecimal } from '$lib/analytics/analytics';
import analyticsEnum, { logAnalytics } from '$lib/analytics/analytics';
import trpc from '$lib/api/trpc';
import { warnMultipleTerms } from '$lib/helpers';
import { setLocalStorageUserId, setLocalStorageDataCache } from '$lib/localStorage';
import { getErrorMessage } from '$lib/utils';
import AppStore from '$stores/AppStore';
import { scheduleComponentsToggleStore } from '$stores/ScheduleComponentsToggleStore';
import { useSessionStore } from '$stores/SessionStore';
Expand All @@ -35,8 +36,10 @@ export const addCourse = (
logAnalytics(postHog, {
category: analyticsEnum.classSearch,
action: analyticsEnum.classSearch.actions.ADD_COURSE,
label: courseDetails.deptCode,
value: courseNumAsDecimal(courseDetails.courseNumber),
customProps: {
courseDept: courseDetails.deptCode,
courseNumber: courseDetails.courseNumber,
},
});
const terms = AppStore.termsInSchedule(term);

Expand Down Expand Up @@ -91,13 +94,6 @@ export function isEmptySchedule(schedules: ShortCourseSchedule[]) {
}

export const saveSchedule = async (providerId: string, rememberMe: boolean, postHog?: PostHog) => {
logAnalytics(postHog, {
category: analyticsEnum.nav,
action: analyticsEnum.nav.actions.SAVE_SCHEDULE,
label: providerId,
value: rememberMe ? 1 : 0,
});

if (providerId != null) {
providerId = providerId.replace(/\s+/g, '');

Expand Down Expand Up @@ -131,28 +127,38 @@ export const saveSchedule = async (providerId: string, rememberMe: boolean, post
);
}
deleteTempSaveData();
logAnalytics(postHog, {
category: analyticsEnum.auth,
action: analyticsEnum.auth.actions.SAVE_SCHEDULE,
customProps: {
autoSave: false,
},
});
AppStore.saveSchedule();
} catch (e) {
if (e instanceof TRPCError) {
if (useSessionStore.getState().sessionIsValid) {
openSnackbar('error', `Schedule could not be saved`);
} else {
openSnackbar('error', `Schedule could not be saved under username "${providerId}`);
openSnackbar('error', `Schedule could not be saved under username "${providerId}"`);
}
} else {
openSnackbar('error', 'Network error or server is down.');
}
logAnalytics(postHog, {
category: analyticsEnum.auth,
action: analyticsEnum.auth.actions.SAVE_SCHEDULE_FAIL,
error: getErrorMessage(e),
customProps: {
autoSave: false,
},
});
}
}
}
};

export async function autoSaveSchedule(providerID: string, postHog?: PostHog) {
logAnalytics(postHog, {
category: analyticsEnum.nav,
action: analyticsEnum.nav.actions.SAVE_SCHEDULE,
label: providerID,
});
if (providerID == null) return;
providerID = providerID.replace(/\s+/g, '');
if (providerID.length < 0) return;
Expand All @@ -166,15 +172,31 @@ export async function autoSaveSchedule(providerID: string, postHog?: PostHog) {
userData: scheduleSaveState,
},
});

deleteTempSaveData();
AppStore.saveSchedule();
logAnalytics(postHog, {
category: analyticsEnum.auth,
action: analyticsEnum.auth.actions.SAVE_SCHEDULE,
customProps: {
providerID,
autoSave: true,
},
});
} catch (e) {
if (e instanceof TRPCError) {
openSnackbar('error', `Schedule could not be auto-saved under username "${providerID}`);
openSnackbar('error', `Schedule could not be auto-saved under username "${providerID}"`);
} else {
openSnackbar('error', 'Network error or server is down.');
}
logAnalytics(postHog, {
category: analyticsEnum.auth,
action: analyticsEnum.auth.actions.SAVE_SCHEDULE_FAIL,
error: getErrorMessage(e),
customProps: {
providerID,
autoSave: true,
},
});
}
}

Expand All @@ -197,7 +219,7 @@ export const mergeShortCourseSchedules = (
currentSchedules.push(...cacheSchedule);
};

const handleScheduleImport = async (username: string, skipImportedCheck = false) => {
const handleScheduleImport = async (username: string, skipImportedCheck = false, postHog?: PostHog) => {
const session = useSessionStore.getState();
if (!session.sessionIsValid) {
throw new Error("Invalid session: User isn't logged in.");
Expand Down Expand Up @@ -231,11 +253,16 @@ const handleScheduleImport = async (username: string, skipImportedCheck = false)

const isScheduleLoaded = await AppStore.loadSchedule(currentSchedules);
if (isScheduleLoaded) {
logAnalytics(postHog, {
category: analyticsEnum.auth,
action: analyticsEnum.auth.actions.IMPORT_LEGACY,
});

openSnackbar('success', `Schedule with name "${username}" imported successfully!`);

scheduleComponentsToggleStore.setState({ openScheduleSelect: true, openLoadingSchedule: false });

await saveSchedule(accounts.providerAccountId, true);
await saveSchedule(accounts.providerAccountId, true, postHog);

await trpc.userData.flagImportedSchedule.mutate({
providerId: username,
Expand All @@ -246,17 +273,17 @@ const handleScheduleImport = async (username: string, skipImportedCheck = false)
return { imported: false, error: null };
};

export const importValidatedSchedule = async (username: string) => {
export const importValidatedSchedule = async (username: string, postHog?: PostHog) => {
try {
return await handleScheduleImport(username, true);
return await handleScheduleImport(username, true, postHog);
} catch (e) {
return { imported: false, error: e };
}
};

export const importScheduleWithUsername = async (username: string) => {
export const importScheduleWithUsername = async (username: string, postHog?: PostHog) => {
try {
return await handleScheduleImport(username, false);
return await handleScheduleImport(username, false, postHog);
} catch (e) {
return { imported: false, error: e };
}
Expand All @@ -268,12 +295,6 @@ export const loadSchedule = async (
accountType: 'GOOGLE' | 'GUEST',
postHog?: PostHog
) => {
logAnalytics(postHog, {
category: analyticsEnum.nav,
action: analyticsEnum.nav.actions.LOAD_SCHEDULE,
label: providerId,
value: rememberMe ? 1 : 0,
});
if (
providerId != null &&
(!AppStore.hasUnsavedChanges() ||
Expand All @@ -295,16 +316,59 @@ export const loadSchedule = async (
const scheduleSaveState = userDataResponse?.userData ?? userDataResponse;

if (await AppStore.loadSchedule(scheduleSaveState)) {
if (accountType === 'GOOGLE') {
logAnalytics(postHog, {
category: analyticsEnum.auth,
action: analyticsEnum.auth.actions.LOAD_SCHEDULE,
});
} else {
logAnalytics(postHog, {
category: analyticsEnum.auth,
action: analyticsEnum.auth.actions.LOAD_SCHEDULE_LEGACY,
customProps: {
rememberMe,
},
});
}
openSnackbar('success', `Schedule loaded.`);
} else {
AppStore.loadSkeletonSchedule(scheduleSaveState);
if (accountType === 'GOOGLE') {
logAnalytics(postHog, {
category: analyticsEnum.auth,
action: analyticsEnum.auth.actions.LOAD_SCHEDULE_FAIL,
error: 'Network error',
customProps: {
providerId,
},
});
} else {
logAnalytics(postHog, {
category: analyticsEnum.auth,
action: analyticsEnum.auth.actions.LOAD_SCHEDULE_LEGACY_FAIL,
error: 'Network error',
customProps: {
providerId,
rememberMe,
},
});
}
openSnackbar(
'error',
`Network error loading course information for "${providerId}".
If this continues to happen, please submit a feedback form.`
);
}
} catch (e) {
logAnalytics(postHog, {
category: analyticsEnum.auth,
action:
accountType === 'GOOGLE'
? analyticsEnum.auth.actions.LOAD_SCHEDULE_FAIL
: analyticsEnum.auth.actions.LOAD_SCHEDULE_LEGACY_FAIL,
error: getErrorMessage(e),
...(accountType !== 'GOOGLE' && { customProps: { rememberMe } }),
});
if (e instanceof TRPCClientError) {
if (e.data.httpStatus === 404) {
openSnackbar('error', e.message);
Expand All @@ -320,38 +384,54 @@ export const loadSchedule = async (
}
};

export const loadScheduleWithSessionToken = async () => {
// logAnalytics({
// category: analyticsEnum.nav.title,
// action: analyticsEnum.nav.actions.LOAD_SCHEDULE,
// label: providerId,
// value: rememberMe ? 1 : 0,
// });
export const loadScheduleWithSessionToken = async (postHog?: PostHog) => {
try {
let analyticsErrorMessage = '';
const userDataResponse = await trpc.userData.getUserDataWithSession.query({
refreshToken: useSessionStore.getState().session ?? '',
});
const scheduleSaveState = userDataResponse?.userData ?? userDataResponse;

if (isEmptySchedule(scheduleSaveState.schedules)) {
logAnalytics(postHog, {
category: analyticsEnum.auth,
action: analyticsEnum.auth.actions.LOAD_SCHEDULE,
});
return true;
}

if (scheduleSaveState == null) {
analyticsErrorMessage = "Couldn't find schedules";
openSnackbar('error', `Couldn't find schedules for this account`);
} else if (await AppStore.loadSchedule(scheduleSaveState)) {
openSnackbar('success', `Schedule loaded.`);
logAnalytics(postHog, {
category: analyticsEnum.auth,
action: analyticsEnum.auth.actions.LOAD_SCHEDULE,
});
return true;
} else {
analyticsErrorMessage = 'Network error';
AppStore.loadSkeletonSchedule(scheduleSaveState);
openSnackbar(
'error',
`Network error loading course information".
If this continues to happen, please submit a feedback form.`
);
}
logAnalytics(postHog, {
category: analyticsEnum.auth,
action: analyticsEnum.auth.actions.LOAD_SCHEDULE_FAIL,
error: analyticsErrorMessage,
});
return false;
} catch (e) {
console.error(e);
logAnalytics(postHog, {
category: analyticsEnum.auth,
action: analyticsEnum.auth.actions.LOAD_SCHEDULE_FAIL,
error: getErrorMessage(e),
});
openSnackbar('error', `Failed to load schedules. If this continues to happen, please submit a feedback form.`);
return false;
}
Expand All @@ -364,14 +444,23 @@ const cacheSchedule = () => {
}
};

export const loginUser = async () => {
export const loginUser = async (postHog?: PostHog) => {
try {
const authUrl = await trpc.userData.getGoogleAuthUrl.query();
if (authUrl) {
cacheSchedule();
window.location.href = authUrl;
}
logAnalytics(postHog, {
category: analyticsEnum.auth,
action: analyticsEnum.auth.actions.SIGN_IN,
});
} catch (error) {
logAnalytics(postHog, {
category: analyticsEnum.auth,
action: analyticsEnum.auth.actions.SIGN_IN_FAIL,
error: getErrorMessage(error),
});
console.error('Error during login initiation', error);
openSnackbar('error', 'Error during login initiation. Please Try Again.');
}
Expand Down
Loading
Loading