From 94f0722522fe20ae6b26039bf319f9e22a2b05b4 Mon Sep 17 00:00:00 2001 From: Sofia De Bellis Date: Fri, 6 Sep 2024 16:59:05 +1000 Subject: [PATCH 01/24] (feat): Started workshopping card components --- frontend/src/component/SetOfTables.jsx | 1 + frontend/src/component/TutLecContentCard.jsx | 33 +++++++++++++++++++ frontend/src/page/Content/ContentLectures.jsx | 1 + .../page/Content/ContentLecturesByTopic.jsx | 5 +-- .../page/Content/ContentLecturesByWeek.jsx | 2 +- .../page/Content/ContentTutorialsByTopic.jsx | 1 - 6 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 frontend/src/component/TutLecContentCard.jsx diff --git a/frontend/src/component/SetOfTables.jsx b/frontend/src/component/SetOfTables.jsx index 89986b8..86dfa95 100644 --- a/frontend/src/component/SetOfTables.jsx +++ b/frontend/src/component/SetOfTables.jsx @@ -16,6 +16,7 @@ import Paper from '@mui/material/Paper'; import { RELEVANCE } from '../util/content'; const SetOfTables = ({ boxes, lectures }) => { + console.log(boxes[0].table) var durationCount = 0 const [noCatchup, setNoCatchup] = React.useState(localStorage.hasOwnProperty('eckles_noCatchup') ? parseInt(localStorage.getItem('eckles_noCatchup')) : 1); const [studentType, setStudentType] = React.useState(localStorage.hasOwnProperty('eckles_studentType') ? localStorage.getItem('eckles_studentType') : 'recommended'); diff --git a/frontend/src/component/TutLecContentCard.jsx b/frontend/src/component/TutLecContentCard.jsx new file mode 100644 index 0000000..b066354 --- /dev/null +++ b/frontend/src/component/TutLecContentCard.jsx @@ -0,0 +1,33 @@ +import * as React from "react"; +import Card from "@mui/material/Card"; +import CardActions from "@mui/material/CardActions"; +import CardContent from "@mui/material/CardContent"; +import Button from "@mui/material/Button"; +import Typography from "@mui/material/Typography"; +import Chip from "@mui/material/Chip"; +import { Stack } from "@mui/material"; + +export default function TutLecContentCard() { + return ( + + + + Title + + + 60 mins + + + + + + + + + + + + ); +} diff --git a/frontend/src/page/Content/ContentLectures.jsx b/frontend/src/page/Content/ContentLectures.jsx index 2a54659..022bfa5 100644 --- a/frontend/src/page/Content/ContentLectures.jsx +++ b/frontend/src/page/Content/ContentLectures.jsx @@ -11,6 +11,7 @@ import { Outlet } from 'react-router-dom'; import SubNavWrapper from '../../component/SubNavWrapper'; import makePage from '../../component/makePage'; +import TutLecContentCard from '../../component/TutLecContentCard'; const ContentLectures = ({ }) => { const menu = [ diff --git a/frontend/src/page/Content/ContentLecturesByTopic.jsx b/frontend/src/page/Content/ContentLecturesByTopic.jsx index e3b8f30..6f4abee 100644 --- a/frontend/src/page/Content/ContentLecturesByTopic.jsx +++ b/frontend/src/page/Content/ContentLecturesByTopic.jsx @@ -1,7 +1,7 @@ import React from 'react'; import Box from '@mui/material/Box'; import Button from '@mui/material/Button'; - +import TutLecContentCard from '../../component/TutLecContentCard'; import SetOfTables from '../../component/SetOfTables'; import { Context, useContext } from '../../context'; import { isTinyMobileWidth } from '../../util/screen'; @@ -14,8 +14,9 @@ const ContentLecturesByTopic = ({ }) => { const boxes = generateContent(getters, 'topic'); return ( <> + - + ); }; diff --git a/frontend/src/page/Content/ContentLecturesByWeek.jsx b/frontend/src/page/Content/ContentLecturesByWeek.jsx index afcb6f0..9657c31 100644 --- a/frontend/src/page/Content/ContentLecturesByWeek.jsx +++ b/frontend/src/page/Content/ContentLecturesByWeek.jsx @@ -17,7 +17,7 @@ const ContentLecturesByWeek = ({ }) => { return ( <> - + ); }; diff --git a/frontend/src/page/Content/ContentTutorialsByTopic.jsx b/frontend/src/page/Content/ContentTutorialsByTopic.jsx index 83038f9..fa99393 100644 --- a/frontend/src/page/Content/ContentTutorialsByTopic.jsx +++ b/frontend/src/page/Content/ContentTutorialsByTopic.jsx @@ -9,7 +9,6 @@ import { generateContent } from './ContentTutorials.content'; const ContentTutorialsByTopic = ({ }) => { const { getters } = useContext(Context); const boxes = generateContent(getters, 'topic'); - return ; }; From 32a2f38de2aba75158c9de14c565b6f2a9b73c3c Mon Sep 17 00:00:00 2001 From: Sofia De Bellis Date: Sun, 8 Sep 2024 20:25:36 +1000 Subject: [PATCH 02/24] Playing with card and data --- frontend/src/Router.jsx | 20 ++---- frontend/src/component/NavList.jsx | 4 +- frontend/src/component/TutLecContentCard.jsx | 18 +++-- frontend/src/config.js | 3 +- .../page/Content/ContentLectures.content.jsx | 66 ------------------- .../page/Content/ContentLecturesByTopic.jsx | 28 -------- .../page/Content/ContentLecturesByWeek.jsx | 28 -------- .../page/Content/ContentLecturesSearch.jsx | 60 +++++++++++++++++ .../page/Content/ContentTutorialsByTopic.jsx | 18 ----- .../page/Content/ContentTutorialsByWeek.jsx | 22 ------- .../page/Content/ContentTutorialsSearch.jsx | 60 +++++++++++++++++ 11 files changed, 139 insertions(+), 188 deletions(-) delete mode 100644 frontend/src/page/Content/ContentLectures.content.jsx delete mode 100644 frontend/src/page/Content/ContentLecturesByTopic.jsx delete mode 100644 frontend/src/page/Content/ContentLecturesByWeek.jsx create mode 100644 frontend/src/page/Content/ContentLecturesSearch.jsx delete mode 100644 frontend/src/page/Content/ContentTutorialsByTopic.jsx delete mode 100644 frontend/src/page/Content/ContentTutorialsByWeek.jsx create mode 100644 frontend/src/page/Content/ContentTutorialsSearch.jsx diff --git a/frontend/src/Router.jsx b/frontend/src/Router.jsx index 9285fe0..f001638 100644 --- a/frontend/src/Router.jsx +++ b/frontend/src/Router.jsx @@ -15,14 +15,10 @@ import TimetableHelpSessions from './page/Timetable/TimetableHelpSessions'; import CourseOutline from './page/CourseOutline'; import ContentBase from './page/Content/ContentBase'; import AssessmentsBase from './page/Assessments/AssessmentsBase'; -import ContentLectures from './page/Content/ContentLectures'; import ContentLecturesSingle from './page/Content/ContentLecturesSingle'; -import ContentLecturesByWeek from './page/Content/ContentLecturesByWeek'; -import ContentLecturesByTopic from './page/Content/ContentLecturesByTopic'; -import ContentTutorials from './page/Content/ContentTutorials'; +import ContentLecturesSearch from './page/Content/ContentLecturesSearch'; import ContentTutorialsSingle from './page/Content/ContentTutorialsSingle'; -import ContentTutorialsByWeek from './page/Content/ContentTutorialsByWeek'; -import ContentTutorialsByTopic from './page/Content/ContentTutorialsByTopic'; +import ContentTutorialsSearch from './page/Content/ContentTutorialsSearch'; import AssessmentsAssignments from './page/Assessments/AssessmentsAssignments'; import AssessmentsExam from './page/Assessments/AssessmentsExam'; import StyleBase from './page/Style/StyleBase'; @@ -69,14 +65,12 @@ const Router = () => { } /> }> - }> - } /> - } /> + }> + } /> } /> - }> - } /> - } /> + }> + } /> } /> @@ -113,4 +107,4 @@ const Router = () => { ); } -export default Router; +export default Router; \ No newline at end of file diff --git a/frontend/src/component/NavList.jsx b/frontend/src/component/NavList.jsx index 28d4654..0c64d24 100644 --- a/frontend/src/component/NavList.jsx +++ b/frontend/src/component/NavList.jsx @@ -51,14 +51,14 @@ export const getPrimaryNavList = (term) => { children: [ { title: 'Lectures', - route: '/content/lectures/week', + route: '/content/lectures/search', loginRequired: true, Icon: TheatersIcon, description: 'View lecture content, slides, and videos', }, { title: 'Tutorials', - route: '/content/tutorials/week', + route: '/content/tutorials/search', loginRequired: true, Icon: SchoolIcon, description: 'View tutorial content, questions, and videos', diff --git a/frontend/src/component/TutLecContentCard.jsx b/frontend/src/component/TutLecContentCard.jsx index b066354..ed08124 100644 --- a/frontend/src/component/TutLecContentCard.jsx +++ b/frontend/src/component/TutLecContentCard.jsx @@ -1,33 +1,31 @@ import * as React from "react"; import Card from "@mui/material/Card"; -import CardActions from "@mui/material/CardActions"; import CardContent from "@mui/material/CardContent"; -import Button from "@mui/material/Button"; import Typography from "@mui/material/Typography"; import Chip from "@mui/material/Chip"; import { Stack } from "@mui/material"; -export default function TutLecContentCard() { +export default function TutLecContentCard(content) { return ( - Title + {content.name} - 60 mins + {content.duration_mins} minutes - + - + {/* - + */} ); -} +} \ No newline at end of file diff --git a/frontend/src/config.js b/frontend/src/config.js index 3651cf0..163f774 100644 --- a/frontend/src/config.js +++ b/frontend/src/config.js @@ -13,6 +13,7 @@ config.joinSchema = { week: ['weeks', true], topic: ['topics', true], video_author: ['staff', true], + content_lectures: ['content_lectures', false], }, }, schedule_lectures: { @@ -78,4 +79,4 @@ config.joinSchema = { } }; -module.exports = config; +module.exports = config; \ No newline at end of file diff --git a/frontend/src/page/Content/ContentLectures.content.jsx b/frontend/src/page/Content/ContentLectures.content.jsx deleted file mode 100644 index 7ce4336..0000000 --- a/frontend/src/page/Content/ContentLectures.content.jsx +++ /dev/null @@ -1,66 +0,0 @@ -import Button from '@mui/material/Button'; - -import { isHalfScreenWidth, isTinyMobileWidth } from '../../util/screen'; -import Relevance from '../../component/Relevance'; - -export const generateContent = (getters, by) => { - const opposingPageType = (by === 'week') ? 'topic' : 'week'; - const secondColumnName = (by === 'week') ? 'Topic' : 'Week'; - const boxName = (by === 'week') - ? grouping => grouping.week === 11 ? 'Extra Content' : `Week ${grouping.week}` - : grouping => `${grouping.emoji} ${grouping.area().name}: ${grouping.name}`; - const boxKey = (by === 'week') - ? grouping => grouping.week - : grouping => grouping.name; - const secondColumnValue = (by === 'week') - ? lecture => lecture.topic ? `${lecture.topic().emoji} ${lecture.topic().name}` : '' - : lecture => `📅 ${lecture.week().week === 11 ? 'Extra' : lecture.week().week}`; - const outerList = (by === 'week') - ? getters.content.weeks.filter(w => w.week != 6) - : getters.content.topics.filter(t => t.name !== 'Admin'); - const secondColumnAnchor = (by === 'week') - ? lecture => lecture.topic().name - : lecture => lecture.week().week; - - const boxes = []; - outerList.forEach(grouping => { - const table = []; - if (grouping.content_lectures) { - grouping.content_lectures().sort((a, b) => a.order - b.order).forEach(lecture => { - if (lecture) { - table.push([ - { value: `${lecture.name}${lecture.live ? ' (live)' : ''}`, link: `/${getters.term}/content/lectures/${lecture.key}`, buttonProps: { variant: 'contained', color: 'info', sx: { textTransform: 'unset !important' } }, }, - { value: secondColumnValue(lecture), link: `/${getters.term}/content/lectures/${opposingPageType}#${secondColumnAnchor(lecture)}` }, - { value: , }, - { value: lecture.duration_mins ? `⏱️ ${lecture.duration_mins} mins` : 'TBD', }, - { Raw: () => { - if (lecture.pdf_url === 'null') { - return <>No Slides; - } else if (lecture.visible === true) { - let url = lecture.pdf_url === undefined ? `/~cs6080/raw/lectures/${lecture.key}.pdf` : lecture.pdf_url; - return ; - } else { - return ; - } - } - } - ]); - } - }); - } - boxes.push({ - title: boxName(grouping), - key: boxKey(grouping), - maxWidth: 800, - headers: [ - { name: 'Name', width: 40, }, - { name: secondColumnName, width: 20, showFn: () => !isTinyMobileWidth(), }, - { name: 'Importance', width: 20, }, - { name: 'Duration', width: 20, showFn: () => !isHalfScreenWidth(), }, - { name: 'Links', width: 20, showFn: () => !isHalfScreenWidth(), }, - ], - table, - }); - }); - return boxes; -}; \ No newline at end of file diff --git a/frontend/src/page/Content/ContentLecturesByTopic.jsx b/frontend/src/page/Content/ContentLecturesByTopic.jsx deleted file mode 100644 index 6f4abee..0000000 --- a/frontend/src/page/Content/ContentLecturesByTopic.jsx +++ /dev/null @@ -1,28 +0,0 @@ -import React from 'react'; -import Box from '@mui/material/Box'; -import Button from '@mui/material/Button'; -import TutLecContentCard from '../../component/TutLecContentCard'; -import SetOfTables from '../../component/SetOfTables'; -import { Context, useContext } from '../../context'; -import { isTinyMobileWidth } from '../../util/screen'; -import YoutubePlaylistButton from '../../component/YoutubePlaylistButton'; -import makePage from '../../component/makePage'; -import { generateContent } from './ContentLectures.content'; - -const ContentLecturesByTopic = ({ }) => { - const { getters } = useContext(Context); - const boxes = generateContent(getters, 'topic'); - return ( - <> - - - - - ); -}; - - -export default makePage(ContentLecturesByTopic, { - loginRequired: true, - title: 'Lecture Content (by topic)', -}); \ No newline at end of file diff --git a/frontend/src/page/Content/ContentLecturesByWeek.jsx b/frontend/src/page/Content/ContentLecturesByWeek.jsx deleted file mode 100644 index 9657c31..0000000 --- a/frontend/src/page/Content/ContentLecturesByWeek.jsx +++ /dev/null @@ -1,28 +0,0 @@ -import React from 'react'; -import Box from '@mui/material/Box'; -import { Link } from 'react-router-dom'; -import Button from '@mui/material/Button'; - -import SetOfTables from '../../component/SetOfTables'; -import { Context, useContext } from '../../context'; -import { isHalfScreenWidth, isTinyMobileWidth } from '../../util/screen'; -import YoutubePlaylistButton from '../../component/YoutubePlaylistButton'; -import makePage from '../../component/makePage'; -import { generateContent } from './ContentLectures.content'; - -const ContentLecturesByWeek = ({ }) => { - const { getters } = useContext(Context); - const boxes = generateContent(getters, 'week'); - - return ( - <> - - - - ); -}; - -export default makePage(ContentLecturesByWeek, { - loginRequired: true, - title: 'Lecture Content (by week)', -}); diff --git a/frontend/src/page/Content/ContentLecturesSearch.jsx b/frontend/src/page/Content/ContentLecturesSearch.jsx new file mode 100644 index 0000000..0c46031 --- /dev/null +++ b/frontend/src/page/Content/ContentLecturesSearch.jsx @@ -0,0 +1,60 @@ +import React from 'react'; +import { useCookies } from 'react-cookie'; +import { useNavigate, useLocation } from 'react-router-dom'; +import Button from '@mui/material/Button'; +import FavoriteIcon from '@mui/icons-material/Favorite'; +import TheatersIcon from '@mui/icons-material/Theaters'; +import SchoolIcon from '@mui/icons-material/School'; +import LocalHospitalIcon from '@mui/icons-material/LocalHospital'; +import { Outlet } from 'react-router-dom'; +import { Context, useContext } from '../../context'; +import TutLecContentCard from '../../component/TutLecContentCard'; +import SubNavWrapper from '../../component/SubNavWrapper'; +import makePage from '../../component/makePage'; + +const ContentLecturesSearch = ({ }) => { + const { getters, setters } = useContext(Context); + const { + content_lectures, + content_tutorials, + schedule_lectures, + schedule_tutorials, + schedule_help_sessions, + weeks, + topics, + staff, + } = getters.content; + console.log( + 'content_lectures', content_lectures, + 'content_tutorials', content_tutorials, + 'schedule_lectures', schedule_lectures, + 'schedule_tutorials', schedule_tutorials, + 'schedule_help_sessions', schedule_help_sessions, + 'weeks', weeks, + 'topics', topics, + 'staff', staff, + ); + + const week1 = weeks[0]; + console.log('week1', week1); + console.log(week1.emoji); + console.log(week1.kla); + console.log(week1.week); + console.log(week1.starts_on); + console.log('schedule lectures', week1.schedule_lectures()); + console.log('schedule help_sessions', week1.schedule_help_sessions()); + console.log('content lectures', week1.content_lectures()); + console.log('content tutorials', week1.content_tutorials()); + console.log('content tutorials first one name', week1.content_tutorials()[0].name); + console.log('content tutorials first one relevant lectures', week1.content_tutorials()[0].content_lectures()[0].name); + console.log('All lectures', content_lectures[1]); + + return <> + + +}; + +export default makePage(ContentLecturesSearch, { + loginRequired: true, + title: '', +}); \ No newline at end of file diff --git a/frontend/src/page/Content/ContentTutorialsByTopic.jsx b/frontend/src/page/Content/ContentTutorialsByTopic.jsx deleted file mode 100644 index fa99393..0000000 --- a/frontend/src/page/Content/ContentTutorialsByTopic.jsx +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react'; - -import makePage from '../../component/makePage'; -import SetOfTables from '../../component/SetOfTables'; -import { Context, useContext } from '../../context'; -import { isTinyMobileWidth } from '../../util/screen'; -import { generateContent } from './ContentTutorials.content'; - -const ContentTutorialsByTopic = ({ }) => { - const { getters } = useContext(Context); - const boxes = generateContent(getters, 'topic'); - return ; -}; - -export default makePage(ContentTutorialsByTopic, { - loginRequired: true, - title: 'Tutorial Content (By Topic)', -}); \ No newline at end of file diff --git a/frontend/src/page/Content/ContentTutorialsByWeek.jsx b/frontend/src/page/Content/ContentTutorialsByWeek.jsx deleted file mode 100644 index 521cca3..0000000 --- a/frontend/src/page/Content/ContentTutorialsByWeek.jsx +++ /dev/null @@ -1,22 +0,0 @@ -import React from 'react'; -import Box from '@mui/material/Box'; -import { Link } from 'react-router-dom'; -import Button from '@mui/material/Button'; - -import makePage from '../../component/makePage'; -import SetOfTables from '../../component/SetOfTables'; -import { Context, useContext } from '../../context'; -import { isTinyMobileWidth } from '../../util/screen'; -import { generateContent } from './ContentTutorials.content'; - -const ContentTutorialsByWeek = ({ }) => { - const { getters } = useContext(Context); - const boxes = generateContent(getters, 'week'); - - return ; -}; - -export default makePage(ContentTutorialsByWeek, { - loginRequired: true, - title: 'Tutorial Content (By Week)', -}); diff --git a/frontend/src/page/Content/ContentTutorialsSearch.jsx b/frontend/src/page/Content/ContentTutorialsSearch.jsx new file mode 100644 index 0000000..0c46031 --- /dev/null +++ b/frontend/src/page/Content/ContentTutorialsSearch.jsx @@ -0,0 +1,60 @@ +import React from 'react'; +import { useCookies } from 'react-cookie'; +import { useNavigate, useLocation } from 'react-router-dom'; +import Button from '@mui/material/Button'; +import FavoriteIcon from '@mui/icons-material/Favorite'; +import TheatersIcon from '@mui/icons-material/Theaters'; +import SchoolIcon from '@mui/icons-material/School'; +import LocalHospitalIcon from '@mui/icons-material/LocalHospital'; +import { Outlet } from 'react-router-dom'; +import { Context, useContext } from '../../context'; +import TutLecContentCard from '../../component/TutLecContentCard'; +import SubNavWrapper from '../../component/SubNavWrapper'; +import makePage from '../../component/makePage'; + +const ContentLecturesSearch = ({ }) => { + const { getters, setters } = useContext(Context); + const { + content_lectures, + content_tutorials, + schedule_lectures, + schedule_tutorials, + schedule_help_sessions, + weeks, + topics, + staff, + } = getters.content; + console.log( + 'content_lectures', content_lectures, + 'content_tutorials', content_tutorials, + 'schedule_lectures', schedule_lectures, + 'schedule_tutorials', schedule_tutorials, + 'schedule_help_sessions', schedule_help_sessions, + 'weeks', weeks, + 'topics', topics, + 'staff', staff, + ); + + const week1 = weeks[0]; + console.log('week1', week1); + console.log(week1.emoji); + console.log(week1.kla); + console.log(week1.week); + console.log(week1.starts_on); + console.log('schedule lectures', week1.schedule_lectures()); + console.log('schedule help_sessions', week1.schedule_help_sessions()); + console.log('content lectures', week1.content_lectures()); + console.log('content tutorials', week1.content_tutorials()); + console.log('content tutorials first one name', week1.content_tutorials()[0].name); + console.log('content tutorials first one relevant lectures', week1.content_tutorials()[0].content_lectures()[0].name); + console.log('All lectures', content_lectures[1]); + + return <> + + +}; + +export default makePage(ContentLecturesSearch, { + loginRequired: true, + title: '', +}); \ No newline at end of file From 8abe0d843e961c1449dc495fe6d50efddc7606af Mon Sep 17 00:00:00 2001 From: Sofia De Bellis Date: Sat, 14 Sep 2024 12:34:39 +1000 Subject: [PATCH 03/24] (feat): Cards --- frontend/src/component/TutLecContentCard.jsx | 63 +++++++-- .../page/Content/ContentLecturesSearch.jsx | 131 ++++++++++++------ .../page/Content/ContentTutorialsSearch.jsx | 46 +++--- 3 files changed, 160 insertions(+), 80 deletions(-) diff --git a/frontend/src/component/TutLecContentCard.jsx b/frontend/src/component/TutLecContentCard.jsx index ed08124..9bfc0cb 100644 --- a/frontend/src/component/TutLecContentCard.jsx +++ b/frontend/src/component/TutLecContentCard.jsx @@ -5,27 +5,64 @@ import Typography from "@mui/material/Typography"; import Chip from "@mui/material/Chip"; import { Stack } from "@mui/material"; -export default function TutLecContentCard(content) { +export default function TutLecContentCard({ + name, + contentKey, + duration_mins, + relevance, + week, + topicEmoji, + topicName +}) { + + // Function to get chip label and color based on relevance + const getRelevanceChip = (relevance) => { + switch (relevance) { + case "Mandatory": + return { label: "Mandatory", color: "success" }; + case "Catchup": + return { label: "Catchup", color: "secondary" }; + case "Recommended": + return { label: "Recommended", color: "info" }; + case "Extension": + return { label: "Extension", color: "warning" }; + default: + return { label: "Unknown", color: "default" }; + } + }; + + const relevanceChip = getRelevanceChip(relevance); + const fullWeek = "Week " + week + const topic = topicEmoji + " " + topicName return ( - + - {content.name} + {name} - {content.duration_mins} minutes + {duration_mins} minutes - - - + + + - {/* - - */} ); -} \ No newline at end of file +} diff --git a/frontend/src/page/Content/ContentLecturesSearch.jsx b/frontend/src/page/Content/ContentLecturesSearch.jsx index 0c46031..e383018 100644 --- a/frontend/src/page/Content/ContentLecturesSearch.jsx +++ b/frontend/src/page/Content/ContentLecturesSearch.jsx @@ -1,60 +1,103 @@ -import React from 'react'; -import { useCookies } from 'react-cookie'; -import { useNavigate, useLocation } from 'react-router-dom'; -import Button from '@mui/material/Button'; -import FavoriteIcon from '@mui/icons-material/Favorite'; -import TheatersIcon from '@mui/icons-material/Theaters'; -import SchoolIcon from '@mui/icons-material/School'; -import LocalHospitalIcon from '@mui/icons-material/LocalHospital'; -import { Outlet } from 'react-router-dom'; -import { Context, useContext } from '../../context'; -import TutLecContentCard from '../../component/TutLecContentCard'; -import SubNavWrapper from '../../component/SubNavWrapper'; -import makePage from '../../component/makePage'; +import React from "react"; +import { useCookies } from "react-cookie"; +import { useNavigate, useLocation } from "react-router-dom"; +import Button from "@mui/material/Button"; +import FavoriteIcon from "@mui/icons-material/Favorite"; +import TheatersIcon from "@mui/icons-material/Theaters"; +import SchoolIcon from "@mui/icons-material/School"; +import LocalHospitalIcon from "@mui/icons-material/LocalHospital"; +import { Outlet } from "react-router-dom"; +import { Context, useContext } from "../../context"; +import TutLecContentCard from "../../component/TutLecContentCard"; +import SubNavWrapper from "../../component/SubNavWrapper"; +import makePage from "../../component/makePage"; +import Box from "@mui/material/Box"; -const ContentLecturesSearch = ({ }) => { +const ContentLecturesSearch = ({}) => { const { getters, setters } = useContext(Context); const { content_lectures, content_tutorials, - schedule_lectures, - schedule_tutorials, - schedule_help_sessions, weeks, topics, - staff, } = getters.content; console.log( - 'content_lectures', content_lectures, - 'content_tutorials', content_tutorials, - 'schedule_lectures', schedule_lectures, - 'schedule_tutorials', schedule_tutorials, - 'schedule_help_sessions', schedule_help_sessions, - 'weeks', weeks, - 'topics', topics, - 'staff', staff, + "content_lectures", + content_lectures, + "content_tutorials", + content_tutorials, + "weeks", + weeks, + "topics", + topics, ); - const week1 = weeks[0]; - console.log('week1', week1); - console.log(week1.emoji); - console.log(week1.kla); - console.log(week1.week); - console.log(week1.starts_on); - console.log('schedule lectures', week1.schedule_lectures()); - console.log('schedule help_sessions', week1.schedule_help_sessions()); - console.log('content lectures', week1.content_lectures()); - console.log('content tutorials', week1.content_tutorials()); - console.log('content tutorials first one name', week1.content_tutorials()[0].name); - console.log('content tutorials first one relevant lectures', week1.content_tutorials()[0].content_lectures()[0].name); - console.log('All lectures', content_lectures[1]); + // const week1 = weeks[0]; + // console.log("week1", week1); + // console.log(week1.emoji); + // console.log(week1.kla); + // console.log(week1.week); + // console.log(week1.starts_on); + // console.log("schedule lectures", week1.schedule_lectures()); + // console.log("schedule help_sessions", week1.schedule_help_sessions()); + // console.log("content lectures", week1.content_lectures()); + // console.log("content tutorials", week1.content_tutorials()); + // console.log( + // "content tutorials first one name", + // week1.content_tutorials()[0].name + // ); + // console.log( + // "content tutorials first one relevant lectures", + // week1.content_tutorials()[0].content_lectures()[0].name + // ); + // console.log("All lectures", content_lectures[1]); - return <> - - + // return ( + // <> + // + // + // ); + console.log(topics) + + const lectures = content_lectures.slice(1); + + return ( + <> + + {lectures.map((lecture, index) => ( +
+ +
+ ))} +
+ + ); }; export default makePage(ContentLecturesSearch, { loginRequired: true, - title: '', -}); \ No newline at end of file + title: "", +}); diff --git a/frontend/src/page/Content/ContentTutorialsSearch.jsx b/frontend/src/page/Content/ContentTutorialsSearch.jsx index 0c46031..2ecf783 100644 --- a/frontend/src/page/Content/ContentTutorialsSearch.jsx +++ b/frontend/src/page/Content/ContentTutorialsSearch.jsx @@ -24,30 +24,30 @@ const ContentLecturesSearch = ({ }) => { topics, staff, } = getters.content; - console.log( - 'content_lectures', content_lectures, - 'content_tutorials', content_tutorials, - 'schedule_lectures', schedule_lectures, - 'schedule_tutorials', schedule_tutorials, - 'schedule_help_sessions', schedule_help_sessions, - 'weeks', weeks, - 'topics', topics, - 'staff', staff, - ); + // console.log( + // 'content_lectures', content_lectures, + // 'content_tutorials', content_tutorials, + // 'schedule_lectures', schedule_lectures, + // 'schedule_tutorials', schedule_tutorials, + // 'schedule_help_sessions', schedule_help_sessions, + // 'weeks', weeks, + // 'topics', topics, + // 'staff', staff, + // ); - const week1 = weeks[0]; - console.log('week1', week1); - console.log(week1.emoji); - console.log(week1.kla); - console.log(week1.week); - console.log(week1.starts_on); - console.log('schedule lectures', week1.schedule_lectures()); - console.log('schedule help_sessions', week1.schedule_help_sessions()); - console.log('content lectures', week1.content_lectures()); - console.log('content tutorials', week1.content_tutorials()); - console.log('content tutorials first one name', week1.content_tutorials()[0].name); - console.log('content tutorials first one relevant lectures', week1.content_tutorials()[0].content_lectures()[0].name); - console.log('All lectures', content_lectures[1]); + // const week1 = weeks[0]; + // console.log('week1', week1); + // console.log(week1.emoji); + // console.log(week1.kla); + // console.log(week1.week); + // console.log(week1.starts_on); + // console.log('schedule lectures', week1.schedule_lectures()); + // console.log('schedule help_sessions', week1.schedule_help_sessions()); + // console.log('content lectures', week1.content_lectures()); + // console.log('content tutorials', week1.content_tutorials()); + // console.log('content tutorials first one name', week1.content_tutorials()[0].name); + // console.log('content tutorials first one relevant lectures', week1.content_tutorials()[0].content_lectures()[0].name); + // console.log('All lectures', content_lectures[1]); return <> From 7390e5670be1e249aff64be62aad12bf96bdfe71 Mon Sep 17 00:00:00 2001 From: Sofia De Bellis Date: Sat, 14 Sep 2024 13:10:30 +1000 Subject: [PATCH 04/24] (feat0: Search bar --- .../page/Content/ContentLecturesSearch.jsx | 177 +++++++++++++++++- 1 file changed, 167 insertions(+), 10 deletions(-) diff --git a/frontend/src/page/Content/ContentLecturesSearch.jsx b/frontend/src/page/Content/ContentLecturesSearch.jsx index e383018..1bc696f 100644 --- a/frontend/src/page/Content/ContentLecturesSearch.jsx +++ b/frontend/src/page/Content/ContentLecturesSearch.jsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useState, useMemo } from "react"; import { useCookies } from "react-cookie"; import { useNavigate, useLocation } from "react-router-dom"; import Button from "@mui/material/Button"; @@ -12,15 +12,21 @@ import TutLecContentCard from "../../component/TutLecContentCard"; import SubNavWrapper from "../../component/SubNavWrapper"; import makePage from "../../component/makePage"; import Box from "@mui/material/Box"; +import { Stack } from "@mui/material"; +import TextField from "@mui/material/TextField"; +import MenuItem from "@mui/material/MenuItem"; +import Select from "@mui/material/Select"; +import InputLabel from "@mui/material/InputLabel"; +import FormControl from "@mui/material/FormControl"; +import Input from "@mui/material/Input"; +import SearchIcon from "@mui/icons-material/Search"; +import FilterListIcon from "@mui/icons-material/FilterList"; +import Modal from "@mui/material/Modal"; const ContentLecturesSearch = ({}) => { const { getters, setters } = useContext(Context); - const { - content_lectures, - content_tutorials, - weeks, - topics, - } = getters.content; + const { content_lectures, content_tutorials, weeks, topics } = + getters.content; console.log( "content_lectures", content_lectures, @@ -29,7 +35,7 @@ const ContentLecturesSearch = ({}) => { "weeks", weeks, "topics", - topics, + topics ); // const week1 = weeks[0]; @@ -61,12 +67,163 @@ const ContentLecturesSearch = ({}) => { // /> // // ); - console.log(topics) + console.log(topics); const lectures = content_lectures.slice(1); + const originalLen = lectures.length; + + const [searchQuery, setSearchQuery] = useState(""); + const [isFiltered, setIsFiltered] = useState(false); + const [filtersOpen, setFiltersOpen] = useState(false); + const [selectedWeek, setSelectedWeek] = useState(""); + const [selectedTopic, setSelectedTopic] = useState(""); + const [selectedRelevance, setSelectedRelevance] = useState(""); + + const toggleFilters = () => { + setFiltersOpen(!filtersOpen); + }; + + const applyFilters = () => { + setFiltersOpen(false); + if (filteredLectures.length !== originalLen) { + setIsFiltered(true); + } else { + setIsFiltered(false); + } + }; + + const filteredLectures = useMemo(() => { + return content_lectures.filter((lecture) => { + const nameMatch = lecture.name + ? lecture.name.toLowerCase().includes(searchQuery.toLowerCase()) + : false; + const weekMatch = !selectedWeek || lecture.week().week === selectedWeek; + const topicMatch = + !selectedTopic || lecture.topic().name === selectedTopic; + const relevanceMatch = + !selectedRelevance || lecture.relevance === selectedRelevance; + + return nameMatch && weekMatch && topicMatch && relevanceMatch; + }); + }, [ + searchQuery, + selectedWeek, + selectedTopic, + selectedRelevance, + content_lectures, + ]); return ( <> + + + } + value={searchQuery} + onChange={(event) => setSearchQuery(event.target.value)} + /> + + + + + + + + +

Filter Content

+ + + Week + + + + Topic + + + + Relevance + + + + + + + +
+
+ { mt: 3, }} > - {lectures.map((lecture, index) => ( + {filteredLectures.map((lecture, index) => (
Date: Sat, 14 Sep 2024 13:53:48 +1000 Subject: [PATCH 05/24] (style): autoformatter --- frontend/src/component/TutLecContentCard.jsx | 17 +- frontend/src/page/Content/ContentBase.jsx | 10 +- frontend/src/page/Content/ContentLectures.jsx | 35 +- .../page/Content/ContentLecturesSearch.jsx | 4 +- .../page/Content/ContentLecturesSingle.jsx | 315 +++++++++++------- .../page/Content/ContentTutorials.content.jsx | 73 ++-- .../src/page/Content/ContentTutorials.jsx | 36 +- .../page/Content/ContentTutorialsSearch.jsx | 44 +-- .../page/Content/ContentTutorialsSingle.jsx | 106 ++++-- 9 files changed, 389 insertions(+), 251 deletions(-) diff --git a/frontend/src/component/TutLecContentCard.jsx b/frontend/src/component/TutLecContentCard.jsx index 9bfc0cb..ceea170 100644 --- a/frontend/src/component/TutLecContentCard.jsx +++ b/frontend/src/component/TutLecContentCard.jsx @@ -12,9 +12,8 @@ export default function TutLecContentCard({ relevance, week, topicEmoji, - topicName + topicName, }) { - // Function to get chip label and color based on relevance const getRelevanceChip = (relevance) => { switch (relevance) { @@ -23,17 +22,17 @@ export default function TutLecContentCard({ case "Catchup": return { label: "Catchup", color: "secondary" }; case "Recommended": - return { label: "Recommended", color: "info" }; + return { label: "Recommended", color: "info" }; case "Extension": - return { label: "Extension", color: "warning" }; + return { label: "Extension", color: "warning" }; default: - return { label: "Unknown", color: "default" }; + return { label: "Unknown", color: "default" }; } }; const relevanceChip = getRelevanceChip(relevance); - const fullWeek = "Week " + week - const topic = topicEmoji + " " + topicName + const fullWeek = "Week " + week; + const topic = topicEmoji + " " + topicName; return ( - {name} + {name} {duration_mins} minutes diff --git a/frontend/src/page/Content/ContentBase.jsx b/frontend/src/page/Content/ContentBase.jsx index c3d89e4..a452742 100644 --- a/frontend/src/page/Content/ContentBase.jsx +++ b/frontend/src/page/Content/ContentBase.jsx @@ -1,9 +1,9 @@ -import React from 'react'; -import { Outlet } from 'react-router-dom'; +import React from "react"; +import { Outlet } from "react-router-dom"; -import makePage from '../../component/makePage'; +import makePage from "../../component/makePage"; -const ContentBase = ({ }) => { +const ContentBase = ({}) => { return ( <> @@ -11,4 +11,4 @@ const ContentBase = ({ }) => { ); }; -export default ContentBase; \ No newline at end of file +export default ContentBase; diff --git a/frontend/src/page/Content/ContentLectures.jsx b/frontend/src/page/Content/ContentLectures.jsx index 022bfa5..61e3765 100644 --- a/frontend/src/page/Content/ContentLectures.jsx +++ b/frontend/src/page/Content/ContentLectures.jsx @@ -1,37 +1,30 @@ -import React from 'react'; -import { useCookies } from 'react-cookie'; -import { useNavigate, useLocation } from 'react-router-dom'; -import Button from '@mui/material/Button'; -import FavoriteIcon from '@mui/icons-material/Favorite'; -import TheatersIcon from '@mui/icons-material/Theaters'; -import SchoolIcon from '@mui/icons-material/School'; -import LocalHospitalIcon from '@mui/icons-material/LocalHospital'; -import { Outlet } from 'react-router-dom'; +import React from "react"; +import { useCookies } from "react-cookie"; +import { useNavigate, useLocation } from "react-router-dom"; +import TheatersIcon from "@mui/icons-material/Theaters"; +import SchoolIcon from "@mui/icons-material/School"; +import { Outlet } from "react-router-dom"; -import SubNavWrapper from '../../component/SubNavWrapper'; - -import makePage from '../../component/makePage'; -import TutLecContentCard from '../../component/TutLecContentCard'; - -const ContentLectures = ({ }) => { +import SubNavWrapper from "../../component/SubNavWrapper"; +const ContentLectures = ({}) => { const menu = [ { - title: 'By Week', + title: "By Week", icon: , - subRoute: 'week', + subRoute: "week", }, { - title: 'By Topic', + title: "By Topic", icon: , - subRoute: 'topic', + subRoute: "topic", }, ]; return ( - + ); }; -export default ContentLectures; \ No newline at end of file +export default ContentLectures; diff --git a/frontend/src/page/Content/ContentLecturesSearch.jsx b/frontend/src/page/Content/ContentLecturesSearch.jsx index 1bc696f..1b5833f 100644 --- a/frontend/src/page/Content/ContentLecturesSearch.jsx +++ b/frontend/src/page/Content/ContentLecturesSearch.jsx @@ -173,7 +173,6 @@ const ContentLecturesSearch = ({}) => { onChange={(event) => setSelectedWeek(event.target.value)} label="Week" > - None {weeks.map((week) => ( {week.week} @@ -189,7 +188,6 @@ const ContentLecturesSearch = ({}) => { onChange={(event) => setSelectedTopic(event.target.value)} label="Topic" > - None {topics.map((topic) => ( {topic.name} @@ -205,7 +203,6 @@ const ContentLecturesSearch = ({}) => { onChange={(event) => setSelectedRelevance(event.target.value)} label="Relevance" > - None Mandatory Catchup Recommended @@ -231,6 +228,7 @@ const ContentLecturesSearch = ({}) => { xs: "repeat(1, 1fr)", sm: "repeat(2, 1fr)", lg: "repeat(3, 1fr)", + xl: "repeat(4, 1fr)", }, gap: 2, mt: 3, diff --git a/frontend/src/page/Content/ContentLecturesSingle.jsx b/frontend/src/page/Content/ContentLecturesSingle.jsx index da92087..c3ffde4 100644 --- a/frontend/src/page/Content/ContentLecturesSingle.jsx +++ b/frontend/src/page/Content/ContentLecturesSingle.jsx @@ -1,38 +1,40 @@ -import { HashLink as Link } from 'react-router-hash-link'; -import React from 'react'; -import { useCookies } from 'react-cookie'; -import { useNavigate, useLocation, useParams } from 'react-router-dom'; -import Button from '@mui/material/Button'; -import Box from '@mui/material/Box'; -import FavoriteIcon from '@mui/icons-material/Favorite'; -import TheatersIcon from '@mui/icons-material/Theaters'; -import SchoolIcon from '@mui/icons-material/School'; -import LocalHospitalIcon from '@mui/icons-material/LocalHospital'; - -import Typography from '@mui/material/Typography'; -import Accordion from '@mui/material/Accordion'; -import AccordionSummary from '@mui/material/AccordionSummary'; -import AccordionDetails from '@mui/material/AccordionDetails'; - -import SubNavWrapper from '../../component/SubNavWrapper'; -import ContentCards from '../../component/ContentCards'; -import makePage from '../../component/makePage'; -import { Context, useContext } from '../../context'; -import Youtube from '../../component/Youtube'; -import { getYoutubeCodeFromUrl } from '../../util/content'; -import TitleCard from '../../component/TitleCard'; -import SectionHeader from '../../component/SectionHeader'; +import { HashLink as Link } from "react-router-hash-link"; +import React from "react"; +import { useCookies } from "react-cookie"; +import { useNavigate, useLocation, useParams } from "react-router-dom"; +import Button from "@mui/material/Button"; +import Box from "@mui/material/Box"; +import FavoriteIcon from "@mui/icons-material/Favorite"; +import TheatersIcon from "@mui/icons-material/Theaters"; +import SchoolIcon from "@mui/icons-material/School"; +import LocalHospitalIcon from "@mui/icons-material/LocalHospital"; + +import Typography from "@mui/material/Typography"; +import Accordion from "@mui/material/Accordion"; +import AccordionSummary from "@mui/material/AccordionSummary"; +import AccordionDetails from "@mui/material/AccordionDetails"; + +import SubNavWrapper from "../../component/SubNavWrapper"; +import ContentCards from "../../component/ContentCards"; +import makePage from "../../component/makePage"; +import { Context, useContext } from "../../context"; +import Youtube from "../../component/Youtube"; +import { getYoutubeCodeFromUrl } from "../../util/content"; +import TitleCard from "../../component/TitleCard"; +import SectionHeader from "../../component/SectionHeader"; const ContentLecturesSingle = ({}) => { const { getters, setters } = useContext(Context); const navigate = useNavigate(); - const [ lecture, setLecture ] = React.useState(null); - const [ relatedLectures, setRelatedLectures ] = React.useState([]); - const [ relatedTutes, setRelatedTutes ] = React.useState([]); + const [lecture, setLecture] = React.useState(null); + const [relatedLectures, setRelatedLectures] = React.useState([]); + const [relatedTutes, setRelatedTutes] = React.useState([]); const params = useParams(); React.useEffect(() => { - const candidates = getters.content.content_lectures.filter(c => c.key === params.lecid); + const candidates = getters.content.content_lectures.filter( + (c) => c.key === params.lecid + ); if (candidates.length === 1) { setLecture(candidates[0]); } @@ -43,106 +45,195 @@ const ContentLecturesSingle = ({}) => { setters.setTitle(`Lecture: ${lecture.name}`); const rl = [ - ...(lecture.lectures_prereq ? lecture.lectures_prereq() : []).map(l => ({ ...l, label: 'Watch first', labelBackground: 'rgb(248,139,139)' })), - ...(getters.content.content_lectures.filter(l => - l.lectures_prereq && l.lectures_prereq().map(lp => lp.key).includes(lecture.key) - )).map(l => ({ ...l, label: 'Up Next', labelBackground: 'rgb(175,239,148)' })) + ...(lecture.lectures_prereq ? lecture.lectures_prereq() : []).map( + (l) => ({ + ...l, + label: "Watch first", + labelBackground: "rgb(248,139,139)", + }) + ), + ...getters.content.content_lectures + .filter( + (l) => + l.lectures_prereq && + l + .lectures_prereq() + .map((lp) => lp.key) + .includes(lecture.key) + ) + .map((l) => ({ + ...l, + label: "Up Next", + labelBackground: "rgb(175,239,148)", + })), ]; - setRelatedLectures(rl.map(lec => ({ - title: lec.name, - linkUrl: `/${getters.term}/content/lectures/${lec.key}`, - imageUrl: `https://img.youtube.com/vi/${lec.video ? getYoutubeCodeFromUrl(lec.video) : ''}/hqdefault.jpg`, - description: lec.description, - staff: lec.staff().map(s => s.name).join(', '), - weektopic: `${lec.week().week === 11 ? 'Extra' : 'Week ' + lec.week().week} ${lec.topic().emoji} - ${lec.topic().name}`, - duration: lec.duration_mins, - label: lec.label, - labelBackground: lec.labelBackground, - }))); + setRelatedLectures( + rl.map((lec) => ({ + title: lec.name, + linkUrl: `/${getters.term}/content/lectures/${lec.key}`, + imageUrl: `https://img.youtube.com/vi/${ + lec.video ? getYoutubeCodeFromUrl(lec.video) : "" + }/hqdefault.jpg`, + description: lec.description, + staff: lec + .staff() + .map((s) => s.name) + .join(", "), + weektopic: `${ + lec.week().week === 11 ? "Extra" : "Week " + lec.week().week + } ${lec.topic().emoji} - ${lec.topic().name}`, + duration: lec.duration_mins, + label: lec.label, + labelBackground: lec.labelBackground, + })) + ); if (lecture.content_tutorials) { - setRelatedTutes(lecture.content_tutorials().map((tutorial, key) => ({ - title: tutorial.key, - description: tutorial.name, - linkUrl: `/${getters.term}/content/tutorials/${tutorial.key}`, - }))); + setRelatedTutes( + lecture.content_tutorials().map((tutorial, key) => ({ + title: tutorial.key, + description: tutorial.name, + linkUrl: `/${getters.term}/content/tutorials/${tutorial.key}`, + })) + ); } else { setRelatedTutes([]); } } - }, [lecture]); if (!lecture) { return <>; } - return <> - - -
- - {lecture.topic().emoji} {lecture.name}   (part of {lecture.topic().name} in {lecture.topic().area().name}) - - - - Duration: {lecture.duration_mins} minutes ⏱️ - - - Author(s): {lecture.staff().map(s => s.name).join(', ')} - - - Description: {lecture.description} - - - Access the code used in the lecture here (may be blank). - - - Should watch no later than end of week {lecture.week().week} - - {lecture.schedule_lectures && ( + return ( + <> + + +
+ + {lecture.topic().emoji} {lecture.name}   (part of{" "} + + {lecture.topic().name} + {" "} + in {lecture.topic().area().name}) + + - {lecture.schedule_lectures().map(r => ( - <> - This lecture is a live lecture. Join the lecture here at {r.time} {r.day} in week {r.week().week} - - ))} - )} - - - {lecture.visible - ? - : - } - - - - {lecture.video && lecture.visible - ? - :
Check back later!
- } -
-
- - {relatedLectures.length > 0 && ( - <> - Related Lectures - - - )} - - {relatedTutes.length > 0 && ( - <> - Now you're ready for these exercises - - - )} - - ; + Duration: {lecture.duration_mins} minutes ⏱️ +
+ + Author(s):{" "} + {lecture + .staff() + .map((s) => s.name) + .join(", ")} + + + Description: {lecture.description} + + + + Access the code used in the lecture here (may be blank). + + + + Should watch no later than end of{" "} + + week {lecture.week().week} + + + {lecture.schedule_lectures && ( + + {lecture.schedule_lectures().map((r) => ( + <> + This lecture is a live lecture. Join the lecture{" "} + + here + {" "} + at {r.time} {r.day} in week {r.week().week} + + ))} + + )} + + + {lecture.visible ? ( + + + + ) : ( + + )} + + + + {lecture.video && lecture.visible ? ( + + ) : ( +
+ Check back later! +
+ )} +
+
+ + {relatedLectures.length > 0 && ( + <> + Related Lectures + + + )} + + {relatedTutes.length > 0 && ( + <> + Now you're ready for these exercises + + + )} + + ); }; export default makePage(ContentLecturesSingle, { loginRequired: true, - title: '', -}); \ No newline at end of file + title: "", +}); diff --git a/frontend/src/page/Content/ContentTutorials.content.jsx b/frontend/src/page/Content/ContentTutorials.content.jsx index fb4d2d6..d36886f 100644 --- a/frontend/src/page/Content/ContentTutorials.content.jsx +++ b/frontend/src/page/Content/ContentTutorials.content.jsx @@ -1,29 +1,43 @@ -import Button from '@mui/material/Button'; -import config from '../../config'; +import Button from "@mui/material/Button"; +import config from "../../config"; -import { isHalfScreenWidth, isTinyMobileWidth, isMobileWidth, isBigDesktopWidth, isDesktopWidth } from '../../util/screen'; +import { + isHalfScreenWidth, + isTinyMobileWidth, + isMobileWidth, + isBigDesktopWidth, + isDesktopWidth, +} from "../../util/screen"; export const generateContent = (getters, by) => { - const opposingPageType = (by === 'week') ? 'topic' : 'week'; - const secondColumnName = (by === 'week') ? 'Topic' : 'Week'; - const boxName = (by === 'week') - ? grouping => `Week ${grouping.week}` - : grouping => `${grouping.emoji} ${grouping.area().name}: ${grouping.name}`; - const boxKey = (by === 'week') - ? grouping => grouping.week - : grouping => grouping.name; - const secondColumnValue = (by === 'week') - ? tutorial => tutorial.topic ? `${tutorial.topic().emoji} ${tutorial.topic().name}` : '' - : tutorial => `📅 ${tutorial.week().week === 11 ? 'Extra' : tutorial.week().week}`; - const outerList = (by === 'week') - ? getters.content.weeks.filter(w => w.week != 6 && w.week <= 10) - : getters.content.topics.filter(t => t.name !== 'Admin'); - const secondColumnAnchor = (by === 'week') - ? tutorial => tutorial.topic().name - : tutorial => tutorial.week().week; + const opposingPageType = by === "week" ? "topic" : "week"; + const secondColumnName = by === "week" ? "Topic" : "Week"; + const boxName = + by === "week" + ? (grouping) => `Week ${grouping.week}` + : (grouping) => + `${grouping.emoji} ${grouping.area().name}: ${grouping.name}`; + const boxKey = + by === "week" ? (grouping) => grouping.week : (grouping) => grouping.name; + const secondColumnValue = + by === "week" + ? (tutorial) => + tutorial.topic + ? `${tutorial.topic().emoji} ${tutorial.topic().name}` + : "" + : (tutorial) => + `📅 ${tutorial.week().week === 11 ? "Extra" : tutorial.week().week}`; + const outerList = + by === "week" + ? getters.content.weeks.filter((w) => w.week != 6 && w.week <= 10) + : getters.content.topics.filter((t) => t.name !== "Admin"); + const secondColumnAnchor = + by === "week" + ? (tutorial) => tutorial.topic().name + : (tutorial) => tutorial.week().week; const boxes = []; - outerList.forEach(grouping => { + outerList.forEach((grouping) => { const table = []; if (grouping.content_tutorials) { grouping.content_tutorials().sort((a, b) => a.order - b.order).forEach(tutorial => { @@ -44,12 +58,12 @@ export const generateContent = (getters, by) => { key: boxKey(grouping), maxWidth: 1100, headers: [ - { name: 'Name', width: 32, }, - { name: secondColumnName, width: 15, }, - { name: 'Duration', width: 11, showFn: () => isDesktopWidth(), }, - { name: 'Stream', width: 10, showFn: () => isBigDesktopWidth(), }, - { name: 'Importance', width: 22, showFn: () => !isMobileWidth(), }, - { name: 'Activity', width: 10, }, + { name: "Name", width: 32 }, + { name: secondColumnName, width: 15 }, + { name: "Duration", width: 11, showFn: () => isDesktopWidth() }, + { name: "Stream", width: 10, showFn: () => isBigDesktopWidth() }, + { name: "Importance", width: 22, showFn: () => !isMobileWidth() }, + { name: "Activity", width: 10 }, ], table, }); @@ -57,8 +71,7 @@ export const generateContent = (getters, by) => { return boxes; }; - - /*const boxes = []; +/*const boxes = []; getters.content.topics.filter(t => t.name !== 'Admin').forEach(topic => { const table = []; if (topic.content_tutorials) { @@ -111,4 +124,4 @@ export const generateContent = (getters, by) => { ], table, }); - });*/ \ No newline at end of file + });*/ diff --git a/frontend/src/page/Content/ContentTutorials.jsx b/frontend/src/page/Content/ContentTutorials.jsx index 8bcc1a1..d746ec8 100644 --- a/frontend/src/page/Content/ContentTutorials.jsx +++ b/frontend/src/page/Content/ContentTutorials.jsx @@ -1,35 +1,35 @@ -import React from 'react'; -import { useCookies } from 'react-cookie'; -import { useNavigate, useLocation } from 'react-router-dom'; -import Button from '@mui/material/Button'; -import FavoriteIcon from '@mui/icons-material/Favorite'; -import TheatersIcon from '@mui/icons-material/Theaters'; -import SchoolIcon from '@mui/icons-material/School'; -import LocalHospitalIcon from '@mui/icons-material/LocalHospital'; -import { Outlet } from 'react-router-dom'; +import React from "react"; +import { useCookies } from "react-cookie"; +import { useNavigate, useLocation } from "react-router-dom"; +import Button from "@mui/material/Button"; +import FavoriteIcon from "@mui/icons-material/Favorite"; +import TheatersIcon from "@mui/icons-material/Theaters"; +import SchoolIcon from "@mui/icons-material/School"; +import LocalHospitalIcon from "@mui/icons-material/LocalHospital"; +import { Outlet } from "react-router-dom"; -import SubNavWrapper from '../../component/SubNavWrapper'; -import makePage from '../../component/makePage'; +import SubNavWrapper from "../../component/SubNavWrapper"; +import makePage from "../../component/makePage"; -const ContentTutorials = ({ }) => { +const ContentTutorials = ({}) => { const menu = [ { - title: 'By Week', + title: "By Week", icon: , - subRoute: 'week', + subRoute: "week", }, { - title: 'By Topic', + title: "By Topic", icon: , - subRoute: 'topic', + subRoute: "topic", }, ]; return ( - + ); }; -export default ContentTutorials; \ No newline at end of file +export default ContentTutorials; diff --git a/frontend/src/page/Content/ContentTutorialsSearch.jsx b/frontend/src/page/Content/ContentTutorialsSearch.jsx index 2ecf783..d9d8a3b 100644 --- a/frontend/src/page/Content/ContentTutorialsSearch.jsx +++ b/frontend/src/page/Content/ContentTutorialsSearch.jsx @@ -1,18 +1,18 @@ -import React from 'react'; -import { useCookies } from 'react-cookie'; -import { useNavigate, useLocation } from 'react-router-dom'; -import Button from '@mui/material/Button'; -import FavoriteIcon from '@mui/icons-material/Favorite'; -import TheatersIcon from '@mui/icons-material/Theaters'; -import SchoolIcon from '@mui/icons-material/School'; -import LocalHospitalIcon from '@mui/icons-material/LocalHospital'; -import { Outlet } from 'react-router-dom'; -import { Context, useContext } from '../../context'; -import TutLecContentCard from '../../component/TutLecContentCard'; -import SubNavWrapper from '../../component/SubNavWrapper'; -import makePage from '../../component/makePage'; +import React from "react"; +import { useCookies } from "react-cookie"; +import { useNavigate, useLocation } from "react-router-dom"; +import Button from "@mui/material/Button"; +import FavoriteIcon from "@mui/icons-material/Favorite"; +import TheatersIcon from "@mui/icons-material/Theaters"; +import SchoolIcon from "@mui/icons-material/School"; +import LocalHospitalIcon from "@mui/icons-material/LocalHospital"; +import { Outlet } from "react-router-dom"; +import { Context, useContext } from "../../context"; +import TutLecContentCard from "../../component/TutLecContentCard"; +import SubNavWrapper from "../../component/SubNavWrapper"; +import makePage from "../../component/makePage"; -const ContentLecturesSearch = ({ }) => { +const ContentLecturesSearch = ({}) => { const { getters, setters } = useContext(Context); const { content_lectures, @@ -49,12 +49,18 @@ const ContentLecturesSearch = ({ }) => { // console.log('content tutorials first one relevant lectures', week1.content_tutorials()[0].content_lectures()[0].name); // console.log('All lectures', content_lectures[1]); - return <> - - + return ( + <> + + + ); }; export default makePage(ContentLecturesSearch, { loginRequired: true, - title: '', -}); \ No newline at end of file + title: "", +}); diff --git a/frontend/src/page/Content/ContentTutorialsSingle.jsx b/frontend/src/page/Content/ContentTutorialsSingle.jsx index 78373ff..a345410 100644 --- a/frontend/src/page/Content/ContentTutorialsSingle.jsx +++ b/frontend/src/page/Content/ContentTutorialsSingle.jsx @@ -1,31 +1,33 @@ -import { HashLink as Link } from 'react-router-hash-link'; -import React from 'react'; -import { useNavigate, useLocation, useParams } from 'react-router-dom'; -import Button from '@mui/material/Button'; -import Box from '@mui/material/Box'; +import { HashLink as Link } from "react-router-hash-link"; +import React from "react"; +import { useNavigate, useLocation, useParams } from "react-router-dom"; +import Button from "@mui/material/Button"; +import Box from "@mui/material/Box"; -import Typography from '@mui/material/Typography'; -import Accordion from '@mui/material/Accordion'; -import AccordionSummary from '@mui/material/AccordionSummary'; -import AccordionDetails from '@mui/material/AccordionDetails'; +import Typography from "@mui/material/Typography"; +import Accordion from "@mui/material/Accordion"; +import AccordionSummary from "@mui/material/AccordionSummary"; +import AccordionDetails from "@mui/material/AccordionDetails"; -import ContentCards from '../../component/ContentCards'; -import makePage from '../../component/makePage'; -import { Context, useContext } from '../../context'; -import Youtube from '../../component/Youtube'; -import { getYoutubeCodeFromUrl } from '../../util/content'; -import TitleCard from '../../component/TitleCard'; -import SectionHeader from '../../component/SectionHeader'; -import config from '../../config'; +import ContentCards from "../../component/ContentCards"; +import makePage from "../../component/makePage"; +import { Context, useContext } from "../../context"; +import Youtube from "../../component/Youtube"; +import { getYoutubeCodeFromUrl } from "../../util/content"; +import TitleCard from "../../component/TitleCard"; +import SectionHeader from "../../component/SectionHeader"; +import config from "../../config"; const ContentTutorialsSingle = () => { const { getters, setters } = useContext(Context); const navigate = useNavigate(); - const [ tutorial, setTutorial ] = React.useState(null); + const [tutorial, setTutorial] = React.useState(null); const params = useParams(); React.useEffect(() => { - const candidates = getters.content.content_tutorials.filter(c => c.key === params.tutid); + const candidates = getters.content.content_tutorials.filter( + (c) => c.key === params.tutid + ); if (candidates.length === 1) { setTutorial(candidates[0]); } @@ -43,10 +45,20 @@ const ContentTutorialsSingle = () => { return ( <> - + - {tutorial.topic().emoji} {tutorial.key}   (part of {tutorial.topic().name} in {tutorial.topic().area().name}) + {tutorial.topic().emoji} {tutorial.key}   (part of{" "} + + {tutorial.topic().name} + {" "} + in {tutorial.topic().area().name}) @@ -68,27 +80,53 @@ const ContentTutorialsSingle = () => { - + - {tutorial.video_author && Tutor who recorded: {tutorial.video_author().name}} - {tutorial.video_url - ? - :
Recording not yet released.
- } + {tutorial.video_author && ( + + Tutor who recorded: {tutorial.video_author().name} + + )} + {tutorial.video_url ? ( + + ) : ( +
+ Recording not yet released. +
+ )}
- ); - return <>hello; + return <>hello; }; export default makePage(ContentTutorialsSingle, { loginRequired: true, - title: '', -});; \ No newline at end of file + title: "", +}); From 29e146b3ccdddd15769c98865b9154fc68704430 Mon Sep 17 00:00:00 2001 From: Sofia De Bellis Date: Sat, 14 Sep 2024 14:56:56 +1000 Subject: [PATCH 06/24] (feat): Add tutorials and filters --- frontend/src/component/TutLecContentCard.jsx | 69 ++-- .../page/Content/ContentLecturesSearch.jsx | 228 ++++++++------ .../page/Content/ContentTutorialsSearch.jsx | 295 ++++++++++++++---- 3 files changed, 423 insertions(+), 169 deletions(-) diff --git a/frontend/src/component/TutLecContentCard.jsx b/frontend/src/component/TutLecContentCard.jsx index ceea170..6ff30b8 100644 --- a/frontend/src/component/TutLecContentCard.jsx +++ b/frontend/src/component/TutLecContentCard.jsx @@ -13,33 +13,49 @@ export default function TutLecContentCard({ week, topicEmoji, topicName, + lecture, }) { // Function to get chip label and color based on relevance const getRelevanceChip = (relevance) => { - switch (relevance) { - case "Mandatory": - return { label: "Mandatory", color: "success" }; - case "Catchup": - return { label: "Catchup", color: "secondary" }; - case "Recommended": - return { label: "Recommended", color: "info" }; - case "Extension": - return { label: "Extension", color: "warning" }; - default: - return { label: "Unknown", color: "default" }; + if (lecture) { + switch (relevance) { + case "Mandatory": + return { label: "Mandatory", color: "success" }; + case "Catchup": + return { label: "Catchup", color: "secondary" }; + case "Recommended": + return { label: "Recommended", color: "info" }; + case "Extension": + return { label: "Extension", color: "warning" }; + default: + return { label: "Unknown", color: "default" }; + } + } else { + switch (relevance) { + case "COMPULSORY": + return { label: "Compulsory", color: "success" }; + case "REFINING": + return { label: "Refining", color: "info" }; + case "EXTENDED": + return { label: "Extended", color: "warning" }; + default: + return { label: "Unknown", color: "default" }; + } } }; const relevanceChip = getRelevanceChip(relevance); const fullWeek = "Week " + week; const topic = topicEmoji + " " + topicName; + return ( - + {name} {duration_mins} minutes - - - - - + + + + + ); } diff --git a/frontend/src/page/Content/ContentLecturesSearch.jsx b/frontend/src/page/Content/ContentLecturesSearch.jsx index 1b5833f..7cf94ab 100644 --- a/frontend/src/page/Content/ContentLecturesSearch.jsx +++ b/frontend/src/page/Content/ContentLecturesSearch.jsx @@ -1,117 +1,95 @@ import React, { useState, useMemo } from "react"; import { useCookies } from "react-cookie"; import { useNavigate, useLocation } from "react-router-dom"; -import Button from "@mui/material/Button"; -import FavoriteIcon from "@mui/icons-material/Favorite"; -import TheatersIcon from "@mui/icons-material/Theaters"; -import SchoolIcon from "@mui/icons-material/School"; -import LocalHospitalIcon from "@mui/icons-material/LocalHospital"; -import { Outlet } from "react-router-dom"; import { Context, useContext } from "../../context"; import TutLecContentCard from "../../component/TutLecContentCard"; -import SubNavWrapper from "../../component/SubNavWrapper"; import makePage from "../../component/makePage"; -import Box from "@mui/material/Box"; -import { Stack } from "@mui/material"; -import TextField from "@mui/material/TextField"; -import MenuItem from "@mui/material/MenuItem"; -import Select from "@mui/material/Select"; -import InputLabel from "@mui/material/InputLabel"; -import FormControl from "@mui/material/FormControl"; -import Input from "@mui/material/Input"; +import { + Box, + Button, + FormControlLabel, + Checkbox, + Modal, + Input, + FormControl, + InputLabel, + Select, + Stack, + Tooltip, + MenuItem, + IconButton, +} from "@mui/material"; import SearchIcon from "@mui/icons-material/Search"; import FilterListIcon from "@mui/icons-material/FilterList"; -import Modal from "@mui/material/Modal"; +import InfoIcon from "@mui/icons-material/Info"; const ContentLecturesSearch = ({}) => { const { getters, setters } = useContext(Context); const { content_lectures, content_tutorials, weeks, topics } = getters.content; - console.log( - "content_lectures", - content_lectures, - "content_tutorials", - content_tutorials, - "weeks", - weeks, - "topics", - topics - ); - - // const week1 = weeks[0]; - // console.log("week1", week1); - // console.log(week1.emoji); - // console.log(week1.kla); - // console.log(week1.week); - // console.log(week1.starts_on); - // console.log("schedule lectures", week1.schedule_lectures()); - // console.log("schedule help_sessions", week1.schedule_help_sessions()); - // console.log("content lectures", week1.content_lectures()); - // console.log("content tutorials", week1.content_tutorials()); - // console.log( - // "content tutorials first one name", - // week1.content_tutorials()[0].name - // ); - // console.log( - // "content tutorials first one relevant lectures", - // week1.content_tutorials()[0].content_lectures()[0].name - // ); - // console.log("All lectures", content_lectures[1]); - - // return ( - // <> - // - // - // ); - console.log(topics); - - const lectures = content_lectures.slice(1); - const originalLen = lectures.length; const [searchQuery, setSearchQuery] = useState(""); const [isFiltered, setIsFiltered] = useState(false); const [filtersOpen, setFiltersOpen] = useState(false); - const [selectedWeek, setSelectedWeek] = useState(""); - const [selectedTopic, setSelectedTopic] = useState(""); - const [selectedRelevance, setSelectedRelevance] = useState(""); + const [filters, setFilters] = useState({ + selectedWeek: "", + selectedTopic: "", + selectedRelevance: "workHard", + completedCOMP1531: true, + }); + const [tempFilters, setTempFilters] = useState({ + selectedWeek: "", + selectedTopic: "", + selectedRelevance: "workHard", + completedCOMP1531: true, + }); const toggleFilters = () => { setFiltersOpen(!filtersOpen); }; const applyFilters = () => { + setFilters(tempFilters); setFiltersOpen(false); - if (filteredLectures.length !== originalLen) { - setIsFiltered(true); - } else { - setIsFiltered(false); - } + setIsFiltered( + tempFilters.selectedRelevance !== "" || + tempFilters.selectedTopic !== "" || + tempFilters.selectedWeek !== "" + ); }; const filteredLectures = useMemo(() => { - return content_lectures.filter((lecture) => { + const getRelevanceOptions = () => { + if (!filters.completedCOMP1531) { + return ["Mandatory", "Catchup"]; + } + switch (filters.selectedRelevance) { + case "bareMinimum": + return ["Mandatory"]; + case "workHard": + return ["Mandatory", "Recommended"]; + case "learnEverything": + return ["Mandatory", "Recommended", "Extension"]; + default: + return []; + } + }; + + const relevanceOptions = getRelevanceOptions(); + return content_lectures.slice(1).filter((lecture) => { const nameMatch = lecture.name ? lecture.name.toLowerCase().includes(searchQuery.toLowerCase()) : false; - const weekMatch = !selectedWeek || lecture.week().week === selectedWeek; + const weekMatch = + !filters.selectedWeek || lecture.week().week === filters.selectedWeek; const topicMatch = - !selectedTopic || lecture.topic().name === selectedTopic; - const relevanceMatch = - !selectedRelevance || lecture.relevance === selectedRelevance; + !filters.selectedTopic || + lecture.topic().name === filters.selectedTopic; + const relevanceMatch = relevanceOptions.includes(lecture.relevance); return nameMatch && weekMatch && topicMatch && relevanceMatch; }); - }, [ - searchQuery, - selectedWeek, - selectedTopic, - selectedRelevance, - content_lectures, - ]); + }, [content_lectures, filters, searchQuery]); return ( <> @@ -122,25 +100,40 @@ const ContentLecturesSearch = ({}) => { gap={2} borderRadius="sm" > - + } + variant="outlined" value={searchQuery} onChange={(event) => setSearchQuery(event.target.value)} + InputProps={{ + startAdornment: , + }} /> + + + { Week setSelectedTopic(event.target.value)} + value={tempFilters.selectedTopic} + onChange={(event) => + setTempFilters((prevFilters) => ({ + ...prevFilters, + selectedTopic: event.target.value, + })) + } label="Topic" > + All {topics.map((topic) => ( {topic.name} @@ -199,16 +204,48 @@ const ContentLecturesSearch = ({}) => { Relevance + + + setTempFilters((prevFilters) => ({ + ...prevFilters, + completedCOMP1531: event.target.checked, + })) + } + /> + } + label="I completed COMP1531" + sx={{ mr: 0 }} + /> + + + + + +
))} diff --git a/frontend/src/page/Content/ContentTutorialsSearch.jsx b/frontend/src/page/Content/ContentTutorialsSearch.jsx index d9d8a3b..fb3160d 100644 --- a/frontend/src/page/Content/ContentTutorialsSearch.jsx +++ b/frontend/src/page/Content/ContentTutorialsSearch.jsx @@ -1,66 +1,253 @@ -import React from "react"; +import React, { useState, useMemo } from "react"; import { useCookies } from "react-cookie"; import { useNavigate, useLocation } from "react-router-dom"; -import Button from "@mui/material/Button"; -import FavoriteIcon from "@mui/icons-material/Favorite"; -import TheatersIcon from "@mui/icons-material/Theaters"; -import SchoolIcon from "@mui/icons-material/School"; -import LocalHospitalIcon from "@mui/icons-material/LocalHospital"; -import { Outlet } from "react-router-dom"; import { Context, useContext } from "../../context"; import TutLecContentCard from "../../component/TutLecContentCard"; -import SubNavWrapper from "../../component/SubNavWrapper"; import makePage from "../../component/makePage"; +import { + Box, + Button, + FormControlLabel, + Modal, + Input, + FormControl, + InputLabel, + Select, + Stack, + MenuItem, +} from "@mui/material"; +import SearchIcon from "@mui/icons-material/Search"; +import FilterListIcon from "@mui/icons-material/FilterList"; -const ContentLecturesSearch = ({}) => { +const ContentTutorialsSearch = ({}) => { const { getters, setters } = useContext(Context); - const { - content_lectures, - content_tutorials, - schedule_lectures, - schedule_tutorials, - schedule_help_sessions, - weeks, - topics, - staff, - } = getters.content; - // console.log( - // 'content_lectures', content_lectures, - // 'content_tutorials', content_tutorials, - // 'schedule_lectures', schedule_lectures, - // 'schedule_tutorials', schedule_tutorials, - // 'schedule_help_sessions', schedule_help_sessions, - // 'weeks', weeks, - // 'topics', topics, - // 'staff', staff, - // ); + const { content_tutorials, weeks, topics } = + getters.content; - // const week1 = weeks[0]; - // console.log('week1', week1); - // console.log(week1.emoji); - // console.log(week1.kla); - // console.log(week1.week); - // console.log(week1.starts_on); - // console.log('schedule lectures', week1.schedule_lectures()); - // console.log('schedule help_sessions', week1.schedule_help_sessions()); - // console.log('content lectures', week1.content_lectures()); - // console.log('content tutorials', week1.content_tutorials()); - // console.log('content tutorials first one name', week1.content_tutorials()[0].name); - // console.log('content tutorials first one relevant lectures', week1.content_tutorials()[0].content_lectures()[0].name); - // console.log('All lectures', content_lectures[1]); + const [searchQuery, setSearchQuery] = useState(""); + const [isFiltered, setIsFiltered] = useState(false); + const [filtersOpen, setFiltersOpen] = useState(false); + const [filters, setFilters] = useState({ + selectedWeek: "", + selectedTopic: "", + selectedRelevance: "workHard", + }); + const [tempFilters, setTempFilters] = useState({ + selectedWeek: "", + selectedTopic: "", + selectedRelevance: "workHard", + }); + + const toggleFilters = () => { + setFiltersOpen(!filtersOpen); + }; + + const applyFilters = () => { + setFilters(tempFilters); + setFiltersOpen(false); + setIsFiltered( + tempFilters.selectedRelevance !== "" || + tempFilters.selectedTopic !== "" || + tempFilters.selectedWeek !== "" + ); + }; + + const filteredTutorials = useMemo(() => { + const getRelevanceOptions = () => { + switch (filters.selectedRelevance) { + case "bareMinimum": + return ["🟢 COMPULSORY"]; + case "workHard": + return ["🟢 COMPULSORY", "🔵 REFINING"]; + case "learnEverything": + return ["🟢 COMPULSORY", "🔵 REFINING", "🟠 EXTENDED"]; + default: + return []; + } + }; + + const relevanceOptions = getRelevanceOptions(); + return content_tutorials.filter((tutorial) => { + const nameMatch = tutorial.name + ? tutorial.name.toLowerCase().includes(searchQuery.toLowerCase()) + : false; + const weekMatch = + !filters.selectedWeek || tutorial.week().week === filters.selectedWeek; + const topicMatch = + !filters.selectedTopic || + tutorial.topic().name === filters.selectedTopic; + const relevanceMatch = relevanceOptions.includes(tutorial.importance); + + return nameMatch && weekMatch && topicMatch && relevanceMatch; + }); + }, [content_tutorials, filters, searchQuery]); + + return ( + <> + + + setSearchQuery(event.target.value)} + InputProps={{ + startAdornment: , + }} + /> + + + + + + + + +

Filter Content

+ + + Week + + + + Topic + + + + Relevance + + + + + + + +
+
+ + + {filteredTutorials.map((tutorial, index) => ( +
+ +
+ ))} +
+ + ); + }; - return ( - <> - - - ); -}; - -export default makePage(ContentLecturesSearch, { +export default makePage(ContentTutorialsSearch, { loginRequired: true, title: "", }); From 8536cb8a33ab9b92408acc76df525042fa15ffc3 Mon Sep 17 00:00:00 2001 From: Sofia De Bellis Date: Sat, 14 Sep 2024 14:58:41 +1000 Subject: [PATCH 07/24] (chore): cleanup --- frontend/src/page/Content/ContentLecturesSearch.jsx | 4 +--- frontend/src/page/Content/ContentTutorialsSearch.jsx | 7 ++----- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/frontend/src/page/Content/ContentLecturesSearch.jsx b/frontend/src/page/Content/ContentLecturesSearch.jsx index 7cf94ab..bd5e55d 100644 --- a/frontend/src/page/Content/ContentLecturesSearch.jsx +++ b/frontend/src/page/Content/ContentLecturesSearch.jsx @@ -1,6 +1,4 @@ import React, { useState, useMemo } from "react"; -import { useCookies } from "react-cookie"; -import { useNavigate, useLocation } from "react-router-dom"; import { Context, useContext } from "../../context"; import TutLecContentCard from "../../component/TutLecContentCard"; import makePage from "../../component/makePage"; @@ -25,7 +23,7 @@ import InfoIcon from "@mui/icons-material/Info"; const ContentLecturesSearch = ({}) => { const { getters, setters } = useContext(Context); - const { content_lectures, content_tutorials, weeks, topics } = + const { content_lectures, weeks, topics } = getters.content; const [searchQuery, setSearchQuery] = useState(""); diff --git a/frontend/src/page/Content/ContentTutorialsSearch.jsx b/frontend/src/page/Content/ContentTutorialsSearch.jsx index fb3160d..14f0bba 100644 --- a/frontend/src/page/Content/ContentTutorialsSearch.jsx +++ b/frontend/src/page/Content/ContentTutorialsSearch.jsx @@ -1,13 +1,10 @@ import React, { useState, useMemo } from "react"; -import { useCookies } from "react-cookie"; -import { useNavigate, useLocation } from "react-router-dom"; import { Context, useContext } from "../../context"; import TutLecContentCard from "../../component/TutLecContentCard"; import makePage from "../../component/makePage"; import { Box, Button, - FormControlLabel, Modal, Input, FormControl, @@ -234,11 +231,11 @@ const ContentTutorialsSearch = ({}) => { contentKey={tutorial.key} name={tutorial.name} duration_mins={tutorial.duration} - relevance={tutorial.importance.split(' ')[1]} // Ensure this is correctly passed if needed + relevance={tutorial.importance.split(' ')[1]} week={tutorial.week().week} topicEmoji={tutorial.topic().emoji} topicName={tutorial.topic().name} - lecture={false} // Set to false if this is for tutorials + lecture={false} /> ))} From 4dcdb00e5d8b5f06cf2fbb317a9a00fcea34eca4 Mon Sep 17 00:00:00 2001 From: Sofia De Bellis Date: Sat, 14 Sep 2024 14:59:02 +1000 Subject: [PATCH 08/24] (chore): cleanup --- frontend/src/component/TutLecContentCard.jsx | 1 - .../page/Content/ContentLecturesSearch.jsx | 3 +- .../page/Content/ContentTutorialsSearch.jsx | 427 +++++++++--------- 3 files changed, 214 insertions(+), 217 deletions(-) diff --git a/frontend/src/component/TutLecContentCard.jsx b/frontend/src/component/TutLecContentCard.jsx index 6ff30b8..16cb57f 100644 --- a/frontend/src/component/TutLecContentCard.jsx +++ b/frontend/src/component/TutLecContentCard.jsx @@ -15,7 +15,6 @@ export default function TutLecContentCard({ topicName, lecture, }) { - // Function to get chip label and color based on relevance const getRelevanceChip = (relevance) => { if (lecture) { switch (relevance) { diff --git a/frontend/src/page/Content/ContentLecturesSearch.jsx b/frontend/src/page/Content/ContentLecturesSearch.jsx index bd5e55d..2724c43 100644 --- a/frontend/src/page/Content/ContentLecturesSearch.jsx +++ b/frontend/src/page/Content/ContentLecturesSearch.jsx @@ -23,8 +23,7 @@ import InfoIcon from "@mui/icons-material/Info"; const ContentLecturesSearch = ({}) => { const { getters, setters } = useContext(Context); - const { content_lectures, weeks, topics } = - getters.content; + const { content_lectures, weeks, topics } = getters.content; const [searchQuery, setSearchQuery] = useState(""); const [isFiltered, setIsFiltered] = useState(false); diff --git a/frontend/src/page/Content/ContentTutorialsSearch.jsx b/frontend/src/page/Content/ContentTutorialsSearch.jsx index 14f0bba..f3c2ab5 100644 --- a/frontend/src/page/Content/ContentTutorialsSearch.jsx +++ b/frontend/src/page/Content/ContentTutorialsSearch.jsx @@ -18,231 +18,230 @@ import FilterListIcon from "@mui/icons-material/FilterList"; const ContentTutorialsSearch = ({}) => { const { getters, setters } = useContext(Context); - const { content_tutorials, weeks, topics } = - getters.content; + const { content_tutorials, weeks, topics } = getters.content; - const [searchQuery, setSearchQuery] = useState(""); - const [isFiltered, setIsFiltered] = useState(false); - const [filtersOpen, setFiltersOpen] = useState(false); - const [filters, setFilters] = useState({ - selectedWeek: "", - selectedTopic: "", - selectedRelevance: "workHard", - }); - const [tempFilters, setTempFilters] = useState({ - selectedWeek: "", - selectedTopic: "", - selectedRelevance: "workHard", - }); - - const toggleFilters = () => { - setFiltersOpen(!filtersOpen); - }; - - const applyFilters = () => { - setFilters(tempFilters); - setFiltersOpen(false); - setIsFiltered( - tempFilters.selectedRelevance !== "" || + const [searchQuery, setSearchQuery] = useState(""); + const [isFiltered, setIsFiltered] = useState(false); + const [filtersOpen, setFiltersOpen] = useState(false); + const [filters, setFilters] = useState({ + selectedWeek: "", + selectedTopic: "", + selectedRelevance: "workHard", + }); + const [tempFilters, setTempFilters] = useState({ + selectedWeek: "", + selectedTopic: "", + selectedRelevance: "workHard", + }); + + const toggleFilters = () => { + setFiltersOpen(!filtersOpen); + }; + + const applyFilters = () => { + setFilters(tempFilters); + setFiltersOpen(false); + setIsFiltered( + tempFilters.selectedRelevance !== "" || tempFilters.selectedTopic !== "" || tempFilters.selectedWeek !== "" - ); + ); + }; + + const filteredTutorials = useMemo(() => { + const getRelevanceOptions = () => { + switch (filters.selectedRelevance) { + case "bareMinimum": + return ["🟢 COMPULSORY"]; + case "workHard": + return ["🟢 COMPULSORY", "🔵 REFINING"]; + case "learnEverything": + return ["🟢 COMPULSORY", "🔵 REFINING", "🟠 EXTENDED"]; + default: + return []; + } }; - - const filteredTutorials = useMemo(() => { - const getRelevanceOptions = () => { - switch (filters.selectedRelevance) { - case "bareMinimum": - return ["🟢 COMPULSORY"]; - case "workHard": - return ["🟢 COMPULSORY", "🔵 REFINING"]; - case "learnEverything": - return ["🟢 COMPULSORY", "🔵 REFINING", "🟠 EXTENDED"]; - default: - return []; - } - }; - - const relevanceOptions = getRelevanceOptions(); - return content_tutorials.filter((tutorial) => { - const nameMatch = tutorial.name - ? tutorial.name.toLowerCase().includes(searchQuery.toLowerCase()) - : false; - const weekMatch = - !filters.selectedWeek || tutorial.week().week === filters.selectedWeek; - const topicMatch = - !filters.selectedTopic || - tutorial.topic().name === filters.selectedTopic; - const relevanceMatch = relevanceOptions.includes(tutorial.importance); - - return nameMatch && weekMatch && topicMatch && relevanceMatch; - }); - }, [content_tutorials, filters, searchQuery]); - - return ( - <> - - - setSearchQuery(event.target.value)} - InputProps={{ - startAdornment: , - }} - /> - - - - - - - - { + const nameMatch = tutorial.name + ? tutorial.name.toLowerCase().includes(searchQuery.toLowerCase()) + : false; + const weekMatch = + !filters.selectedWeek || tutorial.week().week === filters.selectedWeek; + const topicMatch = + !filters.selectedTopic || + tutorial.topic().name === filters.selectedTopic; + const relevanceMatch = relevanceOptions.includes(tutorial.importance); + + return nameMatch && weekMatch && topicMatch && relevanceMatch; + }); + }, [content_tutorials, filters, searchQuery]); + + return ( + <> + + + setSearchQuery(event.target.value)} + InputProps={{ + startAdornment: , }} + /> + + + - - - - - - + Filter + + + + + - {filteredTutorials.map((tutorial, index) => ( -
- -
- ))} +

Filter Content

+ + + Week + + + + Topic + + + + Relevance + + + + + + +
- - ); - }; +
+ + + {filteredTutorials.map((tutorial, index) => ( +
+ +
+ ))} +
+ + ); +}; export default makePage(ContentTutorialsSearch, { loginRequired: true, From fa0afc9fa3bc0019c07d918a61fe2f42a0b66e8f Mon Sep 17 00:00:00 2001 From: Sofia De Bellis Date: Sat, 14 Sep 2024 20:15:37 +1000 Subject: [PATCH 09/24] (fix): tutorial link was broken oops --- frontend/src/component/TutLecContentCard.jsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/frontend/src/component/TutLecContentCard.jsx b/frontend/src/component/TutLecContentCard.jsx index 16cb57f..0f83fd4 100644 --- a/frontend/src/component/TutLecContentCard.jsx +++ b/frontend/src/component/TutLecContentCard.jsx @@ -70,7 +70,11 @@ export default function TutLecContentCard({ }} > - {name} + {lecture ? ( + {name} + ) : ( + {name} + )} {duration_mins} minutes From 7ece58ba3f94fc8ea176f754b642513947169b23 Mon Sep 17 00:00:00 2001 From: Sofia De Bellis Date: Sat, 14 Sep 2024 20:20:34 +1000 Subject: [PATCH 10/24] idk --- frontend/src/component/TutLecContentCard.jsx | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/frontend/src/component/TutLecContentCard.jsx b/frontend/src/component/TutLecContentCard.jsx index 0f83fd4..75d6ceb 100644 --- a/frontend/src/component/TutLecContentCard.jsx +++ b/frontend/src/component/TutLecContentCard.jsx @@ -4,6 +4,7 @@ import CardContent from "@mui/material/CardContent"; import Typography from "@mui/material/Typography"; import Chip from "@mui/material/Chip"; import { Stack } from "@mui/material"; +import { useNavigate, useLocation, useParams } from "react-router-dom"; export default function TutLecContentCard({ name, @@ -15,6 +16,7 @@ export default function TutLecContentCard({ topicName, lecture, }) { + const navigate = useNavigate(); const getRelevanceChip = (relevance) => { if (lecture) { switch (relevance) { @@ -69,12 +71,17 @@ export default function TutLecContentCard({ flex: "1 0 auto", }} > - - {lecture ? ( + navigate(`/NOW/content/lectures/${contentKey}`)} + > + {/* {lecture ? ( {name} ) : ( {name} - )} + )} */} + {name} {duration_mins} minutes From bbd0e03dd22a0f078b9ab8d5b86d6665b2faeb4a Mon Sep 17 00:00:00 2001 From: Sofia De Bellis Date: Fri, 20 Sep 2024 11:33:19 +1000 Subject: [PATCH 11/24] (chore): add comma --- backend/src/config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/config.js b/backend/src/config.js index dc46bf8..1b6b4ba 100644 --- a/backend/src/config.js +++ b/backend/src/config.js @@ -13,7 +13,7 @@ const config = { AIRTABLE_API_KEY: 'patMWMSzpWIIw4ygQ.8905a12dae8ee6ecd484ea4dc3f1f2961f587b9c87a4682407063345298bd802', TUTOR_ID_LIST: [], AUDIT_ID_LIST: [], - ASS_MAP: ["pictocode", "funform", "qanda", "presto"] + ASS_MAP: ["pictocode", "funform", "qanda", "presto"], }, }, TERM_DEFAULT: 'sample', From 585a871c63e9eee36d70f0d6d635b6336841054f Mon Sep 17 00:00:00 2001 From: Sofia De Bellis Date: Fri, 20 Sep 2024 12:25:42 +1000 Subject: [PATCH 12/24] Move weeks out of modal --- .../page/Content/ContentLecturesSearch.jsx | 99 +++++++++----- .../page/Content/ContentTutorialsSearch.jsx | 123 +++++++++++------- 2 files changed, 141 insertions(+), 81 deletions(-) diff --git a/frontend/src/page/Content/ContentLecturesSearch.jsx b/frontend/src/page/Content/ContentLecturesSearch.jsx index 2724c43..f786ed1 100644 --- a/frontend/src/page/Content/ContentLecturesSearch.jsx +++ b/frontend/src/page/Content/ContentLecturesSearch.jsx @@ -1,4 +1,4 @@ -import React, { useState, useMemo } from "react"; +import React, { useEffect, useState, useMemo } from "react"; import { Context, useContext } from "../../context"; import TutLecContentCard from "../../component/TutLecContentCard"; import makePage from "../../component/makePage"; @@ -26,33 +26,59 @@ const ContentLecturesSearch = ({}) => { const { content_lectures, weeks, topics } = getters.content; const [searchQuery, setSearchQuery] = useState(""); + const [week, setWeek] = useState("All"); const [isFiltered, setIsFiltered] = useState(false); const [filtersOpen, setFiltersOpen] = useState(false); const [filters, setFilters] = useState({ - selectedWeek: "", - selectedTopic: "", + selectedTopic: "All", selectedRelevance: "workHard", completedCOMP1531: true, }); const [tempFilters, setTempFilters] = useState({ - selectedWeek: "", - selectedTopic: "", + selectedTopic: "All", selectedRelevance: "workHard", completedCOMP1531: true, }); + useEffect(() => { + const storedFilters = localStorage.getItem("filters"); + if (storedFilters) { + const parsedFilters = JSON.parse(storedFilters); + setFilters(parsedFilters); + setTempFilters(parsedFilters); + setIsFiltered( + parsedFilters.selectedRelevance !== "workHard" || parsedFilters.selectedTopic !== "All" + ); + } + }, []); + const toggleFilters = () => { setFiltersOpen(!filtersOpen); }; + const resetFilters = () => { + setFilters({ + selectedTopic: "All", + selectedRelevance: "workHard", + completedCOMP1531: true, + }); + setTempFilters({ + selectedTopic: "All", + selectedRelevance: "workHard", + completedCOMP1531: true, + }); + setIsFiltered(false); + setFiltersOpen(false); + localStorage.removeItem("filters"); + } + const applyFilters = () => { setFilters(tempFilters); setFiltersOpen(false); setIsFiltered( - tempFilters.selectedRelevance !== "" || - tempFilters.selectedTopic !== "" || - tempFilters.selectedWeek !== "" + tempFilters.selectedRelevance !== "workHard" || tempFilters.selectedTopic !== "All" ); + localStorage.setItem("filters", JSON.stringify(tempFilters)); }; const filteredLectures = useMemo(() => { @@ -77,16 +103,21 @@ const ContentLecturesSearch = ({}) => { const nameMatch = lecture.name ? lecture.name.toLowerCase().includes(searchQuery.toLowerCase()) : false; - const weekMatch = - !filters.selectedWeek || lecture.week().week === filters.selectedWeek; + let selectedWeek = week === "All" ? "" : week; + const weekMatch = !selectedWeek || lecture.week().week === selectedWeek; + let selectedTopic = + filters.selectedTopic === "All" ? "" : filters.selectedTopic; const topicMatch = - !filters.selectedTopic || - lecture.topic().name === filters.selectedTopic; + !selectedTopic || lecture.topic().name === selectedTopic; const relevanceMatch = relevanceOptions.includes(lecture.relevance); + setIsFiltered( + filters.selectedRelevance !== "workHard" || filters.selectedTopic !== "All" + ); + return nameMatch && weekMatch && topicMatch && relevanceMatch; }); - }, [content_lectures, filters, searchQuery]); + }, [content_lectures, filters, searchQuery, week]); return ( <> @@ -109,6 +140,22 @@ const ContentLecturesSearch = ({}) => { }} /> + + Week + +