├── src ├── components │ ├── pages │ │ ├── AdminMeetingsDashBoard │ │ │ ├── ViewAllMeetings │ │ │ │ ├── MeetingInfo.css │ │ │ │ ├── MeetingInfo.js │ │ │ │ ├── ViewAllMeetings.js │ │ │ │ └── VAMC.js │ │ │ ├── DynamicDropdown.js │ │ │ └── CrudModals │ │ │ │ └── DeleteModal.js │ │ ├── MenteeMeetingsDashBoard │ │ │ ├── ViewAllMeetings │ │ │ │ ├── MeetingInfo.css │ │ │ │ ├── MeetingInfo.js │ │ │ │ ├── ViewAllMeetings.js │ │ │ │ └── VAMC.js │ │ │ └── DynamicDropdown.js │ │ ├── MentorMeetingsDashBoard │ │ │ ├── ViewAllMeetings │ │ │ │ ├── MeetingInfo.css │ │ │ │ ├── MeetingInfo.js │ │ │ │ ├── ViewAllMeetings.js │ │ │ │ └── VAMC.js │ │ │ ├── DynamicDropdown.js │ │ │ └── CrudModals │ │ │ │ └── DeleteModal.js │ │ ├── LandingPage │ │ │ ├── index.js │ │ │ ├── resources │ │ │ │ ├── guyatcomputer.jpg │ │ │ │ ├── pointatscreen.jpg │ │ │ │ └── mentorhelpingmentee.jpg │ │ │ ├── LandingPage.js │ │ │ └── LandingPage.less │ │ ├── Profile │ │ │ ├── index.js │ │ │ ├── Profile.js │ │ │ └── ProfileContainer.js │ │ ├── NotFound │ │ │ ├── index.js │ │ │ └── NotFoundPage.js │ │ ├── TicketsDashboard │ │ │ ├── TicketsDashboard.css │ │ │ └── TicketsDashboard.js │ │ ├── SuperAdminForm │ │ │ ├── index.js │ │ │ ├── SuperAdminFormContainer.js │ │ │ └── SuperAdminFormStyle.css │ │ ├── UserManagement │ │ │ ├── index.js │ │ │ └── UserModal.jsx │ │ ├── ManageResources │ │ │ ├── index.js │ │ │ └── ManageResources.js │ │ ├── ProfileList │ │ │ ├── index.js │ │ │ ├── ProfileListContainer.js │ │ │ └── RenderProfileListPage.js │ │ ├── MentorMenteeMatching │ │ │ ├── MentorTable.css │ │ │ └── MentorTable.js │ │ ├── Navbar │ │ │ ├── ud_logo.jpeg │ │ │ ├── ud_logo2.png │ │ │ ├── NavbarFeatures │ │ │ │ ├── MentorPopover.js │ │ │ │ └── ExampleFeature.js │ │ │ ├── Navbar.less │ │ │ └── NavbarItems.js │ │ ├── MenteesProgress │ │ │ └── MenteesProgress.js │ │ ├── Schedule │ │ │ └── Schedule.js │ │ ├── RoleApply │ │ │ ├── Applications │ │ │ │ ├── Styles │ │ │ │ │ ├── test.css │ │ │ │ │ ├── mentorApplication.css │ │ │ │ │ └── menteeApplication.css │ │ │ │ ├── README.dm │ │ │ │ ├── README.md │ │ │ │ ├── AppSuccess.js │ │ │ │ ├── AppRejected.js │ │ │ │ └── AppPending.js │ │ │ └── Styles │ │ │ │ └── apply.css │ │ ├── Availability │ │ │ └── Availability.js │ │ ├── Attendance │ │ │ └── attendance.js │ │ ├── Analytics │ │ │ ├── Analytics.css │ │ │ ├── Analytics.js │ │ │ └── TechStackGraph.jsx │ │ ├── Applications │ │ │ ├── AppTypeMenu.js │ │ │ ├── ApplicationModal.less │ │ │ └── ApplicationModal.js │ │ ├── Memos │ │ │ ├── Memo.less │ │ │ ├── MyMemos.js │ │ │ └── Memos.js │ │ ├── FooterLanding │ │ │ ├── FooterCol.js │ │ │ ├── FooterStyle.js │ │ │ └── FooterLanding.js │ │ ├── Reviews │ │ │ └── MentorReviews.js │ │ ├── Dashboard │ │ │ └── Dashboard.js │ │ ├── AddReviews │ │ │ ├── MenteeAddReview.js │ │ │ └── MentorAddReview.js │ │ ├── PendingApproval │ │ │ └── PendingApproval.js │ │ ├── SupportRequests │ │ │ └── SupportRequests.js │ │ └── MenteeMentorDashboard │ │ │ ├── MenteeMentorDashboard.js │ │ │ ├── MentorModal.jsx │ │ │ └── MenteeModal.jsx │ └── common │ │ ├── constants │ │ ├── index.js │ │ ├── techstack.js │ │ └── states.js │ │ ├── LoadingComponent.js │ │ ├── Loading.js │ │ ├── index.js │ │ ├── PrivateRoute.js │ │ ├── styles │ │ ├── Sidebar.css │ │ ├── Calendar.css │ │ ├── Memos.css │ │ └── Resources.css │ │ ├── ScheduleMeeting.js │ │ ├── Size&Devices.js │ │ ├── FormButton.js │ │ ├── Button.js │ │ ├── FormInput.js │ │ ├── MemosTable │ │ └── AddReply │ │ │ ├── Reply.css │ │ │ ├── showReply.js │ │ │ └── Reply.js │ │ ├── DarkModeToggle.js │ │ ├── Calendar.js │ │ ├── DialogButton │ │ ├── ScheduleButton.js │ │ └── Dialog.js │ │ ├── Sidebar │ │ ├── Sidebar.js │ │ └── SidebarLinks.utils.js │ │ └── SkeletonLoading.js ├── config │ └── index.js ├── state │ ├── actions │ │ ├── lifecycle │ │ │ ├── setFetchEnd.js │ │ │ └── setFetchStart.js │ │ ├── theme │ │ │ └── index.js │ │ ├── auth │ │ │ ├── setRoleId.js │ │ │ ├── setProfileId.js │ │ │ ├── setIsAuthenticated.js │ │ │ └── authenticateUser.js │ │ ├── errors │ │ │ └── setFetchError.js │ │ ├── userProfile │ │ │ ├── setUserProfile.js │ │ │ ├── setCurrentUser.js │ │ │ ├── setApplicationProfile.js │ │ │ └── getProfile.js │ │ ├── applications │ │ │ ├── setCurrentApplication.js │ │ │ ├── applicationModal.js │ │ │ └── handleApplications.js │ │ ├── userMatches │ │ │ ├── setUserMatches.js │ │ │ ├── setSuggestedMatches.js │ │ │ ├── updateUserMatches.js │ │ │ ├── getUserMatches.js │ │ │ └── getSuggestedMatches.js │ │ ├── allUsers │ │ │ ├── getAllUsers.js │ │ │ └── setAllUsers.js │ │ ├── mentee │ │ │ └── index.js │ │ ├── mentor │ │ │ └── index.js │ │ └── index.js │ ├── reducers │ │ ├── themeReducer.js │ │ ├── calendarReducer.js │ │ ├── index.js │ │ ├── applicationsReducer.js │ │ └── userReducer.js │ └── REDUX_README.md ├── setupTests.js ├── utils │ └── README.md ├── hooks │ ├── useLocalStorage.js │ ├── useTheme.js │ ├── useAxiosWithAuth0.js │ └── useForms.js ├── __mocks__ │ └── CreateTestStore.js ├── __tests__ │ ├── LoadingComponent.test.js │ ├── NotFoundPage.test.js │ ├── README.md │ └── AdminDashboard.test.js ├── auth │ ├── ShowPermission.js │ └── auth0ProviderWithHistory.js ├── styles │ └── theme-overrides.js └── api │ └── index.js ├── .env.sample ├── .github ├── CODEOWNERS └── workflows │ └── ci.yml ├── public ├── robots.txt ├── favicon.ico ├── manifest.json ├── index.html └── local.json ├── CODEOWNERS ├── .prettierrc ├── wireframes ├── DeprecatedWireframes │ ├── Login.png │ ├── Signup form.PNG │ ├── homepageWF.png │ ├── userroleflow.PNG │ ├── Mentee upd dashboard.PNG │ ├── mentor_application_form.png │ ├── mentee_application_forms.png │ ├── AdminDashboardpendingapproval.PNG │ ├── create admin and superadmin dashboard.PNG │ └── AdminDashboardpendingapprovalmentormenteeavailability.PNG ├── Mentor View Dash with Edit Dash.png ├── LandingPageWireframes │ ├── Landing-Page.png │ └── Landing-Page-Mobile.png ├── NewDesignProposition │ ├── AdminWireframes │ │ ├── admin_calender.png │ │ ├── Dashboard-Page-Admin.png │ │ ├── admin_track_resources.png │ │ ├── Dashboard-Page-Admin-Modal.png │ │ ├── admin_pending_applications.png │ │ ├── admin_track_resources_empty.png │ │ ├── admin_request_resources_form.png │ │ └── admin_pending_applications_empty.png │ ├── MatchingWireframes │ │ ├── matching-table.jpg │ │ ├── matching-expanded.jpg │ │ └── matching-expanded-alt.jpg │ ├── MenteesWireframes │ │ ├── mentee_calender.png │ │ ├── mentees_meetings.png │ │ ├── mentees_resources.png │ │ ├── mentees_assignments.png │ │ ├── mentees_meetings_empty.png │ │ ├── mentees_resources_empty.png │ │ └── mentees_assignments_empty.png │ ├── MentorWireframes │ │ ├── mentor_calender.png │ │ ├── mentors_mentees.png │ │ ├── mentors_mentees_empty.png │ │ ├── mentors_mentees_dropdown.png │ │ ├── mentors_schedule_meeting.png │ │ ├── mentors_upcoming_meetings.png │ │ ├── mentors_request_resource_form.png │ │ └── mentors_assigned_resources_empty.png │ └── RoleSignupWireframes │ │ ├── Mentee_wireframe.png │ │ ├── Mentor_wireframe.png │ │ └── mentor_mentee_application_forms.png └── README.md ├── jestConfig.js ├── amplify.yml ├── craco.config.js ├── .eslint ├── .gitignore ├── start.js ├── LICENSE ├── pull_request_template.md ├── CODE_OF_CONDUCT.md └── package.json /src/components/pages/AdminMeetingsDashBoard/ViewAllMeetings/MeetingInfo.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/pages/MenteeMeetingsDashBoard/ViewAllMeetings/MeetingInfo.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/pages/MentorMeetingsDashBoard/ViewAllMeetings/MeetingInfo.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/config/index.js: -------------------------------------------------------------------------------- 1 | export const API_URL = process.env.REACT_APP_API_URI; 2 | -------------------------------------------------------------------------------- /.env.sample: -------------------------------------------------------------------------------- 1 | REACT_APP_AUTH0_DOMAIN=auth0domain 2 | REACT_APP_AUTH0_CLIENT_ID=clientIdInfo -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | @paulstgermain 2 | @ashtilawat23 3 | @ryan-hamblin 4 | @tinomen 5 | @frankfusco -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /src/components/pages/LandingPage/index.js: -------------------------------------------------------------------------------- 1 | export { default as Landing } from './LandingPage'; 2 | -------------------------------------------------------------------------------- /src/components/pages/Profile/index.js: -------------------------------------------------------------------------------- 1 | export { default as Profile } from './ProfileContainer'; 2 | -------------------------------------------------------------------------------- /src/components/pages/NotFound/index.js: -------------------------------------------------------------------------------- 1 | export { default as NotFoundPage } from './NotFoundPage'; 2 | -------------------------------------------------------------------------------- /src/components/pages/TicketsDashboard/TicketsDashboard.css: -------------------------------------------------------------------------------- 1 | .ant-layout { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | @paulstgermain 2 | @BrokenShell 3 | @bummings 4 | @frankfusco 5 | @ryan-hamblin 6 | @ashtilawat23 7 | -------------------------------------------------------------------------------- /src/components/pages/SuperAdminForm/index.js: -------------------------------------------------------------------------------- 1 | export { default as SuperAdminForm } from './SuperAdminForm'; 2 | -------------------------------------------------------------------------------- /src/components/pages/UserManagement/index.js: -------------------------------------------------------------------------------- 1 | export { default as UserManagement } from './UserManagement'; 2 | -------------------------------------------------------------------------------- /src/components/pages/ManageResources/index.js: -------------------------------------------------------------------------------- 1 | export { default as ResourceManagement } from './ManageResources'; 2 | -------------------------------------------------------------------------------- /src/components/pages/ProfileList/index.js: -------------------------------------------------------------------------------- 1 | export { default as ProfileListPage } from './ProfileListContainer'; 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "semi": true, 4 | "singleQuote": true, 5 | "arrowParens": "avoid" 6 | } 7 | -------------------------------------------------------------------------------- /src/components/pages/MentorMenteeMatching/MentorTable.css: -------------------------------------------------------------------------------- 1 | .assignMentorTable label.ant-checkbox-wrapper { 2 | width: unset; 3 | } 4 | -------------------------------------------------------------------------------- /src/components/pages/Navbar/ud_logo.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/src/components/pages/Navbar/ud_logo.jpeg -------------------------------------------------------------------------------- /src/components/pages/Navbar/ud_logo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/src/components/pages/Navbar/ud_logo2.png -------------------------------------------------------------------------------- /wireframes/DeprecatedWireframes/Login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/DeprecatedWireframes/Login.png -------------------------------------------------------------------------------- /wireframes/DeprecatedWireframes/Signup form.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/DeprecatedWireframes/Signup form.PNG -------------------------------------------------------------------------------- /wireframes/DeprecatedWireframes/homepageWF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/DeprecatedWireframes/homepageWF.png -------------------------------------------------------------------------------- /wireframes/Mentor View Dash with Edit Dash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/Mentor View Dash with Edit Dash.png -------------------------------------------------------------------------------- /wireframes/DeprecatedWireframes/userroleflow.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/DeprecatedWireframes/userroleflow.PNG -------------------------------------------------------------------------------- /wireframes/LandingPageWireframes/Landing-Page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/LandingPageWireframes/Landing-Page.png -------------------------------------------------------------------------------- /src/components/pages/MenteesProgress/MenteesProgress.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export function MenteesProgress({ LoadingComponent }) { 4 | return <>; 5 | } 6 | -------------------------------------------------------------------------------- /jestConfig.js: -------------------------------------------------------------------------------- 1 | Object.defineProperty(window, 'backingStorePixelRatio', { 2 | value: () => ({ 3 | getPropertyValue: prop => { 4 | return ''; 5 | }, 6 | }), 7 | }); 8 | -------------------------------------------------------------------------------- /src/state/actions/lifecycle/setFetchEnd.js: -------------------------------------------------------------------------------- 1 | export const SET_FETCH_END = 'SET_FETCH_END'; 2 | 3 | export const setFetchEnd = () => { 4 | return { type: SET_FETCH_END }; 5 | }; 6 | -------------------------------------------------------------------------------- /src/state/actions/theme/index.js: -------------------------------------------------------------------------------- 1 | export const SET_THEME = 'SET_THEME'; 2 | 3 | export const setThemeRedux = theme => { 4 | return { type: SET_THEME, payload: theme }; 5 | }; 6 | -------------------------------------------------------------------------------- /wireframes/DeprecatedWireframes/Mentee upd dashboard.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/DeprecatedWireframes/Mentee upd dashboard.PNG -------------------------------------------------------------------------------- /wireframes/LandingPageWireframes/Landing-Page-Mobile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/LandingPageWireframes/Landing-Page-Mobile.png -------------------------------------------------------------------------------- /wireframes/DeprecatedWireframes/mentor_application_form.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/DeprecatedWireframes/mentor_application_form.png -------------------------------------------------------------------------------- /src/components/pages/LandingPage/resources/guyatcomputer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/src/components/pages/LandingPage/resources/guyatcomputer.jpg -------------------------------------------------------------------------------- /src/components/pages/LandingPage/resources/pointatscreen.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/src/components/pages/LandingPage/resources/pointatscreen.jpg -------------------------------------------------------------------------------- /src/state/actions/auth/setRoleId.js: -------------------------------------------------------------------------------- 1 | export const SET_ROLE_ID = 'SET_ROLE_ID'; 2 | 3 | export const setRoleId = role_id => { 4 | return { type: SET_ROLE_ID, payload: role_id }; 5 | }; 6 | -------------------------------------------------------------------------------- /src/state/actions/lifecycle/setFetchStart.js: -------------------------------------------------------------------------------- 1 | export const SET_FETCH_START = 'SET_FETCH_START'; 2 | 3 | export const setFetchStart = () => { 4 | return { type: SET_FETCH_START }; 5 | }; 6 | -------------------------------------------------------------------------------- /wireframes/DeprecatedWireframes/mentee_application_forms.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/DeprecatedWireframes/mentee_application_forms.png -------------------------------------------------------------------------------- /src/components/pages/LandingPage/resources/mentorhelpingmentee.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/src/components/pages/LandingPage/resources/mentorhelpingmentee.jpg -------------------------------------------------------------------------------- /wireframes/DeprecatedWireframes/AdminDashboardpendingapproval.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/DeprecatedWireframes/AdminDashboardpendingapproval.PNG -------------------------------------------------------------------------------- /wireframes/NewDesignProposition/AdminWireframes/admin_calender.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/NewDesignProposition/AdminWireframes/admin_calender.png -------------------------------------------------------------------------------- /src/state/actions/errors/setFetchError.js: -------------------------------------------------------------------------------- 1 | export const SET_FETCH_ERROR = 'SET_FETCH_ERROR'; 2 | 3 | export const setFetchError = error => { 4 | return { type: SET_FETCH_ERROR, payload: error }; 5 | }; 6 | -------------------------------------------------------------------------------- /wireframes/NewDesignProposition/MatchingWireframes/matching-table.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/NewDesignProposition/MatchingWireframes/matching-table.jpg -------------------------------------------------------------------------------- /wireframes/NewDesignProposition/MenteesWireframes/mentee_calender.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/NewDesignProposition/MenteesWireframes/mentee_calender.png -------------------------------------------------------------------------------- /wireframes/NewDesignProposition/MentorWireframes/mentor_calender.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/NewDesignProposition/MentorWireframes/mentor_calender.png -------------------------------------------------------------------------------- /wireframes/NewDesignProposition/MentorWireframes/mentors_mentees.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/NewDesignProposition/MentorWireframes/mentors_mentees.png -------------------------------------------------------------------------------- /src/components/common/constants/index.js: -------------------------------------------------------------------------------- 1 | import states from './states'; 2 | import countries from './countries'; 3 | import tech_stack from './techstack'; 4 | 5 | export { states, countries, tech_stack }; 6 | -------------------------------------------------------------------------------- /src/state/actions/auth/setProfileId.js: -------------------------------------------------------------------------------- 1 | export const SET_PROFILE_ID = 'SET_PROFILE_ID'; 2 | 3 | export const setProfileId = profile_id => { 4 | return { type: SET_PROFILE_ID, payload: profile_id }; 5 | }; 6 | -------------------------------------------------------------------------------- /wireframes/NewDesignProposition/AdminWireframes/Dashboard-Page-Admin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/NewDesignProposition/AdminWireframes/Dashboard-Page-Admin.png -------------------------------------------------------------------------------- /wireframes/NewDesignProposition/MatchingWireframes/matching-expanded.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/NewDesignProposition/MatchingWireframes/matching-expanded.jpg -------------------------------------------------------------------------------- /wireframes/NewDesignProposition/MenteesWireframes/mentees_meetings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/NewDesignProposition/MenteesWireframes/mentees_meetings.png -------------------------------------------------------------------------------- /wireframes/NewDesignProposition/MenteesWireframes/mentees_resources.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/NewDesignProposition/MenteesWireframes/mentees_resources.png -------------------------------------------------------------------------------- /wireframes/DeprecatedWireframes/create admin and superadmin dashboard.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/DeprecatedWireframes/create admin and superadmin dashboard.PNG -------------------------------------------------------------------------------- /wireframes/NewDesignProposition/AdminWireframes/admin_track_resources.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/NewDesignProposition/AdminWireframes/admin_track_resources.png -------------------------------------------------------------------------------- /wireframes/NewDesignProposition/MenteesWireframes/mentees_assignments.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/NewDesignProposition/MenteesWireframes/mentees_assignments.png -------------------------------------------------------------------------------- /wireframes/NewDesignProposition/MentorWireframes/mentors_mentees_empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/NewDesignProposition/MentorWireframes/mentors_mentees_empty.png -------------------------------------------------------------------------------- /wireframes/NewDesignProposition/RoleSignupWireframes/Mentee_wireframe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/NewDesignProposition/RoleSignupWireframes/Mentee_wireframe.png -------------------------------------------------------------------------------- /wireframes/NewDesignProposition/RoleSignupWireframes/Mentor_wireframe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/NewDesignProposition/RoleSignupWireframes/Mentor_wireframe.png -------------------------------------------------------------------------------- /src/state/actions/userProfile/setUserProfile.js: -------------------------------------------------------------------------------- 1 | export const SET_USER_PROFILE = 'SET_USER_PROFILE'; 2 | 3 | export const setUserProfile = profile => { 4 | return { type: SET_USER_PROFILE, payload: profile }; 5 | }; 6 | -------------------------------------------------------------------------------- /wireframes/NewDesignProposition/MatchingWireframes/matching-expanded-alt.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/NewDesignProposition/MatchingWireframes/matching-expanded-alt.jpg -------------------------------------------------------------------------------- /wireframes/NewDesignProposition/MenteesWireframes/mentees_meetings_empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/NewDesignProposition/MenteesWireframes/mentees_meetings_empty.png -------------------------------------------------------------------------------- /wireframes/NewDesignProposition/MenteesWireframes/mentees_resources_empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/NewDesignProposition/MenteesWireframes/mentees_resources_empty.png -------------------------------------------------------------------------------- /wireframes/NewDesignProposition/MentorWireframes/mentors_mentees_dropdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/NewDesignProposition/MentorWireframes/mentors_mentees_dropdown.png -------------------------------------------------------------------------------- /wireframes/NewDesignProposition/MentorWireframes/mentors_schedule_meeting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/NewDesignProposition/MentorWireframes/mentors_schedule_meeting.png -------------------------------------------------------------------------------- /wireframes/NewDesignProposition/AdminWireframes/Dashboard-Page-Admin-Modal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/NewDesignProposition/AdminWireframes/Dashboard-Page-Admin-Modal.png -------------------------------------------------------------------------------- /wireframes/NewDesignProposition/AdminWireframes/admin_pending_applications.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/NewDesignProposition/AdminWireframes/admin_pending_applications.png -------------------------------------------------------------------------------- /wireframes/NewDesignProposition/AdminWireframes/admin_track_resources_empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/NewDesignProposition/AdminWireframes/admin_track_resources_empty.png -------------------------------------------------------------------------------- /wireframes/NewDesignProposition/MenteesWireframes/mentees_assignments_empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/NewDesignProposition/MenteesWireframes/mentees_assignments_empty.png -------------------------------------------------------------------------------- /wireframes/NewDesignProposition/MentorWireframes/mentors_upcoming_meetings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/NewDesignProposition/MentorWireframes/mentors_upcoming_meetings.png -------------------------------------------------------------------------------- /wireframes/NewDesignProposition/AdminWireframes/admin_request_resources_form.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/NewDesignProposition/AdminWireframes/admin_request_resources_form.png -------------------------------------------------------------------------------- /wireframes/NewDesignProposition/MentorWireframes/mentors_request_resource_form.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/NewDesignProposition/MentorWireframes/mentors_request_resource_form.png -------------------------------------------------------------------------------- /wireframes/NewDesignProposition/AdminWireframes/admin_pending_applications_empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/NewDesignProposition/AdminWireframes/admin_pending_applications_empty.png -------------------------------------------------------------------------------- /src/state/actions/userProfile/setCurrentUser.js: -------------------------------------------------------------------------------- 1 | export const SET_CURRENTUSER_PROFILE = 'SET_CURRENTUSER_PROFILE'; 2 | 3 | export const setCurrentUser = profile => { 4 | return { type: SET_CURRENTUSER_PROFILE, payload: profile }; 5 | }; 6 | -------------------------------------------------------------------------------- /wireframes/NewDesignProposition/MentorWireframes/mentors_assigned_resources_empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/NewDesignProposition/MentorWireframes/mentors_assigned_resources_empty.png -------------------------------------------------------------------------------- /src/components/pages/Schedule/Schedule.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export function Schedule({ LoadingComponent }) { 4 | return ( 5 | <> 6 |

This is a test render from Schedule

7 | 8 | ); 9 | } 10 | -------------------------------------------------------------------------------- /wireframes/DeprecatedWireframes/AdminDashboardpendingapprovalmentormenteeavailability.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/DeprecatedWireframes/AdminDashboardpendingapprovalmentormenteeavailability.PNG -------------------------------------------------------------------------------- /wireframes/NewDesignProposition/RoleSignupWireframes/mentor_mentee_application_forms.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BloomTech-Labs/underdog-devs-fe-a/HEAD/wireframes/NewDesignProposition/RoleSignupWireframes/mentor_mentee_application_forms.png -------------------------------------------------------------------------------- /src/components/pages/Profile/Profile.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export function Profile({ LoadingComponent }) { 4 | return ( 5 | <> 6 |

This is a test render from Profile page

7 | 8 | ); 9 | } 10 | -------------------------------------------------------------------------------- /src/components/pages/RoleApply/Applications/Styles/test.css: -------------------------------------------------------------------------------- 1 | label { 2 | background-color: transparent; 3 | } 4 | 5 | /* 6 | TODO: Find why putting this in mentorApplication.css does not work 7 | Why does it work on a separate file? 8 | */ 9 | -------------------------------------------------------------------------------- /src/state/actions/auth/setIsAuthenticated.js: -------------------------------------------------------------------------------- 1 | export const SET_IS_AUTHENTICATED = 'SET_IS_AUTHENTICATED'; 2 | 3 | export const setIsAuthenticated = isAuthenticated => { 4 | return { type: SET_IS_AUTHENTICATED, payload: isAuthenticated }; 5 | }; 6 | -------------------------------------------------------------------------------- /src/state/actions/userProfile/setApplicationProfile.js: -------------------------------------------------------------------------------- 1 | export const SET_APPLICATION_PROFILE = 'SET_APPLICATION_PROFILE'; 2 | 3 | export const setApplicationProfile = profile => { 4 | return { type: SET_APPLICATION_PROFILE, payload: profile }; 5 | }; 6 | -------------------------------------------------------------------------------- /src/components/pages/Availability/Availability.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export function Availability({ LoadingComponent }) { 4 | return ( 5 | <> 6 |

This is a test render from Availavility

7 | 8 | ); 9 | } 10 | -------------------------------------------------------------------------------- /src/state/actions/applications/setCurrentApplication.js: -------------------------------------------------------------------------------- 1 | export const SET_CURRENT_APPLICATION = 'SET_CURRENT_APPLICATION'; 2 | 3 | export const setCurrentApplication = application => { 4 | return { type: SET_CURRENT_APPLICATION, payload: application }; 5 | }; 6 | -------------------------------------------------------------------------------- /src/components/common/LoadingComponent.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import SkeletonLoadingComponent from './SkeletonLoading'; 3 | 4 | const LoadingComponent = props => { 5 | return ; 6 | }; 7 | 8 | export default LoadingComponent; 9 | -------------------------------------------------------------------------------- /src/components/pages/Attendance/attendance.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const Attendance = () => { 4 | return ( 5 | <> 6 |

View Mentee Attendance component goes here

7 | 8 | ); 9 | }; 10 | export default Attendance; 11 | -------------------------------------------------------------------------------- /src/components/pages/SuperAdminForm/SuperAdminFormContainer.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import SuperAdminForm from './SuperAdminForm'; 3 | 4 | function SuperAdminFormContainer({ LoadingComponent }) { 5 | return ; 6 | } 7 | 8 | export default SuperAdminFormContainer; 9 | -------------------------------------------------------------------------------- /src/components/pages/Analytics/Analytics.css: -------------------------------------------------------------------------------- 1 | .analyticsHeader h1 { 2 | font-size: 2rem; 3 | padding-left: 10px; 4 | } 5 | 6 | .techStackGraphInfo { 7 | width: 70%; 8 | } 9 | 10 | .analytics { 11 | display: flex; 12 | flex-direction: column; 13 | align-items: center; 14 | gap: 2rem; 15 | } 16 | -------------------------------------------------------------------------------- /src/components/pages/ManageResources/ManageResources.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { RenderResourceManagement } from './RenderResourceManagement'; 3 | 4 | export function ManageResources({ LoadingComponent }) { 5 | return ( 6 | <> 7 | 8 | 9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /src/components/pages/Profile/ProfileContainer.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import RenderProfile from './RenderProfileContainer'; 3 | 4 | function ProfileContainer({ LoadingComponent }) { 5 | return ( 6 | <> 7 | 8 | 9 | ); 10 | } 11 | 12 | export default ProfileContainer; 13 | -------------------------------------------------------------------------------- /src/state/actions/userMatches/setUserMatches.js: -------------------------------------------------------------------------------- 1 | export const SET_USER_MATCHES = 'SET_USER_MATCHES'; 2 | 3 | export const setUserMatches = arrOfMatches => { 4 | let payload = arrOfMatches.map(row => { 5 | return { 6 | ...row, 7 | }; 8 | }); 9 | return { type: SET_USER_MATCHES, payload }; 10 | }; 11 | -------------------------------------------------------------------------------- /src/components/common/Loading.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | const loadingImg = 3 | 'https://cdn.auth0.com/blog/auth0-react-sample/assets/loading.svg'; 4 | 5 | const Loading = () => ( 6 |
7 | Loading... 8 |
9 | ); 10 | 11 | export default Loading; 12 | -------------------------------------------------------------------------------- /src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | import 'jest-prop-type-error'; 7 | import 'jest-canvas-mock'; 8 | -------------------------------------------------------------------------------- /src/state/actions/userMatches/setSuggestedMatches.js: -------------------------------------------------------------------------------- 1 | export const SET_SUGGESTED_MATCHES = 'SET_SUGGESTED_MATCHES'; 2 | 3 | export const setSuggestedMatches = arrOfSugMatches => { 4 | let payload = arrOfSugMatches.map(row => { 5 | return { 6 | ...row, 7 | }; 8 | }); 9 | return { type: SET_SUGGESTED_MATCHES, payload }; 10 | }; 11 | -------------------------------------------------------------------------------- /src/utils/README.md: -------------------------------------------------------------------------------- 1 | ## Utils 2 | 3 | - This directory is for any of the business logic that your application may need to use. 4 | - Simple one-off _helper_ functions that you may need can be defined in this directory. 5 | - Any reusable logic or handlers or config files can also be used here. 6 | - **REMINDER do not** check any sensitive information into git 7 | -------------------------------------------------------------------------------- /src/state/actions/allUsers/getAllUsers.js: -------------------------------------------------------------------------------- 1 | import { setAllUsers } from './setAllUsers'; 2 | import axios from 'axios'; 3 | import { API_URL } from '../../../config'; 4 | 5 | export const getAllUsers = role => async dispatch => { 6 | const res = await axios.post(`${API_URL}users/read/${role}`); 7 | dispatch(setAllUsers(res.data, role)); 8 | return res.data; 9 | }; 10 | -------------------------------------------------------------------------------- /src/state/actions/userProfile/getProfile.js: -------------------------------------------------------------------------------- 1 | import { setUserProfile } from './setUserProfile'; 2 | import axios from 'axios'; 3 | import { API_URL } from '../../../config'; 4 | 5 | export const getProfile = role => async dispatch => { 6 | const res = await axios.get(`${API_URL}profile/role/${role}`); 7 | dispatch(setUserProfile(res.data)); 8 | return res.data; 9 | }; 10 | -------------------------------------------------------------------------------- /src/components/pages/NotFound/NotFoundPage.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link } from 'react-router-dom'; 3 | 4 | const NotFoundPage = () => { 5 | return ( 6 |
7 |

404 Page Not Found

8 | 9 | 10 | 11 |
12 | ); 13 | }; 14 | 15 | export default NotFoundPage; 16 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /src/components/pages/Navbar/NavbarFeatures/MentorPopover.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const MentorPopover = () => ( 4 | <> 5 |

6 | Please indicate if you are
7 | available to take on new mentees.
8 | This is an important part of our matching
9 | process. 10 |

11 | 12 | ); 13 | export default MentorPopover; 14 | -------------------------------------------------------------------------------- /src/hooks/useLocalStorage.js: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | 3 | export default function useLocalStorage(key, initValue) { 4 | const [storedValue, setStoredValue] = useState(() => { 5 | return localStorage.getItem(key) || initValue; 6 | }); 7 | const setValue = value => { 8 | setStoredValue(value); 9 | localStorage.setItem(key, value); 10 | }; 11 | return [storedValue, setValue]; 12 | } 13 | -------------------------------------------------------------------------------- /src/state/reducers/themeReducer.js: -------------------------------------------------------------------------------- 1 | import * as ACTIONS from '../actions/index'; 2 | 3 | const initialState = { 4 | theme: 'dark', 5 | }; 6 | 7 | const themeReducer = (state = initialState, action) => { 8 | switch (action.type) { 9 | case ACTIONS.SET_THEME: 10 | return { ...state, theme: action.payload }; 11 | default: 12 | return state; 13 | } 14 | }; 15 | 16 | export default themeReducer; 17 | -------------------------------------------------------------------------------- /amplify.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | frontend: 3 | phases: 4 | preBuild: 5 | commands: 6 | - nvm use $VERSION_NODE_12 7 | - npm ci 8 | build: 9 | commands: 10 | - nvm use $VERSION_NODE_12 11 | - node -v 12 | - npm run-script build 13 | artifacts: 14 | baseDirectory: build 15 | files: 16 | - "**/*" 17 | cache: 18 | paths: 19 | - node_modules/**/* 20 | -------------------------------------------------------------------------------- /src/__mocks__/CreateTestStore.js: -------------------------------------------------------------------------------- 1 | import { configureStore } from '@reduxjs/toolkit'; 2 | import rootReducer from '../state/reducers/index'; 3 | import promiseMiddleware from 'redux-promise'; 4 | import thunk from 'redux-thunk'; 5 | 6 | export default function createTestStore() { 7 | const store = configureStore({ 8 | reducer: rootReducer, 9 | middleware: [thunk, promiseMiddleware], 10 | }); 11 | return store; 12 | } 13 | -------------------------------------------------------------------------------- /src/state/actions/userMatches/updateUserMatches.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import { API_URL } from '../../../config/index'; 3 | 4 | export const updateUserMatches = 5 | (profile, matchArr, role) => async dispatch => { 6 | role = role.toLowerCase(); 7 | await axios({ 8 | method: 'patch', 9 | url: `${API_URL}matches/update/${role}/${profile.profile_id}`, 10 | data: matchArr, 11 | }); 12 | return; 13 | }; 14 | -------------------------------------------------------------------------------- /craco.config.js: -------------------------------------------------------------------------------- 1 | const config = require('./src/styles/theme-overrides.js'); 2 | const CracoLessPlugin = require('craco-less'); 3 | 4 | module.exports = { 5 | plugins: [ 6 | { 7 | plugin: CracoLessPlugin, 8 | options: { 9 | lessLoaderOptions: { 10 | lessOptions: { 11 | modifyVars: config, 12 | javascriptEnabled: true, 13 | }, 14 | }, 15 | }, 16 | }, 17 | ], 18 | }; 19 | -------------------------------------------------------------------------------- /src/components/pages/Analytics/Analytics.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import TechStackGraph from './TechStackGraph'; 3 | import './Analytics.css'; 4 | 5 | const Analytics = () => { 6 | return ( 7 | <> 8 |
9 |

Analytics

10 |
11 |
12 | 13 |
14 | 15 | ); 16 | }; 17 | 18 | export default Analytics; 19 | -------------------------------------------------------------------------------- /src/__tests__/LoadingComponent.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | 4 | import { LoadingComponent } from '../components/common'; 5 | 6 | describe('Loading Common Component', () => { 7 | test('it should mount a div based on props', () => { 8 | const loading = render(); 9 | const skeletonLoading = loading.findByTestId('skeleton-loading'); 10 | expect(skeletonLoading).toBeTruthy(); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /.eslint: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "env": { 4 | "browser": true, 5 | "node": true, 6 | "jest": true 7 | }, 8 | "plugins": [ 9 | // ... 10 | "react-hooks" 11 | ], 12 | "rules": { 13 | // ... 14 | "react-hooks/rules-of-hooks": "error", // Checks rules of Hooks 15 | "react-hooks/exhaustive-deps": "warn", // Checks effect dependencies 16 | "semi": "error" 17 | }, 18 | "ignorePatterns": ["src/__tests__/**, **/*.spec.js"], 19 | "extends": "react-app" 20 | } 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # env 12 | .env 13 | 14 | # logs 15 | *.log 16 | 17 | # production 18 | /build 19 | 20 | # misc 21 | .DS_Store 22 | .env.local 23 | .env.development.local 24 | .env.test.local 25 | .env.production.local 26 | 27 | npm-debug.log* 28 | yarn-debug.log* 29 | yarn-error.log* 30 | .vscode 31 | 32 | # Idea Folder 33 | .idea/ 34 | -------------------------------------------------------------------------------- /src/components/common/index.js: -------------------------------------------------------------------------------- 1 | import FormButton from './FormButton'; 2 | import FormInput from './FormInput'; 3 | import LoadingComponent from './LoadingComponent'; 4 | import Button from './Button'; 5 | import PrivateRoute from './PrivateRoute'; 6 | // notice we're building out a 'package' of reusables here and exporting them as an object of component properties. 7 | // to use this, simply `import {foo, bar, baz} from '/ReusableComponents';` 8 | export { FormButton, FormInput, LoadingComponent, Button, PrivateRoute }; 9 | -------------------------------------------------------------------------------- /src/components/common/PrivateRoute.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Route } from 'react-router-dom'; 3 | import { withAuthenticationRequired } from '@auth0/auth0-react'; 4 | import Sidebar from './Sidebar/Sidebar'; 5 | import { Spin } from 'antd'; 6 | 7 | const PrivateRoute = ({ component, ...args }) => ( 8 | 9 | , 12 | })} 13 | {...args} 14 | /> 15 | 16 | ); 17 | 18 | export default PrivateRoute; 19 | -------------------------------------------------------------------------------- /src/components/common/styles/Sidebar.css: -------------------------------------------------------------------------------- 1 | #darkmode { 2 | display: flex; 3 | align-items: center; 4 | justify-content: space-between; 5 | } 6 | 7 | .hidden { 8 | display: none; 9 | } 10 | 11 | .site-layout .site-layout-background { 12 | height: 5%; 13 | margin-top: 20%; 14 | display: flex; 15 | padding-top: 1%; 16 | justify-content: center; 17 | align-items: center; 18 | color: white; 19 | border-radius: 0 5px 5px 0; 20 | width: 2% !important; 21 | flex: 0 !important; 22 | max-width: auto !important; 23 | min-width: auto !important; 24 | } 25 | -------------------------------------------------------------------------------- /src/components/common/ScheduleMeeting.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import CalendarFeature from './Calendar'; 3 | // import SwitchablePicker from './DialogButton/ScheduleButton'; 4 | 5 | // SwitchablePicker is throwing up a lot of errors, and it seems incomplete 6 | // so for the time being, that addition is commented out. 7 | const ScheduleMeeting = () => { 8 | return ( 9 | <> 10 | 11 | {/*
12 | 13 |
*/} 14 | 15 | ); 16 | }; 17 | 18 | export default ScheduleMeeting; 19 | -------------------------------------------------------------------------------- /src/__tests__/NotFoundPage.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import { BrowserRouter as Router } from 'react-router-dom'; 4 | import { NotFoundPage } from '../components/pages/NotFound'; 5 | 6 | describe('Loading Common Component', () => { 7 | test('it should mount a div based on props', () => { 8 | const { getByText } = render( 9 | 10 | 11 | 12 | ); 13 | const h1 = getByText(/404 page not found/i); 14 | expect(h1.textContent).toBe('404 Page Not Found'); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /src/components/common/styles/Calendar.css: -------------------------------------------------------------------------------- 1 | .events { 2 | margin: 0; 3 | padding: 0; 4 | list-style: none; 5 | } 6 | .events .ant-badge-status { 7 | width: 100%; 8 | overflow: hidden; 9 | font-size: 12px; 10 | white-space: nowrap; 11 | text-overflow: ellipsis; 12 | } 13 | .notes-month { 14 | font-size: 28px; 15 | text-align: center; 16 | } 17 | .notes-month section { 18 | font-size: 28px; 19 | } 20 | .DialogBox { 21 | display: flex; 22 | margin-top: 2%; 23 | justify-content: center; 24 | } 25 | .description { 26 | background-color: white; 27 | color: black; 28 | height: 150px; 29 | } 30 | -------------------------------------------------------------------------------- /src/components/common/constants/techstack.js: -------------------------------------------------------------------------------- 1 | const tech_stack = [ 2 | { 3 | label: 'Android', 4 | value: 'Android', 5 | }, 6 | { 7 | label: 'Backend', 8 | value: 'Backend', 9 | }, 10 | { 11 | label: 'Data Science', 12 | value: 'Data Science', 13 | }, 14 | { 15 | label: 'Design UI/UX', 16 | value: 'Design UI/UX', 17 | }, 18 | { 19 | label: 'Frontend', 20 | value: 'Frontend', 21 | }, 22 | { 23 | label: 'Full Stack', 24 | value: 'Full Stack', 25 | }, 26 | { 27 | label: 'iOS', 28 | value: 'iOS', 29 | }, 30 | ]; 31 | 32 | export default tech_stack; 33 | -------------------------------------------------------------------------------- /src/components/pages/Navbar/NavbarFeatures/ExampleFeature.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Button } from 'antd'; 3 | 4 | // Make this component yours!! 5 | 6 | // Rename File name 7 | 8 | // Rename function name on line 16 9 | 10 | // Rename className on line 18 11 | 12 | // Rename export on line 24 13 | 14 | // Import component in index.js 15 | 16 | const ExampleFeature = () => { 17 | return ( 18 |
19 | {/* Your Component Here */} 20 | 23 |
24 | ); 25 | }; 26 | export default ExampleFeature; 27 | -------------------------------------------------------------------------------- /src/components/common/Size&Devices.js: -------------------------------------------------------------------------------- 1 | const size = { 2 | mobileS: '320px', 3 | mobileM: '375px', 4 | mobileL: '425px', 5 | tablet: '768px', 6 | laptop: '1024px', 7 | laptopL: '1440px', 8 | desktop: '2560px', 9 | }; 10 | 11 | export const device = { 12 | mobileS: `(min-width: ${size.mobileS})`, 13 | mobileM: `(min-width: ${size.mobileM})`, 14 | mobileL: `(min-width: ${size.mobileL})`, 15 | tablet: `(min-width: ${size.tablet})`, 16 | laptop: `(min-width: ${size.laptop})`, 17 | laptopL: `(min-width: ${size.laptopL})`, 18 | desktop: `(min-width: ${size.desktop})`, 19 | desktopL: `(min-width: ${size.desktop})`, 20 | }; 21 | -------------------------------------------------------------------------------- /src/components/pages/AdminMeetingsDashBoard/DynamicDropdown.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Select } from 'antd'; 3 | 4 | const DynamicDropdown = ({ options, placeholder, onChange }) => { 5 | return ( 6 | 14 | option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0 15 | } 16 | style={{ width: 200 }} 17 | /> 18 | ); 19 | }; 20 | 21 | export default DynamicDropdown; 22 | -------------------------------------------------------------------------------- /src/components/pages/MentorMeetingsDashBoard/DynamicDropdown.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Select } from 'antd'; 3 | 4 | const DynamicDropdown = ({ options, placeholder, onChange }) => { 5 | return ( 6 | 20 | 21 | 22 | 23 | 24 | ); 25 | } 26 | 27 | export default Filter; 28 | -------------------------------------------------------------------------------- /src/components/common/Button.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | const Button = props => { 5 | // Here is a button for use when simply in need of a button that doesn't require to be wrapped in a form. 6 | // contains a click property for your use onClick 7 | return ( 8 | 15 | ); 16 | }; 17 | 18 | export default Button; 19 | 20 | Button.propTypes = { 21 | buttonText: PropTypes.string.isRequired, 22 | classType: PropTypes.string, 23 | disabled: PropTypes.string, 24 | handleClick: PropTypes.func, 25 | }; 26 | -------------------------------------------------------------------------------- /src/components/pages/RoleApply/Applications/README.dm: -------------------------------------------------------------------------------- 1 | ## Application and onboarding flow 2 | 3 | User will apply as a mentor/mentee (Mentor.js/Mentee.js). 4 | On submission of their application the user will be directed to '/apply/success' as confirmation that their application was successful. 5 | 6 | When/if the superAdmin approves the user, then the user will receive an email confirmation that they've been accepted. 7 | They will also receive a link to create their login information. 8 | 9 | It is unlikely, but possible, that the superAdmin will deny the application--in which case the user will receive an email to this effect. 10 | 11 | This flow is designed to save the stakeholder costs for creating users that MIGHT not continue with the program. 12 | This flow only creates a user after it is confirmed that the user will continue. -------------------------------------------------------------------------------- /src/components/pages/RoleApply/Applications/README.md: -------------------------------------------------------------------------------- 1 | ## Application and onboarding flow 2 | 3 | User will apply as a mentor/mentee (Mentor.js/Mentee.js). 4 | On submission of their application the user will be directed to '/apply/success' as confirmation that their application was successful. 5 | 6 | When/if the superAdmin approves the user, then the user will receive an email confirmation that they've been accepted. 7 | They will also receive a link to create their login information. 8 | 9 | It is unlikely, but possible, that the superAdmin will deny the application--in which case the user will receive an email to this effect. 10 | 11 | This flow is designed to save the stakeholder costs for creating users that MIGHT not continue with the program. 12 | This flow only creates a user after it is confirmed that the user will continue. 13 | -------------------------------------------------------------------------------- /src/state/actions/allUsers/setAllUsers.js: -------------------------------------------------------------------------------- 1 | import { Tag } from 'antd'; 2 | 3 | export const SET_ALL_MENTORS = 'SET_ALL_MENTORS'; 4 | export const SET_ALL_MENTEES = 'SET_ALL_MENTEES'; 5 | 6 | export const setAllUsers = (list, role) => { 7 | let payload = list.map(row => { 8 | return { 9 | name: `${row.first_name} ${row.last_name}`, 10 | numberOfMatches: 11 | row.matches && row.matches.length > 0 ? ( 12 | row.matches.length 13 | ) : ( 14 | No Matches 15 | ), 16 | role: role === 'mentor' ? 'Mentor' : 'Mentee', 17 | matches: row.matches === undefined ? [] : row.matches, 18 | ...row, 19 | }; 20 | }); 21 | if (role === 'mentor') { 22 | return { type: SET_ALL_MENTORS, payload }; 23 | } else { 24 | return { type: SET_ALL_MENTEES, payload }; 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /src/state/actions/mentee/index.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import { API_URL } from '../../../config'; 3 | 4 | import { setFetchError } from '../errors/setFetchError'; 5 | import { setFetchEnd } from '../lifecycle/setFetchEnd'; 6 | import { setFetchStart } from '../lifecycle/setFetchStart'; 7 | 8 | export const MENTEE_ADD_SUCCESS = 'MENTEE_ADD_SUCCESS'; 9 | 10 | export const postNewMenteeAccount = newAccount => { 11 | return async dispatch => { 12 | try { 13 | dispatch(setFetchStart()); 14 | const api = await axios.post( 15 | `${API_URL}application/new/mentee`, 16 | newAccount 17 | ); 18 | dispatch({ type: MENTEE_ADD_SUCCESS, payload: api }); 19 | return api; 20 | } catch (err) { 21 | throw new Error(err, dispatch(setFetchError(err))); 22 | } finally { 23 | dispatch(setFetchEnd()); 24 | } 25 | }; 26 | }; 27 | -------------------------------------------------------------------------------- /src/state/actions/userMatches/getUserMatches.js: -------------------------------------------------------------------------------- 1 | import { setUserMatches } from './setUserMatches'; 2 | import axios from 'axios'; 3 | import { API_URL } from '../../../config'; 4 | 5 | export const getUserMatches = (arrOfProfileIDs, role) => async dispatch => { 6 | if (arrOfProfileIDs) { 7 | role === 'mentor' ? (role = 'mentee') : (role = 'mentor'); 8 | const results = []; 9 | let n = 0; 10 | if (arrOfProfileIDs.length > 0) { 11 | while (n < arrOfProfileIDs.length) { 12 | const res = await axios({ 13 | method: 'post', 14 | url: `${API_URL}matches/read/${role}`, 15 | data: { 16 | profile_id: arrOfProfileIDs[n], 17 | }, 18 | }); 19 | results.push(res.data[0]); 20 | n++; 21 | } 22 | } 23 | return dispatch(setUserMatches(results)); 24 | } else { 25 | return; 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /src/components/pages/Memos/Memo.less: -------------------------------------------------------------------------------- 1 | .memoModal { 2 | .ant-radio-inner::after { 3 | margin-top: 0px; 4 | margin-left: 0px; 5 | } 6 | 7 | .memos-column-container { 8 | display: flex; 9 | flex-direction: column; 10 | } 11 | 12 | .memos-column-container label { 13 | background: #0000; 14 | margin: 0px; 15 | } 16 | 17 | .memos-input-rows { 18 | display: flex; 19 | justify-content: space-between; 20 | } 21 | 22 | .memos-button-rows { 23 | display: flex; 24 | gap: 1em; 25 | } 26 | 27 | .margin-top-1 { 28 | margin-top: 1%; 29 | } 30 | 31 | .add-memo-button { 32 | display: flex; 33 | align-items: center; 34 | padding: 1em 0.5em; 35 | } 36 | 37 | .ant-radio-checked .ant-radio-inner { 38 | border-color: #1990ff !important; 39 | } 40 | 41 | .ant-radio:hover .ant-radio-inner { 42 | border-color: #1990ff !important; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/components/common/styles/Memos.css: -------------------------------------------------------------------------------- 1 | .flag { 2 | display: flex; 3 | justify-content: center; 4 | width: 45%; 5 | border-radius: 20px; 6 | padding: 2px 1em; 7 | font-size: 12px; 8 | font-weight: bold; 9 | text-transform: capitalize; 10 | opacity: 0.8; 11 | color: #000; 12 | } 13 | 14 | .darkFlag { 15 | color: #000; 16 | } 17 | 18 | .cell-text { 19 | text-transform: capitalize; 20 | } 21 | 22 | /* Priority Column */ 23 | .priority-low { 24 | background-color: #6bcb77; 25 | } 26 | 27 | .priority-medium { 28 | background-color: #ffd93d; 29 | } 30 | 31 | .priority-urgent { 32 | background-color: #ff6b6b; 33 | } 34 | 35 | /* Status Column */ 36 | .status-container { 37 | display: flex; 38 | gap: 0.5em; 39 | } 40 | 41 | .memo-menu-btns { 42 | display: flex; 43 | justify-content: flex-end; 44 | } 45 | 46 | .created-by-filter-menu { 47 | padding: 0.5em; 48 | } 49 | 50 | span.badge-container { 51 | width: 25px; 52 | } 53 | -------------------------------------------------------------------------------- /src/state/actions/applications/applicationModal.js: -------------------------------------------------------------------------------- 1 | import { notification } from 'antd'; 2 | 3 | export const OPEN_NOTIFICATION = 'OPEN_NOTIFICATION'; 4 | 5 | export const openNotificationWithIcon = (type, status, err) => { 6 | if (type === 'success') { 7 | if (status === 'approved') { 8 | notification[type]({ 9 | message: 'User has been approved successfully', 10 | }); 11 | } else { 12 | notification[type]({ 13 | message: 'User has been rejected successfully', 14 | }); 15 | } 16 | } 17 | 18 | if (type === 'error') { 19 | if (status === 'approved') { 20 | notification[type]({ 21 | message: 'User could not be approved at this time', 22 | description: `Error: ${err}`, 23 | }); 24 | } else { 25 | notification[type]({ 26 | message: 'User could not be rejected at this time', 27 | description: `Error: ${err}`, 28 | }); 29 | } 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /src/auth/auth0ProviderWithHistory.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useHistory } from 'react-router-dom'; 3 | import { Auth0Provider } from '@auth0/auth0-react'; 4 | 5 | const Auth0ProviderWithHistory = ({ children }) => { 6 | const domain = process.env.REACT_APP_AUTH0_DOMAIN; 7 | const clientId = process.env.REACT_APP_AUTH0_CLIENT_ID; 8 | const audience = process.env.REACT_APP_AUTH0_AUDIENCE; 9 | const history = useHistory(); 10 | 11 | const onRedirectCallback = appState => { 12 | history.push(appState?.returnTo || window.location.pathname); 13 | }; 14 | 15 | return ( 16 | 24 | {children} 25 | 26 | ); 27 | }; 28 | 29 | export default Auth0ProviderWithHistory; 30 | -------------------------------------------------------------------------------- /src/components/pages/RoleApply/Applications/AppSuccess.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Col, Row, Typography, Button } from 'antd'; 3 | import { useHistory } from 'react-router-dom'; 4 | 5 | const { Title } = Typography; 6 | 7 | export default function AppSuccess() { 8 | let history = useHistory(); 9 | const handleHomeClick = () => { 10 | history.push('/'); 11 | }; 12 | 13 | return ( 14 | <> 15 | 16 | 17 | Thank you! 18 | 19 | 20 | 21 | Your application has been received, keep an eye on your email, as 22 | we'll email you if your application has been approved. 23 | 24 | 25 | 26 | 27 | 28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /src/components/common/FormInput.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Button, Form, Input } from 'antd'; 3 | 4 | // const FormInput = props => { 5 | const FormInput = ({ onChange, onSubmit, submitting, onCancel, value }) => ( 6 | <> 7 | 8 | 9 | 10 | 11 | 20 | {/* */} 21 | 22 | 23 | ); 24 | 25 | export default FormInput; 26 | 27 | // FormInput.propTypes = { 28 | // placeholder: PropTypes.string.isRequired, 29 | // // name: PropTypes.string.isRequired, 30 | // labelId: PropTypes.string.isRequired, 31 | // value: PropTypes.string, 32 | // handleInput: PropTypes.func, 33 | // }; 34 | -------------------------------------------------------------------------------- /src/components/pages/FooterLanding/FooterCol.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link } from 'react-router-dom'; 3 | import { ColStyle } from './FooterStyle'; 4 | 5 | export default function FooterCol({ 6 | heading = 'Col Heading', 7 | links = [ 8 | { 9 | type: 'Link', 10 | title: 'Home', 11 | path: '/home', 12 | }, 13 | { 14 | type: 'Link', 15 | title: 'About', 16 | path: '/about', 17 | }, 18 | ], 19 | }) { 20 | return ( 21 | 22 |

{heading}

23 |
24 | {links.map((item, index) => ( 25 |
26 | {item.type === 'Link' ? ( 27 | {item.title} 28 | ) : ( 29 | 30 | {item.title} 31 | 32 | )} 33 |
34 | ))} 35 |
36 |
37 | ); 38 | } 39 | -------------------------------------------------------------------------------- /src/state/REDUX_README.md: -------------------------------------------------------------------------------- 1 | ===== REDUX GUIDELINES ===== 2 | A redux store was added to the project and connected to multiple components. Below is a simple set of guidelines for future dev teams to keep in mind when creating components in the future, and whether or not to use local state or global via Redux: 3 | 4 | (1) Ask yourself, is the slice of state accessed across multiple components in the application? 5 | 6 | (2) If it's accessed across multiple components, how many levels down of props drilling is required? 7 | 8 | (3) When dispatching actions, please use dispatch instead of importing them using Connect for consistency and clarity (i.e., to mitigate confusion if another engineer was looking at a component, they can see that the action is getting dispatch). 9 | 10 | (4) The project is leveraging a rootReduce file to help manage the number of reducer files. If a new reducer is necessary, after adding the file, be sure to import that reducer into rootReduce (index.js) file to keep files clean and organized. 11 | -------------------------------------------------------------------------------- /src/components/common/constants/states.js: -------------------------------------------------------------------------------- 1 | const states = [ 2 | 'Alabama', 3 | 'Alaska', 4 | 'Arizona', 5 | 'Arkansas', 6 | 'California', 7 | 'Colorado', 8 | 'Connecticut', 9 | 'Delaware', 10 | 'Florida', 11 | 'Georgia', 12 | 'Hawaii', 13 | 'Idaho', 14 | 'Illinois', 15 | 'Indiana', 16 | 'Iowa', 17 | 'Kansas', 18 | 'Kentucky', 19 | 'Louisiana', 20 | 'Maine', 21 | 'Maryland', 22 | 'Massachusetts', 23 | 'Michigan', 24 | 'Minnesota', 25 | 'Mississippi', 26 | 'Missouri', 27 | 'MontanaNebraska', 28 | 'Nevada', 29 | 'New Hampshire', 30 | 'New Jersey', 31 | 'New Mexico', 32 | 'New York', 33 | 'North Carolina', 34 | 'North Dakota', 35 | 'Ohio', 36 | 'Oklahoma', 37 | 'Oregon', 38 | 'Pennsylvania', 39 | 'Rhode Island', 40 | 'South Carolina', 41 | 'South Dakota', 42 | 'Tennessee', 43 | 'Texas', 44 | 'Utah', 45 | 'Vermont', 46 | 'Virginia', 47 | 'Washington', 48 | 'West Virginia', 49 | 'Wisconsin', 50 | 'Wyoming', 51 | ]; 52 | 53 | export default states; 54 | -------------------------------------------------------------------------------- /src/components/pages/RoleApply/Applications/Styles/mentorApplication.css: -------------------------------------------------------------------------------- 1 | .container { 2 | display: flex; 3 | justify-content: center; 4 | letter-spacing: 1px; 5 | } 6 | #mentorSubmitButton { 7 | background-color: #003d71; 8 | color: #fff; 9 | margin-bottom: 2vh; 10 | } 11 | .mentorTitle { 12 | background-color: #003d71; 13 | color: #ffffff !important; 14 | text-align: center; 15 | width: 100%; 16 | border-top-right-radius: 12px; 17 | border-top-left-radius: 12px; 18 | padding: 2rem; 19 | } 20 | .user-app-form-input.ant-input-status-error { 21 | background-color: transparent !important; 22 | } 23 | 24 | .col-container { 25 | padding: 2rem; 26 | } 27 | .em { 28 | display: flex; 29 | width: 50%; 30 | } 31 | 32 | .main-col-container { 33 | padding: 2rem; 34 | } 35 | .row-container { 36 | display: flex; 37 | gap: 2rem; 38 | } 39 | .form-group { 40 | display: flex; 41 | flex-direction: column; 42 | gap: 20px; 43 | } 44 | @media only screen and (max-width: 600px) { 45 | .main-col-container { 46 | padding: 1rem; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/components/pages/ProfileList/ProfileListContainer.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { getProfileData } from '../../../api'; 4 | 5 | import { List } from '../../common'; 6 | 7 | import RenderProfileListPage from './RenderProfileListPage'; 8 | 9 | // Here is an example of using our reusable List component to display some list data to the UI. 10 | const ProfileList = () => { 11 | // Variable is created as place-holder. Function destroyed while removing Okta 12 | const authState = null; 13 | return ( 14 | getProfileData(authState)} 17 | // Here we are passing in a component we want to show whilst waiting for our API request 18 | // to complete. 19 | LoadingComponent={() =>
Loading Profiles...
} 20 | // Here we are passing in a component that receives our new data and returns our JSX elements. 21 | RenderItems={RenderProfileListPage} 22 | /> 23 | ); 24 | }; 25 | 26 | export default ProfileList; 27 | -------------------------------------------------------------------------------- /src/components/pages/Memos/MyMemos.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { Button } from 'antd'; 3 | import { PlusCircleOutlined } from '@ant-design/icons'; 4 | import MemosTable from '../../common/MemosTable'; 5 | import MemosForm from './MemosForm'; 6 | const MyMemos = () => { 7 | const [displayModal, setDisplayModal] = useState(false); 8 | 9 | const showModal = () => { 10 | setDisplayModal(true); 11 | }; 12 | 13 | return ( 14 | <> 15 |
16 |

My Memos

17 | 20 | 24 | 28 |
29 | 30 | 31 | ); 32 | }; 33 | 34 | export default MyMemos; 35 | -------------------------------------------------------------------------------- /src/state/actions/auth/authenticateUser.js: -------------------------------------------------------------------------------- 1 | import { setFetchStart } from '../lifecycle/setFetchStart'; 2 | import { setFetchEnd } from '../lifecycle/setFetchEnd'; 3 | import { setFetchError } from '../errors/setFetchError'; 4 | import { setProfileId } from './setProfileId'; 5 | import { setIsAuthenticated } from './setIsAuthenticated'; 6 | 7 | //TODO: needs to be refactored with Auth0 equivalents and then re-imported into PrivateRoute to renew functionality. 8 | export const authenticateUser = (authState, oktaAuth) => dispatch => { 9 | if (oktaAuth.isAuthenticated) { 10 | dispatch(setFetchStart()); 11 | oktaAuth 12 | .getUser() 13 | .then(parsedJWT => { 14 | const profile_id = parsedJWT.sub; // sub = profile_id from Okta JWT 15 | dispatch(setProfileId(profile_id)); 16 | dispatch(setIsAuthenticated(true)); 17 | 18 | localStorage.setItem('token', authState.idToken.idToken); 19 | }) 20 | .catch(error => { 21 | dispatch(setFetchError(error)); 22 | }) 23 | .finally(() => dispatch(setFetchEnd())); 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 labs-master 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/components/pages/ProfileList/RenderProfileListPage.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link } from 'react-router-dom'; 3 | import PropTypes from 'prop-types'; 4 | 5 | const RenderProfileListPage = props => ( 6 |
7 |

8 | Home 9 |

10 | {props.data.map(item => ( 11 |
12 |
13 |

{item.name}

14 |
15 |
16 | ))} 17 |
18 | ); 19 | 20 | export default RenderProfileListPage; 21 | 22 | // Don't forget your prop types! It will save you a lot of debugging headache as you add more features. 23 | RenderProfileListPage.propTypes = { 24 | data: PropTypes.arrayOf( 25 | // Here is an example of enforcing an object structure that we expect to receive in our props: 26 | PropTypes.shape({ 27 | // Here we require an id of type number or string to prevent a "unique key prop" warning 28 | id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, 29 | name: PropTypes.string, 30 | email: PropTypes.string, 31 | }) 32 | ).isRequired, 33 | }; 34 | -------------------------------------------------------------------------------- /src/components/pages/Analytics/TechStackGraph.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react'; 2 | import { API_URL } from '../../../config'; 3 | import axios from 'axios'; 4 | import embed from 'vega-embed'; 5 | import { connect } from 'react-redux'; 6 | 7 | //vega-embed allows us to take a graph object, and display it on the ui. 8 | // for more information visit https://github.com/vega/vega-embed 9 | function TechStackGraph({ themeRedux }) { 10 | const [graphData, setGraphData] = useState({ graph: {}, description: '' }); 11 | 12 | useEffect(() => { 13 | axios 14 | .post(`${API_URL}analytics/graph/tech`, { theme: themeRedux }) 15 | .then(res => { 16 | setGraphData(res.data); 17 | }) 18 | .catch(err => console.error(err)); 19 | }, [themeRedux]); 20 | 21 | embed('#vis', graphData.graph); 22 | 23 | return ( 24 | <> 25 |

{graphData.description}

26 |
27 | 28 | ); 29 | } 30 | 31 | const mapStateToProps = state => { 32 | return { themeRedux: state.theme.theme }; 33 | }; 34 | 35 | export default connect(mapStateToProps)(TechStackGraph); 36 | -------------------------------------------------------------------------------- /src/state/actions/userMatches/getSuggestedMatches.js: -------------------------------------------------------------------------------- 1 | import { setSuggestedMatches } from './setSuggestedMatches'; 2 | import axios from 'axios'; 3 | import { API_URL } from '../../../config'; 4 | 5 | export const getSuggestedMatches = (profile_id, role) => async dispatch => { 6 | const results = []; 7 | let n = 0; 8 | const arrOfProfIDs = await axios({ 9 | method: 'post', 10 | url: `${API_URL}matches/${role}/${profile_id}`, 11 | data: { 12 | profile_id: `${profile_id}`, 13 | }, 14 | }) 15 | .then(resp => { 16 | return resp.data; 17 | }) 18 | .catch(err => console.error(err)); 19 | if (arrOfProfIDs.length > 0) { 20 | while (n < arrOfProfIDs.length) { 21 | const newRole = role === 'mentee' ? 'mentor' : 'mentee'; 22 | const res = await axios({ 23 | method: 'post', 24 | url: `${API_URL}matches/read/${newRole}`, 25 | data: { 26 | profile_id: arrOfProfIDs[n], 27 | }, 28 | }); 29 | results.push(res.data[0]); 30 | n++; 31 | } 32 | } else { 33 | dispatch(setSuggestedMatches([])); 34 | } 35 | return dispatch(setSuggestedMatches(results)); 36 | }; 37 | -------------------------------------------------------------------------------- /src/components/pages/SuperAdminForm/SuperAdminFormStyle.css: -------------------------------------------------------------------------------- 1 | .base { 2 | border-color: #002f5d; 3 | background: #002f5d; 4 | color: #f7f2fa; 5 | font-family: Raleway, 'Open Sans', 'Helvetica Neue', sans-serif; 6 | } 7 | 8 | .flexContainer { 9 | border: 2px solid grey; 10 | border-radius: 5px; 11 | width: 35%; 12 | margin: auto; 13 | display: flex; 14 | flex-flow: column nowrap; 15 | justify-content: stretch; 16 | align-items: stretch; 17 | margin-bottom: 20px; 18 | } 19 | 20 | h1 { 21 | margin: auto; 22 | background: #003d71; 23 | color: #f7fcfc; 24 | width: 100%; 25 | text-align: center; 26 | margin-bottom: 10px; 27 | } 28 | 29 | .field { 30 | width: 100%; 31 | } 32 | 33 | label { 34 | margin-left: 10px; 35 | width: 100%; 36 | } 37 | 38 | .ant-row { 39 | justify-content: flex-start; 40 | } 41 | 42 | .successMessage { 43 | color: red; 44 | margin: auto; 45 | width: 100%; 46 | text-align: center; 47 | } 48 | 49 | .buttonGroup { 50 | display: flex; 51 | flex-flow: row nowrap; 52 | justify-content: space-evenly; 53 | margin-bottom: 15px; 54 | } 55 | 56 | .feedbackMessage { 57 | color: red; 58 | margin-bottom: 15px; 59 | } 60 | -------------------------------------------------------------------------------- /src/components/pages/RoleApply/Applications/AppRejected.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'react-redux'; 3 | import { Col, Row, Typography, Button } from 'antd'; 4 | import { useHistory } from 'react-router-dom'; 5 | 6 | const { Title } = Typography; 7 | 8 | function AppRejected(props) { 9 | let history = useHistory(); 10 | const handleHomeClick = () => { 11 | history.push('/'); 12 | }; 13 | 14 | let { currentUser } = props; 15 | 16 | return ( 17 | <> 18 | 19 | 20 | 21 | You are not currently an active member of Underdog Devs. If you 22 | believe you have reached this page in error email{' '} 23 | underdogdevs@gmail.com 24 | 25 | 26 | 27 | 28 | 29 | ); 30 | } 31 | 32 | const mapStateToProps = state => { 33 | return { currentUser: state.user.currentUser }; 34 | }; 35 | 36 | export default connect(mapStateToProps)(AppRejected); 37 | -------------------------------------------------------------------------------- /src/components/pages/Memos/Memos.js: -------------------------------------------------------------------------------- 1 | /* 2 | All of the commented out code on this page is to remove the 'no-unused-vars' warnings in the console 3 | */ 4 | import React, { useState } from 'react'; 5 | import { Button } from 'antd'; 6 | import { PlusCircleOutlined } from '@ant-design/icons'; 7 | import MemosForm from './MemosForm'; 8 | import MemosTable from '../../common/MemosTable'; 9 | 10 | const Memos = props => { 11 | const [displayModal, setDisplayModal] = useState(false); 12 | 13 | const showModal = () => { 14 | setDisplayModal(true); 15 | }; 16 | 17 | return ( 18 | <> 19 |
20 |

Memos

21 | 24 | 28 | 32 |
33 | 34 | 35 | ); 36 | }; 37 | 38 | export default Memos; 39 | -------------------------------------------------------------------------------- /pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change. 4 | 5 | Fixes # (issue) 6 | 7 | ## Loom Video 8 | 9 | Please paste a link here of a quick loom video walking through what you did in your PR . 10 | 11 | ## Type of change 12 | 13 | Please delete options that are not relevant. 14 | 15 | - [ ] Bug fix (non-breaking change which fixes an issue) 16 | - [ ] New feature (non-breaking change which adds functionality) 17 | - [ ] This change requires a documentation update 18 | 19 | ## Checklist: 20 | 21 | - [ ] My code follows the style guidelines of this project 22 | - [ ] I have performed a self-review of my own code 23 | - [ ] I have removed unnecessary comments/console logs from my code 24 | - [ ] I have made corresponding changes to the documentation if necessary (optional) 25 | - [ ] My changes generate no new warnings 26 | - [ ] I have checked my code and corrected any misspellings 27 | - [ ] No duplicate code left within changed files 28 | - [ ] Size of pull request kept to a minimum 29 | - [ ] Pull request description clearly describes changes made & motivations for said changes 30 | -------------------------------------------------------------------------------- /src/components/pages/FooterLanding/FooterStyle.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const FooterStyle = styled.div` 4 | .container { 5 | display: flex; 6 | gap: 3rem; 7 | } 8 | .footer__col1, 9 | .footer__col5 { 10 | flex: 2; 11 | } 12 | .footer__col2, 13 | .footer__col3, 14 | .footer__col4 { 15 | flex: 15; 16 | } 17 | .copyright { 18 | text-align: left; 19 | padding: 1rem 0; 20 | } 21 | @media only screen and (max-width: 768px) { 22 | .container { 23 | display: flex; 24 | flex-wrap: wrap; 25 | justify-content: space-between; 26 | gap: 0rem; 27 | & > div { 28 | margin-top: 5%; 29 | } 30 | } 31 | .footer__col1 { 32 | width: 100%; 33 | flex-basis: 100%; 34 | display: flex; 35 | justify-content: center; 36 | } 37 | .footer__col2, 38 | .footer__col3, 39 | .footer__col4 { 40 | margin: 0 auto; 41 | padding: 0 1% 0 1%; 42 | } 43 | .copyright { 44 | .container { 45 | div { 46 | margin-top: 0; 47 | } 48 | } 49 | } 50 | } 51 | `; 52 | 53 | export const ColStyle = styled.div` 54 | .heading { 55 | font-size: 1.2rem; 56 | } 57 | a { 58 | font-size: 1rem; 59 | } 60 | `; 61 | -------------------------------------------------------------------------------- /src/components/pages/RoleApply/Applications/AppPending.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'react-redux'; 3 | import { Col, Row, Typography, Button } from 'antd'; 4 | import { useHistory } from 'react-router-dom'; 5 | 6 | const { Title } = Typography; 7 | 8 | function AppPending(props) { 9 | let history = useHistory(); 10 | const handleHomeClick = () => { 11 | history.push('/'); 12 | }; 13 | 14 | let { currentUser } = props; 15 | 16 | return ( 17 | <> 18 | 19 | 20 | Pending Application 21 | 22 | 23 | 24 | Hello {currentUser.first_name}! Your {currentUser.role} application 25 | is still under review! Keep an eye on your email, as we'll email you 26 | if your application has been approved. 27 | 28 | 29 | 30 | 31 | 32 | ); 33 | } 34 | 35 | const mapStateToProps = state => { 36 | return { currentUser: state.user.currentUser }; 37 | }; 38 | 39 | export default connect(mapStateToProps)(AppPending); 40 | -------------------------------------------------------------------------------- /src/state/reducers/applicationsReducer.js: -------------------------------------------------------------------------------- 1 | import { 2 | HANDLE_APPLICATION_APPROVE, 3 | HANDLE_APPLICATION_REJECT, 4 | } from '../actions/applications/handleApplications'; 5 | 6 | import { SET_CURRENT_APPLICATION } from '../actions/applications/setCurrentApplication'; 7 | 8 | const initialState = { 9 | currentApplication: { 10 | role: '', 11 | status: 'pending', 12 | }, 13 | }; 14 | 15 | const applicationsReducer = (state = initialState, action) => { 16 | switch (action.type) { 17 | case HANDLE_APPLICATION_APPROVE: 18 | return { 19 | ...state, 20 | status: { 21 | ...state.status, 22 | props: { 23 | color: 'green', 24 | children: action.payload.status, 25 | }, 26 | }, 27 | }; 28 | case HANDLE_APPLICATION_REJECT: 29 | return { 30 | ...state, 31 | status: { 32 | ...state.status, 33 | props: { 34 | color: 'red', 35 | children: action.payload, 36 | }, 37 | }, 38 | }; 39 | case SET_CURRENT_APPLICATION: 40 | return { 41 | ...state, 42 | currentApplication: action.payload, 43 | }; 44 | default: 45 | return state; 46 | } 47 | }; 48 | 49 | export default applicationsReducer; 50 | -------------------------------------------------------------------------------- /src/state/actions/mentor/index.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import { API_URL } from '../../../config'; 3 | 4 | import { setFetchError } from '../errors/setFetchError'; 5 | import { setFetchEnd } from '../lifecycle/setFetchEnd'; 6 | import { setFetchStart } from '../lifecycle/setFetchStart'; 7 | 8 | export const MENTOR_ADD_SUCCESS = 'MENTOR_ADD_SUCCESS'; 9 | export const MENTOR_ADD_FAILURE = 'MENTOR_ADD_FAILURE'; 10 | 11 | export const postNewMentorAccount = newAccount => { 12 | return async dispatch => { 13 | axios 14 | .post(`application/new/mentor`, newAccount) 15 | .then(() => { 16 | dispatch({ 17 | type: MENTOR_ADD_SUCCESS, 18 | payload: { successPage: '/apply/success' }, 19 | }); 20 | }) 21 | .catch(err => { 22 | dispatch({ type: MENTOR_ADD_FAILURE, payload: { mentorError: err } }); 23 | }); 24 | try { 25 | dispatch(setFetchStart()); 26 | const api = await axios.post( 27 | `${API_URL}application/new/mentor`, 28 | newAccount 29 | ); 30 | dispatch({ type: MENTOR_ADD_SUCCESS, payload: api }); 31 | return api; 32 | } catch (err) { 33 | throw new Error(err, dispatch(setFetchError(err))); 34 | } finally { 35 | dispatch(setFetchEnd()); 36 | } 37 | }; 38 | }; 39 | -------------------------------------------------------------------------------- /src/state/actions/index.js: -------------------------------------------------------------------------------- 1 | export { SET_PROFILE_ID } from './auth/setProfileId'; 2 | export { SET_IS_AUTHENTICATED } from './auth/setIsAuthenticated'; 3 | export { SET_USER_PROFILE } from './userProfile/setUserProfile'; 4 | export { SET_APPLICATION_PROFILE } from './userProfile/setApplicationProfile'; 5 | export { SET_CURRENTUSER_PROFILE } from './userProfile/setCurrentUser'; 6 | export { SET_FETCH_START } from './lifecycle/setFetchStart'; 7 | export { SET_FETCH_END } from './lifecycle/setFetchEnd'; 8 | export { SET_FETCH_ERROR } from './errors/setFetchError'; 9 | export { MENTOR_ADD_SUCCESS } from './mentor'; 10 | export { MENTEE_ADD_SUCCESS } from './mentee'; 11 | export { SET_ROLE_ID } from './auth/setRoleId'; 12 | export { SET_ALL_MENTORS, SET_ALL_MENTEES } from './allUsers/setAllUsers'; 13 | export { SET_USER_MATCHES } from './userMatches/setUserMatches'; 14 | export { SET_SUGGESTED_MATCHES } from './userMatches/setSuggestedMatches'; 15 | export { SET_THEME } from './theme'; 16 | 17 | // CALENDAR ACTIONS---------------------- 18 | export const MENTOR_EVENT_STUB = 'MENTOR_EVENT_STUB'; 19 | export const getEventTemplateStub = event => { 20 | return { type: MENTOR_EVENT_STUB, payload: event }; 21 | }; 22 | export const MENTEE_EVENT_STUB = 'MENTEE_EVENT_STUB'; 23 | export const getEventTemplateStub2 = event => { 24 | return { type: MENTEE_EVENT_STUB, payload: event }; 25 | }; 26 | -------------------------------------------------------------------------------- /src/components/pages/Reviews/MentorReviews.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react'; 2 | import useAxiosWithAuth0 from '../../../hooks/useAxiosWithAuth0'; 3 | import { Table } from 'antd'; 4 | 5 | const columns = [{ title: 'Mentor', dataIndex: 'name', key: 'name' }]; 6 | 7 | const Reviews = () => { 8 | const [reviews, setReviews] = useState([]); 9 | const axiosWithAuth = useAxiosWithAuth0(); 10 | 11 | useEffect(() => { 12 | const getReviews = () => { 13 | axiosWithAuth 14 | .get('/reviews') 15 | .then(res => { 16 | setReviews( 17 | res.data.map(row => ({ 18 | key: row.review_id, 19 | name: row.mentor_id, 20 | notes: 'Mentee ID: ' + row.mentee_id + '. Review: ' + row.review, 21 | })) 22 | ); 23 | }) 24 | .catch(err => { 25 | console.log(err); 26 | }); 27 | }; 28 | getReviews(); 29 | }); 30 | 31 | return ( 32 | <> 33 |

Mentor Reviews

34 | ( 40 |

{record.notes}

41 | ), 42 | }} 43 | /> 44 | 45 | ); 46 | }; 47 | 48 | export default Reviews; 49 | -------------------------------------------------------------------------------- /src/hooks/useTheme.js: -------------------------------------------------------------------------------- 1 | import useLocalStorage from './useLocalStorage'; 2 | import { useEffect } from 'react'; 3 | 4 | const stylesheets = { 5 | light: 'https://cdnjs.cloudflare.com/ajax/libs/antd/4.9.4/antd.min.css', 6 | dark: 'https://cdnjs.cloudflare.com/ajax/libs/antd/4.9.4/antd.dark.min.css', 7 | }; 8 | const createAntStylesheet = () => { 9 | const antStylesheet = document.createElement('link'); 10 | antStylesheet.rel = 'stylesheet'; 11 | antStylesheet.id = 'antd-stylesheet'; 12 | document.head.appendChild(antStylesheet); 13 | }; 14 | 15 | const checkMode = () => { 16 | const theme = localStorage.getItem('theme'); 17 | if (theme === null) { 18 | if (window.matchMedia('(prefers-color-scheme: dark)').matches) { 19 | localStorage.setItem('theme', 'dark'); 20 | return 'dark'; 21 | } else { 22 | localStorage.setItem('theme', 'light'); 23 | return 'light'; 24 | } 25 | } 26 | }; 27 | 28 | export default function useTheme() { 29 | const [theme, setTheme] = useLocalStorage('theme', checkMode()); 30 | const toggle = () => { 31 | if (theme === 'light') { 32 | setTheme('dark'); 33 | } else { 34 | setTheme('light'); 35 | } 36 | }; 37 | useEffect(() => { 38 | createAntStylesheet(); 39 | const antStylesheet = document.getElementById('antd-stylesheet'); 40 | antStylesheet.href = stylesheets[theme]; 41 | }, [theme]); 42 | return [theme, toggle]; 43 | } 44 | -------------------------------------------------------------------------------- /src/components/common/MemosTable/AddReply/Reply.css: -------------------------------------------------------------------------------- 1 | .popup { 2 | position: fixed; 3 | top: 0; 4 | left: 0; 5 | width: 100%; 6 | height: 100%; 7 | background-color: rgba(0, 0, 0, 0.2); 8 | display: flex; 9 | justify-content: center; 10 | align-items: center; 11 | overflow: hidden; 12 | z-index: 100; 13 | } 14 | .popup-inner { 15 | position: relative; 16 | padding: 32px; 17 | width: 100%; 18 | max-width: 640px; 19 | background-color: rgb(61, 61, 68); 20 | color: rgb(54, 50, 50); 21 | } 22 | .popup-inner .close-btn { 23 | position: absolute; 24 | top: 16px; 25 | right: 16px; 26 | background-color: rgba(43, 114, 190, 0.509); 27 | } 28 | 29 | .popup-inner h1 { 30 | color: white; 31 | display: flex; 32 | justify-content: center; 33 | font-size: 1.5rem; 34 | } 35 | 36 | .close-btn h1 { 37 | color: white; 38 | } 39 | 40 | .submit { 41 | margin-top: 2%; 42 | margin-left: 46%; 43 | background-color: rgba(43, 114, 190, 0.509); 44 | padding: 1%; 45 | border: 0; 46 | } 47 | .submit:hover { 48 | transform: translateY(3px); 49 | transition-duration: 0.2s, 1s; 50 | } 51 | 52 | .popup input, 53 | .popup label { 54 | width: 60%; 55 | background-color: rgb(245, 245, 245); 56 | margin-left: 11%; 57 | } 58 | 59 | @media only screen and (max-width: 990px) { 60 | .popup-inner { 61 | width: 55%; 62 | transition: all 1s ease; 63 | } 64 | 65 | .close-btn h1 { 66 | overflow: hidden; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/components/pages/FooterLanding/FooterLanding.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import logo from '../Navbar/ud_logo2.png'; 3 | import { FooterStyle } from './FooterStyle'; 4 | import FooterCol from './FooterCol'; 5 | import { Layout } from 'antd'; 6 | 7 | const { Footer } = Layout; 8 | 9 | export default function FooterLanding() { 10 | return ( 11 | <> 12 |
13 | 14 |
15 |
16 | underdog devs logo 23 |
24 |
25 | 45 |
46 |
47 |
48 |
49 | 50 | ); 51 | } 52 | -------------------------------------------------------------------------------- /src/components/pages/RoleApply/Applications/Styles/menteeApplication.css: -------------------------------------------------------------------------------- 1 | .menteeApplication { 2 | display: flex; 3 | padding: 2vh 6vw; 4 | justify-content: center; 5 | } 6 | 7 | .applicationForm { 8 | border-radius: 4px; 9 | } 10 | 11 | .menteeTitle { 12 | background-color: #003d71; 13 | text-align: center; 14 | color: #fff !important; 15 | padding: 1vh; 16 | } 17 | 18 | #container-main { 19 | margin: 2rem; 20 | width: 75%; 21 | border: 1px #002f5d solid; 22 | display: flex; 23 | flex-direction: column; 24 | align-items: center; 25 | border-radius: 13px; 26 | } 27 | 28 | #menteeSubmitButton { 29 | background-color: #003d71; 30 | color: #fff; 31 | margin-bottom: 2vh; 32 | } 33 | 34 | @media only screen and (max-width: 575px) { 35 | .menteeApplication { 36 | padding: 0; 37 | } 38 | .ant-form-large .ant-form-item-label > label { 39 | height: 80px; 40 | } 41 | } 42 | 43 | .mentorTitle { 44 | background-color: #003d71; 45 | color: #ffffff !important; 46 | text-align: center; 47 | width: 100%; 48 | border-top-right-radius: 12px; 49 | border-top-left-radius: 12px; 50 | padding: 2rem; 51 | } 52 | 53 | .main-col-container { 54 | padding: 0rem; 55 | } 56 | .row-container { 57 | display: flex; 58 | } 59 | .row-container1 { 60 | display: flex; 61 | gap: 1rem; 62 | } 63 | 64 | .form-group { 65 | display: flex; 66 | } 67 | @media only screen and (max-width: 600px) { 68 | .main-col-container { 69 | padding: 1rem; 70 | } 71 | .form-group { 72 | display: flex; 73 | gap: 0rem; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/state/actions/applications/handleApplications.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import { API_URL } from '../../../config'; 3 | 4 | import { setFetchError } from '../errors/setFetchError'; 5 | import { setFetchEnd } from '../lifecycle/setFetchEnd'; 6 | import { setFetchStart } from '../lifecycle/setFetchStart'; 7 | //?Not sure if I need these imports? 8 | 9 | import { openNotificationWithIcon } from './applicationModal'; 10 | 11 | export const HANDLE_APPLICATION_APPROVE = 'HANDLE_APPLICATION_APPROVE'; 12 | 13 | export const HANDLE_APPLICATION_REJECT = 'HANDLE_APPLICATION_REJECT'; 14 | 15 | export const handleApplication = (setDisplayModal, profileId, role, status) => { 16 | return async dispatch => { 17 | dispatch(setFetchStart()); 18 | axios 19 | .put(`${API_URL}application/update-validate_status/${profileId}`, { 20 | role: role, 21 | validate_status: status, 22 | }) 23 | .then(() => { 24 | setDisplayModal(false); 25 | openNotificationWithIcon('success', status); 26 | if (status === 'approved') { 27 | return { type: HANDLE_APPLICATION_APPROVE, payload: status }; 28 | } else if (status === 'rejected') { 29 | return { type: HANDLE_APPLICATION_REJECT, payload: status }; 30 | } 31 | dispatch(setFetchEnd()); 32 | }) 33 | .catch(err => { 34 | console.error(err); 35 | dispatch(setFetchError(err)); 36 | openNotificationWithIcon('error', status, err.message); 37 | dispatch(setFetchEnd()); 38 | }); 39 | }; 40 | }; 41 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | on: 3 | pull_request: 4 | push: 5 | branches: 6 | - main 7 | jobs: 8 | # A job to generate and publish code coverage 9 | lint: 10 | name: Run Lint on source 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | 17 | - uses: actions/setup-node@v1 18 | with: 19 | node-version: "14" 20 | 21 | - run: npm install 22 | 23 | - run: npm run lint 24 | 25 | # A job to generate and publish code coverage 26 | coverage: 27 | name: Test and publish test coverage 28 | 29 | # The OS on which the job will run 30 | runs-on: ubuntu-latest 31 | 32 | # The steps for the job, executed in sequence 33 | steps: 34 | # A GitHub action for checking out the current branch 35 | - uses: actions/checkout@master 36 | 37 | # A GitHub action to setup Node.js 38 | - uses: actions/setup-node@master 39 | with: 40 | node-version: "12" 41 | 42 | # Run the NPM install command before proceeding 43 | - run: npm install 44 | 45 | # A GitHub action for running tests and publishing coverage 46 | - uses: paambaati/codeclimate-action@v3.0.0 47 | env: 48 | # An environment variable, the value is a GitHub repo secret 49 | CC_TEST_REPORTER_ID: ${{ secrets.CODECLIMATEREPORTERID }} 50 | with: 51 | # Run our `coverage` script in our `package.json` 52 | coverageCommand: npm run coverage 53 | # Great for troubleshooting 54 | debug: true 55 | -------------------------------------------------------------------------------- /src/components/pages/Applications/ApplicationModal.less: -------------------------------------------------------------------------------- 1 | .modalStyleMentee, 2 | .modalStyleMentor { 3 | .ant-btn-primary { 4 | background-color: #003d71; 5 | } 6 | .ant-modal-title { 7 | color: white; 8 | display: flex; 9 | justify-content: center; 10 | font-size: 1.5rem; 11 | } 12 | .image-container { 13 | padding-left: 30px; 14 | margin-bottom: 5px; 15 | } 16 | img { 17 | border-radius: 200px; 18 | width: 80px; 19 | } 20 | .profile-intro { 21 | display: flex; 22 | justify-content: space-around; 23 | font-size: 0.75rem; 24 | } 25 | .profile-intro-description { 26 | margin-right: 6rem; 27 | padding-left: 40px; 28 | } 29 | .preferences { 30 | display: flex; 31 | } 32 | .tags-container { 33 | margin-left: 5px; 34 | } 35 | .list-item { 36 | display: flex; 37 | justify-content: center; 38 | } 39 | .list-item-column { 40 | display: flex; 41 | width: 50%; 42 | height: 100%; 43 | margin-top: 10px; 44 | } 45 | .list-item-column li { 46 | width: 100%; 47 | } 48 | p { 49 | margin: 0%; 50 | } 51 | ul { 52 | margin: 0%; 53 | padding-left: 0%; 54 | } 55 | li { 56 | margin-left: 5%; 57 | } 58 | } 59 | 60 | .modalStyleMentee { 61 | .ant-modal-header { 62 | background-color: #7cb305; 63 | } 64 | .mentee-tag { 65 | margin-left: 5px; 66 | } 67 | } 68 | .modalStyleMentor { 69 | .ant-modal-header { 70 | background-color: #2f54eb; 71 | } 72 | .mentor-tag { 73 | margin-top: 5px; 74 | margin-bottom: 5px; 75 | margin-left: 5px; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/__tests__/README.md: -------------------------------------------------------------------------------- 1 | ## Testing your Components 2 | 3 | - You will be using [jest]() along side with [React Testing Library]() to test your application. 4 | - Please put all of your tests for your code in this file. 5 | - You should get into the habit of ensuring that you have coverage for your code _before submitting a pull-request_. 6 | 7 | ### Running your tests 8 | 9 | - When writing tests run the command: 10 | - `cd into` the root of this directory 11 | - `npm test` to run your test suite 12 | - _if you're prompted_ select `a` to run tests in watch mode. This will re-run your test suite when you save any file in your application. 13 | - In your terminal you will see a test runner that looks something like this: 14 | ![Test screenshot](https://tk-assets.lambdaschool.com/bc9ca7b9-4fce-45de-9a16-705cbec062d8_ScreenShot2020-06-25at7.52.52AM.png) 15 | - When you're not actively writing tests its best to close that terminal window so that you don't keep running tests when your files are saved. 16 | 17 | ### Coverage 18 | 19 | > 💡 Code coverage should be a good goal to have and a good starting place. But every application will be different. 20 | 21 | - [Kent Dodds put it nicely](https://kentcdodds.com/blog/common-testing-mistakes#mistake-number-2-100-code-coverage). Strive for solid coverage as we strive to hand you over well-tested code in which we have extreme confidence. 22 | 23 | - To run a coverage report for your application simply run `npm run coverage`. 24 | - You should see a print out in your console that looks like this: 25 | ![code coverage](https://tk-assets.lambdaschool.com/5abec98b-2b61-483f-bd85-71002a9f755a_ScreenShot2020-06-25at7.59.14AM.png) 26 | -------------------------------------------------------------------------------- /src/components/pages/Dashboard/Dashboard.js: -------------------------------------------------------------------------------- 1 | import { useAuth0 } from '@auth0/auth0-react'; 2 | import { connect } from 'react-redux'; 3 | import { getProfile } from '../../../state/actions/userProfile/getProfile'; 4 | import Applications from '../Applications/Applications'; 5 | import MenteeMentorDashboard from '../MenteeMentorDashboard/MenteeMentorDashboard'; 6 | import Mentee from '../RoleApply/Applications/Mentee'; 7 | import Mentor from '../RoleApply/Applications/Mentor'; 8 | import AppPending from '../RoleApply/Applications/AppPending'; 9 | import AppRejected from '../RoleApply/Applications/AppRejected'; 10 | import LoadingComponent from '../../common/LoadingComponent'; 11 | 12 | const Dashboard = ({ currentUser }) => { 13 | const { user } = useAuth0(); 14 | 15 | const { role, tempProfile, validate_status, is_active } = currentUser; 16 | 17 | if (role === 'admin') { 18 | return ; 19 | } else if (validate_status === 'pending') { 20 | return ; 21 | } else if (validate_status === 'rejected' || is_active === false) { 22 | return ; 23 | } else if (!tempProfile && role === 'mentor') { 24 | return ; 25 | } else if (!tempProfile && role === 'mentee') { 26 | return ; 27 | } else if (tempProfile && role === 'mentor') { 28 | return ; 29 | } else if (tempProfile && role === 'mentee') { 30 | return ; 31 | } else { 32 | return ; 33 | } 34 | }; 35 | 36 | const mapStateToProps = state => { 37 | return { currentUser: state.user.currentUser }; 38 | }; 39 | 40 | export default connect(mapStateToProps, { getProfile })(Dashboard); 41 | -------------------------------------------------------------------------------- /wireframes/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |
5 |
6 | 7 | Logo 8 | 9 | 10 |

Underdog Devs

11 | 12 |

13 | "We are a community of software engineers supporting aspiring developers who come from disadvantaged backgrounds or who are formerly incarcerated." 14 |
15 | 16 |

17 |
18 | 19 | ### Wireframes 20 | 21 | - Wireframes are a way to graphically represent a concept for page layout and user flow. 22 | - These wireframes are meant to assist dev teams by providing a foundation from which to start coding. 23 | 24 | ### Built with Whimsical 25 | 26 | - [User Flow](https://whimsical.com/user-flow-K9Xjtm1miG3Brdmc3kmvsw) 27 | - [Wireframes](https://whimsical.com/new-dashboard-proposition-HU4MBYZXVUkTa5XzHc7uws) 28 | 29 | 30 | 31 | ### Roadmap 32 | 33 | - Wireframes for each phase of design will be added as they are completed. 34 | - Please add dev names to the section below as you add wireframes or make changes. 35 | - Please contact listed devs in Slack with questions or suggestions. 36 | 37 | 38 | 39 | ### Contributing Devs 40 | 41 | - Tom Bielawski - UX/UI 42 | - Vaibhavi Balar - UX/UI 43 | - Kenny Miesner - UX/UI 44 | - Johanna Rodriguez - UX/UI 45 | - Raphael Hebert - Frontend 46 | - Jesse Johns - TPM 47 | - Teresa Franxman - UI/UX 48 | - Rafael Mendoza - UI/UX 49 | 50 | Project Link: [https://github.com/Lambda-School-Labs/underdog-devs-fe-a](https://github.com/Lambda-School-Labs/underdog-devs-fe-a) 51 | -------------------------------------------------------------------------------- /src/components/pages/MentorMenteeMatching/MentorTable.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Table } from 'antd'; 3 | import './MentorTable.css'; 4 | 5 | const columns = [ 6 | { 7 | title: 'Mentor', 8 | dataIndex: 'name', 9 | }, 10 | { 11 | title: 'Stack', 12 | dataIndex: 'stack', 13 | }, 14 | { 15 | title: 'Location', 16 | dataIndex: 'location', 17 | }, 18 | { 19 | title: 'Additonal Notes', 20 | dataIndex: 'additonalNotes', 21 | }, 22 | { 23 | title: '#Mentees', 24 | dataIndex: 'numMentees', 25 | }, 26 | ]; 27 | 28 | // This data will be imported by the BE in the future 29 | const data = [ 30 | { 31 | key: '1', 32 | name: 'john doe', 33 | stack: 'React', 34 | location: 'New York', 35 | numMentees: '3', 36 | additonalNotes: 'hello', 37 | }, 38 | { 39 | key: '2', 40 | name: 'john william', 41 | stack: 'Express', 42 | location: 'Washington', 43 | numMentees: '5', 44 | additonalNotes: 'hello', 45 | }, 46 | { 47 | key: '3', 48 | name: 'john doe', 49 | stack: 'SQL', 50 | location: 'Florida', 51 | numMentees: '0', 52 | additonalNotes: 'hello', 53 | }, 54 | ]; 55 | 56 | const MentorTable = props => { 57 | const [selectedMentorKeys, setSelectedMentorKeys] = props.selectedMentors; 58 | 59 | const rowSelection = { 60 | selectedRowKeys: selectedMentorKeys, 61 | onChange: newSelectedKeys => setSelectedMentorKeys(newSelectedKeys), 62 | hideSelectAll: true, 63 | }; 64 | 65 | return ( 66 |
67 |
74 | 75 | ); 76 | }; 77 | 78 | export default MentorTable; 79 | -------------------------------------------------------------------------------- /src/hooks/useAxiosWithAuth0.js: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | import axios from 'axios'; 3 | import { useAuth0 } from '@auth0/auth0-react'; 4 | 5 | /* 6 | NOTE: 7 | React requires that we can only call hooks in function components or within other hooks. As axiosWithAuth is simply a helper function we've built a useAxiosWithAuth0() hook in which we've called both axiosWithAuth AND useAuth0(). 8 | axiosWithAuth serves the same function as it typically does. useAuth0() gives access to getAccessTokenSilently() for authentication/authorization purposes. 9 | This hook below is exported and used throughout the app in place of axiosWithAuth. 10 | THIS useAxiosWithAuth0 HOOK SIMPLY SERVES TO HELP CONNECT THE AXIOS CALL AND THE AUTHENTICATION. 11 | */ 12 | 13 | export default function useAxiosWithAuth0() { 14 | const { getAccessTokenSilently, isAuthenticated } = useAuth0(); 15 | const { AUTH0_AUDIENCE, REACT_APP_API_URI } = process.env; 16 | 17 | const axiosWithAuth = token => { 18 | return axios.create({ 19 | baseURL: REACT_APP_API_URI, 20 | headers: { 21 | authorization: `Bearer ${token}`, 22 | }, 23 | }); 24 | }; 25 | 26 | useEffect(() => { 27 | if (isAuthenticated) { 28 | // check if they are logged in before getAccessTokenSilently which caused errors on homepage 29 | (async () => { 30 | const token = await getAccessTokenSilently({ 31 | audience: AUTH0_AUDIENCE, 32 | scope: 'openid profile email user_metadata', 33 | }); 34 | axiosWithAuth(token); 35 | })(); 36 | } 37 | // eslint-disable-next-line react-hooks/exhaustive-deps 38 | }, [isAuthenticated]); 39 | 40 | return { 41 | // Exported with the same name to reduce the amount of refactoring needed 42 | axiosWithAuth, 43 | }; 44 | } 45 | -------------------------------------------------------------------------------- /src/components/common/MemosTable/AddReply/showReply.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from 'react'; 2 | import useAxiosWithAuth0 from '../../../../hooks/useAxiosWithAuth0'; 3 | import { Comment, Tooltip, List } from 'antd'; 4 | import moment from 'moment'; 5 | 6 | function ShowReply(props) { 7 | const { note_id } = props; 8 | const axiosWithAuth = useAxiosWithAuth0(); 9 | 10 | const { setComments, comments } = props; 11 | useEffect(() => { 12 | const getComments = () => { 13 | axiosWithAuth() 14 | .get(`/notes/${note_id}/comments`) 15 | .then(res => { 16 | setComments(res.data); 17 | }); 18 | }; 19 | getComments(); 20 | }, [axiosWithAuth, note_id, setComments]); 21 | const data = []; 22 | // eslint-disable-next-line array-callback-return 23 | comments.map(t => { 24 | const ticketDetails = { 25 | actions: [Reply to], 26 | author: 'Han Solo', 27 | content: t.comment_text, 28 | datetime: ( 29 | 32 | {moment().subtract(2, 'days').fromNow()} 33 | 34 | ), 35 | }; 36 | data.push(ticketDetails); 37 | }); 38 | 39 | return ( 40 | ( 46 |
  • 47 | 53 |
  • 54 | )} 55 | /> 56 | ); 57 | } 58 | 59 | export default ShowReply; 60 | -------------------------------------------------------------------------------- /src/components/common/styles/Resources.css: -------------------------------------------------------------------------------- 1 | .ant-checkbox-wrapper { 2 | width: 20%; 3 | } 4 | .ant-table-column-title { 5 | padding-left: 10%; 6 | padding-top: 3%; 7 | } 8 | .anticon-filter { 9 | padding-right: 50%; 10 | padding-top: 20%; 11 | } 12 | .anticon-search-main { 13 | padding-right: 50%; 14 | padding-top: 20%; 15 | } 16 | .ant-table-filter-dropdown { 17 | display: flex; 18 | flex-direction: column; 19 | } 20 | .search-container { 21 | padding: 4%; 22 | display: flex; 23 | flex-direction: column; 24 | } 25 | .search-button-group { 26 | display: flex; 27 | flex-direction: row; 28 | justify-content: space-between; 29 | padding: 4% 0; 30 | } 31 | 32 | .ant-form-item-label label { 33 | font-size: 16px; 34 | } 35 | 36 | /* RESOURCE FORM */ 37 | 38 | /* resource/add mentor review form headers */ 39 | .ant-card .ant-card-head { 40 | background: #003d71; 41 | } 42 | /* resource header options */ 43 | .ant-tabs-tab-btn { 44 | color: rgb(255, 255, 255, 0.85) !important; 45 | } 46 | /* resource header bar */ 47 | .ant-tabs-ink-bar-animated { 48 | background: rgb(255, 255, 255, 0.85) !important; 49 | position: relative; 50 | top: 45px; 51 | } 52 | /* resource form titles */ 53 | .ant-form-horizontal .ant-form-item label { 54 | display: flex; 55 | background: #0000; 56 | } 57 | /* review and resource submit button */ 58 | .ant-form-item-control-input-content button { 59 | background: #003d71; 60 | color: rgb(255, 255, 255, 0.85); 61 | border: 1px solid #1990ff; 62 | } 63 | /* review and resource submit button on hover */ 64 | .ant-form-item-control-input-content button:hover { 65 | background: #1990ff; 66 | color: rgb(255, 255, 255, 0.85); 67 | } 68 | 69 | /* add mentor review form */ 70 | .ant-col.ant-col-8.ant-form-item-label > label { 71 | background: #0000; 72 | } 73 | -------------------------------------------------------------------------------- /src/components/pages/AdminMeetingsDashBoard/ViewAllMeetings/ViewAllMeetings.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import VAMC from './VAMC'; 3 | 4 | const ViewAllMeetings = () => { 5 | const [meetingData, setMeetingData] = useState([]); 6 | 7 | // commented out because it's slow and not working... yet 8 | 9 | // const { axiosWithAuth } = useAxiosWithAuth0(); 10 | 11 | // const getDate = num => { 12 | // let d = ''; 13 | // let i = 0; 14 | // let n = new Date(num * 1000).toLocaleString('en-US'); 15 | 16 | // while (n[i] !== ',') { 17 | // d += n[i]; 18 | // i++; 19 | // } 20 | // if (d[1] === '/') d = '0' + d; 21 | // if (d[4] === '/') d = d.substring(0, 3) + '0' + d.substring(3); 22 | // return d; 23 | // }; 24 | 25 | // const switchProp = arr => { 26 | // for (let i = 0; i < arr.length; i++) { 27 | // arr[i].meeting_start_date = getDate(arr[i].meeting_start_date); 28 | // arr[i].date = arr[i].meeting_start_date; 29 | // delete arr[i].meeting_start_date; 30 | // arr[i].type = 'success'; 31 | // (arr[i]); // <--- this is the object that is being passed to the calendar 32 | // } 33 | // return arr; 34 | // }; 35 | 36 | // useEffect(() => { 37 | // axiosWithAuth() 38 | // .get('/meetings') 39 | // .then(response => { 40 | // // (response.data); 41 | // setMeetingData(switchProp(response.data)); 42 | // }) 43 | // .catch(err => console.error(err)); 44 | // // eslint-disable-next-line react-hooks/exhaustive-deps 45 | // }, []); 46 | 47 | return ( 48 |
    49 | 50 |
    51 | ); 52 | }; 53 | 54 | export default ViewAllMeetings; 55 | -------------------------------------------------------------------------------- /src/components/pages/MenteeMeetingsDashBoard/ViewAllMeetings/ViewAllMeetings.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import VAMC from './VAMC'; 3 | 4 | const ViewAllMeetings = () => { 5 | const [meetingData, setMeetingData] = useState([]); 6 | 7 | // commented out because it's slow and not working... yet 8 | 9 | // const { axiosWithAuth } = useAxiosWithAuth0(); 10 | 11 | // const getDate = num => { 12 | // let d = ''; 13 | // let i = 0; 14 | // let n = new Date(num * 1000).toLocaleString('en-US'); 15 | 16 | // while (n[i] !== ',') { 17 | // d += n[i]; 18 | // i++; 19 | // } 20 | // if (d[1] === '/') d = '0' + d; 21 | // if (d[4] === '/') d = d.substring(0, 3) + '0' + d.substring(3); 22 | // return d; 23 | // }; 24 | 25 | // const switchProp = arr => { 26 | // for (let i = 0; i < arr.length; i++) { 27 | // arr[i].meeting_start_date = getDate(arr[i].meeting_start_date); 28 | // arr[i].date = arr[i].meeting_start_date; 29 | // delete arr[i].meeting_start_date; 30 | // arr[i].type = 'success'; 31 | // (arr[i]); // <--- this is the object that is being passed to the calendar 32 | // } 33 | // return arr; 34 | // }; 35 | 36 | // useEffect(() => { 37 | // axiosWithAuth() 38 | // .get('/meetings') 39 | // .then(response => { 40 | // // (response.data); 41 | // setMeetingData(switchProp(response.data)); 42 | // }) 43 | // .catch(err => console.error(err)); 44 | // // eslint-disable-next-line react-hooks/exhaustive-deps 45 | // }, []); 46 | 47 | return ( 48 |
    49 | 50 |
    51 | ); 52 | }; 53 | 54 | export default ViewAllMeetings; 55 | -------------------------------------------------------------------------------- /src/components/pages/MentorMeetingsDashBoard/ViewAllMeetings/ViewAllMeetings.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import VAMC from './VAMC'; 3 | 4 | const ViewAllMeetings = () => { 5 | const [meetingData, setMeetingData] = useState([]); 6 | 7 | // commented out because it's slow and not working... yet 8 | 9 | // const { axiosWithAuth } = useAxiosWithAuth0(); 10 | 11 | // const getDate = num => { 12 | // let d = ''; 13 | // let i = 0; 14 | // let n = new Date(num * 1000).toLocaleString('en-US'); 15 | 16 | // while (n[i] !== ',') { 17 | // d += n[i]; 18 | // i++; 19 | // } 20 | // if (d[1] === '/') d = '0' + d; 21 | // if (d[4] === '/') d = d.substring(0, 3) + '0' + d.substring(3); 22 | // return d; 23 | // }; 24 | 25 | // const switchProp = arr => { 26 | // for (let i = 0; i < arr.length; i++) { 27 | // arr[i].meeting_start_date = getDate(arr[i].meeting_start_date); 28 | // arr[i].date = arr[i].meeting_start_date; 29 | // delete arr[i].meeting_start_date; 30 | // arr[i].type = 'success'; 31 | // (arr[i]); // <--- this is the object that is being passed to the calendar 32 | // } 33 | // return arr; 34 | // }; 35 | 36 | // useEffect(() => { 37 | // axiosWithAuth() 38 | // .get('/meetings') 39 | // .then(response => { 40 | // // (response.data); 41 | // setMeetingData(switchProp(response.data)); 42 | // }) 43 | // .catch(err => console.error(err)); 44 | // // eslint-disable-next-line react-hooks/exhaustive-deps 45 | // }, []); 46 | 47 | return ( 48 |
    49 | 50 |
    51 | ); 52 | }; 53 | 54 | export default ViewAllMeetings; 55 | -------------------------------------------------------------------------------- /src/components/pages/AddReviews/MenteeAddReview.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { Form, Input, Button, Card } from 'antd'; 3 | import '../../common/styles/Resources.css'; 4 | 5 | const { TextArea } = Input; 6 | 7 | const MenteeAddReview = () => { 8 | const [formValues, setFormValues] = useState({ 9 | mentor_name: '', 10 | review: '', 11 | }); 12 | 13 | const handleChange = e => { 14 | setFormValues({ 15 | ...formValues, 16 | [e.target.name]: e.target.value, 17 | }); 18 | }; 19 | 20 | const handleSubmit = e => { 21 | e.preventDefault(); 22 | }; 23 | 24 | return ( 25 | 38 | 46 | 47 | 48 | 49 | 57 |