Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into migrate-rds
Browse files Browse the repository at this point in the history
  • Loading branch information
MinhxNguyen7 committed Dec 2, 2024
2 parents 591a9e0 + 818b168 commit 88956ae
Show file tree
Hide file tree
Showing 9 changed files with 144 additions and 121 deletions.
4 changes: 2 additions & 2 deletions apps/antalmanac/src/actions/ActionTypesStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export interface ClearScheduleAction {

export interface CopyScheduleAction {
type: 'copySchedule';
to: number;
newScheduleName: string;
}

export interface ChangeCourseColorAction {
Expand Down Expand Up @@ -159,7 +159,7 @@ class ActionTypesStore extends EventEmitter {
AppStore.schedule.clearCurrentSchedule();
break;
case 'copySchedule':
AppStore.schedule.copySchedule(action.to);
AppStore.schedule.copySchedule(action.newScheduleName);
break;
default:
break;
Expand Down
12 changes: 6 additions & 6 deletions apps/antalmanac/src/actions/AppStoreActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import { removeLocalStorageUserId, setLocalStorageUserId } from '$lib/localStora
import AppStore from '$stores/AppStore';

export interface CopyScheduleOptions {
onSuccess: (index: number) => unknown;
onError: (index: number) => unknown;
onSuccess: (scheduleName: string) => unknown;
onError: (scheduleName: string) => unknown;
}

export const addCourse = (
Expand Down Expand Up @@ -250,17 +250,17 @@ export const changeCourseColor = (sectionCode: string, term: string, newColor: s
AppStore.changeCourseColor(sectionCode, term, newColor);
};

export const copySchedule = (to: number, options?: CopyScheduleOptions) => {
export const copySchedule = (newScheduleName: string, options?: CopyScheduleOptions) => {
logAnalytics({
category: analyticsEnum.addedClasses.title,
action: analyticsEnum.addedClasses.actions.COPY_SCHEDULE,
});

try {
AppStore.copySchedule(to);
options?.onSuccess(to);
AppStore.copySchedule(newScheduleName);
options?.onSuccess(newScheduleName);
} catch (error) {
options?.onError(to);
options?.onError(newScheduleName);
}
};

Expand Down
20 changes: 16 additions & 4 deletions apps/antalmanac/src/components/dialogs/AddSchedule.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Box, Button, Dialog, DialogActions, DialogContent, DialogTitle, TextField } from '@mui/material';
import type { DialogProps } from '@mui/material';
import { useState } from 'react';
import { useState, useEffect, useCallback } from 'react';

import { addSchedule } from '$actions/AppStoreActions';
import AppStore from '$stores/AppStore';
Expand All @@ -12,7 +12,9 @@ import { useThemeStore } from '$stores/SettingsStore';
function AddScheduleDialog({ onClose, onKeyDown, ...props }: DialogProps) {
const isDark = useThemeStore((store) => store.isDark);

const [name, setName] = useState(AppStore.getDefaultScheduleName());
const [name, setName] = useState(
AppStore.getNextScheduleName(AppStore.getDefaultScheduleName(), AppStore.getScheduleNames().length)
);

const handleCancel = () => {
onClose?.({}, 'escapeKeyDown');
Expand All @@ -24,7 +26,6 @@ function AddScheduleDialog({ onClose, onKeyDown, ...props }: DialogProps) {

const submitName = () => {
addSchedule(name);
setName(AppStore.schedule.getDefaultScheduleName());
onClose?.({}, 'escapeKeyDown');
};

Expand All @@ -46,6 +47,17 @@ function AddScheduleDialog({ onClose, onKeyDown, ...props }: DialogProps) {
}
};

const handleScheduleNamesChange = useCallback(() => {
setName(AppStore.getNextScheduleName(AppStore.getDefaultScheduleName(), AppStore.getScheduleNames().length));
}, []);

useEffect(() => {
AppStore.on('scheduleNamesChange', handleScheduleNamesChange);
return () => {
AppStore.off('scheduleNamesChange', handleScheduleNamesChange);
};
}, [handleScheduleNamesChange]);

return (
<Dialog onKeyDown={handleKeyDown} {...props}>
<DialogTitle>Add Schedule</DialogTitle>
Expand All @@ -60,7 +72,7 @@ function AddScheduleDialog({ onClose, onKeyDown, ...props }: DialogProps) {
<Button onClick={handleCancel} color={isDark ? 'secondary' : 'primary'}>
Cancel
</Button>
<Button onClick={submitName} variant="contained" color="primary" disabled={name.trim() === ''}>
<Button onClick={submitName} variant="contained" color="primary" disabled={name?.trim() === ''}>
Add Schedule
</Button>
</DialogActions>
Expand Down
45 changes: 12 additions & 33 deletions apps/antalmanac/src/components/dialogs/CopySchedule.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@ import {
DialogActions,
DialogContent,
DialogTitle,
MenuItem,
Select,
TextField,
type DialogProps,
} from '@mui/material';
import { SelectChangeEvent } from '@mui/material';
import { useState, useEffect, useCallback } from 'react';

import { copySchedule } from '$actions/AppStoreActions';
Expand All @@ -22,65 +20,46 @@ interface CopyScheduleDialogProps extends DialogProps {
function CopyScheduleDialog(props: CopyScheduleDialogProps) {
const { index } = props;
const { onClose } = props; // destructured separately for memoization.
const [scheduleNames, setScheduleNames] = useState(AppStore.getScheduleNames());
const [selectedSchedule, setSelectedSchedule] = useState<number>(0);
const [name, setName] = useState<string>(`Copy of ${AppStore.getScheduleNames()[index]}`);

const handleScheduleChange = useCallback((event: SelectChangeEvent<number>) => {
setSelectedSchedule(event.target.value as number);
const handleNameChange = useCallback((event: React.ChangeEvent<HTMLTextAreaElement>) => {
setName(event.target.value);
}, []);

const handleCancel = useCallback(() => {
onClose?.({}, 'escapeKeyDown');
}, [onClose]);

const handleCopy = useCallback(() => {
if (selectedSchedule !== scheduleNames.length) {
copySchedule(selectedSchedule);
} else {
scheduleNames.forEach((_, scheduleIndex) => {
if (scheduleIndex !== index) {
copySchedule(scheduleIndex);
}
});
}
copySchedule(name);
onClose?.({}, 'escapeKeyDown');
}, [index, onClose, selectedSchedule, scheduleNames]);
}, [onClose, name]);

const handleScheduleNamesChange = useCallback(() => {
setScheduleNames([...AppStore.getScheduleNames()]);
}, []);
setName(`Copy of ${AppStore.getScheduleNames()[index]}`);
}, [index]);

useEffect(() => {
AppStore.on('scheduleNamesChange', handleScheduleNamesChange);

return () => {
AppStore.off('scheduleNamesChange', handleScheduleNamesChange);
};
}, [handleScheduleNamesChange]);

return (
<Dialog onClose={onClose} {...props}>
<DialogTitle>Copy To Schedule</DialogTitle>

<DialogTitle>Copy Schedule</DialogTitle>
<DialogContent>
<Box padding={1}>
<Select fullWidth value={selectedSchedule} onChange={handleScheduleChange}>
{scheduleNames.map((name, idx) => (
<MenuItem key={idx} value={idx} disabled={index === idx}>
{name}
</MenuItem>
))}
<MenuItem value={scheduleNames.length}>Copy to All Schedules</MenuItem>
</Select>
<TextField fullWidth label="Name" onChange={handleNameChange} value={name} />
</Box>
</DialogContent>

<DialogActions>
<Button onClick={handleCancel} color="inherit">
Cancel
</Button>
<Button onClick={handleCopy} variant="contained" color="primary">
Copy Schedule
<Button onClick={handleCopy} variant="contained" color="primary" disabled={name?.trim() === ''}>
Make a Copy
</Button>
</DialogActions>
</Dialog>
Expand Down
21 changes: 15 additions & 6 deletions apps/antalmanac/src/components/dialogs/DeleteSchedule.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
DialogTitle,
type DialogProps,
} from '@mui/material';
import { useCallback, useMemo } from 'react';
import { useCallback, useEffect, useState } from 'react';

import { deleteSchedule } from '$actions/AppStoreActions';
import AppStore from '$stores/AppStore';
Expand Down Expand Up @@ -35,10 +35,7 @@ function DeleteScheduleDialog(props: ScheduleNameDialogProps) {
* This is destructured separately for memoization.
*/
const { onClose } = props;

const scheduleName = useMemo(() => {
return AppStore.schedule.getScheduleName(index);
}, [index]);
const [name, setName] = useState<string>(AppStore.getScheduleNames()[index]);

const handleCancel = useCallback(() => {
onClose?.({}, 'escapeKeyDown');
Expand All @@ -49,12 +46,24 @@ function DeleteScheduleDialog(props: ScheduleNameDialogProps) {
onClose?.({}, 'escapeKeyDown');
}, [index, onClose]);

const handleScheduleNamesChange = useCallback(() => {
setName(AppStore.getScheduleNames()[index]);
}, [index]);

useEffect(() => {
AppStore.on('scheduleNamesChange', handleScheduleNamesChange);

return () => {
AppStore.off('scheduleNamesChange', handleScheduleNamesChange);
};
}, [handleScheduleNamesChange]);

return (
<Dialog {...dialogProps}>
<DialogTitle>Delete Schedule</DialogTitle>

<DialogContent>
<DialogContentText>Are you sure you want to delete &#34;{scheduleName}&#34;?</DialogContentText>
<DialogContentText>Are you sure you want to delete &#34;{name}&#34;?</DialogContentText>
</DialogContent>

<DialogActions>
Expand Down
20 changes: 6 additions & 14 deletions apps/antalmanac/src/components/dialogs/RenameSchedule.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
TextField,
type DialogProps,
} from '@mui/material';
import { useCallback, useState, useEffect, useMemo } from 'react';
import { useCallback, useState, useEffect } from 'react';

import { renameSchedule } from '$actions/AppStoreActions';
import AppStore from '$stores/AppStore';
Expand All @@ -34,19 +34,11 @@ function RenameScheduleDialog(props: ScheduleNameDialogProps) {
* This is destructured separately for memoization.
*/
const { onClose } = props;

const [scheduleNames, setScheduleNames] = useState(AppStore.getScheduleNames());

const [name, setName] = useState(scheduleNames[index]);

const disabled = useMemo(() => {
return name?.trim() === '';
}, [name]);
const [name, setName] = useState(AppStore.getScheduleNames()[index]);

const handleCancel = useCallback(() => {
onClose?.({}, 'escapeKeyDown');
setName(scheduleNames[index]);
}, [onClose, scheduleNames, index]);
}, [onClose, index]);

const handleNameChange = useCallback((event: React.ChangeEvent<HTMLTextAreaElement>) => {
setName(event.target.value);
Expand Down Expand Up @@ -75,8 +67,8 @@ function RenameScheduleDialog(props: ScheduleNameDialogProps) {
);

const handleScheduleNamesChange = useCallback(() => {
setScheduleNames(AppStore.getScheduleNames());
}, []);
setName(AppStore.getScheduleNames()[index]);
}, [index]);

useEffect(() => {
AppStore.on('scheduleNamesChange', handleScheduleNamesChange);
Expand All @@ -100,7 +92,7 @@ function RenameScheduleDialog(props: ScheduleNameDialogProps) {
<Button onClick={handleCancel} color={'inherit'}>
Cancel
</Button>
<Button onClick={submitName} variant="contained" color="primary" disabled={disabled}>
<Button onClick={submitName} variant="contained" color="primary" disabled={name?.trim() === ''}>
Rename Schedule
</Button>
</DialogActions>
Expand Down
86 changes: 52 additions & 34 deletions apps/antalmanac/src/routes/ErrorPage.tsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,61 @@
import { Typography, Button, Stack } from '@mui/material';
import { Link, useRouteError } from 'react-router-dom';
import { ExpandMore } from '@mui/icons-material';
import { Box, Accordion, AccordionDetails, AccordionSummary, Typography, Button, Stack } from '@mui/material';
import { Link, useLocation, useRouteError } from 'react-router-dom';

export const ErrorPage = () => {
const error = useRouteError();
const location = useLocation();

return (
<Stack
spacing={3}
sx={{
padding: '1rem',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
flexDirection: 'column',
height: '100vh',
gap: 2,
}}
>
<Typography variant="h3" component="h1">
Oops! Something went wrong.
</Typography>
<Stack spacing={2} sx={{ textAlign: 'center' }}>
<Typography variant="h5" component="p">
This error may be caused by your browser having an out of date version of AntAlmanac.
</Typography>
<Typography variant="h5" component="p">
Try refreshing the page. If the error persists, please submit a{' '}
<Link to="https://forms.gle/k81f2aNdpdQYeKK8A">bug report</Link> with the provided error.
<Box sx={{ height: '100dvh', overflowY: 'auto' }}>
<Stack
sx={{
display: 'flex',
justifyContent: 'center',
textAlign: 'center',
maxWidth: 800,
minHeight: '100dvh',
margin: 'auto',
padding: 2,
gap: 2,
}}
>
<Typography variant="h3" component="h1">
Oops! Something went wrong.
</Typography>
<Stack spacing={2}>
<Typography variant="h5" component="p">
This error may be caused by your browser having an out of date version of AntAlmanac.
</Typography>
<Typography variant="h5" component="p">
Try refreshing the page. If the error persists, please submit a{' '}
<Link to="https://forms.gle/k81f2aNdpdQYeKK8A">bug report</Link> with the provided error.
</Typography>
</Stack>
<Link to="/">
<Button variant="contained" size="large">
Back to Home
</Button>
</Link>
<Accordion defaultExpanded disableGutters sx={{ maxWidth: '100%' }}>
<AccordionSummary expandIcon={<ExpandMore />}>
<Typography component="p">View Error Message</Typography>
</AccordionSummary>
<AccordionDetails
sx={{
display: 'flex',
gap: 1,
textAlign: 'left',
flexWrap: 'wrap',
}}
>
<Typography sx={{ fontWeight: '600' }}>Route: {location.pathname}</Typography>
<Typography sx={{ wordBreak: 'break-word' }}>
{error instanceof Error ? error.stack : 'No error stack provided.'}
</Typography>
</AccordionDetails>
</Accordion>
</Stack>
<Link to="/">
<Button variant="contained" size="large">
Back to Home
</Button>
</Link>
<details open>
<summary>View Error Message</summary>
<p>{error instanceof Error && <pre>{error.stack}</pre>}</p>
</details>
</Stack>
</Box>
);
};
Loading

0 comments on commit 88956ae

Please sign in to comment.