Skip to content
Draft
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
54 changes: 43 additions & 11 deletions client/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { LocalizationProvider } from '@mui/x-date-pickers';
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
import * as Sentry from '@sentry/react';
import React, { useContext, useEffect, useMemo } from 'react';
import { Outlet } from 'react-router';
import { Outlet, useLocation } from 'react-router';

import getCourseInfo from './api/getCourseInfo';
import getCoursesList from './api/getCoursesList';
Expand Down Expand Up @@ -134,6 +134,7 @@ const App: React.FC = () => {
setAssignedColors,
} = useContext(CourseContext);

const location = useLocation();
const { preferredTheme, isDarkMode, unscheduleClassesByDefault, convertToLocalTimezone } = useGetUserSettingsQuery();

const decodedAssignedColors = useColorsDecoder(assignedColors, preferredTheme);
Expand Down Expand Up @@ -569,6 +570,46 @@ const App: React.FC = () => {
},
};

const timetableView = useMemo(() => {
const currentPathname = location.pathname;
const searchParams = location.search;
console.log(currentPathname);
if (currentPathname === '/home') {
return (
<>
<TimetableTabs />
<Timetable assignedColors={decodedAssignedColors} handleSelectClass={handleSelectClass} />
<ICSButton
onClick={() => {
downloadIcsFile(selectedCourses, createdEvents, selectedClasses, firstDayOfTerm)
.then(() => {
/* do nothing */
})
.catch(() => {
/* do nothing */
});
}}
>
save to calendar
</ICSButton>
<Sponsors />
<Footer />
<Alerts />
</>
);
} else {
return <Timetable assignedColors={decodedAssignedColors} handleSelectClass={handleSelectClass} />;
}
}, [
location,
selectedClasses,
createdEvents,
selectedCourses,
firstDayOfTerm,
handleSelectClass,
decodedAssignedColors,
]);

return (
<StyledEngineProvider injectFirst>
<ThemeProvider theme={themeObject}>
Expand All @@ -586,16 +627,7 @@ const App: React.FC = () => {
handleRemoveCourse={handleRemoveCourse}
/>
<Outlet />
<TimetableTabs />
<Timetable assignedColors={decodedAssignedColors} handleSelectClass={handleSelectClass} />
<ICSButton
onClick={() => downloadIcsFile(selectedCourses, createdEvents, selectedClasses, firstDayOfTerm)}
>
save to calendar
</ICSButton>
<Sponsors />
<Footer />
<Alerts />
{timetableView}
<SubcomPromotion />
<PromotionPopup
imgSrc={T3SelectGif}
Expand Down
123 changes: 80 additions & 43 deletions client/src/components/controls/Controls.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { Box, Grid } from '@mui/material';
import { styled } from '@mui/material/styles';
import React from 'react';
import React, { useMemo } from 'react';
import { useLocation } from 'react-router';

import { ControlsProps } from '../../interfaces/PropTypes';
import UserProfile from '../sidebar/friends/UserProfile';
import Autotimetabler from './Autotimetabler';
import CourseSelect from './CourseSelect';
import CustomEvents from './CustomEvent';
Expand All @@ -18,6 +20,20 @@ const TermSelectWrapper = styled(Box)`
align-items: flex-start;
`;

const FriendTimetableLabelContainer = styled(Box)`
display: flex;
justify-content: center;
align-items: center;
width: 100%;
background-color: ${({ theme }) => theme.palette.secondary.light};
border: 0.75px solid;
border-color: ${({ theme }) => theme.palette.text.primary};
padding: 10px 0;
border-top-left-radius: ${({ theme }) => theme.shape.borderRadius}px;
border-top-right-radius: ${({ theme }) => theme.shape.borderRadius}px;
font-weight: 700;
`;

const SelectWrapper = styled(Box)`
display: flex;
flex-direction: row;
Expand Down Expand Up @@ -52,50 +68,71 @@ const Controls: React.FC<ControlsProps> = ({
handleSelectCourse,
handleRemoveCourse,
}) => {
const location = useLocation();
const additionalControlsDisplay = useMemo(() => {
if (location.pathname !== '/home') {
return (
<>
<TermSelectWrapper>
<TermSelect />
</TermSelectWrapper>
<FriendTimetableLabelContainer>
<UserProfile firstName="Sunny" lastName="Chen" overrideCollapse={true} />
</FriendTimetableLabelContainer>
</>
);
}
return (
<>
<Grid
container
direction="row"
size={{
xs: 12,
md: 6.5,
}}
>
<TermSelectWrapper>
<TermSelect />
</TermSelectWrapper>

<SelectWrapper minWidth={'296px'}>
<CourseSelect
assignedColors={assignedColors}
handleSelect={handleSelectCourse}
handleRemove={handleRemoveCourse}
/>
</SelectWrapper>
</Grid>
<Grid
container
direction="row"
sx={{
alignItems: 'center',
justifyContent: 'space-between',
}}
size={{
xs: 12,
md: 5.5,
}}
>
<CustomEventsWrapper>
<CustomEvents />
</CustomEventsWrapper>
<AutotimetablerWrapper>
<Autotimetabler handleSelectClass={handleSelectClass} />
</AutotimetablerWrapper>
<HistoryWrapper>
<History />
</HistoryWrapper>
</Grid>
</>
);
}, [location.pathname, assignedColors, handleSelectCourse, handleRemoveCourse, handleSelectClass]);

return (
<Grid container sx={{ paddingLeft: '66px' }} spacing={2}>
<Grid
container
direction="row"
size={{
xs: 12,
md: 6.5,
}}
>
<TermSelectWrapper>
<TermSelect />
</TermSelectWrapper>

<SelectWrapper minWidth={'296px'}>
<CourseSelect
assignedColors={assignedColors}
handleSelect={handleSelectCourse}
handleRemove={handleRemoveCourse}
/>
</SelectWrapper>
</Grid>
<Grid
container
direction="row"
sx={{
alignItems: 'center',
justifyContent: 'space-between',
}}
size={{
xs: 12,
md: 5.5,
}}
>
<CustomEventsWrapper>
<CustomEvents />
</CustomEventsWrapper>
<AutotimetablerWrapper>
<Autotimetabler handleSelectClass={handleSelectClass} />
</AutotimetablerWrapper>
<HistoryWrapper>
<History />
</HistoryWrapper>
</Grid>
{additionalControlsDisplay}
</Grid>
);
};
Expand Down
3 changes: 3 additions & 0 deletions client/src/components/sidebar/CustomModalOpener.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ interface CustomModalOpenerProps {
content: ReactNode;
isClickable: boolean;
isSelected?: boolean;
optionalHandleClick?: () => void;
}

const ShowModalButton = styled(IconButton, { shouldForwardProp: (prop) => prop !== 'isSelected' })<{
Expand Down Expand Up @@ -40,6 +41,7 @@ const CustomModalOpener: React.FC<CustomModalOpenerProps> = ({
content,
isClickable,
isSelected = false,
optionalHandleClick,
}) => {
const [isOpen, setIsOpen] = useState(false);
const { sidebarCollapsed } = useContext(AppContext);
Expand All @@ -48,6 +50,7 @@ const CustomModalOpener: React.FC<CustomModalOpenerProps> = ({
if (isClickable) {
setIsOpen(!isOpen);
}
if (optionalHandleClick) optionalHandleClick();
};

return (
Expand Down
9 changes: 8 additions & 1 deletion client/src/components/sidebar/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { CalendarMonth, Description, Info, Security, Settings as SettingsIcon }
import { Divider, Drawer, Typography, useMediaQuery, useTheme } from '@mui/material';
import { styled } from '@mui/material/styles';
import { useContext, useMemo, useState } from 'react';
import { useLocation, useNavigate } from 'react-router';

import notanglesLogoGif from '../../assets/notangles.gif';
import notanglesLogo from '../../assets/notangles_1.png';
Expand Down Expand Up @@ -158,6 +159,9 @@ const Sidebar = () => {
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
const collapsedWidth = useMemo(() => (isMobile ? 0 : 80), [isMobile]);

const location = useLocation();
const navigate = useNavigate();

const [currLogo, setCurrLogo] = useState(notanglesLogo);
const [friendsListOpen, setFriendsListOpen] = useState(false);
const { sidebarCollapsed, setSidebarCollapsed } = useContext(AppContext);
Expand Down Expand Up @@ -231,7 +235,10 @@ const Sidebar = () => {
// currently not clickable since this is our current page
isClickable={false}
// hardcoded until we move away from single page site
isSelected={true}
isSelected={location.pathname === '/home'}
optionalHandleClick={() => {
navigate('/home');
}}
/>
<FriendsButton
friendsListOpen={friendsListOpen}
Expand Down
22 changes: 16 additions & 6 deletions client/src/components/sidebar/friends/Friend.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import MoreVertIcon from '@mui/icons-material/MoreVert';
import { IconButton, styled, Tooltip } from '@mui/material';
import { Box } from '@mui/system';
import { useContext, useState } from 'react';
import { useCallback, useContext, useState } from 'react';
import { useNavigate } from 'react-router';

import { useGetUserSettingsQuery } from '../../../api/user/queries';
import { AppContext } from '../../../context/AppContext';
Expand All @@ -23,19 +24,28 @@ const StyledFriendContainer = styled(Box, {
isDarkMode ? theme.palette.secondary.dark : theme.palette.secondary.light}
`;

interface FriendProps {
export interface FriendDTO {
firstName: string;
lastName: string;
id: string;
profileURL: string;
}

const Friend = ({ firstName }: FriendProps) => {
const Friend = ({ firstName, lastName, id, profileURL }: FriendDTO) => {
const [kebabOpen, setKebabOpen] = useState(false);
const { sidebarCollapsed } = useContext(AppContext);
const { isDarkMode } = useGetUserSettingsQuery();

const navigate = useNavigate();

const handleFriendClick = useCallback(() => {
navigate(`/friend/${id}`);
}, [id, navigate]);

return (
<Tooltip title={sidebarCollapsed ? firstName : ''} placement="right">
<StyledFriendContainer isDarkMode={isDarkMode} sidebarCollapsed={sidebarCollapsed}>
<UserProfile firstName={firstName} lastName="" />
<Tooltip title={sidebarCollapsed ? `${firstName} ${lastName}` : ''} placement="right">
<StyledFriendContainer isDarkMode={isDarkMode} sidebarCollapsed={sidebarCollapsed} onClick={handleFriendClick}>
<UserProfile firstName={firstName} lastName={lastName} profileURL={profileURL} />
{!sidebarCollapsed && (
<IconButton
onClick={() => {
Expand Down
24 changes: 20 additions & 4 deletions client/src/components/sidebar/friends/FriendsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Fuse from 'fuse.js';
import { useContext, useMemo, useState } from 'react';

import { AppContext } from '../../../context/AppContext';
import Friend from './Friend';
import Friend, { FriendDTO } from './Friend';
import friendList from './friends.json';

const FriendsListContainer = styled(Box)`
Expand All @@ -31,12 +31,28 @@ const FriendsList = () => {
// TODO: replace hard coded data with integration with server
let friends = friendList;
if (searchVal.length === 0) {
return friends.map((friend, index) => <Friend key={index} firstName={friend} />);
return friends.map(({ firstName, lastName, id, profileURL }) => (
<Friend
key={id as string}
firstName={firstName as string}
lastName={lastName as string}
id={id as string}
profileURL={profileURL as string}
/>
));
}

const fuzzy = new Fuse<string>(friendList, { threshold: 0.4 });
const fuzzy = new Fuse<FriendDTO>(friendList, { threshold: 0.4, keys: ['firstName', 'lastName'] });
friends = fuzzy.search(searchVal).map((result) => result.item);
return friends.map((friend, index) => <Friend key={index} firstName={friend} />);
return friends.map(({ firstName, lastName, id, profileURL }) => (
<Friend
key={id as string}
firstName={firstName as string}
lastName={lastName as string}
id={id as string}
profileURL={profileURL as string}
/>
));
}, [searchVal]);

const handleClickSearchBarIcon = () => {
Expand Down
Loading
Loading