diff --git a/client/package.json b/client/package.json index 5a7735fa2..c3c012061 100644 --- a/client/package.json +++ b/client/package.json @@ -42,7 +42,7 @@ }, "devDependencies": { "@types/w3c-web-serial": "^1.0.3", - "@vitejs/plugin-react-swc": "^3.2.0", + "@vitejs/plugin-react-swc": "^3.4.0", "parse-full-name": "^1.2.6" } } diff --git a/client/src/App.jsx b/client/src/App.jsx index 3efe80918..dde94cdd2 100644 --- a/client/src/App.jsx +++ b/client/src/App.jsx @@ -19,6 +19,11 @@ import StudentLogin from './views/StudentLogin/StudentLogin'; import ForgetPassword from './views/TeacherLogin/ForgetPassword'; import ResetPassword from './views/TeacherLogin/ResetPassword'; import TeacherLogin from './views/TeacherLogin/TeacherLogin'; +import ParentSignup from './views/ParentAccount/ParentSignup'; +import RestrictAccess from './views/ParentAccount/RestrictAccess' +import ParentLogin from './views/ParentAccount/ParentLogin'; +import MissedClass from './views/MissedClass/MissedClass'; + const App = () => { return ( @@ -27,6 +32,9 @@ const App = () => { } /> } /> } /> + } /> + } /> + } /> } /> } /> } /> @@ -80,6 +88,14 @@ const App = () => { } /> + + + + } + /> { if (!result.role) { return { role: 'Student', + id: result }; } else if (result.role.type === 'content_creator') { return { diff --git a/client/src/assets/share.png b/client/src/assets/share.png new file mode 100644 index 000000000..7e4e7fcc7 Binary files /dev/null and b/client/src/assets/share.png differ diff --git a/client/src/components/NavBar/NavBar.jsx b/client/src/components/NavBar/NavBar.jsx index 3896c3159..d19578e65 100644 --- a/client/src/components/NavBar/NavBar.jsx +++ b/client/src/components/NavBar/NavBar.jsx @@ -8,6 +8,7 @@ import { DownOutlined } from '@ant-design/icons'; import { removeUserSession } from '../../Utils/AuthRequests'; import { useGlobalState } from '../../Utils/userState'; + export default function NavBar() { const [value] = useGlobalState('currUser'); let currentRoute = window.location.pathname; @@ -99,6 +100,24 @@ export default function NavBar() {   Sign Out ) : null} + {shouldShowRoute('ParentLogin') ? ( + + + value.id % 2 == 0 ? ( + handleRouteChange(routes.ParentLogin)}> + +   Parent Login + + ) : ( + handleRouteChange(routes.ParentSignUp)}> + +   Parent Sign Up + + ) + + + ) : null} + ); diff --git a/client/src/components/NavBar/NavBarConfig.json b/client/src/components/NavBar/NavBarConfig.json index 27282d536..770ad46f0 100644 --- a/client/src/components/NavBar/NavBarConfig.json +++ b/client/src/components/NavBar/NavBarConfig.json @@ -9,12 +9,14 @@ "AccountInfo": "/account", "ContentCreatorDashboard": "/ccdashboard", "ResearcherDashboard": "/report", - "BugReport": "/bugreport" + "BugReport": "/bugreport", + "ParentSignUp": "/parent-signup", + "ParentLogin": "/parentlogin" }, "users": { "DefaultUser": ["Home", "TeacherLogin", "Sandbox", "About"], "Mentor": ["Dashboard", "AccountInfo", "SignOut", "Sandbox", "BugReport"], - "Student": ["SignOut"], + "Student": ["SignOut", "ParentSignUp", "ParentLogin"], "ContentCreator": [ "ContentCreatorDashboard", "AccountInfo", diff --git a/client/src/views/MissedClass/MissedClass.jsx b/client/src/views/MissedClass/MissedClass.jsx new file mode 100644 index 000000000..9510a4140 --- /dev/null +++ b/client/src/views/MissedClass/MissedClass.jsx @@ -0,0 +1,94 @@ +import React from 'react'; +import NavBar from '../../components/NavBar/NavBar'; +import './MissedClass.less' +import { Link } from 'react-router-dom' + +// const [announcements, setAnnouncements] = React.useState([]); + +const LectureMaterials = ({ resources }) => { + return ( +
+

Lecture Materials

+ {resources.map((resource, index) => ( +
+ {resource.title} +

Last updated: {resource.lastUpdated}

+
+ ))} +
+ ); + }; + + + const Announcements = ({ announcements }) => { + if (!Array.isArray(announcements)) { + // Handle the case where announcements is not an array + return
No announcements available.
; + } + + return ( +
+

Announcements

+ {announcements.map((announcement, index) => ( +
+

{announcement.content}

+

Last updated: {announcement.lastUpdated}

+
+ ))} +
+ ); + }; + + + const MissedClassDetails = () => { + const missedDetails = { + date: 'YYYY-MM-DD', + topic: 'The topic covered in the missed', + resources: [ + { + title: 'Lecture Video', + url: 'http://example.com/lecture', + lastUpdated: '2023-08-21', + }, + { + title: 'Reading Material', + url: 'http://example.com/reading', + lastUpdated: '2023-04-21', + }, + { + title: 'Homework Assignment', + url: 'http://example.com/homework', + lastUpdated: '2023-12-21', + } + ], + announcements: [ + { + content: 'Midterm grades have been posted.', + lastUpdated: '2023-08-09', + }, + { + content: `Next week's class will be held in a different room.`, + lastUpdated: '2023-05-01', + } + ] + }; + + return( +
+ + +
+
+ +
+
+ +
+
+
+ ); +}; + +export default MissedClassDetails; \ No newline at end of file diff --git a/client/src/views/MissedClass/MissedClass.less b/client/src/views/MissedClass/MissedClass.less new file mode 100644 index 000000000..23f211b35 --- /dev/null +++ b/client/src/views/MissedClass/MissedClass.less @@ -0,0 +1,66 @@ +@import "../../assets/style"; + +#missed-class-container { + position: absolute; + top: 53vh; + left: 10vw; + margin: -40vh auto 0 auto; + height: 85vh; + width: 80vw; + background-color: #colors[tertiary]; + border-radius: 15px; + border: 4px solid; + border-color: #colors[secondary]; + display: flex; + flex-direction: column; + align-items: stretch; + justify-content: center; //bruh +} + +.column { + flex: 1; // Each column flexes equally + padding: 20px; // Padding inside the columns + box-sizing: border-box; // Include padding and border in the width and height + min-height: 300px; + overflow: auto; // Add scrollbars if content overflows +} + +#divider{ + flex: none; + width: 2px; + background-color: #000; + margin: 0 20px; +} + +#header { + width: 50%; + min-height: 4vh; + font-size: 2.25vh; + font-weight: none; + position: relative; + top: -20px; + left: -30px; + line-height: 45px; + text-align: left; + display: flex; + align-items: center; + justify-content: center; +} + +#class-content{ + display: flex; // Make it a flex container + flex-direction: column; // Lay out children in a + flex: 1; // Allow it to fill the available space + height: calc(100% - 4vh); +} + +#class-content::after { + content: ''; // Required for the pseudo-element to work + display: block; // Makes it a block element + height: 1px; // Height of the divider line + width: 100%; // Full width of the container + background-color: black; // Color of the divider + position: absolute; // Absolute positioning + left: 0; // Starts at the left edge of the container + top: 50%; // Position it in the middle of the container vertically +} \ No newline at end of file diff --git a/client/src/views/ParentAccount/Parent.less b/client/src/views/ParentAccount/Parent.less new file mode 100644 index 000000000..518b6f625 --- /dev/null +++ b/client/src/views/ParentAccount/Parent.less @@ -0,0 +1,559 @@ +@import '../../assets/style.less'; + +.container { + background-color: #colors[primary]; + height: 100%; + min-height: 100vh; + width: 100%; + min-width: 100vw; + text-align: center; +} + +#content-wrapper { + margin: 12vh auto 8vh auto; + display: inline-block; +} + +#box { + width: 300px; + padding: 40px 20px; + background-color: #colors[tertiary]; + text-align: center; + border-radius: 15px; + border: 4px solid; + border-color: #colors[secondary]; +} + +#box-title { + background-color: #colors[secondary]; + border-radius: 80px; + width: 80%; + min-height: 8%; + color: #colors[text-secondary]; + font-size: 1.3em; + font-weight: bold; + position: relative; + top: -60px; + left: -40px; + line-height: 50px; + text-align: center; +} + +#box input[type='text'], +#box input[type='email'], +#box input[type='password'] { + display: block; + background: none; + margin: 20px auto 0px; + border: 2px solid; + border-color: #colors[secondary]; + padding: 14px 10px; + width: 200px; + outline: none; + color: #colors[text-primary]; + border-radius: 8px; + transition: 0.25s; +} + +#box input[type='text']:focus, +#box input[type='email']:focus, +#box input[type='password']:focus { + width: 220px; +} + +#box input[type='button'] { + background: darken(#colors[tertiary], 30%); + width: 80%; + display: block; + margin: 0 auto; + border: 2px solid; + border-color: #colors[secondary]; + padding: 14px 40px; + outline: none; + color: #colors[text-primary]; + background-color: #colors[quaternary]; + font-size: 1.2em; + font-weight: 500; + border-radius: 30px; + cursor: pointer; + transition: 0.25s; + position: relative; + bottom: -65px; + + &:hover { + background-color: #colors[quinary]; + color: #colors[text-primary]; + } +} + +#box #forgot-password { + margin-top: 5px; + margin-bottom: 0px; + float: right; + margin-right: 2rem; + + &:hover { + cursor: pointer; + } +} + +//ForgetPassword + +#forgot-pass-wrapper { + margin: 12vh auto 8vh auto; + display: inline-block; +} + +#forgot-pass-title { + background-color: #colors[secondary]; + border-radius: 80px; + width: 80%; + min-height: 8%; + color: #colors[text-secondary]; + font-size: 1.4em; + font-weight: bold; + position: relative; + top: 25px; + left: -40px; + line-height: 50px; + text-align: center; +} + +#forgot-pass-form { + width: 400px; + padding: 40px 20px; + background-color: #colors[tertiary]; + text-align: center; + border-radius: 15px; + border: 4px solid; + border-color: #colors[secondary]; + + input, + textarea { + display: block; + background: none; + margin: 20px auto 0px; + border: 2px solid; + border-color: #colors[secondary]; + padding: 14px 10px; + width: 300px; + outline: none; + color: #colors[text-primary]; + border-radius: 8px; + transition: 0.25s; + } + + .ant-btn-primary { + display: flex; + justify-content: center; + align-items: center; + background: #colors[quaternary]; + width: 50%; + // display: block; + margin: 0 auto; + border: 2px solid; + border-color: #colors[secondary]; + padding: 14px 40px; + outline: none; + color: #colors[text-primary]; + font-size: 1.2em; + font-weight: 500; + border-radius: 30px; + position: relative; + bottom: -90px; + + &:hover { + background-color: #colors[quinary]; + } + } +} + +//ResetPassword + +#reset-pass-wrapper { + margin: 12vh auto 8vh auto; + display: inline-block; +} + +#reset-pass-title { + background-color: #colors[secondary]; + border-radius: 80px; + width: 80%; + min-height: 8%; + color: #colors[text-secondary]; + font-size: 1.4em; + font-weight: bold; + position: relative; + top: 25px; + left: -40px; + line-height: 50px; + text-align: center; +} + +#reset-pass-form { + width: 400px; + padding: 40px 20px; + background-color: #colors[tertiary]; + text-align: center; + border-radius: 15px; + border: 4px solid; + border-color: #colors[secondary]; + + input[type='password'] { + display: block; + background: none; + margin: 20px auto 0px; + border: 2px solid; + border-color: #colors[secondary]; + padding: 14px 10px; + width: 300px; + outline: none; + color: #colors[text-primary]; + border-radius: 8px; + transition: 0.25s; + } + + .ant-btn-primary { + display: flex; + justify-content: center; + align-items: center; + background: #colors[quaternary]; + width: 50%; + // display: block; + margin: 0 auto; + border: 2px solid; + border-color: #colors[secondary]; + padding: 14px 40px; + outline: none; + color: #colors[text-primary]; + font-size: 1.2em; + font-weight: 500; + border-radius: 30px; + position: relative; + bottom: -90px; + + &:hover { + background-color: #colors[quinary]; + } + } +} + +#forgot-pass-form { + width: 400px; + padding: 40px 20px; + background-color: #colors[tertiary]; + text-align: center; + border-radius: 15px; + border: 4px solid; + border-color: #colors[secondary]; + + input[type='email'] { + display: block; + background: none; + margin: 20px auto 0px; + border: 2px solid; + border-color: #colors[secondary]; + padding: 14px 10px; + width: 300px; + outline: none; + color: #colors[text-primary]; + border-radius: 8px; + transition: 0.25s; + } + + .ant-btn-primary { + display: flex; + justify-content: center; + align-items: center; + background: #colors[quaternary]; + width: 50%; + // display: block; + margin: 0 auto; + border: 2px solid; + border-color: #colors[secondary]; + padding: 14px 40px; + outline: none; + color: #colors[text-primary]; + font-size: 1.2em; + font-weight: 500; + border-radius: 30px; + position: relative; + bottom: -90px; + + &:hover { + background-color: #colors[quinary]; + } + } + + +} + + +//ResetPassword + +#reset-pass-wrapper { + margin: 12vh auto 8vh auto; + display: inline-block; +} + +#reset-pass-title { + background-color: #colors[secondary]; + border-radius: 80px; + width: 80%; + min-height: 8%; + color: #colors[text-secondary]; + font-size: 1.4em; + font-weight: bold; + position: relative; + top: 25px; + left: -40px; + line-height: 50px; + text-align: center; +} + +#reset-pass-form { + width: 400px; + padding: 40px 20px; + background-color: #colors[tertiary]; + text-align: center; + border-radius: 15px; + border: 4px solid; + border-color: #colors[secondary]; + + input[type='password'] { + display: block; + background: none; + margin: 20px auto 0px; + border: 2px solid; + border-color: #colors[secondary]; + padding: 14px 10px; + width: 300px; + outline: none; + color: #colors[text-primary]; + border-radius: 8px; + transition: 0.25s; + } + + .ant-btn-primary { + display: flex; + justify-content: center; + align-items: center; + background: #colors[quaternary]; + width: 50%; + // display: block; + margin: 0 auto; + border: 2px solid; + border-color: #colors[secondary]; + padding: 14px 40px; + outline: none; + color: #colors[text-primary]; + font-size: 1.2em; + font-weight: 500; + border-radius: 30px; + position: relative; + bottom: -90px; + + &:hover { + background-color: #colors[quinary]; + } + } + +} + +#main-header { + color: #colors[text-secondary]; + font-size: 2em; + font-weight: bolder; + margin-left: 10%; + margin-bottom: 3%; + text-align: left; + padding-top: 20px; +} + +#classrooms-container { + margin: 6vh auto 4vh auto; + padding-top: 40px; + padding-bottom: 40px; + width: 80vw; + height: auto; + background: #colors[senary]; + border-radius: 5px; + border: 2px solid #colors[secondary]; +} + +#dashboard-card-container { + display: inline-grid; + grid-template-columns: auto auto; + justify-content: center; + width: 80vw; + margin: auto auto auto 2%; +} + +#dashboard-class-card { + display: flex; + flex-direction: row; + text-align: center; + width: 24vw; + height: auto; + margin: auto 6vh 6vh auto; + background: #colors[tertiary]; + color: #colors[text-primary]; + border: none; + border-color: #colors[secondary]; + border-radius: 10px; + box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.377); + + + #card-button-container { + // margin: 10% auto 0 auto; + + button { + width: 9vw; + height: auto; + font-size: 1vw; + font-weight: 500; + border-radius: 30px; + margin: 10% auto auto auto; + background: #colors[quaternary]; + border: none; + color: #colors[text-primary]; + transition: 0.25s; + cursor: pointer; + box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.377); + + &:hover { + width: 10vw; + background: #colors[quinary]; + } + } + } + + #card-left-content-container { + position: relative; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + width: 72%; + padding: 24px 24px; + + #card-title { + text-align: center; + font-size: 1.4vw; + margin: 10px; + line-height: 1.6vw; + } + } + + #card-right-content-container { + display: flex; + flex-direction: column; + min-width: 28%; + + #number { + font-size: 1.4vw; + margin: 0; + padding-top: 20px; + + } + + #label { + font-size: 1vw; + padding-bottom: 20px; + } + + #dashboard-display-code-modal { + height: 49.5%; + + #dashboard-display-code-btn { + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + width: 100%; + height: 100%; + background-color: #colors[quaternary]; + border-top-right-radius: 10px; + border: none; + + &:hover { + background: #colors[quinary]; + } + + #code-display-text { + font-size: 15em; + text-align: center; + } + } + } + + #divider { + background-color: #colors[tertiary]; + height: 1%; + } + + #student-number-container { + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + width: 100%; + height: 49.5%; + background-color: #colors[quaternary]; + border-bottom-right-radius: 10px; + } + } + +} + +.manage-access-page-container { + padding: 24px; + background-color: #f0f2f5; + + .manage-access-page-title { + font-size: 24px; + margin-bottom: 20px; + } + + .manage-access-card { + display: flex; + flex-direction: column; + background: #fff; + padding: 16px; + border-radius: 8px; + box-shadow: 0 4px 8px rgba(0,0,0,0.1); + margin-bottom: 24px; + } + + .access-card-header { + font-size: 20px; + color: #333; + margin-bottom: 16px; + } + + .access-card-content { + display: flex; + justify-content: space-between; + align-items: center; + } + + .access-feature-title { + font-size: 16px; + color: #666; + } + + #access-toggle-container { + display: flex; + align-items: center; + + + .access-toggle-label { + font-size: 24px; + color: #666; + } + } +} + + + + \ No newline at end of file diff --git a/client/src/views/ParentAccount/ParentLogin.jsx b/client/src/views/ParentAccount/ParentLogin.jsx new file mode 100644 index 000000000..671c7b6f4 --- /dev/null +++ b/client/src/views/ParentAccount/ParentLogin.jsx @@ -0,0 +1,81 @@ +import { message } from 'antd'; +import React, { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; +import NavBar from '../../components/NavBar/NavBar'; +import { postUser, setUserSession } from '../../Utils/AuthRequests'; +import './ParentLogin.less'; + +const useFormInput = (initialValue) => { + const [value, setValue] = useState(initialValue); + + const handleChange = (e) => { + setValue(e.target.value); + }; + return { + value, + onChange: handleChange, + }; +}; + +export default function ParentLogin() { + const email = useFormInput(''); + const password = useFormInput(''); + const [loading, setLoading] = useState(false); + const navigate = useNavigate(); + + const handleLogin = () => { + setLoading(true); + let body = { identifier: email.value, password: password.value }; + + postUser(body) + .then((response) => { + setUserSession(response.data.jwt, JSON.stringify(response.data.user)); + setLoading(false); + if (response.data.user.role.name === 'Content Creator') { + navigate('/ccdashboard'); + } else if (response.data.user.role.name === 'Researcher') { + navigate('/report'); + } else { + navigate('/dashboard'); + } + }) + .catch((error) => { + setLoading(false); + message.error('Login failed. Please input a valid email and password.'); + }); + }; + + return ( +
+ +
+
{ + if (e.key === 'Enter') handleLogin(); + }} + > +
Parental Controls
+ +

navigate('/forgot-password')}> + Forgot Password? +

+

navigate('/restrict-access')}> + Skip Login +

+ +
+
+
+ ); +} diff --git a/client/src/views/ParentAccount/ParentLogin.less b/client/src/views/ParentAccount/ParentLogin.less new file mode 100644 index 000000000..3e37b7a75 --- /dev/null +++ b/client/src/views/ParentAccount/ParentLogin.less @@ -0,0 +1,364 @@ +@import '../../assets/style.less'; + +.container { + background-color: #colors[primary]; + height: 100%; + min-height: 100vh; + width: 100%; + min-width: 100vw; + text-align: center; +} + +#content-wrapper { + margin: 12vh auto 8vh auto; + display: inline-block; +} + +#box { + width: 300px; + padding: 40px 20px; + background-color: #colors[tertiary]; + text-align: center; + border-radius: 15px; + border: 4px solid; + border-color: #colors[secondary]; +} + +#box-title { + background-color: #colors[secondary]; + border-radius: 80px; + width: 80%; + min-height: 8%; + color: #colors[text-secondary]; + font-size: 1.5em; + font-weight: bold; + position: relative; + top: -60px; + left: -40px; + line-height: 50px; + text-align: center; +} + +#box input[type='text'], +#box input[type='email'], +#box input[type='password'] { + display: block; + background: none; + margin: 20px auto 0px; + border: 2px solid; + border-color: #colors[secondary]; + padding: 14px 10px; + width: 200px; + outline: none; + color: #colors[text-primary]; + border-radius: 8px; + transition: 0.25s; +} + +#box input[type='text']:focus, +#box input[type='email']:focus, +#box input[type='password']:focus { + width: 220px; +} + +#box input[type='button'] { + background: darken(#colors[tertiary], 30%); + width: 80%; + display: block; + margin: 0 auto; + border: 2px solid; + border-color: #colors[secondary]; + padding: 14px 40px; + outline: none; + color: #colors[text-primary]; + background-color: #colors[quaternary]; + font-size: 1.2em; + font-weight: 500; + border-radius: 30px; + cursor: pointer; + transition: 0.25s; + position: relative; + bottom: -65px; + + &:hover { + background-color: #colors[quinary]; + color: #colors[text-primary]; + } +} + +#box #forgot-password { + margin-top: 5px; + margin-bottom: 0px; + float: right; + margin-right: 2rem; + + &:hover { + cursor: pointer; + } +} + +//ForgetPassword + +#forgot-pass-wrapper { + margin: 12vh auto 8vh auto; + display: inline-block; +} + +#forgot-pass-title { + background-color: #colors[secondary]; + border-radius: 80px; + width: 80%; + min-height: 8%; + color: #colors[text-secondary]; + font-size: 1.4em; + font-weight: bold; + position: relative; + top: 25px; + left: -40px; + line-height: 50px; + text-align: center; +} + +#forgot-pass-form { + width: 400px; + padding: 40px 20px; + background-color: #colors[tertiary]; + text-align: center; + border-radius: 15px; + border: 4px solid; + border-color: #colors[secondary]; + + input, + textarea { + display: block; + background: none; + margin: 20px auto 0px; + border: 2px solid; + border-color: #colors[secondary]; + padding: 14px 10px; + width: 300px; + outline: none; + color: #colors[text-primary]; + border-radius: 8px; + transition: 0.25s; + } + + .ant-btn-primary { + display: flex; + justify-content: center; + align-items: center; + background: #colors[quaternary]; + width: 50%; + // display: block; + margin: 0 auto; + border: 2px solid; + border-color: #colors[secondary]; + padding: 14px 40px; + outline: none; + color: #colors[text-primary]; + font-size: 1.2em; + font-weight: 500; + border-radius: 30px; + position: relative; + bottom: -90px; + + &:hover { + background-color: #colors[quinary]; + } + } +} + +//ResetPassword + +#reset-pass-wrapper { + margin: 12vh auto 8vh auto; + display: inline-block; +} + +#reset-pass-title { + background-color: #colors[secondary]; + border-radius: 80px; + width: 80%; + min-height: 8%; + color: #colors[text-secondary]; + font-size: 1.4em; + font-weight: bold; + position: relative; + top: 25px; + left: -40px; + line-height: 50px; + text-align: center; +} + +#reset-pass-form { + width: 400px; + padding: 40px 20px; + background-color: #colors[tertiary]; + text-align: center; + border-radius: 15px; + border: 4px solid; + border-color: #colors[secondary]; + + input[type='password'] { + display: block; + background: none; + margin: 20px auto 0px; + border: 2px solid; + border-color: #colors[secondary]; + padding: 14px 10px; + width: 300px; + outline: none; + color: #colors[text-primary]; + border-radius: 8px; + transition: 0.25s; + } + + .ant-btn-primary { + display: flex; + justify-content: center; + align-items: center; + background: #colors[quaternary]; + width: 50%; + // display: block; + margin: 0 auto; + border: 2px solid; + border-color: #colors[secondary]; + padding: 14px 40px; + outline: none; + color: #colors[text-primary]; + font-size: 1.2em; + font-weight: 500; + border-radius: 30px; + position: relative; + bottom: -90px; + + &:hover { + background-color: #colors[quinary]; + } + } +} + +#forgot-pass-form { + width: 400px; + padding: 40px 20px; + background-color: #colors[tertiary]; + text-align: center; + border-radius: 15px; + border: 4px solid; + border-color: #colors[secondary]; + + input[type='email'] { + display: block; + background: none; + margin: 20px auto 0px; + border: 2px solid; + border-color: #colors[secondary]; + padding: 14px 10px; + width: 300px; + outline: none; + color: #colors[text-primary]; + border-radius: 8px; + transition: 0.25s; + } + + .ant-btn-primary { + display: flex; + justify-content: center; + align-items: center; + background: #colors[quaternary]; + width: 50%; + // display: block; + margin: 0 auto; + border: 2px solid; + border-color: #colors[secondary]; + padding: 14px 40px; + outline: none; + color: #colors[text-primary]; + font-size: 1.2em; + font-weight: 500; + border-radius: 30px; + position: relative; + bottom: -90px; + + &:hover { + background-color: #colors[quinary]; + } + } + + +} + + +//ResetPassword + +#reset-pass-wrapper { + margin: 12vh auto 8vh auto; + display: inline-block; +} + +#reset-pass-title { + background-color: #colors[secondary]; + border-radius: 80px; + width: 80%; + min-height: 8%; + color: #colors[text-secondary]; + font-size: 1.4em; + font-weight: bold; + position: relative; + top: 25px; + left: -40px; + line-height: 50px; + text-align: center; +} + +#reset-pass-form { + width: 400px; + padding: 40px 20px; + background-color: #colors[tertiary]; + text-align: center; + border-radius: 15px; + border: 4px solid; + border-color: #colors[secondary]; + + input[type='password'] { + display: block; + background: none; + margin: 20px auto 0px; + border: 2px solid; + border-color: #colors[secondary]; + padding: 14px 10px; + width: 300px; + outline: none; + color: #colors[text-primary]; + border-radius: 8px; + transition: 0.25s; + } + + .ant-btn-primary { + display: flex; + justify-content: center; + align-items: center; + background: #colors[quaternary]; + width: 50%; + // display: block; + margin: 0 auto; + border: 2px solid; + border-color: #colors[secondary]; + padding: 14px 40px; + outline: none; + color: #colors[text-primary]; + font-size: 1.2em; + font-weight: 500; + border-radius: 30px; + position: relative; + bottom: -90px; + + &:hover { + background-color: #colors[quinary]; + } + } + +} + + + \ No newline at end of file diff --git a/client/src/views/ParentAccount/ParentSignup.jsx b/client/src/views/ParentAccount/ParentSignup.jsx new file mode 100644 index 000000000..75e4a2604 --- /dev/null +++ b/client/src/views/ParentAccount/ParentSignup.jsx @@ -0,0 +1,77 @@ +import { message } from 'antd'; +import React, { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; +import NavBar from '../../components/NavBar/NavBar'; +import './Parent.less'; + +const useFormInput = (initialValue) => { + const [value, setValue] = useState(initialValue); + + const handleChange = (e) => { + setValue(e.target.value); + }; + + return { + value, + onChange: handleChange, + }; +}; + +export default function ParentSignup() { + const name = useFormInput(''); + const email = useFormInput(''); + const password = useFormInput(''); + const confirmPassword = useFormInput(''); + const [loading, setLoading] = useState(false); + const navigate = useNavigate(); + + const handleSignup = () => { + //TODO: Handle backend to allow parent account signup + }; + + return ( +
+ +
+
{ + if (e.key === 'Enter') handleSignup(); + }} + > +
Create Parent Account
+ + + + + +
+
+
+ ); +} diff --git a/client/src/views/ParentAccount/RestrictAccess.jsx b/client/src/views/ParentAccount/RestrictAccess.jsx new file mode 100644 index 000000000..fe6330f75 --- /dev/null +++ b/client/src/views/ParentAccount/RestrictAccess.jsx @@ -0,0 +1,34 @@ +import React, { useState } from 'react'; +import { Switch } from 'antd'; +import './Parent.less'; +import NavBar from '../../components/NavBar/NavBar'; +import MentorSubHeader from '../../components/MentorSubHeader/MentorSubHeader'; + +export default function ManageAccessPage() { + const [isSharingEnabled, setIsSharingEnabled] = useState(true); + + const toggleSharing = (checked) => { + setIsSharingEnabled(checked); + //TODO: Add logic to handle the change in sharing access state + }; + + return ( +
+ + +
+
+
+
+

Sharing Feature

+
+
+ + {isSharingEnabled ? 'On' : 'Off'} +
+
+
+
+
+ ); +} diff --git a/client/src/views/Student/Student.jsx b/client/src/views/Student/Student.jsx index 1a03837e7..7ae39fffb 100644 --- a/client/src/views/Student/Student.jsx +++ b/client/src/views/Student/Student.jsx @@ -1,13 +1,18 @@ -import { message } from 'antd'; +import { message, Modal } from 'antd'; import React, { useEffect, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import NavBar from '../../components/NavBar/NavBar'; import { getStudentClassroom } from '../../Utils/requests'; +import ShareImage from '../../assets/share.png'; import './Student.less'; function Student() { const [learningStandard, setLessonModule] = useState({}); const navigate = useNavigate(); + const [showMissedClassPrompt, setShowMissedClassPrompt] = useState( + !sessionStorage.getItem('missedClassPromptDismissed') + ); + const [isModalVisible, setIsModalVisible] = useState(false); useEffect(() => { const fetchData = async () => { @@ -20,7 +25,9 @@ function Student() { } else { message.error(res.err); } - } catch {} + } catch (error) { + console.error(error); + } }; fetchData(); }, []); @@ -32,9 +39,33 @@ function Student() { navigate('/workspace'); }; + const dismissPrompt = () => { + setShowMissedClassPrompt(false); + sessionStorage.setItem('missedClassPromptDismissed', 'true'); + }; + return (
+ + {showMissedClassPrompt && ( + { + dismissPrompt(); + navigate('/missed-class'); + }} + onCancel={() => { + dismissPrompt(); + }} + okText = "Yes" + cancelText="No" + > +

Did you miss yesterday's class?

+
+ )} +
)) ) : (

There is currently no active learning standard set.

-

- When your classroom manager selects one, it will appear here. -

+

When your classroom manager selects one, it will appear here.

)}
+ +
+
View programs other students have shared with you
+
); } export default Student; + diff --git a/client/src/views/Student/Student.less b/client/src/views/Student/Student.less index 5563e29e2..95870b394 100644 --- a/client/src/views/Student/Student.less +++ b/client/src/views/Student/Student.less @@ -13,6 +13,21 @@ border-color: #colors[secondary]; } +#bottom-section { + background-color: #colors[secondary]; + border-radius: 80px; + width: 40%; + min-height: 4vh; + color: #colors[text-secondary]; + font-size: 2.25vh; + font-weight: bold; + position: relative; + top: 400px; + left: 125px; + line-height: 45px; + text-align: center; +} + #header { background-color: #colors[secondary]; border-radius: 80px; @@ -86,4 +101,17 @@ li { color: #colors[secondary]; } } -} \ No newline at end of file +} + +.activity-item { + display: flex; + align-items: center; +} + +.share-icon { + order: 1; + width: 35px; + height: 35px; + margin-left: 700px; +} + diff --git a/client/yarn.lock b/client/yarn.lock index a18b81215..bc0ade870 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -331,7 +331,7 @@ resolved "https://registry.yarnpkg.com/@types/w3c-web-serial/-/w3c-web-serial-1.0.5.tgz#09ed1265b642703c7f5556f36717bf4b1eddb10c" integrity sha512-gpWNghA1RjPc92puT2HRRRFjv0MDVcpS9yTjJPLwCRU+w1YQTmJommTEL1w7l6Llq5/2cbzH1B4jHx/EP0PcjQ== -"@vitejs/plugin-react-swc@^3.2.0": +"@vitejs/plugin-react-swc@^3.4.0": version "3.4.0" resolved "https://registry.yarnpkg.com/@vitejs/plugin-react-swc/-/plugin-react-swc-3.4.0.tgz#53ca6a07423abadec92f967e188d5ba49b350830" integrity sha512-m7UaA4Uvz82N/0EOVpZL4XsFIakRqrFKeSNxa1FBLSXGvWrWRBwmZb4qxk+ZIVAZcW3c3dn5YosomDgx62XWcQ== diff --git a/server/extensions/documentation/documentation/1.0.0/full_documentation.json b/server/extensions/documentation/documentation/1.0.0/full_documentation.json index 49963424f..9067d2253 100755 --- a/server/extensions/documentation/documentation/1.0.0/full_documentation.json +++ b/server/extensions/documentation/documentation/1.0.0/full_documentation.json @@ -14,7 +14,9 @@ "name": "Apache 2.0", "url": "https://www.apache.org/licenses/LICENSE-2.0.html" }, - "x-generation-date": "10/12/2023 1:28:43 PM" + + "x-generation-date": "11/07/2023 6:26:48 AM" + }, "x-strapi-config": { "path": "/documentation",