Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merging lucy and chanel friends activity #918

Open
wants to merge 64 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
693b898
feat: year, term and classNo added to class data
M7s7 Sep 18, 2024
556cda2
feat: add sync functions for add/remove/edit timetables. Create/dupli…
M7s7 Sep 18, 2024
f78a65d
feat: added routing for friends page
hhuolu Sep 22, 2024
b34215a
chore: revert addition of syncing fuctions to individual components
M7s7 Sep 24, 2024
6fa8fad
feat: sync timetables function refactored to use setInterval
M7s7 Sep 24, 2024
c5413ad
fix: logic for sync timetables
M7s7 Sep 24, 2024
a8d3859
Merge branch 'dev' of github.com:devsoc-unsw/notangles into sync-time…
M7s7 Sep 24, 2024
33939c2
fix: bugs with typing w/ course codes and class no
M7s7 Sep 24, 2024
5e58572
temp fix: change events back to old schema:
M7s7 Sep 24, 2024
8b30f08
feat: add database dto to frontend object parsing. Also, add event to…
M7s7 Sep 29, 2024
4f1d08c
feat: add subtype to event in schema
M7s7 Sep 29, 2024
100b6e9
fix: class info is correctly extracted from map
M7s7 Sep 29, 2024
1ce381b
feat: course code returned in scraped-class object from backend
M7s7 Sep 29, 2024
1f145df
feat: add default assigned colors for courses when reconstructing tim…
M7s7 Sep 29, 2024
3d4ac6f
feat: syncing timetable updates user context
M7s7 Sep 30, 2024
9090244
fix: updated type in runsync arg
M7s7 Sep 30, 2024
fb4b4b7
merge: fix conflicts
M7s7 Oct 1, 2024
292ddd9
fix: reverted unwanted regression in timetable creation logic
M7s7 Oct 1, 2024
07669d3
feat: store timetable logic moved to usercontext
M7s7 Oct 1, 2024
f8a85f7
fix: bug fixes
M7s7 Oct 1, 2024
83d0b22
feat: add mapkey/termkey to schema
M7s7 Oct 2, 2024
041c5bf
fix: merge conflicts
hhuolu Oct 2, 2024
dab2162
fix: add back friends routing
hhuolu Oct 2, 2024
68f7fba
feat: add term key logic to frontend
M7s7 Oct 2, 2024
c8e382a
merged master in sync branch
Rayahhhmed Oct 3, 2024
4a7ede0
fixed header bug
Rayahhhmed Oct 3, 2024
d478241
sent request to BE when creating a default timetable
Oct 4, 2024
45bd563
removing logout problems
Rayahhhmed Oct 4, 2024
859e20b
Changed createDefaultTimetable to accept userID and make a call to BE…
Oct 4, 2024
a8109ad
Merge branch 'sync-timetables' of github.com:devsoc-unsw/notangles in…
Oct 4, 2024
493d289
reduced four useEffects in App.tsx into one
Oct 4, 2024
923ed2a
added fix for logout bugs
Rayahhhmed Oct 4, 2024
d6727d7
checked for valid term, before gettingUserInfo and creating default t…
Oct 4, 2024
4536dfa
removed timeout and fixed delete timetable by including header
Oct 4, 2024
038c665
separated useEffect in App.tsx so that displayTimetables is its own t…
Oct 4, 2024
f0096ab
fix: user display timetables are deep copies, and other course/app co…
M7s7 Oct 6, 2024
2ce5dd6
fix: remove hard-coding of term in add timetable, and added back inte…
M7s7 Oct 6, 2024
572938e
fix: first user timetable not being saved to backend fix
M7s7 Oct 6, 2024
c6471f5
added types for tt dto
Rayahhhmed Oct 7, 2024
dc16c10
fix: DTO structure fixed, and cleaned up code
M7s7 Oct 8, 2024
bfc0daf
removed groupsSidebarCollapsed as location.pathname == /friends can b…
Oct 25, 2024
301c47c
added group banner information as fixed
Oct 25, 2024
695eb80
fixed useLocation to display group information banner
Oct 25, 2024
9faa0b3
deleted TimetableShared and made Friends page only display a timetable
Oct 25, 2024
2403478
fixed top left border radius conditionally rendered on only / page
Oct 25, 2024
3c0054c
created fixed right side bar for friends activities
Oct 25, 2024
6e1b1ab
restyled activity side bar
Oct 25, 2024
6e0690f
adjusted zIndex of the activity bar to 999 to be below top navbar
Oct 25, 2024
e5b5484
added some of chanels functions to FriendsActivity.tsx as noted, and …
Oct 25, 2024
be0f6e6
changed duplicateClasses in timetableHelpers to generate a new uuid f…
Oct 29, 2024
be33adf
merged sync-timetable with lucy-and-chanel-activity
Oct 30, 2024
34a67c4
returned timetables of the friends of the logged in user
Oct 30, 2024
dd02549
added activity to be saved in the backend for classes
Nov 1, 2024
a18b451
unscheduled items are saved to BE
Nov 1, 2024
89a73b5
fixed interface typing
Nov 1, 2024
a4dab5e
fix: revert compaction of useUpdateEffects to fix local storage on lo…
M7s7 Nov 3, 2024
7f46f36
Merge branch 'sync-timetables' into merging-lucy-and-chanel-friends-a…
Nov 5, 2024
e538669
Merge branch 'dev' of https://github.com/devsoc-unsw/notangles into m…
Shzmj Nov 15, 2024
1acc2b9
fixing repeated classData key
Shzmj Nov 15, 2024
f740f20
fixed minor issues with merging
Shzmj Nov 15, 2024
f1d95cf
fixing friendactivity call to getCourseInfo since term string now inc…
Shzmj Nov 15, 2024
dc34091
fixing dbCourseToCourseData error with number args
Shzmj Nov 15, 2024
ce67f1b
attempt at fixing getcurrentactivity. outlined what needs to be done …
Shzmj Nov 15, 2024
816438a
partial fix for getCurrentActivity + findCurrentActivity so easier fo…
Shzmj Nov 15, 2024
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
40 changes: 20 additions & 20 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 } from 'react';
import { Outlet } from 'react-router-dom';
import { Outlet, useLocation } from 'react-router-dom';

import getCourseInfo from './api/getCourseInfo';
import getCoursesList from './api/getCoursesList';
Expand All @@ -14,7 +14,6 @@ import Footer from './components/footer/Footer';
import Sidebar from './components/sidebar/Sidebar';
import Sponsors from './components/Sponsors';
import Timetable from './components/timetable/Timetable';
import TimetableShared from './components/timetableShared.tsx/TimetableShared';
import { TimetableTabs } from './components/timetableTabs/TimetableTabs';
import { contentPadding, darkTheme, leftContentPadding, lightTheme, rightContentPadding } from './constants/theme';
import {
Expand Down Expand Up @@ -91,6 +90,7 @@ const ICSButton = styled(Button)`
`;

const App: React.FC = () => {
const location = useLocation();
const {
is12HourMode,
isDarkMode,
Expand Down Expand Up @@ -135,7 +135,7 @@ const App: React.FC = () => {
setAssignedColors,
} = useContext(CourseContext);

const { user, setUser, groupsSidebarCollapsed, setGroupsSidebarCollapsed } = useContext(UserContext);
const { user, setUser } = useContext(UserContext);

setDropzoneRange(days.length, earliestStartTime, latestEndTime);

Expand Down Expand Up @@ -615,29 +615,29 @@ const App: React.FC = () => {
<Sidebar />
<ContentWrapper>
<Content>
<Controls
assignedColors={assignedColors}
handleSelectClass={handleSelectClass}
handleSelectCourse={handleSelectCourse}
handleRemoveCourse={handleRemoveCourse}
/>
<Outlet />
{groupsSidebarCollapsed ? (
{location.pathname === '/friends' ? (
<></>
) : (
<>
<Controls
assignedColors={assignedColors}
handleSelectClass={handleSelectClass}
handleSelectCourse={handleSelectCourse}
handleRemoveCourse={handleRemoveCourse}
/>
<TimetableTabs />
<Timetable assignedColors={assignedColors} handleSelectClass={handleSelectClass} />
<ICSButton
onClick={() => downloadIcsFile(selectedCourses, createdEvents, selectedClasses, firstDayOfTerm)}
>
save to calendar
</ICSButton>
<Sponsors />
<Footer />
<Alerts />
</>
) : (
<TimetableShared assignedColors={assignedColors} handleSelectClass={handleSelectClass} />
)}
<ICSButton
onClick={() => downloadIcsFile(selectedCourses, createdEvents, selectedClasses, firstDayOfTerm)}
>
save to calendar
</ICSButton>
<Sponsors />
<Footer />
<Alerts />
</Content>
</ContentWrapper>
</StyledApp>
Expand Down
33 changes: 33 additions & 0 deletions client/src/components/friends/ActivityBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { styled } from '@mui/system';

import FriendsActivity from './FriendsActivity';

const ActivityBarContainer = styled('div')`
position: fixed;
top: 64px;
right: 0;
padding: 12px 32px;
z-index: 999;
background: white;
height: 100vh;
display: flex;
flex-direction: column;
gap: 12px;
`;

const StyledTitle = styled('p')`
font-size: 1.2rem;
font-weight: 700;
margin: 0;
`;

const ActivityBar = () => {
return (
<ActivityBarContainer>
<StyledTitle>Your Friends Activity</StyledTitle>
<FriendsActivity />
</ActivityBarContainer>
);
};

export default ActivityBar;
43 changes: 43 additions & 0 deletions client/src/components/friends/Friends.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import styled from '@emotion/styled';
import { useContext } from 'react';

import { unknownErrorMessage } from '../../constants/timetable';
import { AppContext } from '../../context/AppContext';
import { CourseContext } from '../../context/CourseContext';
import { UserContext } from '../../context/UserContext';
import { ClassData } from '../../interfaces/Periods';
import Timetable from '../timetable/Timetable';
import GroupInfoNavbar from './GroupInfoNavbar';

const Container = styled('div')`
margin-top: 80px;
`;

const Friends = () => {
const { assignedColors, setSelectedClasses } = useContext(CourseContext);
const { setAlertMsg, setErrorVisibility } = useContext(AppContext);
const { groups } = useContext(UserContext);

const handleSelectClass = (classData: ClassData) => {
setSelectedClasses((prev) => {
prev = { ...prev };

try {
prev[classData.courseCode][classData.activity] = classData;
} catch (err) {
setAlertMsg(unknownErrorMessage);
setErrorVisibility(true);
}

return prev;
});
};
return (
<Container>
<GroupInfoNavbar />
{groups.length > 0 && <Timetable assignedColors={assignedColors} handleSelectClass={handleSelectClass} />}
</Container>
);
};

export default Friends;
201 changes: 201 additions & 0 deletions client/src/components/friends/FriendsActivity.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
import { styled } from '@mui/system';
import { useContext, useEffect } from 'react';

import { API_URL } from '../../api/config';
import { UserContext } from '../../context/UserContext';



const Container = styled('div')`
display: flex;
flex-direction: column;
gap: 12px;
`;

const FriendContainer = styled('div')`
display: flex;
flex-direction: column;
border-radius: 8px;
background-color: #f2f3f5;
padding: 16px;
gap: 12px;
`;

const UserNameText = styled('p')`
font-weight: 600;
font-size: 1rem;
margin: 0;
`;

const UserActivity = styled('p')`
margin: 0;
color: #90949a;
font-size: 0.8rem;
`;

const ClassLocationContainer = styled('div')`
display: flex;
flex-direction: row;
background-color: white;
border-radius: 4px;
padding: 10px;
gap: 12px;
`;

const Location = styled('div')`
font-size: 0.8rem;
`;

const ClassTime = styled('div')`
font-size: 0.8rem;
`;

const TextContainer = styled('div')`
display: flex;
flex-direction: column;
`;

const UserDetailsContainer = styled('div')`
display: flex;
flex-direction: row;
gap: 16px;
`;

const UserProfile = styled('div')`
width: 35px;
height: 35px;
border-radius: 20px;
background-color: white;
`;

/*
TODO: tldr just need to fix getCurrentActivity and findCurrentActivity to return a useful object like the below from the database timetable object
export type CurrentActivity = {
friendName: string;
activityTitle: string; // i.e. in a [activity] tutorial
location: string; // so this will be `[course_code] at [room location]`
time_slot: string; // i.e. 12:00 - 14:00
};
^ or if its a custom event then minor changes based on the event info
*/

////////////////////////////////////////////////////// CHANEL'S BE STUFF //////////////////////////////////////////////////////
export interface Friend {
name: string;
userId: string;
// show next event within the hour
currentActivity: CurrentActivity | null;
}

export type FriendsList = Friend[];

export type CurrentActivity = {
friendName: string;
activityTitle: string; // i.e. in a [activity] tutorial
location: string; // so this will be `[course_code] at [room location]`
time_slot: string; // i.e. 12:00 - 14:00
};

const getCurrentActivity = async (userId: string): Promise<CurrentActivity | null> => {
try {
const res = await fetch(`${API_URL.server}/user/timetable/${userId}`, {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
});

if (!res.ok) {
throw new Error('Failed to fetch timetable data');
}

const timetable = await res.json();
// Currently we only consider the first timetable as the main
return findCurrentActivity(timetable.data[0]);
} catch (error) {
console.error('Error fetching current activity:', error);
return null;
}
};

const findCurrentActivity = (timetable: any): CurrentActivity | null => {
const now = new Date();
const currentDay = now.toLocaleString('en-US', { weekday: 'long' }).slice(0, 3);
const currentTime = now.toTimeString().split(' ')[0].slice(0, 5);

for (const clz of timetable.selectedClasses) {
if (clz.times.day === currentDay && clz.times.time.start <= currentTime && clz.times.time.end >= currentTime) {
return {
friendName: timetable.friendName,
activityTitle: `in a ${clz.activity} tutorial`,
location: `${clz.courseCode} at ${clz.times.location}`,
time_slot: `${clz.times.time.start} - ${clz.times.time.end}`,
};
}
}

return null;
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

const FriendsActivity = () => {
const { user } = useContext(UserContext);

useEffect(() => {
// TODO: fix this integration here and store friend activity in state...
const dosomething = async () => {
for (const friend of user.friends) {
console.log('friend', friend);
const res = await getCurrentActivity(friend.userID);
console.log('friend activity res', res);
}
};
dosomething();
}, []);

return (
<Container>
<FriendContainer>
<UserDetailsContainer>
<UserProfile />
<TextContainer>
<UserNameText>Raiyan Ahmed</UserNameText>
<UserActivity>Currently teaching</UserActivity>
</TextContainer>
</UserDetailsContainer>
<ClassLocationContainer>
<Location>COMP1531 at TablaK17G7</Location>
<ClassTime>14:00 - 16:00</ClassTime>
</ClassLocationContainer>
</FriendContainer>
<FriendContainer>
<UserDetailsContainer>
<UserProfile />
<TextContainer>
<UserNameText>Shaam Jevan</UserNameText>
<UserActivity>Currently teaching</UserActivity>
</TextContainer>
</UserDetailsContainer>
<ClassLocationContainer>
<Location>COMP3121 at DA_BASEMENT</Location>
<ClassTime>14:00 - 16:00</ClassTime>
</ClassLocationContainer>
</FriendContainer>
<FriendContainer>
<UserDetailsContainer>
<UserProfile />
<TextContainer>
<UserNameText>Jeremy Le</UserNameText>
<UserActivity>Chilln</UserActivity>
</TextContainer>
</UserDetailsContainer>
<ClassLocationContainer>
<Location>Ainsworth L3</Location>
</ClassLocationContainer>
</FriendContainer>
</Container>
);
};

export default FriendsActivity;
Loading