diff --git a/README.md b/README.md index 7b2e136..8e816ab 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,10 @@ -# MakeItMVP Launch Academy Phase 4: Project AccountaBuddy +# MakeItMVP Launch Academy Phase 5: Project AccountaPair ## Project Description -Welcome to the MakeItMVP Launch Academy Phase 4 - Project AccountaBuddy! This project is built using React and Sass, leveraging OpenAI's API to enhance its functionality. +Welcome to the MakeItMVP Launch Academy Phase 5 - Project AccountaPair! This project is built using React, Sass, and Firebase. -AccountaBuddy extends the capabilities of makeitMVP's existing Communiti platform. Our mission is to empower individuals to achieve their professional goals through meaningful peer-to-peer accountability partnerships. - -By using a detailed questionnaire to assess users' backgrounds and skills, we match them with partners who can help each other stay accountable. The use of AI facilitates the creation of personalized shared goals for these pairs to accomplish together. +AccountaPair extends the capabilities of makeitMVP's existing Communiti platform. Our mission is to empower individuals to achieve their professional goals through meaningful peer-to-peer accountability partnerships. Accountapair provides a variety of challenges for both developers and designers, and matches you with an accountability partner to ensure you both reach your maximum potential. ## Table of Contents @@ -23,13 +21,13 @@ To view the project, follow these steps: 1. Clone this repository to your local machine: ```bash - git clone https://github.com/makeitMVPadmin/P4_Connect_AI.git + git clone https://github.com/makeitMVPadmin/LAP5_Accountabuddy ``` 2. Change the working directory to the cloned repository: ```bash - cd P4_Connect_AI + cd LAP5_Accountabuddy ``` 3. Install the project dependencies: @@ -38,7 +36,7 @@ To view the project, follow these steps: npm install ``` -4. Create a .env file with the necessary environment variables for Firebase and OpenAI. +4. Create a .env file with the necessary environment variables for Firebase. ```bash REACT_APP_FIREBASE_API_KEY= @@ -48,7 +46,6 @@ To view the project, follow these steps: REACT_APP_FIREBASE_MESSAGING_SENDER_ID= REACT_APP_FIREBASE_APP_ID= REACT_APP_FIREBASE_MEASUREMENT_ID= - REACT_APP_OPENAI_API_KEY= ``` 5. Start the development server: @@ -70,18 +67,18 @@ The project structure is organized as follows: ├── src/ │ ├── assets/ │ ├── components/ -│ │ ├── QuizPage +│ │ ├── Pair │ │ │ ├── ... │ │ ├── ... │ ├── config/ │ ├── pages/ -│ │ ├── PromptPage +│ │ ├── LandingPage │ │ │ ├── ... │ ├── ... │ ├── styles/ │ │ ├── partials │ ├── utils/ -│ │ ├── functions +│ │ ├── Functions ├── App.js ├── data.js ├── firebase.js @@ -96,7 +93,6 @@ The project structure is organized as follows: - `src/`: Contains the main source code for the project, including React components and styles. - `package.json`: Defines project dependencies and scripts. -- Our components are conditionally shown through React states and use mainly one page (PromptPage), instead of routes ## Technologies @@ -104,93 +100,57 @@ This repository uses the following technologies: - React: A JavaScript library for building user interfaces. - Sass: A CSS extension language that adds features like variables, nesting, and more. -- OpenAI: An AI platform providing natural language processing capabilities, used for personalizing user interactions and goal formation in the project. ## Contributors -Our team comprises two sub-teams - "Project AccountaBuddy" and "Project Infrastructure". -Project AccountaBuddy handled the front-end designs and code, and Project Infrastructure handled the back-end code and database. +Our team comprises two mains teams, developers and designers. Designers are responsible for all aspects of the design not limited to user research, wireframing, prototyping and creating detailed figma files to hand off to developers. For this project, developers got a chance to try out various aspects of the stack including backend and frontend. -### Designers (Project AccountaBuddy) +### Designers -- [Anna Ryzha](https://www.linkedin.com/in/anna-ryzha/) -- [Helena Dinh](https://www.linkedin.com/in/helena-thy-dinh/) -- [Isha Umaima](https://www.linkedin.com/in/isha-umaima/) +- [Anish Yadav](https://www.linkedin.com/in/anishyadav1/) +- [Daniel Karp](https://www.linkedin.com/in/danielnoahkarp/) +- [Rachel Hakimi](https://www.linkedin.com/in/rachel-hakimi/) +- [Tre Muraki](https://www.linkedin.com/in/tre-muraki/) -### Front-end Developers (Project AccountaBuddy) +### Developers -- [Aparna Dhara](https://www.linkedin.com/in/aparna-dhara/) -- [Gloria Lau](https://www.linkedin.com/in/gloria-sm-lau/) -- [John Henriksen](https://www.linkedin.com/in/john-henriksen/) +- [Ali Nix](https://www.linkedin.com/in/ali-nix-38b9b9126/) +- [Juan (Joey) Qi](https://www.linkedin.com/in/juan-qi/) - [Jagadeep Avula](https://www.linkedin.com/in/jagadeepavula/) -- [Madhuja Mitra](https://www.linkedin.com/in/madhuja-mitra-0a083377/) -- [Mohan Krishna Hasti](https://www.linkedin.com/in/mohankrishnahasti/) - -### Back-end Developers (Project Infrastructure) - -- [Andrea Matos](https://www.linkedin.com/in/drevm/) -- [Avi Brar](https://www.linkedin.com/in/avi-brar/) -- [Masoud Arefi](https://www.linkedin.com/in/masoud-arefi/) +- [Laxmi Kuntoji](http://linkedin.com/in/laxmi-kuntoji) +- [T. Truitt Janney ](https://www.linkedin.com/in/t-truitt-janney/) +- [Tim Wallace](https://www.linkedin.com/in/timothy-wallace-dev/) +- [Tolu Ajisola](https://www.linkedin.com/in/toluwalope-ajisola/) ### Product Manager -- [Alberto Borgonovo](https://www.linkedin.com/in/alberto-borgonovo/) (Project Infrastructure) +- [Julie Hildabrand](https://www.linkedin.com/in/julie-hildabrand-29857a184/) +- [Krishna Chaitanya](linkedin.com/in/krishna-chaitanya-tumuluru-846855189) ### Team Leads -- [Dinne Kopelevich](https://www.linkedin.com/in/dinne-kopelevich/) (Project AccountaBuddy) -- [Scott Schwab](https://www.linkedin.com/in/scott-p-schwab/) (Project Infrastructure) +- [Mohan Krishna Hasti](https://www.linkedin.com/in/mohankrishnahasti/) ## Screenshots -### Home page - -![Accountabuddy1](https://github.com/user-attachments/assets/2ace6b54-654b-4650-a15f-58636a0b6d9a) - - -### Quiz Screen - -![Accountabuddy2](https://github.com/user-attachments/assets/3497489f-25d2-48b4-89db-2c6db0fd3041) - - -### Loading Screen - -![AccountabuddyLoading](https://github.com/user-attachments/assets/4f0fc30c-d459-4061-b733-0187eeea166e) - - -### Match Screen - -![Accountabuddy3](https://github.com/user-attachments/assets/197a40ef-48b3-4beb-ae15-0e6b0698ebbb) - - -### Roadmap Landing Screen - -![Accountabuddy4](https://github.com/user-attachments/assets/e55ecdc2-7a3b-4626-8441-60945e239c1e) - - -### Roadmap Hover State Active - -![Accountabuddy4hover](https://github.com/user-attachments/assets/35f291ff-e06c-47ff-a822-56ffbc98c724) - - -### Roadmap Hover State Inactive - -![Accountabuddy4hover2](https://github.com/user-attachments/assets/18921642-6eed-406d-9cc6-f8d510980798) - - -### Roadmap Goal Modal - -![Accountabuddy5](https://github.com/user-attachments/assets/94a2c62a-e767-4bad-81c4-acc8bb3930b8) +### Home page -### Roadmap Mid-progress Hover +![Screenshot 2024-10-24 183737](https://github.com/user-attachments/assets/2514ea5f-eb48-481e-b4b1-bbf698183b03) -![Accountabuddy5hover](https://github.com/user-attachments/assets/fea0e067-4c34-412f-8157-8326ad22f8ab) +### Prompt sequence +![Screenshot 2024-10-24 183756](https://github.com/user-attachments/assets/0a7a7742-aae2-49c1-b64d-6476663ed914) +![Screenshot 2024-10-24 183828](https://github.com/user-attachments/assets/4929e0b0-cdbf-44db-bbd8-15d68db36fc1) +![Screenshot 2024-10-24 183853](https://github.com/user-attachments/assets/5718b5d0-d27f-4c59-988b-58f654d9ffc4) +![Screenshot 2024-10-24 183916](https://github.com/user-attachments/assets/c5cf97d8-adba-47ed-81dc-41b934ce759c) -### Roadmap Goal Achieved Screen +### Challenge Page and filter board +![Screenshot 2024-10-24 183934](https://github.com/user-attachments/assets/942a8d54-09f8-49be-a892-c37ca798c001) +![Screenshot 2024-10-24 184006](https://github.com/user-attachments/assets/d33cc599-f1c0-4251-bf3c-72070f1141b9) -![Accountabuddy6](https://github.com/user-attachments/assets/b8774529-165b-4a51-a44d-3d0f7444da94) +### Challenge details page +![ScreenRecording2024-10-24184638](https://github.com/user-attachments/assets/0a6ba326-a794-4526-949f-46f9e7cfd941) This project is licensed under the [MIT License](LICENSE). diff --git a/public/coffeeMugWithHat_happy.svg b/public/coffeeMugWithHat_happy.svg new file mode 100644 index 0000000..356fc8e --- /dev/null +++ b/public/coffeeMugWithHat_happy.svg @@ -0,0 +1,154 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/index.html b/public/index.html index f396607..cb5ba27 100644 --- a/public/index.html +++ b/public/index.html @@ -2,7 +2,7 @@ - + - Connect AI + AccountaPair diff --git a/src/App.js b/src/App.js index da019fa..a46e6f3 100644 --- a/src/App.js +++ b/src/App.js @@ -1,21 +1,31 @@ +import React from "react"; import { Routes, Route } from "react-router-dom"; +import { PageProvider } from "./contexts/PageContext.js"; import Home from "./main.js"; import PromptPage from "./pages/PromptPage/PromptPage"; -import BackEndTest from "./pages/BackEnd/Backend.jsx"; -import AiBackendTest from "./pages/BackEnd/AiBackendTest.js"; -import LoadingPage from "./components/LoadingPage/LoadingPage.jsx"; +import BackEndTest from "./backend/Backend.jsx"; +import AiBackendTest from "./backend/AiBackendTest.js"; +import { ChallengeDetails } from "./pages/ChallengeDetails/ChallengeDetails.jsx"; +import LoadingPage from "./pages/LoadingPage/LoadingPage.jsx"; +import ChallengePage from "./components/P5AP_ChallengePage/ChallengePage.jsx"; +import P5ChallenegeTaskMainLayout from "../src/components/P5ChallenegeTaskMainLayout/P5ChallenegeTaskMainLayout" +import PairupBoard from "./pages/P5AP_PairupBoard/PairupBoard.jsx"; function App() { return ( - <> + } /> } /> + } /> } /> } /> - }/> + } /> + } /> + } /> + } /> - + ); } diff --git a/src/assets/icons/brifcaseIcon.svg b/src/assets/icons/brifcaseIcon.svg new file mode 100644 index 0000000..5878d5a --- /dev/null +++ b/src/assets/icons/brifcaseIcon.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/assets/icons/closeIcon.svg b/src/assets/icons/closeIcon.svg new file mode 100644 index 0000000..e288dde --- /dev/null +++ b/src/assets/icons/closeIcon.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/assets/icons/close_icon.svg b/src/assets/icons/close_icon.svg new file mode 100644 index 0000000..166e12f --- /dev/null +++ b/src/assets/icons/close_icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/icons/ideaIcon.svg b/src/assets/icons/ideaIcon.svg new file mode 100644 index 0000000..af9078c --- /dev/null +++ b/src/assets/icons/ideaIcon.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/icons/idealIcon.svg b/src/assets/icons/idealIcon.svg new file mode 100644 index 0000000..7757cc8 --- /dev/null +++ b/src/assets/icons/idealIcon.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/assets/icons/infoIcon.svg b/src/assets/icons/infoIcon.svg new file mode 100644 index 0000000..f57a573 --- /dev/null +++ b/src/assets/icons/infoIcon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/icons/levelIcon.svg b/src/assets/icons/levelIcon.svg new file mode 100644 index 0000000..87afd5b --- /dev/null +++ b/src/assets/icons/levelIcon.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/assets/icons/lightbulb.svg b/src/assets/icons/lightbulb.svg new file mode 100644 index 0000000..18d5593 --- /dev/null +++ b/src/assets/icons/lightbulb.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/assets/icons/pen.svg b/src/assets/icons/pen.svg new file mode 100644 index 0000000..109d4b4 --- /dev/null +++ b/src/assets/icons/pen.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/assets/images/ChallengeCardBanner1.png b/src/assets/images/ChallengeCardBanner1.png new file mode 100644 index 0000000..3e14aaf Binary files /dev/null and b/src/assets/images/ChallengeCardBanner1.png differ diff --git a/src/assets/images/ChallengeCardBanner2.png b/src/assets/images/ChallengeCardBanner2.png new file mode 100644 index 0000000..17df20d Binary files /dev/null and b/src/assets/images/ChallengeCardBanner2.png differ diff --git a/src/assets/images/ChallengeCardBanner3.png b/src/assets/images/ChallengeCardBanner3.png new file mode 100644 index 0000000..270849e Binary files /dev/null and b/src/assets/images/ChallengeCardBanner3.png differ diff --git a/src/assets/images/ChallengeCardBanner4.png b/src/assets/images/ChallengeCardBanner4.png new file mode 100644 index 0000000..e005add Binary files /dev/null and b/src/assets/images/ChallengeCardBanner4.png differ diff --git a/src/assets/images/ChallengeCardBanner5.png b/src/assets/images/ChallengeCardBanner5.png new file mode 100644 index 0000000..7d85014 Binary files /dev/null and b/src/assets/images/ChallengeCardBanner5.png differ diff --git a/src/assets/images/ChallengeCardBanner6.png b/src/assets/images/ChallengeCardBanner6.png new file mode 100644 index 0000000..c45fbe6 Binary files /dev/null and b/src/assets/images/ChallengeCardBanner6.png differ diff --git a/src/assets/images/ChallengeCardBanner7.png b/src/assets/images/ChallengeCardBanner7.png new file mode 100644 index 0000000..8205a36 Binary files /dev/null and b/src/assets/images/ChallengeCardBanner7.png differ diff --git a/src/assets/images/ChallengeCardBanner8.png b/src/assets/images/ChallengeCardBanner8.png new file mode 100644 index 0000000..f24f824 Binary files /dev/null and b/src/assets/images/ChallengeCardBanner8.png differ diff --git a/src/assets/images/ChallengeCardBanner9.png b/src/assets/images/ChallengeCardBanner9.png new file mode 100644 index 0000000..4d7b76a Binary files /dev/null and b/src/assets/images/ChallengeCardBanner9.png differ diff --git a/src/assets/images/Clock.png b/src/assets/images/Clock.png new file mode 100644 index 0000000..cee08f6 Binary files /dev/null and b/src/assets/images/Clock.png differ diff --git a/src/assets/images/Idea.png b/src/assets/images/Idea.png new file mode 100644 index 0000000..a6b180d Binary files /dev/null and b/src/assets/images/Idea.png differ diff --git a/src/assets/images/Pen.png b/src/assets/images/Pen.png new file mode 100644 index 0000000..ddefdd7 Binary files /dev/null and b/src/assets/images/Pen.png differ diff --git a/src/assets/images/Pen.svg b/src/assets/images/Pen.svg new file mode 100644 index 0000000..29cebb3 --- /dev/null +++ b/src/assets/images/Pen.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/images/Profile Image.jpg b/src/assets/images/Profile Image.jpg new file mode 100644 index 0000000..0de23fd Binary files /dev/null and b/src/assets/images/Profile Image.jpg differ diff --git a/src/assets/images/arrowLeft.svg b/src/assets/images/arrowLeft.svg new file mode 100644 index 0000000..a7bb362 --- /dev/null +++ b/src/assets/images/arrowLeft.svg @@ -0,0 +1,22 @@ + + + + diff --git a/src/assets/images/file-chart_24px.jpg b/src/assets/images/file-chart_24px.jpg new file mode 100644 index 0000000..c6eb99a Binary files /dev/null and b/src/assets/images/file-chart_24px.jpg differ diff --git a/src/assets/images/filterIcon.svg b/src/assets/images/filterIcon.svg new file mode 100644 index 0000000..1753d01 --- /dev/null +++ b/src/assets/images/filterIcon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/images/icons8-google-meet-96 1.jpg b/src/assets/images/icons8-google-meet-96 1.jpg new file mode 100644 index 0000000..0d6bcd9 Binary files /dev/null and b/src/assets/images/icons8-google-meet-96 1.jpg differ diff --git a/src/assets/images/loadingActiveIcon.svg b/src/assets/images/loadingActiveIcon.svg new file mode 100644 index 0000000..df0e54a --- /dev/null +++ b/src/assets/images/loadingActiveIcon.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/assets/images/loadingInactiveIcon.svg b/src/assets/images/loadingInactiveIcon.svg new file mode 100644 index 0000000..5470376 --- /dev/null +++ b/src/assets/images/loadingInactiveIcon.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/assets/images/profileImage.jpeg b/src/assets/images/profileImage.jpeg new file mode 100644 index 0000000..94fdc70 Binary files /dev/null and b/src/assets/images/profileImage.jpeg differ diff --git a/src/assets/images/u_linkedin.jpg b/src/assets/images/u_linkedin.jpg new file mode 100644 index 0000000..8894d3d Binary files /dev/null and b/src/assets/images/u_linkedin.jpg differ diff --git a/src/assets/images/work_24px.jpg b/src/assets/images/work_24px.jpg new file mode 100644 index 0000000..798de5b Binary files /dev/null and b/src/assets/images/work_24px.jpg differ diff --git a/src/pages/BackEnd/AiBackendTest.js b/src/backend/AiBackendTest.js similarity index 94% rename from src/pages/BackEnd/AiBackendTest.js rename to src/backend/AiBackendTest.js index 4e78c30..7fb92e7 100644 --- a/src/pages/BackEnd/AiBackendTest.js +++ b/src/backend/AiBackendTest.js @@ -1,6 +1,6 @@ // src/components/AiBackendTest.jsx import React, { useState } from "react"; -import { callOpenAiApi } from "../../utils/Functions/openaiFunctions"; +import { callOpenAiApi } from "../utils/Functions/openaiFunctions"; const AiBackendTest = () => { const [goals, setGoals] = useState(null); diff --git a/src/backend/Backend.jsx b/src/backend/Backend.jsx new file mode 100644 index 0000000..b972ace --- /dev/null +++ b/src/backend/Backend.jsx @@ -0,0 +1,78 @@ +import React, { useState, useEffect } from "react"; +import { COLLECTIONS } from "../constants.js"; +import { + createData, + readData, + updateData, + deleteData, +} from "../utils/Functions/functions"; + +const BackEndTest = () => { + const [data, setData] = useState([]); + const [error, setError] = useState(null); + const collectionName = COLLECTIONS.USERS; + + const fetchDataAndUpdateState = async () => { + const result = await readData(collectionName); + setData(result); + }; + + useEffect(() => { + fetchDataAndUpdateState(); + }, []); + + const handleCreate = async () => { + const newData = { name: "New Item", description: "Description" }; + await createData(collectionName, newData); + setData((prevData) => [...prevData, newData]); + }; + + const handleUpdate = async (id) => { + const updatedData = { + name: "Updated Item", + description: "Updated Description", + }; + await updateData(collectionName, id, updatedData); + setData((prevData) => + prevData.map((item) => (item.id === id ? updatedData : item)) + ); + }; + + const handleDelete = async (id) => { + setError(null); + try { + await deleteData(collectionName, id); + fetchDataAndUpdateState(); + } catch (error) { + setError("Error deleting data"); + console.error(error); + } + }; + + return ( +
+ {error &&

{error}

} + + {data.length > 0 ? ( + data.map(({ id, firstName, description }) => ( +
+

{firstName}

+

{description}

+ + +
+ )) + ) : ( +

No data

+ )} +
+ ); +}; + +export default BackEndTest; diff --git a/src/components/Button/Button.jsx b/src/components/Button/Button.jsx index 4b75b7c..f84c5e7 100644 --- a/src/components/Button/Button.jsx +++ b/src/components/Button/Button.jsx @@ -7,13 +7,16 @@ const Button = ({ className = "", type = "button", disabled, - children + border, + children, }) => { return ( + + {isOpen && ( +
+
Leveling Up in Accountapair
+
+ What determines someone's expertise on the Communiti platform? +
+
+ When you join Communiti, your account is initially set to Beginner. + As you complete more challenges, your expertise will gradually increase through levels: + Beginner, Intermediate, and Advanced. + This helps users identify the experience level of their challenge partners, + particularly when using the AccountaPair feature. +
+ + + +
+ )} + + ); +}; + +export default ButtonWithPanel; \ No newline at end of file diff --git a/src/components/P5AP_ButtonWithPanel/ButtonWithPanel.scss b/src/components/P5AP_ButtonWithPanel/ButtonWithPanel.scss new file mode 100644 index 0000000..2b0bc92 --- /dev/null +++ b/src/components/P5AP_ButtonWithPanel/ButtonWithPanel.scss @@ -0,0 +1,84 @@ +.button-with-panel { + position: absolute; + top: 0; + left: 50%; + z-index: 10; + + .userLevel { + background-color: white; + border: 2px solid white; + border-radius: 0.7rem; + display: flex; + padding: 0.1rem 0.3rem 0.1rem 0.4rem; + align-items: center; + gap: 0.1rem; + font-family: "Corben-Bold"; + font-size: 0.5rem; + color: #333; + cursor: pointer; + white-space: nowrap; + + .userLevel_levelIcon { + width: 0.875rem; + height: 0.875rem; + } + } + + .userLevel_infoIcon{ + color:black; + width:0.8rem; + padding-top: 0.05rem; + } + + .userLevel_levelIcon{ + color:black; + } + + .info-panel { + position: absolute; + top: 1.5rem; + left: -1.25rem; + width: 29rem; + background-color: white; + border: 2px solid black; + border-radius: 0.6rem; + box-shadow: 2px 3px 0 black; + padding: 0.6rem 1.1rem; + z-index: 100; + + + .info-panel_title { + font-family: "Corben-Bold"; + font-size: 0.75rem; + padding-bottom: 0.8rem; + color: #0954a3; + margin-bottom: 1rem; + border-bottom: 1px solid #ddd; + } + + .info-panel_subtitle { + font-family: "Corben-Regular"; + font-size: 0.6rem; + color: #22b4ee; + margin-bottom: 0.5rem; + } + + + .info-panel_text { + font-family: "Corben-Regular"; + font-size: 0.7rem; + color: #333; + line-height: 1.2; + } + + .close-button { + position: absolute; + top: 0.625rem; + right: 0.625rem; + background: transparent; + border: none; + font-size: 1rem; + cursor: pointer; + } + } +} \ No newline at end of file diff --git a/src/components/P5AP_ChallengePage/ChallengePage.jsx b/src/components/P5AP_ChallengePage/ChallengePage.jsx new file mode 100644 index 0000000..8c2e9f5 --- /dev/null +++ b/src/components/P5AP_ChallengePage/ChallengePage.jsx @@ -0,0 +1,165 @@ +import React, { useState, useEffect, useContext } from "react"; +import { readData } from "../../utils/Functions/functions"; +import ChallengeCard from "../ChallengeCard/ChallengeCard"; +import DashboardNavbar from "../DashboardNavbar/DashboardNavbar"; +import filterIcon from "../../assets/images/filterIcon.svg"; +import FilterBoard from "../P5AP_FilterBoard/FilterBoard"; +import { PageContext } from "../../contexts/PageContext"; +import "./ChallengePage.scss"; +import closeIcon from "../../assets/icons/close_icon.svg"; + +const ChallengePage = () => { + const { userFeedback } = useContext(PageContext); + const [challenges, setChallenges] = useState([]); + const [isLoading, setIsLoading] = useState(true); + const [error, setError] = useState(null); + const [selectedIndustry, setSelectedIndustry] = useState(["Development"]); // Development is always selected since we dont have any data for design in firestore + const [selectedDifficulties, setSelectedDifficulties] = useState([]); + const [selectedTechnologies, setSelectedTechnologies] = useState([]); + const [isFilterBoardOpen, setIsFilterBoardOpen] = useState(false); + + useEffect(() => { + const fetchChallenges = async () => { + setIsLoading(true); + try { + const fetchedChallenges = await readData("Challenges"); + setChallenges(fetchedChallenges); + setError(null); + } catch (error) { + setError("Failed to fetch challenges. Please try again later."); + } finally { + setIsLoading(false); + } + }; + + fetchChallenges(); + }, []); + + useEffect(() => { + if (userFeedback.field && userFeedback.field !== "Development") { + // Development is always selected since we dont have any data for design in firestore + setSelectedIndustry(["Development", userFeedback.field]); + } + if (userFeedback.skillLevel) { + setSelectedDifficulties([userFeedback.skillLevel]); + } + if (userFeedback.skillToImprove) { + setSelectedTechnologies([userFeedback.skillToImprove]); + } + }, [userFeedback]); + + const filteredChallenges = challenges.filter((challenge) => { + const industryMatch = true; // Always true because "Development" is always included + const difficultyMatch = + selectedDifficulties.length === 0 || + selectedDifficulties.includes(challenge.difficulty); + const technologyMatch = + selectedTechnologies.length === 0 || + selectedTechnologies.some((tech) => challenge.category.includes(tech)); + return industryMatch && difficultyMatch && technologyMatch; + }); + + const applyFilters = (filters) => { + setSelectedIndustry(["Development", ...(filters.industry || [])]); + setSelectedDifficulties(filters.difficulty || []); + setSelectedTechnologies(filters.technology || []); + setIsFilterBoardOpen(false); + }; + + if (isLoading) { + return
Loading challenges...
; + } + + if (error) { + return
Error: {error}
; + } + + return ( + <> + +
+
+

Challenges ({filteredChallenges.length})

+
setIsFilterBoardOpen(true)}> + Filter Icon + Filter +
+
+ +
+ Filter: +
+ {selectedIndustry.map((industry) => ( +
+ {industry} + Remove filter + setSelectedIndustry( + selectedIndustry.filter((i) => i !== industry) + ) + } + /> +
+ ))} + {selectedDifficulties.map((difficulty) => ( +
+ {difficulty} + Remove filter + setSelectedDifficulties( + selectedDifficulties.filter((d) => d !== difficulty) + ) + } + /> +
+ ))} + {selectedTechnologies.map((technology) => ( +
+ {technology} + Remove filter + setSelectedTechnologies( + selectedTechnologies.filter((t) => t !== technology) + ) + } + /> +
+ ))} +
+
+
+ {filteredChallenges.length > 0 ? ( + filteredChallenges.map((challenge) => ( + + )) + ) : ( +

No challenges found matching the current filters.

+ )} +
+ + {isFilterBoardOpen && ( +
+ setIsFilterBoardOpen(false)} + initialIndustry={selectedIndustry} + initialDifficulty={selectedDifficulties} + initialTechnology={selectedTechnologies} + /> +
+ )} +
+ + ); +}; + +export default ChallengePage; diff --git a/src/components/P5AP_ChallengePage/ChallengePage.scss b/src/components/P5AP_ChallengePage/ChallengePage.scss new file mode 100644 index 0000000..c42be6a --- /dev/null +++ b/src/components/P5AP_ChallengePage/ChallengePage.scss @@ -0,0 +1,109 @@ +@use "../../styles/partials/mixins" as *; + +.challenge-page { + padding: 20px 20px; + max-width: 1300px; + margin: auto; + + .modal-overlay { + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + background: rgba(0, 0, 0, 0.6); + display: flex; + justify-content: center; + align-items: center; + z-index: 1000; + } + + .header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 20px; + + h1 { + font-family: 'Corben', sans-serif; + font-size: 2rem; + margin: 0; + } + + .filter { + display: flex; + align-items: center; + cursor: pointer; + + img { + margin-right: 8px; + } + + span { + font-family: 'Corben', sans-serif; + font-weight: bold; + font-size: larger; + } + } + } + + .selected-filters-container { + display: flex; + align-items: center; + margin-bottom: 20px; + } + + .filter-name { + font-size: larger; + font-family: 'Corben', sans-serif; + margin-right: 15px; + } + + .selected-filters { + display: flex; + // flex-wrap: wrap; + gap: 15px; + justify-content: center; + } + + .filter-tab { + display: inline-flex; + align-items: center; + // margin-right: 10px; + border: 2px solid #000000; + background-color: #FFD700; + padding: 5px 10px; + border-radius: 10px; + font-size: large; + font-weight: 800; + } + + .filter-text { + display: flex; + margin-right: 5px; + padding-bottom: 1px; + } + + .close-icon { + width: 20px; + height: 20px; + cursor: pointer; + } + + .card-container { + gap: 20px; + display: flex; + flex-direction: column; + align-items: center; + + @include Tablet { + display: grid; + grid-template-columns: repeat(2, 1fr); + } + + @include Desktop { + display: grid; + grid-template-columns: repeat(3, 1fr); + } + } +} \ No newline at end of file diff --git a/src/components/P5AP_FilterBoard/FilterBoard.jsx b/src/components/P5AP_FilterBoard/FilterBoard.jsx new file mode 100644 index 0000000..d8b8630 --- /dev/null +++ b/src/components/P5AP_FilterBoard/FilterBoard.jsx @@ -0,0 +1,144 @@ +import React, { useState, useEffect } from "react"; +import "./FilterBoard.scss"; +import { ReactComponent as Exit } from "../../assets/images/exit.svg"; + +const FilterBoard = ({ + onApplyFilters, + onClose, + initialIndustry, + initialDifficulty, + initialTechnology, +}) => { + const [industry, setIndustry] = useState(initialIndustry || []); + const [difficulty, setDifficulty] = useState(initialDifficulty || []); + const [technology, setTechnology] = useState(initialTechnology || []); + + const industries = ["Design", "Development"]; + const difficulties = ["Easy", "Intermediate", "Hard"]; + const technologies = ["Python", "React", "DSA", "Java"]; + + // Ensure "Development" is always selected + useEffect(() => { + if (!industry.includes("Development")) { + setIndustry((prev) => [...prev, "Development"]); + } + }, [industry]); + + const handleIndustryChange = (selectedIndustry) => { + if (selectedIndustry === "Development") return; // Prevent deselecting Development + if (industry.includes(selectedIndustry)) { + setIndustry(industry.filter((selected) => selected !== selectedIndustry)); + } else { + setIndustry([...industry, selectedIndustry]); + } + }; + + const handleDifficultyChange = (level) => { + if (difficulty.includes(level)) { + setDifficulty(difficulty.filter((l) => l !== level)); + } else { + setDifficulty([...difficulty, level]); + } + }; + + const handleTechnologyChange = (tech) => { + if (technology.includes(tech)) { + setTechnology(technology.filter((t) => t !== tech)); + } else { + setTechnology([...technology, tech]); + } + }; + + const handleClearAll = () => { + setIndustry(["Development"]); + setDifficulty([]); + setTechnology([]); + }; + + const handleSubmit = () => { + // Remove "Development" from the industry array before applying filters + const filteredIndustry = industry.filter((ind) => ind !== "Development"); + onApplyFilters({ + industry: filteredIndustry, + difficulty, + technology, + }); + }; + + return ( +
+
+
+

Filters

+ +
+
+ +
+ {/* Industry Section */} +
+

Industry

+ {industries.map((ind) => ( + + ))} +
+ + {/* Difficulty Section */} +
+

Difficulty

+ {difficulties.map((level) => ( + + ))} +
+ + {/* Technology Section */} +
+

Technology

+ {technologies.map((tech) => ( + + ))} +
+
+ +
+
+ + +
+
+
+ ); +}; + +export default FilterBoard; diff --git a/src/components/P5AP_FilterBoard/FilterBoard.scss b/src/components/P5AP_FilterBoard/FilterBoard.scss new file mode 100644 index 0000000..7ecdacc --- /dev/null +++ b/src/components/P5AP_FilterBoard/FilterBoard.scss @@ -0,0 +1,165 @@ +@import "../../styles/partials/mixins.scss"; +@import "../../styles/partials/variables.scss"; +@import "../../styles/partials/typography.scss"; + +//used to center the filter board +.filterboard-container { + display: flex; + justify-content: center; + align-items: center; + min-height: auto; + border-radius: 20px; + background-color: $MVP-Cream; // Optional background for visibility +} + +.filterboard { + width: 580px; // Adjusted width based on the screenshot + border: 1px solid $Light-Gray; + display: flex; + flex-direction: column; + align-items: flex-start; + padding: 24px; + gap: 7px; + background-color: $MVP-White; + border-radius: 10px; + box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.05); // Subtle shadow for depth + font-family: Corben-Bold; + + &__header { + display: flex; + width: 100%; + justify-content: space-between; + align-items: center; + + + h2 { + font-family: Corben; + font-size: 20px; + font-weight: 700; + margin-bottom: 8px; // Increase margin for better spacing + text-align: left; + } + + &__close { + + top: 16px; // Adjust based on padding and positioning needs + right: 16px; // Adjust for alignment with the border + background: none; + border: none; + cursor: pointer; + + svg { + width: 24px; // Adjust size of the SVG + height: 24px; // Adjust size of the SVG + fill: $MVP-black; // Change the fill color to match the design + } + + &:hover { + svg { + fill: $MVP-Red; // Optional: Change color on hover + } + } + } + } + + // First and last divider lines + &__divider { + width: calc(100% + 48px); // Expand the line beyond padding + height: 1px; + background-color: $MVP-black; + border: none; + margin-left: -24px; // Pull the line to the left to touch the border + margin-right: -24px; // Ensure the line touches the right border + margin-bottom: 24px; // Space after the line + } + + &__divider--bottom { + margin-top: 24px; // Adjust top margin for space between the last section and the bottom line + } + + &__choice { + width: 100%; // Ensure full width for internal sections + + &__sections { + margin-bottom: 32px; + + h3 { + font-family: Corben-Bold; + font-size: 18px; + margin-bottom: 10px; + color: $MVP-Dark-Blue; + } + + &__button { + margin: 5px; + padding: 10px 15px; + border: 1px solid $MVP-black; + border-radius: 5px; + background-color: $MVP-White; + cursor: pointer; + font-family: Gilroy; + transition: background-color 0.3s ease; + + &.active { + background-color: $MVP-Yellow; + color: $MVP-black; + border-color: $MVP-Yellow; + font-family: Gilroy; + } + + &:hover { + background-color: $MVP-Light-Blue; + color: $MVP-White; + } + } + } + + // Add horizontal lines between sections + &__sections:not(:last-child) { + border-bottom: 1px solid $Light-Gray; + padding-bottom: 20px; + } + } + + &__actions { + display: flex; + width: 100%; + justify-content: space-between; + align-items: center; + //border-top: 1px solid $Light-Gray; // Top border for the action section + padding-top: 20px; + + .clear-button { + padding: 10px 20px; + background-color: $MVP-White; + border: none; + font-family: Corben; + cursor: pointer; + border-radius: 5px; + + &:hover { + background-color: $MVP-Red; + color: $MVP-White; + } + } + + .submit-button { + padding: 10px 20px; + background-color: $MVP-Light-Blue; + border: none; + color: $MVP-black; + font-family: Corben; + cursor: pointer; + border-radius: 4px; + border-top: 3px solid $MVP-black; + border-right: 6px solid $MVP-black; + border-bottom: 6px solid $MVP-black; + border-left: 3px solid $MVP-black; + + &:hover { + background-color: $MVP-Dark-Blue; + } + } + + } +} \ No newline at end of file diff --git a/src/components/P5AP_PhotoCard/photocard.jsx b/src/components/P5AP_PhotoCard/photocard.jsx new file mode 100644 index 0000000..33b6078 --- /dev/null +++ b/src/components/P5AP_PhotoCard/photocard.jsx @@ -0,0 +1,40 @@ +import React from "react"; +import "./photocard.scss"; +import ideaIcon from "../../assets/icons/ideaIcon.svg"; +import brifcaseIcon from "../../assets/icons/brifcaseIcon.svg"; +import ButtonWithPanel from "../../components/P5AP_ButtonWithPanel/ButtonWithPanel"; +import profilePicture from "../../assets/images/profileImage.jpeg"; + +const PhotoCard = ({ user }) => { + const { name, level, role, skills } = user || {}; + + return ( +
+
+ {`${name}`} + +
+
+

{name}

+

+ briefcase Icon + {role} +

+

+ idea Icon + {Array.isArray(skills) ? skills.join(" · ") : "No skills listed"} +

+
+
+ ); +}; + +export default PhotoCard; diff --git a/src/components/P5AP_PhotoCard/photocard.scss b/src/components/P5AP_PhotoCard/photocard.scss new file mode 100644 index 0000000..0bbe707 --- /dev/null +++ b/src/components/P5AP_PhotoCard/photocard.scss @@ -0,0 +1,81 @@ + +.photocard { + position: relative; + background-color: white; + border-radius: 0.6rem; + border: 3px solid black; + box-shadow: 3px 3px 0 black; + width: 100%; + max-width: 20rem; + aspect-ratio: 8 / 10; + display: flex; + flex-direction: column; + text-align: left; + font-family: "Corben-Bold"; + + .photocard__level { + font-family: "Corben-Bold"; + position: absolute; + top: 0.625rem; + left: 0.625rem; + background-color: white; + padding: 0.125 1rem; + border-radius: 1.2rem; + font-size: 0.6rem; + color: #333; + z-index: 10; + } + + &__header { + + flex-basis: 70%; + overflow: hidden; + z-index: 1; + + .photocard__image { + width: 100%; + height: 100%; + object-fit: cover; + border-top-left-radius: 0.625rem; + border-top-right-radius: 0.625rem; + } + + } + + &__info { + padding: 1rem; + padding-top: 0; + + .photocard__name { + font-family: "Corben-Bold"; + font-size: 1rem; + padding-top: 0.5rem; + font-weight: bold; + color: #333; + } + + .photocard__role { + font-family: "Corben-Regular"; + font-size: 0.9rem; + color: #555; + } + + .photocard_briefcase { + width: 1.2rem; + margin-right: 8px; + color: #555; + } + + .photocard__skills { + font-family: "Corben-Regular"; + font-size: 0.9rem; + color: #777; + + .photocard_idea { + width: 1.2rem; + margin-right: 0.5rem; + color: #ff9900; + } + } + } +} \ No newline at end of file diff --git a/src/components/P5AP_TaskBar/TaskBar.jsx b/src/components/P5AP_TaskBar/TaskBar.jsx new file mode 100644 index 0000000..312721a --- /dev/null +++ b/src/components/P5AP_TaskBar/TaskBar.jsx @@ -0,0 +1,33 @@ +import React, { useState } from 'react'; +import "./TaskBar.scss"; + +const TaskBar = () => { + const [ steps, setSteps ] = setSteps([ + { id: 1, completed: false }, + { id: 2, completed: false }, + { id: 3, completed: false } + ]); + +// Handle Step Click +const handleStepClick = (id) => { + setSteps(prevSteps => prevSteps.map(step => step.id === id ? { ...step, completed: !step.completed } : step)); +}; + +return ( +
+

Task List

+ +
+ ); +} + +export default TaskBar; \ No newline at end of file diff --git a/src/components/P5AP_TaskBar/TaskBar.scss b/src/components/P5AP_TaskBar/TaskBar.scss new file mode 100644 index 0000000..19d8bd8 --- /dev/null +++ b/src/components/P5AP_TaskBar/TaskBar.scss @@ -0,0 +1,13 @@ +.checkmark { + color: green; + font-size: 20px; + } + + .circle { + border: 2px solid black; + border-radius: 50%; + width: 20px; + height: 20px; + text-align: center; + line-height: 20px; + } \ No newline at end of file diff --git a/src/components/P5ChallenegeTaskMainLayout/P5ChallenegeTaskMainLayout.jsx b/src/components/P5ChallenegeTaskMainLayout/P5ChallenegeTaskMainLayout.jsx new file mode 100644 index 0000000..04c51b8 --- /dev/null +++ b/src/components/P5ChallenegeTaskMainLayout/P5ChallenegeTaskMainLayout.jsx @@ -0,0 +1,29 @@ +import React from "react"; +import ChallengeTaskHeader from "../ChallengeTaskHeader/ChallengeTaskHeader"; +import ChallengeProfileSideBar from "../ChallengeProfileSideBar/ChallengeProfileSideBar"; +import P5ChallengeTaskStepper from "../P5ChallengeTaskStepper/P5ChallengeTaskStepper"; +import "./P5ChallenegeTaskMainLayout.scss"; +import DashboardNavbar from "../DashboardNavbar/DashboardNavbar"; + +const P5ChallengeTaskMainLayout = () => { + return ( + <> + +
+ {/* Left Section: Challenge Task Header and Stepper */} +
+ + Stepper component + +
+ + {/* Right Section: Profile Display */} +
+ +
+
+ + ); +}; + +export default P5ChallengeTaskMainLayout; diff --git a/src/components/P5ChallenegeTaskMainLayout/P5ChallenegeTaskMainLayout.scss b/src/components/P5ChallenegeTaskMainLayout/P5ChallenegeTaskMainLayout.scss new file mode 100644 index 0000000..4ee9cbd --- /dev/null +++ b/src/components/P5ChallenegeTaskMainLayout/P5ChallenegeTaskMainLayout.scss @@ -0,0 +1,22 @@ +.main-layout-container { + display: flex; + justify-content: space-between; + align-items: flex-start; + padding: 40px 0px 40px 40px; + gap: 40px; +} + +.left-section { + width: 60%; /* Adjust according to how much space you want to allocate to the left side */ + display: flex; + flex-direction: column; + // gap: 40px; + border-right: 0.5px solid #757575; +} + +.right-section { + width: 35%; /* Adjust width accordingly */ + display: flex; + flex-direction: column; + gap: 40px; +} diff --git a/src/components/P5ChallengeTaskStepper/P5ChallengeTaskStepper.jsx b/src/components/P5ChallengeTaskStepper/P5ChallengeTaskStepper.jsx new file mode 100644 index 0000000..5a89d2c --- /dev/null +++ b/src/components/P5ChallengeTaskStepper/P5ChallengeTaskStepper.jsx @@ -0,0 +1,125 @@ +import React, { useState } from "react"; +import "./P5ChallengeTaskStepper.scss"; +import { useNavigate } from "react-router-dom"; +import { Preview } from "@mui/icons-material"; + +const P5ChallengeTaskStepper = () => { + const navigate = useNavigate(); + const taskDetails = { + steps: [ + { + stepTitle: "Connect with Partner", + stepContent: [ + { + sectionTitle: "LinkedIn", + description: + '• Connect with your partner by using the LinkedIn button located in the right tab next to "Connect." Alternatively, you can look them up by their username.', + }, + { + sectionTitle: "Google Meet", + description: + '• Use the Google Meet button in the right tab next to "Connect." This will direct you to Google Meet, where a meeting template will be prefilled, making it easier to schedule a session with your partner.', + }, + ], + }, + { + stepTitle: "Review Partner's Code", + stepContent: [ + { + sectionTitle: "Challenge Overview", + description: + "1. Use HTML to create a card layout, including an image, title, description, and a hidden section with text.\n2. Apply CSS for layout and design (e.g., background color, padding, and shadows).\n3. Implement JavaScript to toggle the visibility of the hidden text when the card is clicked.", + }, + { + sectionTitle: "Send and Review Code", + description: + "• Ensure the click event works and the hidden text reveals itself correctly.\n• Review the structure and organization of the HTML, CSS, and JavaScript. Are there ways to improve readability or modularity? Evaluate the overall appearance of the card.\n• Is the design polished and responsive across various screen sizes?", + }, + ], + }, + { + stepTitle: "Finalize Component Together", + stepContent: [ + { + sectionTitle: "Apply feedback", + description: + "• Collaborate with your partner to apply any feedback or improvements based on your reviews.", + }, + { + sectionTitle: "Test the Final Version", + description: + "• Work together to test the final component and ensure everything functions correctly.", + }, + { + sectionTitle: "Submit the Final Challenge", + description: + "• Once you are both satisfied with the final version of the component, submit the challenge by clicking Complete.", + }, + ], + }, + ], + }; + + const handleDashboard = () => { + navigate("/ChallengePage"); + }; + const [currentStep, setCurrentStep] = useState(0); + + const handleNextStep = () => { + if (currentStep < 3) { + // Assuming you have 3 steps (you can adjust this value based on your step count) + setCurrentStep(currentStep + 1); + } + }; + return ( +
+ {taskDetails.steps.map((step, index) => ( + <> +
+ {/* Dynamic Button for each step */} +
index ? "completed" : currentStep === index ? "active" : ""}`} + style={{ backgroundColor: step.buttonColor }} + > +
{step.stepTitle}
+
+ + {/* Task Details */} +
+ {step.stepContent.map((content, subIndex) => ( +
+
{content.sectionTitle}
+
+ {content.description} +
+
+ ))} +
+
+ + ))} +
+ + {/* */} + {currentStep >= 3 ? ( + + ) : ( + + )} +
+
+ ); +}; + +export default P5ChallengeTaskStepper; diff --git a/src/components/P5ChallengeTaskStepper/P5ChallengeTaskStepper.scss b/src/components/P5ChallengeTaskStepper/P5ChallengeTaskStepper.scss new file mode 100644 index 0000000..c96299b --- /dev/null +++ b/src/components/P5ChallengeTaskStepper/P5ChallengeTaskStepper.scss @@ -0,0 +1,180 @@ +.task-stepper-container { + width: 100%; + display: flex; + flex-direction: column; + gap: 16px; + padding: 40px; + + @media (max-width: 768px) { + gap: 12px; + } + + @media (max-width: 480px) { + gap: 8px; + } +} + +.step-button { + padding: 2px 16px; + background-color: #dadada; + border-radius: 40px; + display: flex; + justify-content: center; + align-items: center; + gap: 10px; + width: fit-content; + text-align: center; + font-size: 12px; + font-family: "Corben", sans-serif; + font-weight: 700; + line-height: 24px; + letter-spacing: 0.36px; + word-wrap: break-word; + + &.completed { + background-color: green; /* Green when step is completed */ + color: white; + } + &.active { + background-color: #0954b0; + color: white; + } + &.inactive { + background-color: #dadada; + color: black; + } + + @media (max-width: 768px) { + padding: 6px 14px; + .button-text { + font-size: 12px; + } + } + + @media (max-width: 480px) { + padding: 4px 12px; + .button-text { + font-size: 10px; + } + } +} + +.task-details { + width: 100%; + padding-left: 8px; + padding-right: 8px; + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: flex-start; + gap: 16px; + + @media (max-width: 768px) { + gap: 12px; + } + + @media (max-width: 480px) { + gap: 8px; + } +} + +.task-section { + width: 100%; + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: flex-start; + gap: 8px; + + .section-title { + color: #000; + font-size: 12px; + font-family: "Corben", sans-serif; + font-weight: 700; + line-height: 24px; + letter-spacing: 0.36px; + word-wrap: break-word; + } + + .section-description { + color: #000; + font-size: 14px; + font-family: "Corben-regular", sans-serif; + font-weight: 400; + line-height: 24px; + word-wrap: break-word; + text-align: justify; + } + + @media (max-width: 768px) { + .section-title { + font-size: 14px; + } + .section-description { + font-size: 12px; + } + } + + @media (max-width: 480px) { + .section-title { + font-size: 12px; + } + .section-description { + font-size: 10px; + } + } +} + +.navigation-bottom-buttons { + margin-top: 40px; + display: flex; /* Flexbox for side-by-side layout */ + justify-content: flex-start; /* Aligns buttons to the left */ + gap: 24px; /* Space between the buttons */ + // padding-left: 48px; + // padding-right: 48px; + width: 100%; + + .dashboard-button, + .next-button { + flex: 1; /* Allow buttons to scale */ + max-width: 200px; /* Set a maximum width for each button */ + padding: 2px 0px 2px 0px; + display: inline-flex; + justify-content: center; + align-items: center; + gap: 8px; + cursor: pointer; + border-radius: 4px; + border-left: 3px solid black; + border-top: 3px solid black; + border-right: 6px solid black; + border-bottom: 6px solid black; + font-family: "Corben", sans-serif; + font-weight: 700; + line-height: 28px; + word-wrap: break-word; + font-size: 20px; + text-align: center; + + &.active { + background-color: #0954b0; /* Green when step is completed */ + } + &.completed{ + background-color: green; /* Green when step is completed */ + + } + } + + .dashboard-button { + background-color: white; + } + + .next-button { + background-color: #0099ff; + } + + .dashboard-text, + .next-text { + color: black; + } +} diff --git a/src/components/P5ChallengeTaskTimer/P5ChallengeTaskTimer.jsx b/src/components/P5ChallengeTaskTimer/P5ChallengeTaskTimer.jsx new file mode 100644 index 0000000..b18b0c6 --- /dev/null +++ b/src/components/P5ChallengeTaskTimer/P5ChallengeTaskTimer.jsx @@ -0,0 +1,31 @@ +import React from 'react'; +import './P5ChallengeTaskTimer.scss'; +import Pen from '../../assets/images/Pen.png'; +import Clock from '../../assets/images/Clock.png'; +import Idea from '../../assets/images/Idea.png'; + +const P5ChallengeTaskTimer = () => { + return ( +
+ {/* Task: Code */} +
+ Pen Icon +
Code
+
+ + {/* Task Duration: 60-90 min */} +
+ Clock Icon +
60-90 min
+
+ + {/* Technologies: HTML · CSS · JavaScript */} +
+ Idea Icon +
HTML · CSS · JavaScript
+
+
+ ); +} + +export default P5ChallengeTaskTimer; diff --git a/src/components/P5ChallengeTaskTimer/P5ChallengeTaskTimer.scss b/src/components/P5ChallengeTaskTimer/P5ChallengeTaskTimer.scss new file mode 100644 index 0000000..6de1f24 --- /dev/null +++ b/src/components/P5ChallengeTaskTimer/P5ChallengeTaskTimer.scss @@ -0,0 +1,25 @@ +.task-timer-wrapper { + display: flex; + flex-direction: column; /* Stack items vertically */ + gap: 8px; /* Adjust gap between items */ +} + +.task-item { + display: flex; + align-items: center; + gap: 8px; /* Adjust spacing between icon and text */ +} + +.task-icon { + width: 24px; + height: 24px; +} + +.task-text { + color: #343434; + font-size: 18px; + font-family: 'Corben'; + font-weight: 400; + line-height: 24px; + letter-spacing: 0.54px; +} diff --git a/src/components/P5ConnectSection/P5ConnectSection.jsx b/src/components/P5ConnectSection/P5ConnectSection.jsx new file mode 100644 index 0000000..69cd0ff --- /dev/null +++ b/src/components/P5ConnectSection/P5ConnectSection.jsx @@ -0,0 +1,27 @@ +import React from 'react'; +import './P5ConnectSection.scss'; +import googleMeetIcon from '../../assets/images/icons8-google-meet-96 1.jpg'; +import linkedinIcon from '../../assets/images/u_linkedin.jpg'; + +const P5ConnectSection = () => { + return ( +
+
Connect
+
+ {/* LinkedIn Button */} +
+ LinkedIn +
Kate-Tanner
+
+ + {/* Google Meet Button */} +
+ Google Meet +
vww-snqc-ynw
+
+
+
+ ); +}; + +export default P5ConnectSection; diff --git a/src/components/P5ConnectSection/P5ConnectSection.scss b/src/components/P5ConnectSection/P5ConnectSection.scss new file mode 100644 index 0000000..ff2e423 --- /dev/null +++ b/src/components/P5ConnectSection/P5ConnectSection.scss @@ -0,0 +1,44 @@ +.connect-section { + display: flex; + align-items: flex-start; + gap: 16px; +} + +.connect-title { + color: #131313; + font-size: 18px; + font-family: 'Corben-regular'; + font-weight: 400; + line-height: 24px; + letter-spacing: 0.54px; + margin-right: 16px; /* Add spacing between title and buttons */ +} + +.connect-buttons { + display: flex; + flex-direction: column; /* Align buttons vertically */ + gap: 12px; +} + +.connect-button { + display: flex; + align-items: center; + background-color: #EFEFEF; + border-radius: 20px; + padding: 4px 8px; + gap: 8px; +} + +.connect-icon { + width: 24px; + height: 24px; +} + +.connect-text { + color: #343434; + font-size: 12px; + font-family: 'Corben'; + font-weight: 700; + line-height: 24px; + letter-spacing: 0.36px; +} diff --git a/src/components/P5PartnerInfo/P5PartnerInfo.jsx b/src/components/P5PartnerInfo/P5PartnerInfo.jsx new file mode 100644 index 0000000..1b0f2f2 --- /dev/null +++ b/src/components/P5PartnerInfo/P5PartnerInfo.jsx @@ -0,0 +1,40 @@ +import React from 'react'; +import './P5PartnerInfo.scss'; +import profileImage from '../../assets/images/Profile Image.jpg'; // Path to the partner's profile image +import beginnerIcon from '../../assets/images/work_24px.jpg'; // Path to the beginner level icon +import fullStackIcon from '../../assets/images/file-chart_24px.jpg'; // Path to the full stack icon + +const P5PartnerInfo = () => { + return ( +
+ {/* Partner Title */} +
Partner
+ + {/* Partner Info Section */} +
+ {/* Kate Tanner Profile */} +
+ Kate Tanner +
Kate Tanner
+
+ + {/* Stacked Badges */} +
+ {/* Beginner Badge */} +
+ Beginner Icon +
Beginner
+
+ + {/* Full Stack Dev Badge */} +
+ Full Stack Dev Icon +
Full Stack Dev
+
+
+
+
+ ); +}; + +export default P5PartnerInfo; diff --git a/src/components/P5PartnerInfo/P5PartnerInfo.scss b/src/components/P5PartnerInfo/P5PartnerInfo.scss new file mode 100644 index 0000000..9cea8f9 --- /dev/null +++ b/src/components/P5PartnerInfo/P5PartnerInfo.scss @@ -0,0 +1,76 @@ +.partner-info-wrapper { + display: flex; + align-items: center; + gap: 16px; +} + +.partner-title { + color: #131313; + font-size: 18px; + font-family: 'Corben-regular'; + font-weight: 400; + line-height: 24px; + letter-spacing: 0.54px; +} + +.partner-info-container { + display: flex; + flex-direction: column; /* Ensures vertical stacking */ + gap: 8px; +} + +.partner-badge { + display: flex; + align-items: center; + padding: 8px 12px; + border-radius: 20px; + gap: 8px; +} + +.primary-badge { + background-color: #0954B0; +} + +.partner-image { + width: 24px; + height: 24px; + border-radius: 50%; + object-fit: cover; +} + +.partner-name { + color: #fff; + font-size: 12px; + font-family: 'Corben'; + font-weight: 700; + line-height: 24px; + letter-spacing: 0.36px; +} + +.partner-badge-container { + display: flex; + flex-direction: column; /* Ensures badges stack vertically */ + gap: 8px; +} + +.secondary-badge { + background-color: #EFEFEF; + padding: 8px 12px; + display: flex; + align-items: center; + border-radius: 20px; +} + +.badge-icon { + width: 24px; + height: 24px; +} + +.badge-text { + color: #343434; + font-size: 12px; + font-family: 'Corben'; + font-weight: 700; + line-height: 24px; + letter-spacing: 0.36px; +} diff --git a/src/components/Roadmap/Roadmap.jsx b/src/components/Roadmap/Roadmap.jsx index 8d73155..985279f 100644 --- a/src/components/Roadmap/Roadmap.jsx +++ b/src/components/Roadmap/Roadmap.jsx @@ -14,6 +14,7 @@ import user1Picture from "../../assets/images/user1.png"; import user2Picture from "../../assets/images/user2.png"; import { callOpenAiApi } from "../../utils/Functions/openaiFunctions"; import LoadingPage from "../LoadingPage/LoadingPage"; +import { GOALS_DATA, MOCK_MATCH_DATA } from "../../mock-data/roadmapMockData"; const Roadmap = () => { const [activeGoal, setActiveGoal] = useState(null); @@ -21,119 +22,10 @@ const Roadmap = () => { const [hovering, setHovering] = useState(null); - const [user1Pic, setUser1Pic] = useState(user1Picture); //replace user1 with null instead of image placeholder - const [user2Pic, setUser2Pic] = useState(user2Picture); //replace user2 with null instead of image placeholder - const [user1Name, setUser1Name] = useState("User1"); const [user2Name, setUser2Name] = useState("User2"); const [completionPercentage, setCompletionPercentage] = useState(0); - - // useEffect(() => { - // console.log("aicall"); - // const aiApiCallData = async () => { - // console.log("aicall111"); - - // const userA = { firstName: "Alice", skills: ["JavaScript", "React"] }; - // const userB = { firstName: "Bob", skills: ["Python", "Django"] }; - // const project = "building a web application"; - - // try { - // console.log("aicall122"); - - // const data = await callOpenAiApi(userA, userB, project); - // console.log(data.goals); - // setGoals(data.goals); - // setLoadingPage(false); - // // console.log("loading"); - // } catch (error) { - // console.error("Error fetching data:", error); - // } - // } - // aiApiCallData(); - // }, []); - - // CALL BACKEND FUNCTION: Get Matches - // Use the data of only the most recent match - - // CALL BACKEND FUNCTION: Get User - // Get both users based on user id from the match table - - // CALL BACKEND FUNCTION: Get UserGoalCompletion - // Get UserGoalCompletion data with match id (all 5 records) - - // CALL BACKEND FUNCTION: Get Goals - // Get Goals from UserGoalCompletion goal id - - // CALL BACKEND FUNCTION: Get UserSubtaskCompletion - // Get UserSubtaskCompletion data with goal id (all 5 records) - - // CALL BACKEND FUNCTION: Get Subtasks - // Get Goals from UserSubtaskCompletion subtask id - - //mock roadmap data - const goalsData = [ - { - goal: "Attend 4 meetings", - subtasks: [ - "Schedule & attend 1 accountability meeting", - "Attend 2 accountability meetings", - "Attend 3 accountability meetings", - "Attend all 4 accountability meetings", - ], - }, - { - goal: "Design and implement the frontend of the web application using JavaScript and React", - subtasks: [ - "Discuss and finalize the UI/UX design for the application", - "Break down the design into reusable React components", - "Implement the React components using JavaScript", - "Test the components individually and as a whole to ensure they work as expected", - ], - }, - { - goal: "Develop the backend of the web application using Python and Django", - subtasks: [ - "Design the database schema and establish the necessary Django models", - "Implement the necessary views and templates in Django", - "Integrate the Django backend with the React frontend", - "Test the backend functionality and ensure it works with the frontend", - ], - }, - { - goal: "Deploy the web application", - subtasks: [ - "Choose a suitable hosting platform for the application", - "Configure the deployment settings for both frontend and backend", - "Deploy the application and test it in the production environment", - "Monitor the application performance and fix any issues that arise", - ], - }, - { - goal: "Attend 4 meetings to go over what you’ve learned", - subtasks: [ - "Schedule & attend 1 accountability meeting", - "Attend 2 accountability meetings", - "Attend 3 accountability meetings", - "Attend all 4 accountability meetings", - ], - }, - ]; - console.log(goalsData[0].subtasks); - - // This object is temporary and only here to provide mock data to show the functionality of the popup - const mockMatchData = { - goal1Task: "Goal 1 task", - goal2Task: "Goal 2 task", - goal3Task: "Goal 3 task", - goal4Task: "Goal 4 task", - goal5Task: "Goal 5 task", - user1Picture: user1Picture, - user2Picture: user2Picture, - }; - - - const handleGoalClickModal = (goalNumber) => { setActiveGoal(goalNumber); setmodalOpen(true); @@ -158,8 +50,8 @@ const Roadmap = () => { @@ -167,7 +59,6 @@ const Roadmap = () => { ); }; - return (
@@ -184,12 +75,12 @@ const Roadmap = () => {
user1 avatar user2 avatar @@ -212,12 +103,12 @@ const Roadmap = () => { offsetX={"8.4rem"} offsetY={"8.4rem"} number={1} - task={mockMatchData.goal1Task} + task={MOCK_MATCH_DATA.goal1Task} locked={false} user1Complete={true} user2Complete={false} - user1Picture={mockMatchData.user1Picture} - user2Picture={mockMatchData.user2Picture} + user1Picture={user1Picture} + user2Picture={user2Picture} /> )}
@@ -239,12 +130,12 @@ const Roadmap = () => { offsetX={"7.3rem"} offsetY={"7.3rem"} number={2} - task={mockMatchData.goal2Task} + task={MOCK_MATCH_DATA.goal2Task} locked={true} user1Complete={false} user2Complete={false} - user1Picture={mockMatchData.user1Picture} - user2Picture={mockMatchData.user2Picture} + user1Picture={user1Picture} + user2Picture={user2Picture} /> )}
@@ -266,12 +157,12 @@ const Roadmap = () => { offsetX={"6.1rem"} offsetY={"6.1rem"} number={3} - task={mockMatchData.goal3Task} + task={MOCK_MATCH_DATA.goal3Task} locked={true} user1Complete={false} user2Complete={false} - user1Picture={mockMatchData.user1Picture} - user2Picture={mockMatchData.user2Picture} + user1Picture={user1Picture} + user2Picture={user2Picture} /> )}
@@ -293,12 +184,12 @@ const Roadmap = () => { offsetX={"4.95rem"} offsetY={"4.95rem"} number={4} - task={mockMatchData.goal4Task} + task={MOCK_MATCH_DATA.goal4Task} locked={true} user1Complete={false} user2Complete={false} - user1Picture={mockMatchData.user1Picture} - user2Picture={mockMatchData.user2Picture} + user1Picture={user1Picture} + user2Picture={user2Picture} /> )}
@@ -320,12 +211,12 @@ const Roadmap = () => { offsetX={"3.7rem"} offsetY={"3.7rem"} number={5} - task={mockMatchData.goal5Task} + task={MOCK_MATCH_DATA.goal5Task} locked={true} user1Complete={false} user2Complete={false} - user1Picture={mockMatchData.user1Picture} - user2Picture={mockMatchData.user2Picture} + user1Picture={user1Picture} + user2Picture={user2Picture} /> )}
diff --git a/src/components/StatusStarted/StatusStarted.jsx b/src/components/StatusStarted/StatusStarted.jsx new file mode 100644 index 0000000..d0f6f48 --- /dev/null +++ b/src/components/StatusStarted/StatusStarted.jsx @@ -0,0 +1,17 @@ +import React from 'react'; +import './StatusStarted.scss'; + +const StatusStarted = () => { + return ( +
+ {/* Status Title */} +
Status
+ {/* Status Box */} +
+
Started
+
+
+ ); +} + +export default StatusStarted; diff --git a/src/components/StatusStarted/StatusStarted.scss b/src/components/StatusStarted/StatusStarted.scss new file mode 100644 index 0000000..93a35f2 --- /dev/null +++ b/src/components/StatusStarted/StatusStarted.scss @@ -0,0 +1,36 @@ +.status-wrapper { + display: flex; + align-items: center; + gap: 16px; /* Adjusts the spacing between the "Status" title and the status box */ +} + +.status-title { + color: #131313; + font-size: 18px; + font-family: 'Corben'; + font-weight: 400; + line-height: 24px; + letter-spacing: 0.54px; +} + +.status-container { + padding: 8px 16px; + background-color: #018C06; + border-radius: 40px; + justify-content: center; + align-items: center; + display: flex; + width: 92px; /* Ensure this matches with the size of the "Kate Turner" box */ +} + +.status-text { + text-align: center; + color: white; + font-size: 12px; + font-family: 'Corben'; + font-weight: 700; + line-height: 24px; + letter-spacing: 0.36px; + word-wrap: break-word; +} + diff --git a/src/components/TaskPageDetailedInstructions/TaskPageDetailedInstructions.jsx b/src/components/TaskPageDetailedInstructions/TaskPageDetailedInstructions.jsx new file mode 100644 index 0000000..f55cc26 --- /dev/null +++ b/src/components/TaskPageDetailedInstructions/TaskPageDetailedInstructions.jsx @@ -0,0 +1,111 @@ +import "./TaskPageDetailedInstructions.scss"; +import { db } from "../../firebase"; +import { useEffect, useState, useRef } from "react"; +import { getDoc, doc } from "firebase/firestore"; +import closeIcon from "../../assets/icons/close_icon.svg" +import Button from "../Button/Button"; + +export default function TaskPageDetailedInstructions({ id }) { + + const challengeId = id + + const [challengeData, setChallengeData] = useState(null); + + const modalRef = useRef() + + useEffect(() => { + async function getChallengeData() { + + const docRef = doc(db, "Challenges", challengeId); + const docSnap = await getDoc(docRef); + + if (docSnap.exists()) { + const data = docSnap.data() + setChallengeData(data); + } + } + + getChallengeData() + }, [challengeId]) + + function toggleDetailsModal() { + //get the reference + + //change its style + if (modalRef.current.style.display === "none") { + modalRef.current.style.display = "flex" + } + else { + modalRef.current.style.display = "none" + } + } + + + if (!challengeData) { + return
Loading
; + } + return ( + <> + +
+
+ close Icon + <> +

{challengeData.task}

+

+ {challengeData.detailedProblem.description} +

+ + + +
+

Constraints

+
    + {challengeData.detailedProblem.constraints.map( + (constraint, index) => { + return ( +
  • + {constraint} +
  • + ); + } + )} +
+
+ +
+

Examples

+
    + {challengeData.detailedProblem.examples.map( + (example, index) => { + return ( + + Input: {example.input}
    Output: {example.output} +
    + ); + } + )} +
+
+ +
+

Solution Approach

+
    + {challengeData.detailedProblem.solutionApproach.map( + (example, index) => { + return ( +
  • + {example} +
  • + ); + } + )} +
+
+ + +
+
+ + ); +} \ No newline at end of file diff --git a/src/components/TaskPageDetailedInstructions/TaskPageDetailedInstructions.scss b/src/components/TaskPageDetailedInstructions/TaskPageDetailedInstructions.scss new file mode 100644 index 0000000..1c78ccc --- /dev/null +++ b/src/components/TaskPageDetailedInstructions/TaskPageDetailedInstructions.scss @@ -0,0 +1,38 @@ +@use "../../styles/partials/variables" as *; + +.details-modal { + width: 100%; + height: 100vh; + background-color: rgba(255, 255, 255, 0.5); + display: flex; + justify-content: center; + align-items: center; + border: 1px solid black; + position: absolute; + top: 0; + + &__overview { + width: 75%; + display: flex; + flex-direction: column; + gap: 2rem; + border-top: 3px solid $MVP-black; + border-right: 6px solid $MVP-black; + border-bottom: 6px solid $MVP-black; + border-left: 3px solid $MVP-black; + padding: 4rem; + position: relative; + } + + &__close-icon { + position: absolute; + top: 3rem; + right: 3.5rem; + height: 2rem; + + &:hover { + transform: scale(1.1) + } + + } +} \ No newline at end of file diff --git a/src/components/TaskStepper/TaskStepper.jsx b/src/components/TaskStepper/TaskStepper.jsx new file mode 100644 index 0000000..9a860e4 --- /dev/null +++ b/src/components/TaskStepper/TaskStepper.jsx @@ -0,0 +1,98 @@ +import React from 'react'; +import "./TaskStepper.scss"; + + +const TaskStepper = () => { + return ( +
+ {/* First Card - Blue Button */} +
+ +
+
LinkedIn
+
+ After building your component, input your code into the designated + User Code section and click Submit. +
+
+
+
Review Partner's Code
+
+ Use HTML to structure the card with an image, title, description, and + hidden section for additional text. Style the card using CSS (e.g., + background color, padding, shadows, etc.). Write JavaScript to toggle + the hidden text when the card is clicked. +
+
+
+
Finalize Component
+
+ Discuss and apply any feedback with your partner to refine your + components. Make sure everything works smoothly. Click Complete once + both of you are satisfied with the final version. +
+
+
+ + {/* Second Card - Green Button */} +
+ +
+
LinkedIn
+
+ After building your component, input your code into the designated + User Code section and click Submit. +
+
+
+
Review Partner's Code
+
+ Use HTML to structure the card with an image, title, description, and + hidden section for additional text. Style the card using CSS (e.g., + background color, padding, shadows, etc.). Write JavaScript to toggle + the hidden text when the card is clicked. +
+
+
+
Finalize Component
+
+ Discuss and apply any feedback with your partner to refine your + components. Make sure everything works smoothly. Click Complete once + both of you are satisfied with the final version. +
+
+
+ + {/* Third Card - Ash Button */} +
+ +
+
LinkedIn
+
+ After building your component, input your code into the designated + User Code section and click Submit. +
+
+
+
Review Partner's Code
+
+ Use HTML to structure the card with an image, title, description, and + hidden section for additional text. Style the card using CSS (e.g., + background color, padding, shadows, etc.). Write JavaScript to toggle + the hidden text when the card is clicked. +
+
+
+
Finalize Component
+
+ Discuss and apply any feedback with your partner to refine your + components. Make sure everything works smoothly. Click Complete once + both of you are satisfied with the final version. +
+
+
+
+ ); + }; + +export default TaskStepper; diff --git a/src/components/TaskStepper/TaskStepper.scss b/src/components/TaskStepper/TaskStepper.scss new file mode 100644 index 0000000..7154b3e --- /dev/null +++ b/src/components/TaskStepper/TaskStepper.scss @@ -0,0 +1,71 @@ +/* General styling for the card */ +.card-container { + display: flex; + flex-direction: column; + gap: 20px; + } + + .card { + border: 1px dotted #9747ff; + border-radius: 5px; + padding: 20px; + display: flex; + flex-direction: column; + gap: 12px; + } + + /* Title and button */ + .button { + padding: 10px 16px; + border-radius: 40px; + text-align: center; + font-family: 'Corben', sans-serif; + font-weight: 700; + font-size: 12px; + line-height: 24px; + letter-spacing: 0.36px; + color: white; + display: inline-flex; + justify-content: center; + align-items: center; + } + + .blue { + background-color: #0954b0; + } + + .green { + background-color: #018c06; + } + + .ash { + background-color: #dadada; + color: #131313; + } + + /* Section headers and descriptions */ + .section-header { + font-family: 'Corben', sans-serif; + font-weight: 700; + font-size: 12px; + color: black; + line-height: 24px; + letter-spacing: 0.36px; + } + + .section-description { + font-family: 'Corben', sans-serif; + font-weight: 400; + font-size: 16px; + color: black; + line-height: 24px; + } + + /* Section for tasks */ + .task-section { + display: flex; + flex-direction: column; + gap: 8px; + padding: 8px; + } + \ No newline at end of file diff --git a/src/constants.js b/src/constants.js new file mode 100644 index 0000000..b3dcc16 --- /dev/null +++ b/src/constants.js @@ -0,0 +1,3 @@ +export const COLLECTIONS = { + USERS: "Users", +}; diff --git a/src/contexts/PageContext.js b/src/contexts/PageContext.js new file mode 100644 index 0000000..b0fdd1f --- /dev/null +++ b/src/contexts/PageContext.js @@ -0,0 +1,71 @@ +import { createContext, useState, useMemo, useCallback } from "react"; +import { useNavigate } from "react-router-dom"; + +export const PageContext = createContext(); + +export const PageProvider = ({ children }) => { + const navigate = useNavigate(); + + const [currentPageIndex, setCurrentPageIndex] = useState(0); + const [progressBarIndex, setProgressBarIndex] = useState(0); + const [userFeedback, setUserFeedback] = useState({}); + + const progressArray = useMemo( + () => ["prompt", "onboarding1", "onboarding2", "onboarding3"], + [] + ); + + const updateUserFeedback = useCallback((key, value) => { + setUserFeedback((prevFeedback) => { + const newFeedback = { ...prevFeedback, [key]: value }; + return newFeedback; + }); + }, []); + + const handleNext = useCallback(() => { + const maxPages = progressArray.length - 1; + + if (currentPageIndex < maxPages) { + setProgressBarIndex((prevIndex) => prevIndex + 1); + setCurrentPageIndex((prevIndex) => prevIndex + 1); + } else { + navigate("/ChallengePage"); + } + }, [currentPageIndex, navigate, progressArray]); + + const handleBack = useCallback(() => { + if (progressBarIndex > 0 && currentPageIndex > 0) { + setProgressBarIndex((prevIndex) => prevIndex - 1); + setCurrentPageIndex((prevIndex) => prevIndex - 1); + } else { + navigate("/"); + } + }, [currentPageIndex, navigate, progressBarIndex]); + + const contextValue = useMemo( + () => ({ + currentPageIndex, + setCurrentPageIndex, + progressBarIndex, + setProgressBarIndex, + handleNext, + handleBack, + progressArray, + userFeedback, + updateUserFeedback, + }), + [ + currentPageIndex, + progressBarIndex, + handleNext, + handleBack, + progressArray, + userFeedback, + updateUserFeedback, + ] + ); + + return ( + {children} + ); +}; diff --git a/src/main.js b/src/main.js index c7e6119..a051174 100644 --- a/src/main.js +++ b/src/main.js @@ -1,12 +1,43 @@ import { Link } from "react-router-dom"; +import CoffeeMugWithHat_happy from "./assets/images/coffeeMugWithHat_happy.svg"; import "./styles/partials/_global.scss"; const Home = () => { return (
-

Welcome to AccountaBuddy!

- Click to go to AccountaBuddy +
+
+ <> +
+
+
+
+ +
+
+
+ Welcome to AccountaPair! +
+
+
+ + + + +
+
+
+
+ +
+
); }; diff --git a/src/mock-data/mockChallenges.js b/src/mock-data/mockChallenges.js new file mode 100644 index 0000000..6380c48 --- /dev/null +++ b/src/mock-data/mockChallenges.js @@ -0,0 +1,1974 @@ +export const MOCK_CHALLENGES = { + challenges: [ + { + id: 1, + technology: ["Python"], + category: "Python", + difficulty: "Easy", + duration: "60 mins", + task: "Sum even numbers", + details: + "Write a Python function that takes a list of integers and returns the sum of all even numbers.", + detailedProblem: { + description: + "Given a list of integers, write a function that returns the sum of all even numbers in the list.", + examples: [ + { + input: "[1, 2, 3, 4, 5]", + output: "6", + explanation: + "The even numbers in the list are 2 and 4. Their sum is 2 + 4 = 6.", + }, + { + input: "[7, 11, 13, 17]", + output: "0", + explanation: + "There are no even numbers in the list, so the sum is 0.", + }, + { + input: "[2, 4, 6, 8]", + output: "20", + explanation: + "All numbers in the list are even, so the sum is 2 + 4 + 6 + 8 = 20.", + }, + ], + constraints: [ + "The list can contain negative integers.", + "The list can contain at most 10^4 integers.", + ], + solutionApproach: [ + "Loop through the list of integers.", + "Use a conditional check to see if a number is even (i.e., divisible by 2).", + "Sum up all the even numbers and return the result.", + ], + }, + }, + + { + id: 2, + technology: ["Python"], + category: "Python", + difficulty: "Easy", + duration: "45 mins", + task: "Reverse a string", + details: + "Write a Python function that takes a string and returns its reverse.", + detailedProblem: { + description: + "Given a string, write a function that returns the string in reverse order.", + examples: [ + { + input: '"hello"', + output: '"olleh"', + explanation: "The characters are reversed from left to right.", + }, + { + input: '"Python"', + output: '"nohtyP"', + explanation: "The characters are reversed from left to right.", + }, + ], + constraints: [ + "The input string can contain any ASCII character.", + "The maximum length of the string is 10^5 characters.", + ], + solutionApproach: [ + "Use string slicing with a step of -1 to reverse the string.", + "Alternatively, convert the string to a list, reverse it, and join it back into a string.", + ], + }, + }, + { + id: 3, + technology: ["Python"], + category: "Python", + difficulty: "Easy", + duration: "30 mins", + task: "Count vowels", + details: + "Write a Python function that counts the number of vowels in a given string.", + detailedProblem: { + description: + "Given a string, write a function that returns the count of vowels (a, e, i, o, u) in the string. The function should be case-insensitive.", + examples: [ + { + input: '"Hello World"', + output: "3", + explanation: "The vowels are 'e', 'o', and 'o'.", + }, + { + input: '"Python Programming"', + output: "4", + explanation: "The vowels are 'o', 'o', 'a', and 'i'.", + }, + ], + constraints: [ + "The input string contains only ASCII characters.", + "The function should be case-insensitive (treat 'A' the same as 'a').", + "The maximum length of the string is 10^4 characters.", + ], + solutionApproach: [ + "Convert the string to lowercase.", + "Define a set of vowels.", + "Iterate through the string and count characters that are in the vowel set.", + ], + }, + }, + { + id: 4, + technology: ["Python"], + category: "Python", + difficulty: "Easy", + duration: "40 mins", + task: "Find the largest number", + details: + "Write a Python function that finds the largest number in a list of integers.", + detailedProblem: { + description: + "Given a list of integers, write a function that returns the largest number in the list.", + examples: [ + { + input: "[1, 4, 9, 2, 5, 6]", + output: "9", + explanation: "9 is the largest number in the list.", + }, + { + input: "[-1, -5, -3, -2]", + output: "-1", + explanation: + "-1 is the largest number in the list of negative integers.", + }, + ], + constraints: [ + "The list contains at least one integer.", + "The list can contain both positive and negative integers.", + "The maximum length of the list is 10^5 elements.", + ], + solutionApproach: [ + "Use the built-in max() function to find the largest number.", + "Alternatively, initialize the largest number as the first element and iterate through the list to find a larger number.", + ], + }, + }, + { + id: 5, + technology: ["Python"], + category: "Python", + difficulty: "Intermediate", + duration: "60 mins", + task: "Anagram check", + details: + "Write a Python function to check if two strings are anagrams, ignoring spaces and capitalization.", + detailedProblem: { + description: + "Given two strings, write a function to determine if the strings are anagrams of each other. An anagram is formed by rearranging the letters of another word using all original letters exactly once. The function should ignore spaces and capitalization.", + examples: [ + { + input: '"Listen", "Silent"', + output: "True", + explanation: + "After ignoring the case and spaces, both strings are rearrangements of each other.", + }, + { + input: '"Dormitory", "Dirty room"', + output: "True", + explanation: + "Ignoring the space and case, 'Dormitory' can be rearranged to form 'Dirty room'.", + }, + { + input: '"Hello", "World"', + output: "False", + explanation: + "The two words don't have the same characters, so they are not anagrams.", + }, + ], + constraints: [ + "The input strings consist of lowercase and uppercase English letters and spaces.", + "The length of each string is at most 10^5 characters.", + ], + solutionApproach: [ + "Remove all spaces and convert both strings to lowercase.", + "Sort both strings and check if they are equal.", + "If the sorted versions of the strings are the same, return True; otherwise, return False.", + ], + }, + }, + { + id: 6, + technology: ["Python"], + category: "Python", + difficulty: "Intermediate", + duration: "60 mins", + task: "Implement a stack data structure", + details: + "Create a Stack class with push, pop, and peek operations using a Python list.", + detailedProblem: { + description: + "Implement a Stack class that uses a Python list to store elements. The class should have methods for push (add an element), pop (remove and return the top element), peek (return the top element without removing it), and is_empty (check if the stack is empty).", + examples: [ + { + input: + "stack = Stack()\nstack.push(1)\nstack.push(2)\nstack.pop()\nstack.peek()", + output: "2\n1", + explanation: + "Push 1 and 2 to the stack, pop the top element (2), then peek at the new top element (1).", + }, + ], + constraints: [ + "The Stack should use a Python list for internal storage.", + "All operations should have O(1) time complexity.", + ], + solutionApproach: [ + "Use a Python list as the underlying data structure.", + "Implement push by appending to the list.", + "Implement pop by removing and returning the last element of the list.", + "Implement peek by returning the last element without removing it.", + "Implement is_empty by checking if the list's length is zero.", + ], + }, + }, + { + id: 7, + technology: ["Python"], + category: "Python", + difficulty: "Intermediate", + duration: "75 mins", + task: "Implement a binary search algorithm", + details: + "Write a function to perform binary search on a sorted list of integers.", + detailedProblem: { + description: + "Implement a binary search function that takes a sorted list of integers and a target value. The function should return the index of the target value if it's in the list, or -1 if it's not found.", + examples: [ + { + input: "binary_search([1, 3, 5, 7, 9], 5)", + output: "2", + explanation: "The value 5 is found at index 2 in the list.", + }, + { + input: "binary_search([1, 3, 5, 7, 9], 6)", + output: "-1", + explanation: "The value 6 is not in the list, so -1 is returned.", + }, + ], + constraints: [ + "The input list is always sorted in ascending order.", + "The list can contain up to 10^6 elements.", + ], + solutionApproach: [ + "Initialize two pointers, left and right, to the start and end of the list.", + "While left <= right, calculate the middle index.", + "If the middle element is the target, return its index.", + "If the target is less than the middle element, search the left half.", + "If the target is greater than the middle element, search the right half.", + "If the loop ends without finding the target, return -1.", + ], + }, + }, + { + id: 8, + technology: ["Python"], + category: "Python", + difficulty: "Intermediate", + duration: "90 mins", + task: "Implement a basic web scraper", + details: + "Create a Python script that scrapes a website and extracts specific information.", + detailedProblem: { + description: + "Write a Python script that scrapes a given URL for all the paragraph text on the page. The script should use the requests library to fetch the HTML content and the BeautifulSoup library to parse it.", + examples: [ + { + input: 'scrape_paragraphs("https://example.com")', + output: + '["This is the first paragraph.", "This is the second paragraph.", ...]', + explanation: + "The function returns a list of all paragraph texts found on the page.", + }, + ], + constraints: [ + "Use the requests library to fetch the HTML content.", + "Use BeautifulSoup from bs4 to parse the HTML.", + "Handle potential network errors gracefully.", + ], + solutionApproach: [ + "Import the necessary libraries (requests and BeautifulSoup).", + "Define a function that takes a URL as input.", + "Use requests.get() to fetch the HTML content.", + "Create a BeautifulSoup object with the HTML content.", + "Use soup.find_all('p') to locate all paragraph tags.", + "Extract the text from each paragraph and store in a list.", + "Return the list of paragraph texts.", + ], + }, + }, + { + id: 9, + technology: ["Python"], + category: "Python", + difficulty: "Intermediate", + duration: "60 mins", + task: "Implement a basic decorator", + details: + "Create a decorator that measures the execution time of a function.", + detailedProblem: { + description: + "Write a decorator function called 'timer' that measures the execution time of any function it decorates. The decorator should print the time taken by the function to execute.", + examples: [ + { + input: + "@timer\ndef slow_function():\n time.sleep(2)\n return 'Done'\n\nslow_function()", + output: + "Function 'slow_function' took 2.00 seconds to execute.\n'Done'", + explanation: + "The decorator prints the execution time, and the function returns its result.", + }, + ], + constraints: [ + "Use the time module to measure execution time.", + "The decorator should work with any function, regardless of its arguments or return value.", + ], + solutionApproach: [ + "Import the time module and functools.wraps.", + "Define the timer decorator function.", + "Use @functools.wraps to preserve the metadata of the decorated function.", + "Inside the wrapper, record the start time, call the function, record the end time.", + "Calculate and print the execution time.", + "Return the result of the function call.", + ], + }, + }, + { + id: 10, + technology: ["Python"], + category: "Python", + difficulty: "Hard", + duration: "120 mins", + task: "Implement a basic neural network", + details: + "Create a simple neural network class with forward propagation and backpropagation.", + detailedProblem: { + description: + "Implement a basic neural network class with a single hidden layer. The class should support forward propagation, backpropagation, and training using gradient descent. Use numpy for efficient matrix operations.", + examples: [ + { + input: + "nn = NeuralNetwork(2, 3, 1)\nX = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])\ny = np.array([[0], [1], [1], [0]])\nnn.train(X, y, epochs=10000)\nnn.predict(np.array([0, 0]))", + output: "[[0.02]]", + explanation: + "Train the neural network on XOR problem and predict for input [0, 0].", + }, + ], + constraints: [ + "Use numpy for matrix operations.", + "Implement both forward propagation and backpropagation.", + "Use sigmoid activation function.", + ], + solutionApproach: [ + "Create a NeuralNetwork class with input, hidden, and output layer sizes.", + "Initialize weights and biases randomly.", + "Implement sigmoid and its derivative functions.", + "Create methods for forward propagation and backpropagation.", + "Implement a train method using gradient descent.", + "Create a predict method for making predictions on new data.", + ], + }, + }, + { + id: 11, + technology: ["Python"], + category: "Python", + difficulty: "Hard", + duration: "90 mins", + task: "Implement a basic blockchain", + details: "Create a simple blockchain implementation in Python.", + detailedProblem: { + description: + "Implement a basic blockchain class that allows adding blocks, validating the chain, and mining new blocks with a proof-of-work mechanism.", + examples: [ + { + input: + "blockchain = Blockchain()\nblockchain.add_block('Transaction 1')\nblockchain.add_block('Transaction 2')\nprint(blockchain.is_chain_valid())", + output: "True", + explanation: + "Create a blockchain, add two blocks, and verify its validity.", + }, + ], + constraints: [ + "Use SHA-256 for hashing.", + "Implement a simple proof-of-work mechanism.", + "Each block should contain: index, timestamp, data, previous hash, hash, and nonce.", + ], + solutionApproach: [ + "Create a Block class to represent individual blocks.", + "Implement a Blockchain class to manage the chain of blocks.", + "Use hashlib for SHA-256 hashing.", + "Implement methods for creating genesis block, adding blocks, and mining blocks.", + "Create a method to validate the entire blockchain.", + "Implement a simple proof-of-work algorithm (e.g., find a hash with leading zeros).", + ], + }, + }, + { + id: 12, + technology: ["Python"], + category: "Python", + difficulty: "Hard", + duration: "150 mins", + task: "Implement a basic compiler", + details: + "Create a simple compiler that translates a basic language into Python bytecode.", + detailedProblem: { + description: + "Implement a basic compiler that can translate a simple custom language into Python bytecode. The language should support variable assignments, arithmetic operations, and print statements.", + examples: [ + { + input: 'compiler.compile("x = 5\ny = 10\nprint x + y")', + output: " at 0x...>", + explanation: "Compile the given code into Python bytecode.", + }, + ], + constraints: [ + "The custom language should support integer variables, addition, and print statements.", + "Use the dis module to generate and inspect bytecode.", + "Handle basic syntax errors in the input language.", + ], + solutionApproach: [ + "Implement a lexer to tokenize the input code.", + "Create a parser to build an abstract syntax tree (AST) from the tokens.", + "Implement a code generator that translates the AST into Python bytecode.", + "Use the types.CodeType to create a code object from the generated bytecode.", + "Implement error handling for basic syntax errors.", + "Create a method to execute the compiled code.", + ], + }, + }, + { + id: 13, + technology: ["Python"], + category: "Python", + difficulty: "Hard", + duration: "120 mins", + task: "Implement a basic distributed key-value store", + details: + "Create a simple distributed key-value store using sockets and threading.", + detailedProblem: { + description: + "Implement a basic distributed key-value store with a server and multiple clients. The server should handle concurrent connections and maintain a shared key-value store. Clients should be able to connect, set values, get values, and disconnect.", + examples: [ + { + input: "client.set('key', 'value')\nclient.get('key')", + output: "'value'", + explanation: + "Set a key-value pair and retrieve it from the distributed store.", + }, + ], + constraints: [ + "Use sockets for network communication.", + "Use threading to handle multiple client connections.", + "Implement basic error handling and connection management.", + ], + solutionApproach: [ + "Create a Server class that listens for incoming connections.", + "Implement a ClientHandler class to manage each client connection.", + "Use a dictionary to store the key-value pairs on the server.", + "Implement a simple protocol for communication (e.g., 'SET key value', 'GET key').", + "Create a Client class that can connect to the server and send commands.", + "Use threading.Lock to ensure thread-safe access to the shared dictionary.", + "Implement error handling for network issues and invalid commands.", + ], + }, + }, + { + id: 14, + technology: ["Python"], + category: "Python", + difficulty: "Hard", + duration: "60 mins", + task: "Matrix rotation", + details: + "Rotate a given N x N matrix 90 degrees clockwise using only O(1) space.", + detailedProblem: { + description: + "Given an N x N matrix, rotate the matrix by 90 degrees clockwise in place. This means that the operation should be performed without using any additional matrices (i.e., using only O(1) space).", + examples: [ + { + input: "[[1, 2, 3], [4, 5, 6], [7, 8, 9]]", + output: "[[7, 4, 1], [8, 5, 2], [9, 6, 3]]", + explanation: "The matrix is rotated 90 degrees clockwise.", + }, + { + input: + "[[5, 1, 9, 11], [2, 4, 8, 10], [13, 3, 6, 7], [15, 14, 12, 16]]", + output: + "[[15, 13, 2, 5], [14, 3, 4, 1], [12, 6, 8, 9], [16, 7, 10, 11]]", + explanation: "The matrix is rotated 90 degrees clockwise.", + }, + ], + constraints: [ + "The matrix will always be an N x N grid, where 1 <= N <= 1000.", + "The matrix contains integers between -1000 and 1000.", + ], + solutionApproach: [ + "Transpose the matrix (swap rows with columns).", + "Reverse each row.", + "This will rotate the matrix 90 degrees clockwise in place.", + ], + }, + }, + { + id: 15, + technology: ["React", "useState"], + category: "React", + difficulty: "Easy", + duration: "45 mins", + task: "Button click counter", + details: + "Create a React component with a button that displays the number of times it has been clicked.", + detailedProblem: { + description: + "Implement a React component that renders a button. The button should display the number of times it has been clicked. The count should update each time the button is pressed.", + examples: [ + { + input: "Initial render", + output: "Button displays: 'Clicks: 0'", + }, + { + input: "After 3 clicks", + output: "Button displays: 'Clicks: 3'", + }, + ], + constraints: [ + "Use the useState hook to manage the click count.", + "The button should update its text immediately after each click.", + ], + solutionApproach: [ + "Create a state variable to store the click count.", + "Implement an onClick handler that increments the count.", + "Display the current count within the button text.", + ], + }, + }, + { + id: 16, + technology: ["React", "useState"], + category: "React", + difficulty: "Easy", + duration: "30 mins", + task: "Toggle visibility", + details: + "Create a React component with a button that toggles the visibility of a text element.", + detailedProblem: { + description: + "Implement a React component that contains a button and a text element. Clicking the button should toggle the visibility of the text element.", + examples: [ + { + input: "Initial render", + output: "Button visible, text hidden", + }, + { + input: "After first click", + output: "Button visible, text visible", + }, + { + input: "After second click", + output: "Button visible, text hidden again", + }, + ], + constraints: [ + "Use the useState hook to manage the visibility state.", + "The text should be completely removed from the DOM when hidden, not just visually hidden.", + ], + solutionApproach: [ + "Create a state variable to store the visibility status.", + "Implement an onClick handler that toggles the visibility state.", + "Use conditional rendering to show or hide the text element based on the state.", + ], + }, + }, + { + id: 17, + technology: ["React", "useState"], + category: "React", + difficulty: "Easy", + duration: "40 mins", + task: "Simple form input", + details: + "Create a React component with an input field that displays its value in real-time.", + detailedProblem: { + description: + "Implement a React component with a text input field. As the user types, the current value of the input should be displayed below it in real-time.", + examples: [ + { + input: "User types 'Hello'", + output: + "Input field contains 'Hello', and 'You typed: Hello' is displayed below", + }, + ], + constraints: [ + "Use the useState hook to manage the input value.", + "The displayed text should update with each keystroke.", + ], + solutionApproach: [ + "Create a state variable to store the input value.", + "Implement an onChange handler that updates the state with the current input value.", + "Display the current state value below the input field.", + ], + }, + }, + { + id: 18, + technology: ["React", "useState"], + category: "React", + difficulty: "Easy", + duration: "50 mins", + task: "Color picker", + details: + "Create a React component that allows users to select a color and displays the chosen color.", + detailedProblem: { + description: + "Implement a React component with a color picker input. When a color is selected, display a div element with that color as its background.", + examples: [ + { + input: "User selects red color", + output: "A red div is displayed below the color picker", + }, + ], + constraints: [ + "Use the useState hook to manage the selected color.", + "The color display should update immediately when a new color is selected.", + ], + solutionApproach: [ + "Create a state variable to store the selected color.", + "Use an input of type 'color' for the color picker.", + "Implement an onChange handler that updates the color state.", + "Render a div with its background color set to the selected color.", + ], + }, + }, + + // Intermediate React Challenges + { + id: 19, + technology: ["React", "useState"], + category: "React", + difficulty: "Intermediate", + duration: "75 mins", + task: "Filterable product list", + details: + "Create a React component that displays a list of products with a search filter.", + detailedProblem: { + description: + "Implement a React component that renders a list of products. Include a search input that filters the products in real-time as the user types.", + examples: [ + { + input: "User types 'apple' in the search field", + output: "Only products with 'apple' in their name are displayed", + }, + ], + constraints: [ + "Use the useState hook to manage the search term and filtered products.", + "The filtering should be case-insensitive.", + "The list should update in real-time as the user types.", + ], + solutionApproach: [ + "Create state variables for the search term and the list of products.", + "Implement an onChange handler for the search input that updates the search term state.", + "Use the useEffect hook to filter the products when the search term changes.", + "Render the filtered list of products.", + ], + }, + }, + { + id: 20, + technology: ["React", "useState"], + category: "React", + difficulty: "Intermediate", + duration: "90 mins", + task: "Pagination component", + details: + "Create a React component that implements pagination for a large dataset.", + detailedProblem: { + description: + "Implement a React component that displays a paginated list of items. Include controls to navigate between pages and allow users to select the number of items per page.", + examples: [ + { + input: "100 items, 10 items per page, user clicks 'Next' button", + output: "Second page of 10 items is displayed", + }, + ], + constraints: [ + "Use the useState hook to manage the current page and items per page.", + "Implement 'Previous' and 'Next' buttons for navigation.", + "Allow users to select from predefined options for items per page (e.g., 10, 25, 50).", + ], + solutionApproach: [ + "Create state variables for current page, items per page, and total items.", + "Implement functions to calculate the total number of pages and which items to display.", + "Create navigation buttons that update the current page state.", + "Implement a dropdown to select items per page.", + "Use the useEffect hook to update the displayed items when page or items per page changes.", + ], + }, + }, + { + id: 21, + technology: ["React", "useState"], + category: "React", + difficulty: "Intermediate", + duration: "60 mins", + task: "Accordion component", + details: + "Create a React accordion component that can expand and collapse sections.", + detailedProblem: { + description: + "Implement a React accordion component that displays a list of sections. Each section should have a header that, when clicked, expands or collapses the section's content.", + examples: [ + { + input: "User clicks on a collapsed section header", + output: + "The section expands to show its content, while other sections collapse", + }, + ], + constraints: [ + "Use the useState hook to manage the expanded/collapsed state of sections.", + "Only one section should be expanded at a time.", + "The component should be reusable with different content and number of sections.", + ], + solutionApproach: [ + "Create a state variable to track which section is currently expanded.", + "Implement a function to toggle the expanded state when a section header is clicked.", + "Use conditional rendering to show or hide section content based on the expanded state.", + "Create separate components for the accordion container and individual sections for better organization.", + ], + }, + }, + { + id: 22, + technology: ["React", "useState"], + category: "React", + difficulty: "Intermediate", + duration: "80 mins", + task: "Drag and drop list", + details: + "Create a React component that allows reordering list items via drag and drop.", + detailedProblem: { + description: + "Implement a React component that displays a list of items that can be reordered using drag and drop functionality.", + examples: [ + { + input: "User drags an item from position 3 to position 1", + output: + "The list updates to reflect the new order with the dragged item in position 1", + }, + ], + constraints: [ + "Use the useState hook to manage the list order.", + "Implement drag and drop without using external libraries.", + "The component should work with touch devices as well as mouse input.", + ], + solutionApproach: [ + "Create state variables for the list of items and the currently dragged item.", + "Implement onDragStart, onDragOver, and onDrop event handlers.", + "Use the HTML5 Drag and Drop API for basic functionality.", + "Update the list order in the onDrop handler.", + "Add touch event handlers to support mobile devices.", + ], + }, + }, + + // Hard React Challenges + { + id: 23, + technology: ["React", "useState"], + category: "React", + difficulty: "Hard", + duration: "120 mins", + task: "Virtual scrolling component", + details: + "Create a React component that implements virtual scrolling for a large list of items.", + detailedProblem: { + description: + "Implement a React component that can efficiently render a very large list of items (e.g., 100,000+ items) using virtual scrolling techniques. Only the visible items should be rendered at any given time.", + examples: [ + { + input: "List of 100,000 items, user scrolls to middle", + output: + "Only the visible items (e.g., 20-30 items) around the scroll position are rendered", + }, + ], + constraints: [ + "Use React hooks (useState, useEffect, useCallback) for state management and optimization.", + "The scrolling should be smooth and performant, even with very large lists.", + "Implement dynamic height calculations for list items.", + ], + solutionApproach: [ + "Create state variables for scroll position, visible range, and rendered items.", + "Use the useEffect hook to add scroll event listeners and clean up on unmount.", + "Implement a function to calculate which items should be visible based on scroll position.", + "Use absolute positioning and transform to place list items correctly.", + "Optimize rerenders using React.memo and useCallback.", + ], + }, + }, + { + id: 24, + technology: ["React", "useState"], + category: "React", + difficulty: "Hard", + duration: "150 mins", + task: "Real-time collaborative editor", + details: + "Create a React component for a real-time collaborative text editor.", + detailedProblem: { + description: + "Implement a React component that allows multiple users to edit a document simultaneously in real-time. Changes made by one user should be immediately visible to all other users.", + examples: [ + { + input: + "User A types 'Hello' while User B simultaneously types 'World'", + output: + "Both users see 'HelloWorld' (or a merged version) in real-time", + }, + ], + constraints: [ + "Use WebSockets or a similar technology for real-time communication.", + "Implement operational transformation or a similar algorithm for conflict resolution.", + "Handle network latency and disconnections gracefully.", + ], + solutionApproach: [ + "Set up a WebSocket connection for real-time updates.", + "Implement a basic operational transformation algorithm for merging changes.", + "Use the useEffect hook to manage WebSocket lifecycle and event listeners.", + "Create a custom hook for managing the editor state and operations.", + "Implement debouncing for sending updates to reduce network traffic.", + ], + }, + }, + { + id: 25, + technology: ["React", "useState"], + category: "React", + difficulty: "Hard", + duration: "180 mins", + task: "State management library", + details: + "Create a custom state management library for React applications.", + detailedProblem: { + description: + "Implement a lightweight state management library for React applications, similar to Redux but with a simpler API. The library should support actions, reducers, and a way to access the global state from any component.", + examples: [ + { + input: "Component dispatches an action to update user data", + output: "All connected components receive the updated user data", + }, + ], + constraints: [ + "Use only React hooks and context API (no external state management libraries).", + "Support middleware for side effects (like async actions).", + "Provide a simple way to connect components to the global state.", + ], + solutionApproach: [ + "Create a context to hold the global state and dispatch function.", + "Implement a custom hook that combines useContext and useReducer for state management.", + "Create a Provider component that wraps the app and provides the state and dispatch function.", + "Implement a way to combine multiple reducers.", + "Create a middleware system for handling side effects.", + "Provide a connect function or hook for easy component connection to the global state.", + ], + }, + }, + { + id: 26, + technology: ["React", "useState"], + category: "React", + difficulty: "Hard", + duration: "140 mins", + task: "GraphQL client implementation", + details: "Create a custom GraphQL client for React applications.", + detailedProblem: { + description: + "Implement a lightweight GraphQL client for React applications. The client should support queries, mutations, and subscriptions, and provide a way to easily use GraphQL operations in React components.", + examples: [ + { + input: "Component uses a query to fetch user data", + output: + "Component receives and displays the user data from the GraphQL API", + }, + ], + constraints: [ + "Implement the client without using existing GraphQL client libraries.", + "Support caching of query results.", + "Provide a way to handle loading and error states.", + ], + solutionApproach: [ + "Create a context to hold the GraphQL client instance.", + "Implement functions for sending queries and mutations to a GraphQL API.", + "Create a custom hook for executing queries and mutations in components.", + "Implement basic caching mechanism for query results.", + "Add support for subscriptions using WebSockets.", + "Provide loading and error states as part of the hook's return value.", + ], + }, + }, + { + id: 27, + technology: ["React", "useState"], + category: "React", + difficulty: "Easy", + duration: "60 mins", + task: "Simple counter component", + details: + "Create a React component that displays a counter with increment and decrement buttons.", + detailedProblem: { + description: + "In this challenge, you will create a simple counter component in React. The counter should start from 0 and increase or decrease when buttons are clicked.", + examples: [ + { + input: "Initial counter value: 0. Click increment button.", + output: "Counter value: 1", + }, + { + input: "Counter value: 1. Click decrement button.", + output: "Counter value: 0", + }, + ], + constraints: [ + "The component should manage its own state using React hooks.", + "The buttons should properly update the counter value.", + ], + solutionApproach: [ + "Use the `useState` hook to create and manage the counter state.", + "Create two buttons that update the state using the `setState` function.", + ], + }, + }, + { + id: 28, + technology: ["React", "conditional rendering"], + category: "React", + difficulty: "Intermediate", + duration: "60 mins", + task: "Interactive card component", + details: + "Build a card component that reveals hidden content upon clicking.", + detailedProblem: { + description: + "In this challenge, you will create an interactive card component that displays additional information when clicked. The focus is on writing clean, modular code and improving your understanding of React and DOM manipulation.", + examples: [ + { + input: "A card that shows details on click", + output: "Details are revealed on clicking the card.", + }, + ], + constraints: [ + "Use React state to track whether the card is expanded or collapsed.", + "Ensure the UI updates efficiently when the card is clicked.", + ], + solutionApproach: [ + "Use the `useState` hook to manage the card’s visibility state.", + "Toggle the visibility of the card’s content when clicked.", + ], + }, + }, + { + id: 29, + technology: ["React", "localStorage"], + category: "React", + difficulty: "Hard", + duration: "60 mins", + task: "Todo list with React and Local Storage", + details: + "Create a todo list application that saves items to local storage and allows them to persist between page reloads.", + detailedProblem: { + description: + "In this challenge, you will build a todo list application in React. The app should allow users to add, remove, and mark items as completed. Additionally, the todo items should be saved to local storage and persist between page reloads.", + examples: [ + { + input: "Add a todo item 'Buy milk'. Reload the page.", + output: "The todo list persists, showing the 'Buy milk' item.", + }, + ], + constraints: [ + "The app should store and retrieve todo items from local storage.", + "Use React state and hooks for managing the todo list.", + ], + solutionApproach: [ + "Use the `useState` and `useEffect` hooks to manage state and local storage.", + "Ensure that todo items persist across page reloads by interacting with the browser’s local storage.", + ], + }, + }, + + { + id: 30, + category: "DSA", + difficulty: "Easy", + duration: "30 mins", + task: "Reverse a string", + details: "Write a function to reverse a given string.", + detailedProblem: { + description: + "Given a string, write a function to return the string in reverse order.", + examples: [ + { + input: '"hello"', + output: '"olleh"', + explanation: "The characters are reversed from left to right.", + }, + { + input: '"world"', + output: '"dlrow"', + explanation: "The characters are reversed from left to right.", + }, + ], + constraints: [ + "The string can contain only English letters and spaces.", + "The maximum length of the string is 10^4.", + ], + solutionApproach: [ + "Use a two-pointer approach, swapping characters from both ends towards the middle.", + "Alternatively, use string slicing with a step of -1 to reverse the string.", + ], + }, + }, + { + id: 31, + category: "DSA", + difficulty: "Easy", + duration: "45 mins", + task: "Find the maximum element in an array", + details: + "Write a function to find the largest element in an array of integers.", + detailedProblem: { + description: + "Given an array of integers, write a function that returns the largest number in the array.", + examples: [ + { + input: "[3, 7, 2, 8, 1]", + output: "8", + explanation: "8 is the largest number in the given array.", + }, + { + input: "[-1, -5, -3, -2]", + output: "-1", + explanation: + "-1 is the largest number in the array of negative integers.", + }, + ], + constraints: [ + "The array contains at least one integer.", + "The array can contain both positive and negative integers.", + "The maximum length of the array is 10^5 elements.", + ], + solutionApproach: [ + "Initialize the maximum as the first element of the array.", + "Iterate through the array, updating the maximum if a larger number is found.", + "Return the maximum after the iteration is complete.", + ], + }, + }, + { + id: 32, + category: "DSA", + difficulty: "Easy", + duration: "40 mins", + task: "Check if a number is palindrome", + details: + "Write a function to determine if a given integer is a palindrome.", + detailedProblem: { + description: + "Given an integer, write a function that returns true if the integer is a palindrome, and false otherwise. An integer is a palindrome when it reads the same backward as forward.", + examples: [ + { + input: "121", + output: "true", + explanation: + "121 reads as 121 from left to right and from right to left.", + }, + { + input: "-121", + output: "false", + explanation: + "From left to right, it reads -121. From right to left, it becomes 121-. Therefore it is not a palindrome.", + }, + ], + constraints: [ + "The input is a signed 32-bit integer.", + "Solve it without converting the integer to a string.", + ], + solutionApproach: [ + "Reverse the integer by extracting digits and reconstructing.", + "Compare the reversed integer with the original.", + "Handle edge cases like negative numbers and numbers ending with 0.", + ], + }, + }, + { + id: 33, + category: "DSA", + difficulty: "Easy", + duration: "35 mins", + task: "Implement a stack using an array", + details: + "Write a class to implement a stack data structure using an array.", + detailedProblem: { + description: + "Implement a stack class that uses an array to store elements. The class should have methods for push (add an element), pop (remove and return the top element), peek (return the top element without removing it), and isEmpty (check if the stack is empty).", + examples: [ + { + input: "push(1), push(2), pop(), peek()", + output: "2, 1", + explanation: + "After pushing 1 and 2, pop returns 2, and peek returns 1.", + }, + ], + constraints: [ + "The stack should use a fixed-size array for storage.", + "Handle stack overflow and underflow conditions.", + ], + solutionApproach: [ + "Use an array to store elements and a variable to keep track of the top of the stack.", + "Implement push by adding an element to the top and incrementing the top index.", + "Implement pop by decrementing the top index and returning the element.", + "Implement peek by returning the element at the top index without modifying the stack.", + ], + }, + }, + + // Intermediate DSA Challenges + { + id: 34, + category: "DSA", + difficulty: "Intermediate", + duration: "60 mins", + task: "Longest palindrome substring", + details: "Find the longest palindromic substring in a given string.", + detailedProblem: { + description: + "Given a string, write a function to find the longest substring that is a palindrome.", + examples: [ + { + input: '"babad"', + output: '"bab" or "aba"', + explanation: + "Both 'bab' and 'aba' are valid longest palindromic substrings.", + }, + { + input: '"cbbd"', + output: '"bb"', + explanation: "'bb' is the longest palindromic substring.", + }, + ], + constraints: [ + "The input string consists of lowercase English letters.", + "The length of the string is at most 1000 characters.", + ], + solutionApproach: [ + "Use dynamic programming or expand around center approach.", + "For each character, consider it as the center of a palindrome and expand outwards.", + "Keep track of the longest palindrome found so far.", + ], + }, + }, + { + id: 35, + category: "DSA", + difficulty: "Intermediate", + duration: "75 mins", + task: "Implement a binary search tree", + details: + "Write a class to implement a binary search tree with insert, delete, and search operations.", + detailedProblem: { + description: + "Implement a binary search tree class that supports inserting elements, deleting elements, and searching for elements. The tree should maintain the binary search tree property.", + examples: [ + { + input: + "insert(5), insert(3), insert(7), search(3), delete(5), search(5)", + output: "true, false", + explanation: + "After inserting 5, 3, and 7, searching for 3 returns true. After deleting 5, searching for 5 returns false.", + }, + ], + constraints: [ + "The tree should maintain the binary search tree property at all times.", + "Handle edge cases like deleting the root node or a node with two children.", + ], + solutionApproach: [ + "Implement a Node class to represent tree nodes.", + "Implement insert recursively, comparing values to decide left or right subtree.", + "Implement search by traversing the tree based on comparisons.", + "Implement delete by considering cases: leaf node, node with one child, node with two children.", + ], + }, + }, + { + id: 36, + category: "DSA", + difficulty: "Intermediate", + duration: "70 mins", + task: "Implement merge sort", + details: + "Write a function to sort an array of integers using the merge sort algorithm.", + detailedProblem: { + description: + "Implement the merge sort algorithm to sort an array of integers in ascending order.", + examples: [ + { + input: "[38, 27, 43, 3, 9, 82, 10]", + output: "[3, 9, 10, 27, 38, 43, 82]", + explanation: + "The array is sorted in ascending order using merge sort.", + }, + ], + constraints: [ + "The input array can contain duplicate elements.", + "The maximum length of the array is 10^5 elements.", + ], + solutionApproach: [ + "Implement the divide step: recursively divide the array into two halves.", + "Implement the conquer step: recursively sort the two halves.", + "Implement the combine step: merge the sorted halves into a single sorted array.", + "Use a helper function to merge two sorted arrays.", + ], + }, + }, + { + id: 37, + category: "DSA", + difficulty: "Intermediate", + duration: "65 mins", + task: "Implement a queue using two stacks", + details: + "Write a class to implement a queue data structure using two stacks.", + detailedProblem: { + description: + "Implement a queue class that uses two stacks internally to perform queue operations (enqueue, dequeue, peek, and empty).", + examples: [ + { + input: "enqueue(1), enqueue(2), dequeue(), peek(), empty()", + output: "1, 2, false", + explanation: + "After enqueuing 1 and 2, dequeue returns 1, peek returns 2, and the queue is not empty.", + }, + ], + constraints: [ + "Use only standard stack operations (push, pop, top, isEmpty).", + "The queue should support enqueue, dequeue, peek, and empty operations.", + ], + solutionApproach: [ + "Use two stacks: one for enqueue operations and one for dequeue operations.", + "For enqueue: push the new element onto the enqueue stack.", + "For dequeue: if the dequeue stack is empty, transfer all elements from the enqueue stack to the dequeue stack, then pop from the dequeue stack.", + "For peek: similar to dequeue, but return the top element without removing it.", + ], + }, + }, + + // Hard DSA Challenges + { + id: 38, + category: "DSA", + difficulty: "Hard", + duration: "90 mins", + task: "Find shortest path in a maze", + details: + "Implement an algorithm to find the shortest path in a maze using BFS.", + detailedProblem: { + description: + "Given a 2D grid representing a maze, find the shortest path from the start position to the end position using Breadth-First Search (BFS).", + examples: [ + { + input: "[[1, 0, 1], [1, 1, 0], [0, 1, 1]]", + output: "4", + explanation: + "The shortest path from the top-left to the bottom-right is 4 steps.", + }, + ], + constraints: [ + "The grid consists of 1s (walkable) and 0s (blocked).", + "The size of the grid is at most 100 x 100.", + "The start position is always the top-left corner, and the end position is always the bottom-right corner.", + ], + solutionApproach: [ + "Use a queue to implement BFS, starting from the start position.", + "Keep track of visited cells to avoid revisiting.", + "Use a distance matrix to store the shortest distance to each cell.", + "Explore neighboring cells in all four directions (up, down, left, right).", + "Return the distance when the end position is reached.", + ], + }, + }, + { + id: 39, + category: "DSA", + difficulty: "Hard", + duration: "120 mins", + task: "Implement a trie with wildcard search", + details: + "Write a class to implement a trie data structure with support for wildcard search.", + detailedProblem: { + description: + "Implement a trie class that supports inserting words, searching for words, and searching with wildcards. The wildcard '.' can represent any single character.", + examples: [ + { + input: + 'insert("cat"), insert("dog"), search("cat"), search("do."), search("...")', + output: "true, true, true", + explanation: + "'cat' is in the trie, 'do.' matches 'dog', and '...' matches both 'cat' and 'dog'.", + }, + ], + constraints: [ + "The trie should support lowercase English letters and the wildcard character '.'.", + "The maximum length of a word is 20 characters.", + "The trie should efficiently handle large numbers of insertions and searches.", + ], + solutionApproach: [ + "Implement a TrieNode class with children nodes and a flag to mark the end of a word.", + "Implement insert by creating or traversing nodes for each character.", + "Implement search by traversing nodes and handling wildcards recursively.", + "For wildcard search, explore all possible paths when encountering a '.'.", + ], + }, + }, + { + id: 40, + category: "DSA", + difficulty: "Hard", + duration: "150 mins", + task: "Implement a LRU cache", + details: "Write a class to implement a Least Recently Used (LRU) cache.", + detailedProblem: { + description: + "Implement a data structure for a Least Recently Used (LRU) cache. The cache should support get and put operations in O(1) time complexity.", + examples: [ + { + input: + "LRUCache cache = new LRUCache(2); cache.put(1, 1); cache.put(2, 2); cache.get(1); cache.put(3, 3); cache.get(2);", + output: "1, -1", + explanation: + "After putting (1,1) and (2,2), get(1) returns 1. Putting (3,3) evicts (2,2), so get(2) returns -1 (not found).", + }, + ], + constraints: [ + "The capacity of the cache is positive.", + "The get and put operations should have O(1) time complexity.", + "The cache should support up to 10^5 operations.", + ], + solutionApproach: [ + "Use a hash map to store key-value pairs for O(1) access.", + "Use a doubly linked list to keep track of the order of elements.", + "Move an element to the front of the list when it's accessed or updated.", + "Remove the least recently used element (at the end of the list) when the cache is full and a new element is added.", + ], + }, + }, + { + id: 41, + category: "DSA", + difficulty: "Hard", + duration: "180 mins", + task: "Implement a basic database engine", + details: + "Write a class to implement a simple in-memory relational database engine.", + detailedProblem: { + description: + "Implement a basic in-memory relational database engine that supports creating tables, inserting data, and executing simple SQL queries.", + examples: [ + { + input: + "CREATE TABLE users (id INT, name VARCHAR); INSERT INTO users VALUES (1, 'John'); SELECT * FROM users;", + output: + "Table created, 1 row inserted, Query result: [(1, 'John')]", + }, + ], + constraints: [ + "Support basic data types: INT, VARCHAR.", + "Implement CREATE TABLE, INSERT, and SELECT operations.", + "Support basic WHERE clauses in SELECT statements.", + "The database should efficiently handle tables with up to 10^6 rows.", + ], + solutionApproach: [ + "Create classes to represent tables, rows, and columns.", + "Implement a parser for simple SQL statements.", + "Create methods to execute CREATE TABLE, INSERT, and SELECT operations.", + "Implement a basic query executor that can filter rows based on WHERE clauses.", + ], + }, + }, + + { + id: 42, + category: "DSA", + difficulty: "Easy", + duration: "60 mins", + task: "Reverse a string", + details: "Write a function to reverse a given string.", + detailedProblem: { + description: + "Given a string, write a function to return the string in reverse order.", + examples: [ + { + input: '"hello"', + output: '"olleh"', + }, + { + input: '"world"', + output: '"dlrow"', + }, + ], + constraints: [ + "The string can contain only English letters and spaces.", + "The maximum length of the string is 10^4.", + ], + solutionApproach: [ + "Use slicing or a loop to reverse the characters in the string.", + "Return the reversed string.", + ], + }, + }, + { + id: 43, + category: "DSA", + difficulty: "Intermediate", + duration: "60 mins", + task: "Longest palindrome substring", + details: "Find the longest palindromic substring in a given string.", + detailedProblem: { + description: + "Given a string, write a function to find the longest substring that is a palindrome.", + examples: [ + { + input: '"babad"', + output: '"bab" or "aba"', + }, + { + input: '"cbbd"', + output: '"bb"', + }, + ], + constraints: [ + "The input string consists of lowercase English letters.", + "The length of the string is at most 1000 characters.", + ], + solutionApproach: [ + "Use dynamic programming or expand around center approach to find the longest palindromic substring.", + ], + }, + }, + { + id: 44, + category: "DSA", + difficulty: "Hard", + duration: "60 mins", + task: "Find shortest path in a maze", + details: + "Implement an algorithm to find the shortest path in a maze using BFS.", + detailedProblem: { + description: + "Given a 2D grid representing a maze, find the shortest path from the start position to the end position using Breadth-First Search (BFS).", + examples: [ + { + input: "[[1, 0, 1], [1, 1, 0], [0, 1, 1]]", + output: "4", + explanation: + "The shortest path from the top-left to the bottom-right is 4 steps.", + }, + ], + constraints: [ + "The grid consists of 1s (walkable) and 0s (blocked).", + "The size of the grid is at most 100 x 100.", + ], + solutionApproach: [ + "Use BFS to explore the maze level by level, keeping track of visited cells to avoid revisiting.", + ], + }, + }, + + { + id: 45, + category: "Java", + difficulty: "Easy", + duration: "45 mins", + task: "Reverse a string", + details: "Write a Java program to reverse a given string.", + detailedProblem: { + description: + "Given a string, write a function to return the string in reverse order.", + examples: [ + { + input: '"hello"', + output: '"olleh"', + explanation: "The characters are reversed from left to right.", + }, + { + input: '"Java"', + output: '"avaJ"', + explanation: "The characters are reversed from left to right.", + }, + ], + constraints: [ + "The string can contain any ASCII character.", + "The maximum length of the string is 10^5 characters.", + ], + solutionApproach: [ + "Convert the string to a character array.", + "Swap characters from both ends towards the middle.", + "Convert the character array back to a string.", + ], + }, + }, + { + id: 46, + category: "Java", + difficulty: "Easy", + duration: "30 mins", + task: "Find the largest number in an array", + details: + "Write a Java program to find the largest number in an array of integers.", + detailedProblem: { + description: + "Given an array of integers, write a function that returns the largest number in the array.", + examples: [ + { + input: "[10, 5, 8, 12, 3]", + output: "12", + explanation: "12 is the largest number in the given array.", + }, + { + input: "[-1, -5, -3, -2]", + output: "-1", + explanation: + "-1 is the largest number in the array of negative integers.", + }, + ], + constraints: [ + "The array contains at least one integer.", + "The array can contain both positive and negative integers.", + "The maximum length of the array is 10^6 elements.", + ], + solutionApproach: [ + "Initialize the largest number as the first element of the array.", + "Iterate through the array, updating the largest number if a larger number is found.", + "Return the largest number after the iteration is complete.", + ], + }, + }, + { + id: 47, + category: "Java", + difficulty: "Easy", + duration: "40 mins", + task: "Check if a number is prime", + details: "Write a Java program to determine if a given number is prime.", + detailedProblem: { + description: + "Given a positive integer, write a function that returns true if the number is prime, and false otherwise.", + examples: [ + { + input: "17", + output: "true", + explanation: + "17 is a prime number as it's only divisible by 1 and itself.", + }, + { + input: "24", + output: "false", + explanation: + "24 is not a prime number as it's divisible by 1, 2, 3, 4, 6, 8, 12, and 24.", + }, + ], + constraints: [ + "The input is a positive integer.", + "The maximum value of the input is 10^9.", + ], + solutionApproach: [ + "Check if the number is less than 2 (not prime).", + "Iterate from 2 to the square root of the number.", + "If the number is divisible by any value in this range, it's not prime.", + "If no divisors are found, the number is prime.", + ], + }, + }, + { + id: 48, + category: "Java", + difficulty: "Easy", + duration: "35 mins", + task: "Calculate the sum of digits", + details: + "Write a Java program to calculate the sum of digits of a given number.", + detailedProblem: { + description: + "Given a non-negative integer, write a function that returns the sum of its digits.", + examples: [ + { + input: "123", + output: "6", + explanation: "1 + 2 + 3 = 6", + }, + { + input: "9045", + output: "18", + explanation: "9 + 0 + 4 + 5 = 18", + }, + ], + constraints: [ + "The input is a non-negative integer.", + "The maximum value of the input is 10^9.", + ], + solutionApproach: [ + "Initialize a sum variable to 0.", + "While the number is not 0, extract the last digit using modulo 10 and add it to the sum.", + "Divide the number by 10 to remove the last digit.", + "Repeat until all digits have been processed.", + ], + }, + }, + + // Intermediate Java Challenges + { + id: 49, + category: "Java", + difficulty: "Intermediate", + duration: "60 mins", + task: "Implement a stack using two queues", + details: + "Write a Java program to implement a stack data structure using two queues.", + detailedProblem: { + description: + "Implement a stack class that uses two queues internally to perform stack operations (push, pop, top, and empty).", + examples: [ + { + input: "push(1), push(2), top(), pop(), empty()", + output: "2, 2, false", + explanation: + "After pushing 1 and 2, top returns 2, pop removes and returns 2, and the stack is not empty.", + }, + ], + constraints: [ + "Use only standard queue operations (enqueue, dequeue, front, isEmpty).", + "The stack should support push, pop, top, and empty operations.", + ], + solutionApproach: [ + "Use two queues: q1 and q2.", + "For push: enqueue the new element to q1.", + "For pop: move all elements except the last from q1 to q2, remove and return the last element from q1, then swap q1 and q2.", + "For top: similar to pop, but enqueue the last element back to q2 instead of removing it.", + ], + }, + }, + { + id: 50, + category: "Java", + difficulty: "Intermediate", + duration: "75 mins", + task: "Implement LRU Cache", + details: + "Write a Java program to implement an LRU (Least Recently Used) cache.", + detailedProblem: { + description: + "Implement an LRU cache that supports get and put operations in O(1) time complexity.", + examples: [ + { + input: + "LRUCache cache = new LRUCache(2); cache.put(1, 1); cache.put(2, 2); cache.get(1); cache.put(3, 3); cache.get(2);", + output: "1, -1", + explanation: + "After putting (1,1) and (2,2), get(1) returns 1. Putting (3,3) evicts (2,2), so get(2) returns -1 (not found).", + }, + ], + constraints: [ + "The capacity of the cache is positive.", + "The get and put operations should have O(1) time complexity.", + ], + solutionApproach: [ + "Use a HashMap to store key-value pairs for O(1) access.", + "Use a doubly linked list to keep track of the order of elements.", + "Move an element to the front of the list when it's accessed or updated.", + "Remove the least recently used element (at the end of the list) when the cache is full and a new element is added.", + ], + }, + }, + { + id: 51, + category: "Java", + difficulty: "Intermediate", + duration: "70 mins", + task: "Implement a trie (prefix tree)", + details: + "Write a Java program to implement a trie data structure for efficient string search operations.", + detailedProblem: { + description: + "Implement a trie class that supports insert, search, and startsWith operations for strings.", + examples: [ + { + input: + 'Trie trie = new Trie(); trie.insert("apple"); trie.search("apple"); trie.search("app"); trie.startsWith("app");', + output: "true, false, true", + explanation: + '"apple" is in the trie, "app" is not, but "app" is a prefix of a word in the trie.', + }, + ], + constraints: [ + "The trie should support lowercase English letters only.", + "The maximum length of a word is 20 characters.", + ], + solutionApproach: [ + "Create a TrieNode class with children nodes and a flag to mark the end of a word.", + "Implement insert by creating or traversing nodes for each character.", + "Implement search by traversing nodes and checking if the last node is marked as the end of a word.", + "Implement startsWith similarly to search, but without checking for the end of word flag.", + ], + }, + }, + { + id: 52, + category: "Java", + difficulty: "Intermediate", + duration: "65 mins", + task: "Implement a thread-safe singleton", + details: + "Write a Java program to implement a thread-safe singleton class using double-checked locking.", + detailedProblem: { + description: + "Implement a singleton class that is thread-safe and uses lazy initialization with double-checked locking.", + examples: [ + { + input: "Singleton.getInstance()", + output: + "Returns the same instance every time it's called, even in a multi-threaded environment.", + }, + ], + constraints: [ + "The singleton should be lazily initialized.", + "The implementation should be thread-safe.", + "Use double-checked locking for better performance.", + ], + solutionApproach: [ + "Use a private static volatile field to hold the instance.", + "Implement a public static method getInstance() for accessing the instance.", + "Use double-checked locking inside getInstance() to ensure thread safety and lazy initialization.", + "Make the constructor private to prevent direct instantiation.", + ], + }, + }, + + // Hard Java Challenges + { + id: 53, + category: "Java", + difficulty: "Hard", + duration: "90 mins", + task: "Implement a concurrent hash map", + details: + "Write a Java program to implement a basic concurrent hash map without using java.util.concurrent package.", + detailedProblem: { + description: + "Implement a thread-safe hash map that supports concurrent read and write operations without using built-in concurrent collections.", + examples: [ + { + input: + "put(1, 'A'), get(1), remove(1) from multiple threads concurrently", + output: "Thread-safe operations without data races", + }, + ], + constraints: [ + "Do not use java.util.concurrent package.", + "Support basic operations: put, get, remove.", + "Ensure thread-safety for all operations.", + ], + solutionApproach: [ + "Use an array of buckets, each containing a linked list of key-value pairs.", + "Implement fine-grained locking by using a separate lock for each bucket.", + "Use volatile keyword for the array of buckets to ensure visibility across threads.", + "Implement methods for put, get, and remove with proper synchronization.", + ], + }, + }, + { + id: 54, + category: "Java", + difficulty: "Hard", + duration: "120 mins", + task: "Implement a basic garbage collector", + details: + "Write a Java program to implement a simple mark-and-sweep garbage collector.", + detailedProblem: { + description: + "Implement a basic garbage collector that uses the mark-and-sweep algorithm to collect unreachable objects.", + examples: [ + { + input: + "A set of objects with references between them, some unreachable", + output: "Unreachable objects are identified and 'collected'", + }, + ], + constraints: [ + "Implement a simple object system with references.", + "Implement the mark phase to identify reachable objects.", + "Implement the sweep phase to collect unreachable objects.", + ], + solutionApproach: [ + "Create a class to represent objects with references to other objects.", + "Implement a method to create a graph of objects with some unreachable ones.", + "Implement the mark phase using depth-first search from root objects.", + "Implement the sweep phase to collect unmarked objects.", + "Provide a method to trigger garbage collection.", + ], + }, + }, + { + id: 55, + category: "Java", + difficulty: "Hard", + duration: "150 mins", + task: "Implement a basic JVM", + details: + "Write a Java program to implement a simplified Java Virtual Machine that can execute basic bytecode.", + detailedProblem: { + description: + "Implement a basic JVM that can load, verify, and execute simple Java bytecode instructions.", + examples: [ + { + input: "Bytecode for a simple Java method", + output: "Correct execution of the bytecode instructions", + }, + ], + constraints: [ + "Support a subset of JVM instructions (e.g., arithmetic operations, method calls).", + "Implement a basic class loader.", + "Implement a simplified execution engine.", + ], + solutionApproach: [ + "Create a class to represent the JVM with methods for loading and executing bytecode.", + "Implement a basic class loader that can read and parse class files.", + "Create a bytecode verifier to check for basic structural validity.", + "Implement an execution engine that can interpret bytecode instructions.", + "Support a stack-based architecture for method execution.", + ], + }, + }, + { + id: 56, + category: "Java", + difficulty: "Hard", + duration: "180 mins", + task: "Implement a basic database engine", + details: + "Write a Java program to implement a simple in-memory relational database engine.", + detailedProblem: { + description: + "Implement a basic in-memory relational database engine that supports creating tables, inserting data, and executing simple SQL queries.", + examples: [ + { + input: + "CREATE TABLE users (id INT, name VARCHAR); INSERT INTO users VALUES (1, 'John'); SELECT * FROM users;", + output: + "Table created, 1 row inserted, Query result: [(1, 'John')]", + }, + ], + constraints: [ + "Support basic data types: INT, VARCHAR.", + "Implement CREATE TABLE, INSERT, and SELECT operations.", + "Support basic WHERE clauses in SELECT statements.", + ], + solutionApproach: [ + "Create classes to represent tables, rows, and columns.", + "Implement a parser for simple SQL statements.", + "Create methods to execute CREATE TABLE, INSERT, and SELECT operations.", + "Implement a basic query executor that can filter rows based on WHERE clauses.", + "Use appropriate data structures (e.g., HashMap) to store tables and data in memory.", + ], + }, + }, + + { + id: 57, + category: "Java", + difficulty: "Easy", + duration: "60 mins", + task: "Factorial of a number", + details: "Write a Java program to calculate the factorial of a number.", + detailedProblem: { + description: + "Given a non-negative integer, write a function to calculate its factorial.", + examples: [ + { + input: "5", + output: "120", + }, + { + input: "0", + output: "1", + }, + ], + constraints: [ + "The input is a non-negative integer.", + "The result should fit within the range of a 64-bit integer.", + ], + solutionApproach: [ + "Use recursion or iteration to compute the factorial of the number.", + ], + }, + }, + { + id: 58, + category: "Java", + difficulty: "Intermediate", + duration: "60 mins", + task: "Check balanced parentheses", + details: + "Write a Java program to check if an expression has balanced parentheses.", + detailedProblem: { + description: + "Given a string containing parentheses, write a function to check if the parentheses are balanced.", + examples: [ + { + input: '"(a + b) * (c - d)"', + output: "True", + }, + { + input: '"(a + b * (c - d)"', + output: "False", + }, + ], + constraints: [ + "The input string consists of alphanumeric characters and parentheses.", + "The maximum length of the string is 1000 characters.", + ], + solutionApproach: [ + "Use a stack to check for matching opening and closing parentheses.", + ], + }, + }, + { + id: 59, + category: "Java", + difficulty: "Hard", + duration: "60 mins", + task: "Serialize and deserialize binary tree", + details: + "Write a Java program to serialize and deserialize a binary tree.", + detailedProblem: { + description: + "Given a binary tree, write a function to serialize the tree into a string and another function to deserialize the string back into the binary tree.", + examples: [ + { + input: "Binary Tree: [1,2,3,null,null,4,5]", + output: 'Serialized string: "1,2,null,null,3,4,5"', + }, + ], + constraints: [ + "The binary tree consists of integers.", + "The number of nodes in the tree is at most 10000.", + ], + solutionApproach: [ + "Use a preorder traversal to serialize the tree and reverse the process to deserialize.", + ], + }, + }, + ], +}; diff --git a/src/mock-data/roadmapMockData.js b/src/mock-data/roadmapMockData.js new file mode 100644 index 0000000..dd9ad93 --- /dev/null +++ b/src/mock-data/roadmapMockData.js @@ -0,0 +1,55 @@ + export const GOALS_DATA = [ + { + goal: "Attend 4 meetings", + subtasks: [ + "Schedule & attend 1 accountability meeting", + "Attend 2 accountability meetings", + "Attend 3 accountability meetings", + "Attend all 4 accountability meetings", + ], + }, + { + goal: "Design and implement the frontend of the web application using JavaScript and React", + subtasks: [ + "Discuss and finalize the UI/UX design for the application", + "Break down the design into reusable React components", + "Implement the React components using JavaScript", + "Test the components individually and as a whole to ensure they work as expected", + ], + }, + { + goal: "Develop the backend of the web application using Python and Django", + subtasks: [ + "Design the database schema and establish the necessary Django models", + "Implement the necessary views and templates in Django", + "Integrate the Django backend with the React frontend", + "Test the backend functionality and ensure it works with the frontend", + ], + }, + { + goal: "Deploy the web application", + subtasks: [ + "Choose a suitable hosting platform for the application", + "Configure the deployment settings for both frontend and backend", + "Deploy the application and test it in the production environment", + "Monitor the application performance and fix any issues that arise", + ], + }, + { + goal: "Attend 4 meetings to go over what you’ve learned", + subtasks: [ + "Schedule & attend 1 accountability meeting", + "Attend 2 accountability meetings", + "Attend 3 accountability meetings", + "Attend all 4 accountability meetings", + ], + }, + ]; + +export const MOCK_MATCH_DATA = { + goal1Task: "Goal 1 task", + goal2Task: "Goal 2 task", + goal3Task: "Goal 3 task", + goal4Task: "Goal 4 task", + goal5Task: "Goal 5 task", +}; \ No newline at end of file diff --git a/src/mockCurrentUserforMatch.js b/src/mockCurrentUserforMatch.js new file mode 100644 index 0000000..425cf3e --- /dev/null +++ b/src/mockCurrentUserforMatch.js @@ -0,0 +1,164 @@ +const MockCurrentUser = [ + { + id: 'U001', + profilePicture: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Emily Harris', + role: 'Developer', + skills: ['JavaScript', 'Python', 'React', 'Firbase'], + level: 'Beginner', + }, + { + id: 'U002', + profilePicture: 'https://images.unsplash.com/photo-1600180758895-177ad3c473cf?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'James Carter', + role: 'Developer', + skills: ['Java', 'C#', 'JavaScript', 'Firbase'], + level: 'Expert', + }, + { + id: 'U003', + profilePicture: 'https://images.unsplash.com/photo-1552374196-c4e7ffc6e126?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Natalie Robinson', + role: 'Developer', + skills: ['JavaScript', 'Swift', 'PHP', 'React'], + level: 'Intermediate', + }, + { + id: 'U004', + profilePicture: 'https://images.unsplash.com/photo-1503437313881-503a912264eb?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Ryan Phillips', + role: 'Developer', + skills: ['Python', 'Go', 'Java', 'React'], + level: 'Expert', + }, + { + id: 'U005', + profilePicture: 'https://images.unsplash.com/photo-1517841905240-472988babdf9?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Sophia Collins', + role: 'Developer', + skills: ['Python', 'Go', 'Java', 'React'], + level: 'Expert', + }, + { + id: 'U006', + profilePicture: 'https://images.unsplash.com/photo-1529626455594-4ff0802cfb7e?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Jack Evans', + role: 'Developer', + skills: ['Java', 'C++', 'Firbase', 'HTML'], + level: 'Intermediate', + }, + { + id: 'U007', + profilePicture: 'https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Grace Lopez', + role: 'Developer', + skills: ['HTML', 'CSS', 'JavaScript', 'Python', 'Firbase'], + level: 'Intermediate', + }, + { + id: 'U008', + profilePicture: 'https://images.unsplash.com/photo-1522075469751-3a6694fb2f61?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Oliver Perez', + role: 'Developer', + skills: ['Python', 'Java', 'DSA', 'React', 'Firebase'], + level: 'Beginner', + }, + { + id: 'U009', + profilePicture: 'https://images.unsplash.com/photo-1541532713592-79a0317b6b77?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Charlotte Lee', + role: 'Developer', + skills: ['C#', 'Go', 'PHP', 'DSA'], + level: 'Expert', + }, + { + id: 'U010', + profilePicture: 'https://images.unsplash.com/photo-1499350943936-4d611f0cfee3?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Henry Scott', + role: 'Developer', + skills: ['Java', 'Python'], + level: 'Intermediate', + }, + { + id: 'U011', + profilePicture: 'https://images.unsplash.com/photo-1488426862026-3ee34a7d66df?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Mia Davis', + role: 'Developer', + skills: ['JavaScript', 'PHP', 'React'], + level: 'Beginner', + }, + { + id: 'U012', + profilePicture: 'https://images.unsplash.com/photo-1532074205216-d0e1f6b53d77?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Daniel Lewis', + role: 'Developer', + skills: ['Go', 'Python', 'DSA', 'React'], + level: 'Expert', + }, + { + id: 'U013', + profilePicture: 'https://images.unsplash.com/photo-1521737604893-d14cc237f11d?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Amelia Young', + role: 'Developer', + skills: ['Python', 'Java', 'HTML', 'Firbase'], + level: 'Intermediate', + }, + { + id: 'U014', + profilePicture: 'https://images.unsplash.com/photo-1544717305-996b815c338c?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Michael Thompson', + role: 'Developer', + skills: ['Java', 'C#', 'Firbase', 'React'], + level: 'Expert', + }, + { + id: 'U015', + profilePicture: 'https://images.unsplash.com/photo-1506794778202-cad84cf45f1d?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Ella White', + role: 'Developer', + skills: ['JavaScript', 'PHP', 'Go'], + level: 'Intermediate', + }, + { + id: 'U016', + profilePicture: 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Alexander King', + role: 'Developer', + skills: ['C++', 'Java', 'Firbase'], + level: 'Intermediate', + }, + { + id: 'U017', + profilePicture: 'https://images.unsplash.com/photo-1524504388940-b1c1722653e1?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Chloe Martinez', + role: 'Developer', + skills: ['JavaScript', 'PHP', 'Swift', 'Firbase'], + level: 'Beginner', + }, + { + id: 'U018', + profilePicture: 'https://images.unsplash.com/photo-1590080874701-babed91e77b0?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Isabella Taylor', + role: 'Developer', + skills: ['JavaScript', 'Go', 'PHP'], + level: 'Intermediate', + }, + { + id: 'U019', + profilePicture: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Ryan Phillips', + role: 'Developer', + skills: ['Python', 'Go', 'Java', 'Firbase', 'HTML'], + level: 'Expert', + }, + { + id: 'U020', + profilePicture: 'https://images.unsplash.com/photo-1524504388940-b1c1722653e1?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Avery Brown', + role: 'Developer', + skills: ['JavaScript', 'C++', 'Python'], + level: 'Beginner', + } + ]; + + export default MockCurrentUser; \ No newline at end of file diff --git a/src/mockDataForPhotocard.js b/src/mockDataForPhotocard.js new file mode 100644 index 0000000..e0a15f6 --- /dev/null +++ b/src/mockDataForPhotocard.js @@ -0,0 +1,433 @@ + +const mockMatchedUser = [ + { + id: 'B001', + profilePicture: 'https://images.unsplash.com/photo-1508214751196-bcfd4ca60f91?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Aaron Johnson', + role: 'Developer', + skills: ['Python', 'Go', 'DSA', 'HTML'], + level: 'Expert', + }, + { + id: 'B002', + profilePicture: 'https://th.bing.com/th/id/R.b5c998820a169bc5c45ba540192e35a0?rik=Bjmft1IBcCuKmA&pid=ImgRaw&r=0', + name: 'Ava Wilson', + role: 'Developer', + skills: ['JavaScript', 'PHP', 'Swift', 'Firbase'], + level: 'Intermediate', + }, + { + id: 'B003', + profilePicture: 'https://images.unsplash.com/photo-1517841905240-472988babdf9?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Daniel Lee', + role: 'Developer', + skills: ['Java', 'C#', 'Python'], + level: 'Expert', + }, + { + id: 'B004', + profilePicture: 'https://img.sydao.cn/uploads/2022/08/25/11da9649ce2df556f8d6f199e7cdb94b.jpg', + name: 'Megan Brown', + role: 'Developer', + skills: ['Swift', 'JavaScript'], + level: 'Beginner', + }, + { + id: 'B005', + profilePicture: 'https://th.bing.com/th/id/OIP.jr0DsER8j9Tpm0Yqs5mGSwHaLG?rs=1&pid=ImgDetMain', + name: 'Lucas Martinez', + role: 'Developer', + skills: ['C++', 'Java', 'Go', 'HTML', 'React',], + level: 'Intermediate', + }, + { + id: 'B006', + profilePicture: 'https://thumbs.dreamstime.com/b/beautiful-young-woman-face-blue-eyes-subset-62103003.jpg', + name: 'Sophie Taylor', + role: 'Developer', + skills: ['JavaScript', 'PHP', 'Python', 'React'], + level: 'Intermediate', + }, + { + id: 'B007', + profilePicture: 'https://images.unsplash.com/photo-1552058544-f2b08422138a?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Elijah Harris', + role: 'Developer', + skills: ['C++', 'Go'], + level: 'Expert', + }, + { + id: 'B008', + profilePicture: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Olivia Nelson', + role: 'Developer', + skills: ['JavaScript', 'Swift', 'PHP'], + level: 'Beginner', + }, + { + id: 'B009', + profilePicture: 'https://th.bing.com/th/id/R.3ee3f6f3314c6bc22aa1c4e0b19e7b4b?rik=x4Mi8kDEtv0bxw&riu=http%3a%2f%2fpic13.nipic.com%2f20110304%2f5252423_100326794000_2.jpg&ehk=m66NtLnK9ouQEso2mdNnR3DQHhcTaZV1H2Hs3fTtymY%3d&risl=&pid=ImgRaw&r=0', + name: 'Mason Carter', + role: 'Developer', + skills: ['Java', 'C#', 'JavaScript', 'React'], + level: 'Intermediate', + }, + { + id: 'B010', + profilePicture: 'https://th.bing.com/th/id/OIP.Ogjebb8Y58jxcl5lPCnAHwAAAA?rs=1&pid=ImgDetMain', + name: 'Isabella King', + role: 'Developer', + skills: ['Python', 'Java'], + level: 'Expert', + }, + { + id: 'B011', + profilePicture: 'https://images.unsplash.com/photo-1508214751196-bcfd4ca60f91?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Liam Walker', + role: 'Developer', + skills: ['Go', 'PHP', 'React'], + level: 'Beginner', + }, + { + id: 'B012', + profilePicture: 'https://i.etsystatic.com/44133513/r/il/e3fca2/5443594664/il_794xN.5443594664_g4nc.jpg', + name: 'Sophia Allen', + role: 'Developer', + skills: ['Java', 'Python'], + level: 'Intermediate', + }, + { + id: 'B013', + profilePicture: 'https://images.unsplash.com/photo-1517841905240-472988babdf9?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'William Scott', + role: 'Developer', + skills: ['C++', 'JavaScript', 'React'], + level: 'Expert', + }, + { + id: 'B014', + profilePicture: 'https://images.unsplash.com/photo-1517841905240-472988babdf9?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Charlotte Lopez', + role: 'Developer', + skills: ['PHP', 'Python'], + level: 'Intermediate', + }, + { + id: 'B015', + profilePicture: 'https://images.unsplash.com/photo-1522075469751-3a6694fb2f61?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Henry Young', + role: 'Developer', + skills: ['JavaScript', 'Go', 'C++'], + level: 'Expert', + }, + { + id: 'B016', + profilePicture: 'https://images.unsplash.com/photo-1529626455594-4ff0802cfb7e?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Grace Baker', + role: 'Developer', + skills: ['Python', 'PHP', 'Swift'], + level: 'Intermediate', + }, + { + id: 'B017', + profilePicture: 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Matthew Harris', + role: 'Developer', + skills: ['C++', 'Go', 'Java', 'React'], + level: 'Expert', + }, + { + id: 'B018', + profilePicture: 'https://images.unsplash.com/photo-1517841905240-472988babdf9?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Amelia Morgan', + role: 'Developer', + skills: ['JavaScript', 'Java'], + level: 'Beginner', + }, + { + id: 'B019', + profilePicture: 'https://cdn.f1connect.net/photo/employees/r/385x473/70735/bd75528c-df4d-490a-8955-fedb2b750b72.png?_=1', + name: 'Ethan Mitchell', + role: 'Developer', + skills: ['PHP', 'C#'], + level: 'Intermediate', + }, + { + id: 'B021', + profilePicture: 'https://images.unsplash.com/photo-1599566150163-29194dcaad36?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Aaron Robinson', + role: 'Developer', + skills: ['Python', 'Java', 'Go', 'C++'], + level: 'Intermediate', + }, + { + id: 'B022', + profilePicture: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Sophia Lee', + role: 'Developer', + skills: ['JavaScript', 'React', 'CSS'], + level: 'Expert', + }, + { + id: 'B023', + profilePicture: 'https://images.unsplash.com/photo-1544723795-3fb6469f5b39?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Liam Smith', + role: 'Developer', + skills: ['C#', 'JavaScript', 'HTML'], + level: 'Beginner', + }, + { + id: 'B024', + profilePicture: 'https://i.etsystatic.com/13915170/r/il/fd5d1c/1940853433/il_794xN.1940853433_l3xh.jpg', + name: 'Olivia Turner', + role: 'Developer', + skills: ['JavaScript', 'Python', 'Ruby'], + level: 'Intermediate', + }, + { + id: 'B025', + profilePicture: 'https://images.unsplash.com/photo-1534524551095-2f4cce25f48b?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Ethan Johnson', + role: 'Developer', + skills: ['Java', 'PHP', 'C++', 'Go'], + level: 'Expert', + }, + { + id: 'B026', + profilePicture: 'https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Emma White', + role: 'Developer', + skills: ['HTML', 'CSS', 'JavaScript', 'Python', 'Swift'], + level: 'Intermediate', + }, + { + id: 'B027', + profilePicture: 'https://images.unsplash.com/photo-1529626455594-4ff0802cfb7e?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Alexander Green', + role: 'Developer', + skills: ['JavaScript', 'Go', 'PHP', 'React'], + level: 'Beginner', + }, + { + id: 'B028', + profilePicture: 'https://images.unsplash.com/photo-1524504388940-b1c1722653e1?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Chloe Lewis', + role: 'Developer', + skills: ['Python', 'Java', 'C++'], + level: 'Expert', + }, + { + id: 'B029', + profilePicture: 'https://s3.amazonaws.com/build-abc/wp-content/uploads/2016/08/24143420/profile_test_4.jpg', + name: 'Mason Brown', + role: 'Developer', + skills: ['Java', 'Kotlin', 'Go'], + level: 'Intermediate', + }, + { + id: 'B030', + profilePicture: 'https://images.unsplash.com/photo-1520333789090-1afc82db536a?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Amelia Martinez', + role: 'Developer', + skills: ['JavaScript', 'Vue.js', 'HTML', 'CSS'], + level: 'Beginner', + }, + { + id: 'B031', + profilePicture: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Lucas Harris', + role: 'Developer', + skills: ['Java', 'C#', 'Swift'], + level: 'Intermediate', + }, + { + id: 'B032', + profilePicture: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Isabella Jones', + role: 'Developer', + skills: ['JavaScript', 'Python', 'PHP'], + level: 'Expert', + }, + { + id: 'B033', + profilePicture: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Daniel Martinez', + role: 'Developer', + skills: ['C++', 'Kotlin', 'Go', 'PHP'], + level: 'Intermediate', + }, + { + id: 'B034', + profilePicture: 'https://images.unsplash.com/photo-1529626455594-4ff0802cfb7e?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Charlotte Wilson', + role: 'Developer', + skills: ['Java', 'JavaScript', 'React', 'Node.js'], + level: 'Beginner', + }, + { + id: 'B035', + profilePicture: 'https://images.unsplash.com/photo-1506794778202-cad84cf45f1d?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Michael King', + role: 'Developer', + skills: ['Python', 'Go', 'C++'], + level: 'Expert', + }, + { + id: 'B036', + profilePicture: 'https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Emily Davis', + role: 'Developer', + skills: ['JavaScript', 'PHP', 'Ruby'], + level: 'Intermediate', + }, + { + id: 'B037', + profilePicture: 'https://images.unsplash.com/photo-1522075469751-3a6694fb2f61?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Henry White', + role: 'Developer', + skills: ['Java', 'Kotlin', 'Swift'], + level: 'Beginner', + }, + { + id: 'B038', + profilePicture: 'https://thumbs.dreamstime.com/b/portrait-young-african-american-female-advisor-standing-workplace-portrait-young-african-american-female-advisor-standing-247199084.jpg', + name: 'Mia Lopez', + role: 'Developer', + skills: ['JavaScript', 'PHP', 'HTML', 'CSS'], + level: 'Expert', + }, + { + id: 'B039', + profilePicture: 'https://th.bing.com/th/id/R.3ee3f6f3314c6bc22aa1c4e0b19e7b4b?rik=x4Mi8kDEtv0bxw&riu=http%3a%2f%2fpic13.nipic.com%2f20110304%2f5252423_100326794000_2.jpg&ehk=m66NtLnK9ouQEso2mdNnR3DQHhcTaZV1H2Hs3fTtymY%3d&risl=&pid=ImgRaw&r=0', + name: 'James Lewis', + role: 'Developer', + skills: ['Python', 'JavaScript', 'Go'], + level: 'Intermediate', + }, + { + id: 'B040', + profilePicture: 'https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Grace Wilson', + role: 'Developer', + skills: ['PHP', 'C++', 'Swift', 'Java', 'Kotlin'], + level: 'Beginner', + }, + { + id: 'B041', + profilePicture: 'https://images.unsplash.com/photo-1517841905240-472988babdf9?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Ella Anderson', + role: 'Developer', + skills: ['JavaScript', 'Python', 'Go', 'PHP', 'C++'], + level: 'Expert', + }, + { + id: 'B042', + profilePicture: 'https://images.unsplash.com/photo-1600180758895-177ad3c473cf?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Ryan Walker', + role: 'Developer', + skills: ['Java', 'Swift', 'Kotlin'], + level: 'Intermediate', + }, + { + id: 'B043', + profilePicture: 'https://www.carvermostardi.com/cmos/wp-content/uploads/2018/05/professional_headshots_tampa_010.jpg', + name: 'Amelia Miller', + role: 'Developer', + skills: ['JavaScript', 'PHP', 'Python', 'Swift', 'Ruby'], + level: 'Expert', + }, + { + id: 'B044', + profilePicture: 'https://thumbs.dreamstime.com/b/vertical-close-up-portrait-awesome-handsome-young-caucasian-male-smiling-looking-camera-workplace-bearded-man-laughing-280837682.jpg', + name: 'James Nelson', + role: 'Developer', + skills: ['Java', 'C#', 'Kotlin'], + level: 'Intermediate', + }, + { + id: 'B045', + profilePicture: 'https://i.pinimg.com/originals/43/dc/da/43dcdae374bccd3b7f4bc02524dd765b.jpg', + name: 'Sophia Wilson', + role: 'Developer', + skills: ['JavaScript', 'HTML', 'CSS', 'Python'], + level: 'Beginner', + }, + { + id: 'B046', + profilePicture: 'https://thumbs.dreamstime.com/b/beautiful-smiling-businesswoman-portrait-workplace-beautiful-smiling-businesswoman-portrait-workplace-look-camera-white-128396388.jpg', + name: 'Oliver Davis', + role: 'Developer', + skills: ['Java', 'Python', 'Go', 'PHP'], + level: 'Intermediate', + }, + { + id: 'B047', + profilePicture: 'https://i.pinimg.com/originals/b5/e6/d6/b5e6d6c39a235e9f7b2ec8ef12ee565d.jpg', + name: 'Emily Clark', + role: 'Developer', + skills: ['JavaScript', 'Ruby', 'Kotlin'], + level: 'Expert', + }, + { + id: 'B048', + profilePicture: 'https://i.pinimg.com/originals/54/4a/5a/544a5a9fd523177dc3ba22edc0ceb911.jpg', + name: 'Liam Rodriguez', + role: 'Developer', + skills: ['C#', 'Swift', 'Java', 'Kotlin'], + level: 'Intermediate', + }, + { + id: 'B049', + profilePicture: 'https://i.pinimg.com/originals/08/11/58/0811588c1350407b49f42e8b5877c1e7.jpg', + name: 'Olivia Martinez', + role: 'Developer', + skills: ['Python', 'Go', 'PHP', 'C++'], + level: 'Beginner', + }, + + { + id: 'B056', + profilePicture: 'https://www.carvermostardi.com/cmos/wp-content/uploads/2018/05/professional_headshots_tampa_007.jpg', + name: 'Isabella Lee', + role: 'Developer', + skills: ['JavaScript', 'React', 'Kotlin', 'Go'], + level: 'Intermediate', + }, + { + id: 'B057', + profilePicture: 'https://th.bing.com/th/id/OIP.NF-jE1qzAAF9vPKkae0FIAHaE8?rs=1&pid=ImgDetMain', + name: 'Mason Lopez', + role: 'Developer', + skills: ['Java', 'PHP', 'Python', 'HTML'], + level: 'Beginner', + }, + { + id: 'B058', + profilePicture: 'https://images.unsplash.com/photo-1517841905240-472988babdf9?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Amelia Scott', + role: 'Developer', + skills: ['JavaScript', 'SCSS', 'Firebase', 'Go'], + level: 'Intermediate', + }, + { + id: 'B059', + profilePicture: 'https://www.theirishstore.com/media/catalog/product/cache/b66486118cc37b39a1ee812394ec6654/c/a/cardh001-cream-aran-cable-hat.jpg', + name: 'James Allen', + role: 'Developer', + skills: ['Python', 'Ruby', 'Java', 'Kotlin', 'Go'], + level: 'Expert', + }, + { + id: 'B060', + profilePicture: 'https://images.unsplash.com/photo-1600180758895-177ad3c473cf?crop=faces&fit=crop&w=500&h=500&q=80', + name: 'Emily Harris', + role: 'Developer', + skills: ['JavaScript', 'React', 'C++', 'PHP'], + level: 'Beginner', + }, + + + +]; + +export default mockMatchedUser; \ No newline at end of file diff --git a/src/pages/BackEnd/Backend.jsx b/src/pages/BackEnd/Backend.jsx deleted file mode 100644 index 8347c8a..0000000 --- a/src/pages/BackEnd/Backend.jsx +++ /dev/null @@ -1,60 +0,0 @@ -// src/components/SomeComponent.js -import React, { useState, useEffect } from 'react'; -import { createData, readData, updateData, deleteData } from '../../utils/Functions/functions'; - -const BackEndTest = () => { - const [data, setData] = useState([]); - const collectionName = 'Users'; - - useEffect(() => { - const fetchData = async () => { - const result = await readData(collectionName); - setData(result); - console.log(result); - }; - fetchData(); - }, []); - if(data.length>0){ - console.log(data); - } - - const handleCreate = async () => { - const newData = { name: 'New Item', description: 'Description' }; - await createData(collectionName, newData); - // Refresh the data - const updatedData = await readData(collectionName); - setData(updatedData); - }; - - const handleUpdate = async (id) => { - const updatedData = { name: 'Updated Item', description: 'Updated Description' }; - await updateData(collectionName, id, updatedData); - // Refresh the data - const updatedDataList = await readData(collectionName); - setData(updatedDataList); - }; - - const handleDelete = async (id) => { - await deleteData(collectionName, id); - // Refresh the data - const updatedDataList = await readData(collectionName); - setData(updatedDataList); - }; - - return ( -
- - {console.log(data)} - {data.map(item => ( -
-

{item.firstName}

-

{item.description}

- - -
- ))} -
- ); -}; - -export default BackEndTest; diff --git a/src/pages/ChallengeDetails/ChallengeDetails.jsx b/src/pages/ChallengeDetails/ChallengeDetails.jsx new file mode 100644 index 0000000..dedd392 --- /dev/null +++ b/src/pages/ChallengeDetails/ChallengeDetails.jsx @@ -0,0 +1,189 @@ +import "./ChallengeDetails.scss"; +import { Link, useParams } from "react-router-dom"; +import DashboardNavbar from "../../components/DashboardNavbar/DashboardNavbar"; +import clock from "../../assets/icons/clock.svg"; +import pen from "../../assets/icons/pen.svg"; +import bulb from "../../assets/icons/lightbulb.svg"; +import backIcon from "../../assets/images/back.svg"; +import { db } from "../../firebase"; +import { useEffect, useState } from "react"; +import { useNavigate } from "react-router-dom"; +import { getDoc, doc } from "firebase/firestore"; + + +import { findMatchedUser } from '../../utils/Functions/matchUser'; +import MockCurrentUser from '../../mockCurrentUserforMatch'; + +export function ChallengeDetails() { + const { challengeId } = useParams(); + + const [challengeData, setChallengeData] = useState(null); + + const navigate = useNavigate(); + + useEffect(() => { + async function getChallengeData() { + + const docRef = doc(db, "Challenges", challengeId); + const docSnap = await getDoc(docRef); + + if (docSnap.exists()) { + const data = docSnap.data() + setChallengeData(data); + } else { + navigate("/testPage") + } + } + + getChallengeData() + }, [challengeId, navigate]) + + const handlePairUp = () => { + const currentUser = MockCurrentUser[0]; + const matchedUser = findMatchedUser(currentUser); + navigate('/PairupBoard', { state: { matchedUser } }); + }; + + if (!challengeData) { + return
Loading
; + } + + + return ( + <> + +
+ computer on a desk + +
+
+
+ {challengeData.difficulty} +
+

{challengeData.task}

+

+ {challengeData.detailedProblem.description} +

+ +
+
+ pen icon + + {challengeData.category} + +
+
+ pen icon + + {challengeData.duration} + +
+
+ pen icon + + VS Code, {challengeData.category} + +
+
+ +
+

Constraints

+
    + {challengeData.detailedProblem.constraints.map( + (constraint, index) => { + return ( +
  • + {constraint} +
  • + ); + } + )} +
+
+ +
+

Examples

+
    + {challengeData.detailedProblem.examples.map( + (example, index) => { + return ( + + Input: {example.input}
    Output: {example.output} +
    + ); + } + )} +
+
+ + +
+

Solution Approach

+
    + {challengeData.detailedProblem.solutionApproach.map( + (example, index) => { + return ( +
  • + {example} +
  • + ); + } + )} +
+
+ +
+ + + + +
+
+ +
+
+
Complete the challenge
+
    +
  • + Create a solution that works with all the examples. Make sure + your solution adheres the all constraints given. +
  • +
+
+
+
Submit Your Code
+
    +
  • + After completing the challenge, input your code into the + designated User Code section and click Submit. +
  • +
+
+
+
Finalize your solution
+
    +
  • + After receiving feedback, implement any improvements that have + been suggested by your partner. +
  • +
+
+
+
+
+ + ); +} diff --git a/src/pages/ChallengeDetails/ChallengeDetails.scss b/src/pages/ChallengeDetails/ChallengeDetails.scss new file mode 100644 index 0000000..6d83973 --- /dev/null +++ b/src/pages/ChallengeDetails/ChallengeDetails.scss @@ -0,0 +1,244 @@ +@use "../../styles/partials/mixins" as *; +@use "../../styles/partials/variables" as *; + +.main { + @include Mobile { + padding: 1rem; + } + + @include Tablet { + padding: 40px; + } + + @include Desktop { + padding: 40px 128px; + } + +} + +.image { + width: 100%; + height: 300px; + object-fit: cover; +} + +.challenge { + @include Mobile { + flex-direction: column + } + + @include Tablet { + + display: flex; + flex-direction: row; + margin-top: 40px; + } + + +} + +.overview { + + @include Mobile { + width: auto; + margin: 1rem; + } + + @include Tablet { + width: 66%; + margin: 40px; + } + + &__difficulty { + background: #09F; + border-radius: 50px; + font-size: 12px; + padding: 2.5px 16px 5.5px 16px; + color: $MVP-White; + font-weight: 700; + display: inline-flex; + align-items: center; + justify-content: center; + line-height: 1; + text-transform: capitalize; + letter-spacing: 1px; + } + + &__title { + font-size: 3rem; + font-family: Corben; + line-height: 1.1; + margin-top: 1rem; + } + + &__overview { + margin-top: 1rem; + font-family: Corben-Regular; + font-weight: 400; + } + + &__details { + display: flex; + flex-direction: column; + gap: 1rem; + margin-top: 3rem; + } + + &__type { + display: flex; + align-items: center; + gap: 0.5rem; + } + + &__type-text { + font-size: 18px; + font-family: Corben-Regular; + } + + &__icon { + height: 1.5rem; + width: 1.5rem; + } +} + +.objectives, +.solutions { + margin-top: 3rem; + + &__title { + font-size: 1.25rem; + font-family: Corben; + } + + &__item { + list-style-position: inside; + font-family: Corben-Regular; + font-size: 1rem; + } +} + +.examples { + margin-top: 3rem; + + &__title { + font-size: 1.25rem; + font-family: Corben; + } + + &__item { + display: block; + margin-top: 1rem; + font-size: 16px; + } + + &__item:first-child { + margin-top: 0.5rem; + + } +} + +.instructions { + + @include Mobile { + width: auto; + padding: 1rem; + } + + @include Tablet { + padding: 40px; + width: 33%; + border-left: 1px solid #757575; + } + + + &__chip { + background: #0954B0; + display: inline-block; + border-radius: 50px; + border-radius: 50px; + font-size: 12px; + padding: 2.5px 16px 5.5px 16px; + color: $MVP-White; + font-weight: 700; + display: inline-flex; + align-items: center; + justify-content: center; + line-height: 1; + text-transform: capitalize; + letter-spacing: 1px; + margin-top: 1rem; + } + + &__list { + margin-top: 1rem; + } + + &__item { + list-style-position: inside; + font-family: Corben-Regular; + font-size: 1rem; + } +} + +.action { + display: flex; + gap: 1.5rem; + margin-top: 3rem; + + @include Mobile { + flex-direction: column; + } + + @include Tablet { + flex-direction: row; + } + + &__button { + background-color: $MVP-Light-Blue; + color: $MVP-black; + font-family: Corben; + border-radius: 4px; + font-size: 1.25rem; + padding: 0.5rem 2.5rem; + border-top: 3px solid $MVP-black; + border-right: 6px solid $MVP-black; + border-bottom: 6px solid $MVP-black; + border-left: 3px solid $MVP-black; + + @include Mobile { + width: 100%; + } + + @include Desktop { + width: auto; + } + + &:hover { + background: #0954B0; + } + + + &--secondary { + background-color: $MVP-White; + display: flex; + align-items: center; + gap: 1rem; + justify-content: flex-start; + padding-left: 2rem; + + + &:hover { + background-color: $MVP-Yellow; + } + } + } + + &__back-icon { + height: 24px; + } +} + +.steps { + flex: 1; + margin: 40px; +} \ No newline at end of file diff --git a/src/pages/ChallengeDetails/challenges.json b/src/pages/ChallengeDetails/challenges.json new file mode 100644 index 0000000..5846d2f --- /dev/null +++ b/src/pages/ChallengeDetails/challenges.json @@ -0,0 +1,378 @@ +{ + "challenges": [ + { + "id": 1, + "imgSrc": "https://png.pngtree.com/background/20230517/original/pngtree-what-can-a-home-computer-desk-look-like-picture-image_2625455.jpg", + "category": "Python", + "difficulty": "easy", + "duration": "60 mins", + "task": "Sum even numbers", + "details": "Write a Python function that takes a list of integers and returns the sum of all even numbers.", + "detailedProblem": { + "description": "Given a list of integers, write a function that returns the sum of all even numbers in the list.", + "examples": [ + { + "input": "[1, 2, 3, 4, 5]", + "output": "6", + "explanation": "The even numbers in the list are 2 and 4. Their sum is 2 + 4 = 6." + }, + { + "input": "[7, 11, 13, 17]", + "output": "0", + "explanation": "There are no even numbers in the list, so the sum is 0." + }, + { + "input": "[2, 4, 6, 8]", + "output": "20", + "explanation": "All numbers in the list are even, so the sum is 2 + 4 + 6 + 8 = 20." + } + ], + "constraints": [ + "The list can contain negative integers.", + "The list can contain at most 10^4 integers." + ], + "solutionApproach": [ + "Loop through the list of integers.", + "Use a conditional check to see if a number is even (i.e., divisible by 2).", + "Sum up all the even numbers and return the result." + ] + } + }, + { + "id": 2, + "imgSrc": "https://png.pngtree.com/background/20230517/original/pngtree-what-can-a-home-computer-desk-look-like-picture-image_2625455.jpg", + "category": "Python", + "difficulty": "intermediate", + "duration": "60 mins", + "task": "Anagram check", + "details": "Write a Python function to check if two strings are anagrams, ignoring spaces and capitalization.", + "detailedProblem": { + "description": "Given two strings, write a function to determine if the strings are anagrams of each other. An anagram is formed by rearranging the letters of another word using all original letters exactly once. The function should ignore spaces and capitalization.", + "examples": [ + { + "input": "\"Listen\", \"Silent\"", + "output": "True", + "explanation": "After ignoring the case and spaces, both strings are rearrangements of each other." + }, + { + "input": "\"Dormitory\", \"Dirty room\"", + "output": "True", + "explanation": "Ignoring the space and case, 'Dormitory' can be rearranged to form 'Dirty room'." + }, + { + "input": "\"Hello\", \"World\"", + "output": "False", + "explanation": "The two words don't have the same characters, so they are not anagrams." + } + ], + "constraints": [ + "The input strings consist of lowercase and uppercase English letters and spaces.", + "The length of each string is at most 10^5 characters." + ], + "solutionApproach": [ + "Remove all spaces and convert both strings to lowercase.", + "Sort both strings and check if they are equal.", + "If the sorted versions of the strings are the same, return True; otherwise, return False." + ] + } + }, + { + "id": 3, + "imgSrc": "https://png.pngtree.com/background/20230517/original/pngtree-what-can-a-home-computer-desk-look-like-picture-image_2625455.jpg", + "category": "Python", + "difficulty": "hard", + "duration": "60 mins", + "task": "Matrix rotation", + "details": "Rotate a given N x N matrix 90 degrees clockwise using only O(1) space.", + "detailedProblem": { + "description": "Given an N x N matrix, rotate the matrix by 90 degrees clockwise in place. This means that the operation should be performed without using any additional matrices (i.e., using only O(1) space).", + "examples": [ + { + "input": "[[1, 2, 3], [4, 5, 6], [7, 8, 9]]", + "output": "[[7, 4, 1], [8, 5, 2], [9, 6, 3]]", + "explanation": "The matrix is rotated 90 degrees clockwise." + }, + { + "input": "[[5, 1, 9, 11], [2, 4, 8, 10], [13, 3, 6, 7], [15, 14, 12, 16]]", + "output": "[[15, 13, 2, 5], [14, 3, 4, 1], [12, 6, 8, 9], [16, 7, 10, 11]]", + "explanation": "The matrix is rotated 90 degrees clockwise." + } + ], + "constraints": [ + "The matrix will always be an N x N grid, where 1 <= N <= 1000.", + "The matrix contains integers between -1000 and 1000." + ], + "solutionApproach": [ + "Transpose the matrix (swap rows with columns).", + "Reverse each row.", + "This will rotate the matrix 90 degrees clockwise in place." + ] + } + }, + { + "id": 4, + "imgSrc": "https://png.pngtree.com/background/20230517/original/pngtree-what-can-a-home-computer-desk-look-like-picture-image_2625455.jpg", + "category": "React", + "difficulty": "easy", + "duration": "60 mins", + "task": "Simple counter component", + "details": "Create a React component that displays a counter with increment and decrement buttons.", + "detailedProblem": { + "description": "In this challenge, you will create a simple counter component in React. The counter should start from 0 and increase or decrease when buttons are clicked.", + "examples": [ + { + "input": "Initial counter value: 0. Click increment button.", + "output": "Counter value: 1" + }, + { + "input": "Counter value: 1. Click decrement button.", + "output": "Counter value: 0" + } + ], + "constraints": [ + "The component should manage its own state using React hooks.", + "The buttons should properly update the counter value." + ], + "solutionApproach": [ + "Use the `useState` hook to create and manage the counter state.", + "Create two buttons that update the state using the `setState` function." + ] + } + }, + { + "id": 5, + "imgSrc": "https://png.pngtree.com/background/20230517/original/pngtree-what-can-a-home-computer-desk-look-like-picture-image_2625455.jpg", + "category": "React", + "difficulty": "intermediate", + "duration": "60 mins", + "task": "Interactive card component", + "details": "Build a card component that reveals hidden content upon clicking.", + "detailedProblem": { + "description": "In this challenge, you will create an interactive card component that displays additional information when clicked. The focus is on writing clean, modular code and improving your understanding of React and DOM manipulation.", + "examples": [ + { + "input": "A card that shows details on click", + "output": "Details are revealed on clicking the card." + } + ], + "constraints": [ + "Use React state to track whether the card is expanded or collapsed.", + "Ensure the UI updates efficiently when the card is clicked." + ], + "solutionApproach": [ + "Use the `useState` hook to manage the card’s visibility state.", + "Toggle the visibility of the card’s content when clicked." + ] + } + }, + { + "id": 6, + "imgSrc": "https://png.pngtree.com/background/20230517/original/pngtree-what-can-a-home-computer-desk-look-like-picture-image_2625455.jpg", + "category": "React", + "difficulty": "hard", + "duration": "60 mins", + "task": "Todo list with React and Local Storage", + "details": "Create a todo list application that saves items to local storage and allows them to persist between page reloads.", + "detailedProblem": { + "description": "In this challenge, you will build a todo list application in React. The app should allow users to add, remove, and mark items as completed. Additionally, the todo items should be saved to local storage and persist between page reloads.", + "examples": [ + { + "input": "Add a todo item 'Buy milk'. Reload the page.", + "output": "The todo list persists, showing the 'Buy milk' item." + } + ], + "constraints": [ + "The app should store and retrieve todo items from local storage.", + "Use React state and hooks for managing the todo list." + ], + "solutionApproach": [ + "Use the `useState` and `useEffect` hooks to manage state and local storage.", + "Ensure that todo items persist across page reloads by interacting with the browser’s local storage." + ] + } + }, + { + "id": 7, + "imgSrc": "https://png.pngtree.com/background/20230517/original/pngtree-what-can-a-home-computer-desk-look-like-picture-image_2625455.jpg", + "category": "DSA", + "difficulty": "easy", + "duration": "60 mins", + "task": "Reverse a string", + "details": "Write a function to reverse a given string.", + "detailedProblem": { + "description": "Given a string, write a function to return the string in reverse order.", + "examples": [ + { + "input": "\"hello\"", + "output": "\"olleh\"" + }, + { + "input": "\"world\"", + "output": "\"dlrow\"" + } + ], + "constraints": [ + "The string can contain only English letters and spaces.", + "The maximum length of the string is 10^4." + ], + "solutionApproach": [ + "Use slicing or a loop to reverse the characters in the string.", + "Return the reversed string." + ] + } + }, + { + "id": 8, + "imgSrc": "https://png.pngtree.com/background/20230517/original/pngtree-what-can-a-home-computer-desk-look-like-picture-image_2625455.jpg", + "category": "DSA", + "difficulty": "intermediate", + "duration": "60 mins", + "task": "Longest palindrome substring", + "details": "Find the longest palindromic substring in a given string.", + "detailedProblem": { + "description": "Given a string, write a function to find the longest substring that is a palindrome.", + "examples": [ + { + "input": "\"babad\"", + "output": "\"bab\" or \"aba\"" + }, + { + "input": "\"cbbd\"", + "output": "\"bb\"" + } + ], + "constraints": [ + "The input string consists of lowercase English letters.", + "The length of the string is at most 1000 characters." + ], + "solutionApproach": [ + "Use dynamic programming or expand around center approach to find the longest palindromic substring." + ] + } + }, + { + "id": 9, + "imgSrc": "https://png.pngtree.com/background/20230517/original/pngtree-what-can-a-home-computer-desk-look-like-picture-image_2625455.jpg", + "category": "DSA", + "difficulty": "hard", + "duration": "60 mins", + "task": "Find shortest path in a maze", + "details": "Implement an algorithm to find the shortest path in a maze using BFS.", + "detailedProblem": { + "description": "Given a 2D grid representing a maze, find the shortest path from the start position to the end position using Breadth-First Search (BFS).", + "examples": [ + { + "input": "[[1, 0, 1], [1, 1, 0], [0, 1, 1]]", + "output": "4", + "explanation": "The shortest path from the top-left to the bottom-right is 4 steps." + } + ], + "constraints": [ + "The grid consists of 1s (walkable) and 0s (blocked).", + "The size of the grid is at most 100 x 100." + ], + "solutionApproach": [ + "Use BFS to explore the maze level by level, keeping track of visited cells to avoid revisiting." + ] + } + }, + { + "id": 10, + "imgSrc": "https://png.pngtree.com/background/20230517/original/pngtree-what-can-a-home-computer-desk-look-like-picture-image_2625455.jpg", + "category": "Java", + "difficulty": "easy", + "duration": "60 mins", + "task": "Factorial of a number", + "details": "Write a Java program to calculate the factorial of a number.", + "detailedProblem": { + "description": "Given a non-negative integer, write a function to calculate its factorial.", + "examples": [ + { + "input": "5", + "output": "120" + }, + { + "input": "0", + "output": "1" + } + ], + "constraints": [ + "The input is a non-negative integer.", + "The result should fit within the range of a 64-bit integer." + ], + "solutionApproach": [ + "Use recursion or iteration to compute the factorial of the number." + ] + } + }, + { + "id": 11, + "imgSrc": "https://png.pngtree.com/background/20230517/original/pngtree-what-can-a-home-computer-desk-look-like-picture-image_2625455.jpg", + "category": "Java", + "difficulty": "intermediate", + "duration": "60 mins", + "task": "Check balanced parentheses", + "details": "Write a Java program to check if an expression has balanced parentheses.", + "detailedProblem": { + "description": "Given a string containing parentheses, write a function to check if the parentheses are balanced.", + "examples": [ + { + "input": "\"(a + b) * (c - d)\"", + "output": "True" + }, + { + "input": "\"(a + b * (c - d)\"", + "output": "False" + } + ], + "constraints": [ + "The input string consists of alphanumeric characters and parentheses.", + "The maximum length of the string is 1000 characters." + ], + "solutionApproach": [ + "Use a stack to check for matching opening and closing parentheses." + ] + } + }, + { + "id": 12, + "imgSrc": "https://png.pngtree.com/background/20230517/original/pngtree-what-can-a-home-computer-desk-look-like-picture-image_2625455.jpg", + "category": "Java", + "difficulty": "hard", + "duration": "60 mins", + "task": "Serialize and deserialize binary tree", + "details": "Write a Java program to serialize and deserialize a binary tree.", + "detailedProblem": { + "description": "Given a binary tree, write a function to serialize the tree into a string and another function to deserialize the string back into the binary tree.", + "examples": [ + { + "input": "Binary Tree: [1,2,3,null,null,4,5]", + "output": "Serialized string: \"1,2,null,null,3,4,5\"" + } + ], + "constraints": [ + "The binary tree consists of integers.", + "The number of nodes in the tree is at most 10000." + ], + "solutionApproach": [ + "Use a preorder traversal to serialize the tree and reverse the process to deserialize." + ] + } + } + ], + "placeholderData": { + "imgSrc": "https://png.pngtree.com/background/20230517/original/pngtree-what-can-a-home-computer-desk-look-like-picture-image_2625455.jpg", + "title": "Interactive Card component with JavaScript", + "difficulty": "Easy", + "type": "Code", + "time": "60 - 90 min", + "tech": "HTML - CSS - JavaScript", + "overview": "In this challenge, you will create an interactive card component that displays additional information when clicked. You will be paired with a partner to review each other's code and provide suggestions for improvement. The focus is on writing clean, modular code and improving your understanding of DOM manipulation.", + "objectives": [ + "Build a card component that reveals hidden content upon clicking.", + "Use JavaScript to toggle visibility of the card's details", + "Write Modular, reusable code for future component scalability.", + "Provide constructive feedback to your partner's code and suggest improvements" + ] + } +} \ No newline at end of file diff --git a/src/components/LoadingPage/LoadingPage.jsx b/src/pages/LoadingPage/LoadingPage.jsx similarity index 91% rename from src/components/LoadingPage/LoadingPage.jsx rename to src/pages/LoadingPage/LoadingPage.jsx index 615c701..edf807f 100644 --- a/src/components/LoadingPage/LoadingPage.jsx +++ b/src/pages/LoadingPage/LoadingPage.jsx @@ -1,5 +1,5 @@ import "./LoadingPage.scss"; -import LoadingBar from "../LoadingBar/LoadingBar"; +import LoadingBar from "../../components/LoadingBar/LoadingBar"; import CoffeeMugWithHat_happy from "../../assets/images/coffeeMugWithHat_happy.svg"; import connectAiIcon from "../../assets/images/connectAiIcon.svg"; import { useEffect, useState } from "react"; @@ -13,8 +13,7 @@ const LoadingPage = ({ currentPage, setCurrentPage }) => { }, 2000); setPage(currentPage); } - if(page==="loading1") - { + if (page === "loading1") { setTimeout(() => { setCurrentPage("roadmap"); }, 2000); diff --git a/src/components/LoadingPage/LoadingPage.scss b/src/pages/LoadingPage/LoadingPage.scss similarity index 100% rename from src/components/LoadingPage/LoadingPage.scss rename to src/pages/LoadingPage/LoadingPage.scss diff --git a/src/pages/OnboardingPage/OnboardingPage.scss b/src/pages/OnboardingPage/OnboardingPage.scss new file mode 100644 index 0000000..deeca92 --- /dev/null +++ b/src/pages/OnboardingPage/OnboardingPage.scss @@ -0,0 +1,92 @@ +@import "../../styles/partials/mixins.scss"; +@import "../../styles/partials/variables.scss"; +@import "../../styles/partials/typography.scss"; + +.onboarding-page__container { + background-color: $MVP-White; + border-radius: 0.75rem; + box-shadow: 0px 0px 12px 2px rgba(82, 82, 82, 0.16); + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 4rem; + padding: 1em; + position: relative; + border-top: 3px solid $MVP-black; + border-right: 6px solid $MVP-black; + border-bottom: 6px solid $MVP-black; + border-left: 3px solid $MVP-black; + width: calc(100vw - 2rem); + + @include Desktop { + width: calc(100vw - 8rem); + padding: 6rem; + gap: 1rem; + } +} + +.left-arrow-container { + position: absolute; + left: 2.25rem; + top: 2.25rem; +} + +.arrow-left { + cursor: pointer; +} + +.onboarding-page__text-container { + display: flex; + flex-direction: column; + align-items: center; + gap: 2.5rem; + align-self: stretch; + margin-top: 4rem; + + @include Desktop { + margin-top: 0; + } +} + +.welcome-message { + font-family: Corben; + font-size: 2rem; + font-weight: 700; + font-style: normal; + line-height: 2.5rem; +} + +.onboarding-button-container { + display: flex; + justify-content: center; + align-items: flex-start; + align-self: stretch; + flex-direction: column; + gap: 2rem; + + @include Desktop { + flex-direction: row; + padding: 4rem; + gap: 1rem; + } + + button { + display: flex; + min-width: 16.9375rem; + padding: 0.625rem 3rem; + justify-content: center; + align-items: center; + gap: 0.5rem; + background-color: $MVP-White; + transition: background-color 0.2s ease; + + @include Desktop { + width: 16.9375rem; + } + + &:hover { + background-color: #FFD22F; + } + } +} \ No newline at end of file diff --git a/src/pages/OnboardingPage/OnboardingPage1.jsx b/src/pages/OnboardingPage/OnboardingPage1.jsx new file mode 100644 index 0000000..29be9e5 --- /dev/null +++ b/src/pages/OnboardingPage/OnboardingPage1.jsx @@ -0,0 +1,72 @@ +import React, { useContext } from "react"; +import "./OnboardingPage.scss"; +import Button from "../../components/Button/Button"; +import { PageContext } from "../../contexts/PageContext"; +import loadingInactiveIcon from "../../assets/images/loadingInactiveIcon.svg"; +import loadingActiveIcon from "../../assets/images/loadingActiveIcon.svg"; +import arrowLeft from "../../assets/images/arrowLeft.svg"; + +const OnboardingPage1 = () => { + const { handleNext, handleBack, progressBarIndex } = useContext(PageContext); + + const handleClick = (field) => { + handleNext(); + }; + + return ( +
+
+ <> +
+ arrowLeft +
+
+
+ What field are you looking to work on? +
+
+
+
+
+ loadingIcon + loadingIcon + loadingIcon + loadingIcon +
+ +
+
+ ); +}; + +export default OnboardingPage1; diff --git a/src/pages/OnboardingPage/OnboardingPage2.jsx b/src/pages/OnboardingPage/OnboardingPage2.jsx new file mode 100644 index 0000000..cc09bd8 --- /dev/null +++ b/src/pages/OnboardingPage/OnboardingPage2.jsx @@ -0,0 +1,84 @@ +import { useContext } from "react"; +import "./OnboardingPage.scss"; +import Button from "../../components/Button/Button"; +import { PageContext } from "../../contexts/PageContext"; +import loadingInactiveIcon from "../../assets/images/loadingInactiveIcon.svg"; +import loadingActiveIcon from "../../assets/images/loadingActiveIcon.svg"; +import arrowLeft from "../../assets/images/arrowLeft.svg"; + +const OnboardingPage2 = () => { + const { + handleNext, + handleBack, + progressBarIndex, + updateUserFeedback, + userFeedback, + } = useContext(PageContext); + + const handleSkillSelection = (skillLevel) => { + updateUserFeedback("skillLevel", skillLevel); + handleNext(); + }; + + return ( +
+
+ <> +
+ arrowLeft +
+
+
+ How good are you at {userFeedback.field || "your field"}? +
+
+
+
+
+ loadingActiveIcon + loadingInactiveIcon + loadingInactiveIcon + loadingInactiveIcon +
+ +
+
+ ); +}; + +export default OnboardingPage2; diff --git a/src/pages/OnboardingPage/OnboardingPage3.jsx b/src/pages/OnboardingPage/OnboardingPage3.jsx new file mode 100644 index 0000000..a48e8cb --- /dev/null +++ b/src/pages/OnboardingPage/OnboardingPage3.jsx @@ -0,0 +1,90 @@ +import { useContext } from "react"; +import "./OnboardingPage.scss"; +import Button from "../../components/Button/Button"; +import { PageContext } from "../../contexts/PageContext"; +import loadingInactiveIcon from "../../assets/images/loadingInactiveIcon.svg"; +import loadingActiveIcon from "../../assets/images/loadingActiveIcon.svg"; +import arrowLeft from "../../assets/images/arrowLeft.svg"; + +const OnboardingPage3 = () => { + const { + handleNext, + handleBack, + progressBarIndex, + updateUserFeedback, + userFeedback, + } = useContext(PageContext); + + const handleSkillSelection = (skill) => { + updateUserFeedback("skillToImprove", skill); + handleNext(); + }; + + return ( +
+
+ <> +
+ arrowLeft +
+
+
+ What skill do you want to work on in{" "} + {userFeedback.field || "your field"}? +
+
+
+
+
+ loadingActiveIcon + loadingInactiveIcon + loadingInactiveIcon + loadingInactiveIcon +
+ +
+
+ ); +}; + +export default OnboardingPage3; diff --git a/src/pages/P5AP_PairupBoard/PairupBoard.jsx b/src/pages/P5AP_PairupBoard/PairupBoard.jsx new file mode 100644 index 0000000..5de6586 --- /dev/null +++ b/src/pages/P5AP_PairupBoard/PairupBoard.jsx @@ -0,0 +1,62 @@ +import { useState, useEffect } from 'react'; +import { useNavigate, useLocation } from 'react-router-dom'; +import mockMatchedUser from '../../mockDataForPhotocard'; +import PhotoCard from '../../components/P5AP_PhotoCard/photocard'; +import './PairupBoard.scss'; + +const PairupBoard = () => { + const location = useLocation(); + const [loading, setLoading] = useState(false); + const [matchedUser, setMatchedUser] = useState(location.state?.matchedUser || null); + const navigate = useNavigate(); + + useEffect(() => { + + if (!matchedUser) { + + setMatchedUser(mockMatchedUser[0]); + } + }, [matchedUser]); + + const handleBeginChallenge = () => { + navigate('/taskPage'); + }; + + const handleGoBack = () => { + navigate('/challengePage'); + }; + + return ( +
+ {loading &&
Loading...
} + {!loading && ( + <> +
+ We found a buddy to pair with. +
+ {matchedUser ? ( + + ) : ( +

No user data available

+ )} +
+ What are you waiting for? +
+
+ + +
+ + )} +
+ ); +}; + +export default PairupBoard; diff --git a/src/pages/P5AP_PairupBoard/PairupBoard.scss b/src/pages/P5AP_PairupBoard/PairupBoard.scss new file mode 100644 index 0000000..30baded --- /dev/null +++ b/src/pages/P5AP_PairupBoard/PairupBoard.scss @@ -0,0 +1,114 @@ +@import "../../styles/partials/mixins.scss"; +@import "../../styles/partials/variables.scss"; +@import "../../styles/partials/typography.scss"; + +.pairup-board { + display: flex; + flex-direction: column; + font-family: "Corben-Bold"; + align-items: center; + padding: 2rem; + background-color: #f9f9f9; + min-height: 100vh; + } + + + .pairup-board_text{ + font-family:"Corben-Bold" ; + font-size: 1.6rem; + margin-bottom: 2rem; + } + + .pairup-board__actions { + margin-top: 1.5rem; + display: flex; + gap: 1rem; + } + + .btn-primary:hover + .btn-secondary, + .btn-secondary:hover + .btn-primary { + background-color: #007bff; + color: whitesmoke; + border-color: #007bff; + } + .btn-secondary:hover + .btn-primary, + .btn-primary:hover + .btn-secondary { + background-color: whitesmoke; + color: black; + border-color: black; + } + + .pairup-board_text-bottom{ + font-family:"Corben-Bold" ; + font-size: 1.6rem; + margin-top:3rem; + } + + +.btn { + font-size: 0.8rem; + border-radius: 0.25rem; + border: 3px solid black; + background-color: whitesmoke; + color: black; + box-shadow: 2px 3px 0 black; + cursor: pointer; + font-family: "Corben-Bold"; + width: 15rem; + height: 2.2rem; + transition: background-color 0.3s ease, box-shadow 0.3s ease, transform 0.1s ease; + + &:hover { + background-color: #007bff; + color: whitesmoke; + border-color: #007bff; + } + + &:active { + background-color: #007bff; + transform: scale(0.98); + } +} + +.btn-primary { + background-color: #007bff; + color: whitesmoke; + border: 2px solid #007bff; + color: black; + box-shadow: 2px 3px 0 black; + border: 3px solid black; + + &:hover { + background-color: $MVP-Dark-Blue-faded; + + color: black; + box-shadow: 2px 3px 0 black; + border: 3px solid black; + } + + &:active { + background-color: #007bff; + + } +} + +.btn-secondary { + background-color: whitesmoke; + color: black; + border: 2px solid black; + + &:hover { + color: whitesmoke; + background-color: $MVP-Dark-Blue-faded; + + color: black; + box-shadow: 2px 3px 0 black; + border: 3px solid black; + } + + &:active { + background-color: #007bff; + + } +} + diff --git a/src/pages/PromptPage/PromptPage.jsx b/src/pages/PromptPage/PromptPage.jsx index 806a695..e88a65c 100644 --- a/src/pages/PromptPage/PromptPage.jsx +++ b/src/pages/PromptPage/PromptPage.jsx @@ -1,104 +1,105 @@ +import { useEffect, useContext } from "react"; import "./PromptPage.scss"; -import { useNavigate } from "react-router-dom"; import DashboardNavbar from "../../components/DashboardNavbar/DashboardNavbar"; import Button from "../../components/Button/Button"; -import CoffeeMugWithHat_happy from "../../assets/images/coffeeMugWithHat_happy.svg"; -import { useEffect, useState } from "react"; -import QuizPage from "../../components/QuizPage/QuizPage"; -import Roadmap from "../../components/Roadmap/Roadmap"; -import GoalAchieved from "../../components/GoalAchieved/GoalAchieved"; -import LoadingPage from "../../components/LoadingPage/LoadingPage"; +import { PageContext } from "../../contexts/PageContext"; +import OnboardingPage1 from "../OnboardingPage/OnboardingPage1"; +import OnboardingPage2 from "../OnboardingPage/OnboardingPage2"; +import OnboardingPage3 from "../OnboardingPage/OnboardingPage3"; +import loadingInactiveIcon from "../../assets/images/loadingInactiveIcon.svg"; +import loadingActiveIcon from "../../assets/images/loadingActiveIcon.svg"; const PromptPage = () => { - const navigate = useNavigate(); - const [currentPage, setCurrentPage] = useState("prompt"); - - // ACCESS MATCH ALGO RESULTS through a state passed into quizPage - const [matchResults, setMatchResults] = useState(null); - + const { + currentPageIndex, + setCurrentPageIndex, + progressBarIndex, + handleNext, + handleBack, + progressArray, + } = useContext(PageContext); useEffect(() => { - setCurrentPage("prompt"); - sessionStorage.removeItem("formData"); - sessionStorage.removeItem("answeredQuestions"); - sessionStorage.removeItem("selectedAnswerIdsJSON"); - }, []); + setCurrentPageIndex(0); + }, [setCurrentPageIndex]); - const handleClick = () => { - setCurrentPage("quiz"); - }; - const handleBack = () => { - navigate("/"); - }; return (
- {currentPage === "prompt" && ( - <> -
-
-
-
- -
-
-
- Welcome to AccountaBuddy! -
-
- Our AI feature empowers you to achieve your professional - goals through personalized accountability partnerships. By - taking our quick matching quiz, you’ll be paired with a - peer who complements your skills, and you both will work - towards a common goal. -
-
- Click "Next" to get started on your journey to effective - peer-to-peer accountability. -
-
-
-
+ {currentPageIndex === 0 && ( +
+
+
Welcome to AccountaPair
+
+ Set your preferences and skills before moving to the dashboard
-
- - )} - {/* other pages */} - {(currentPage === "quiz" || - currentPage === "new-match" || - currentPage === "no-match") && ( - +
+
+
+ loadingIcon + loadingIcon + loadingIcon + loadingIcon +
+
)} - {currentPage === "roadmap" && } - {currentPage === "goalachieved" && } - {(currentPage === "loading"||currentPage==="loading1") && ( + + {currentPageIndex === 1 && } + + {currentPageIndex === 2 && } + + {currentPageIndex === 3 && } + {/* handle loading page */} + + {/* {(currentPageIndex === 4 || currentPageIndex === 5) && ( - )} + )} */}
diff --git a/src/pages/PromptPage/PromptPage.scss b/src/pages/PromptPage/PromptPage.scss index 4bcef2e..2d63d82 100644 --- a/src/pages/PromptPage/PromptPage.scss +++ b/src/pages/PromptPage/PromptPage.scss @@ -3,91 +3,97 @@ @import "../../styles/partials/typography.scss"; .promptpage { - // font-family: "Corben-Regular"; - background-color: $Powder-Blue; - min-width: 100%; - position: absolute; - top: 0; - z-index: -1; + min-height: calc(100vh - 5rem); + padding: 2.5rem 5rem; display: flex; flex-direction: column; + justify-content: center; align-items: center; + align-self: stretch; + overflow: hidden; + flex-shrink: 0; + gap: 2.5rem; +} + +.promptpage__home-container { + border-radius: 0.75rem; + display: flex; + flex-direction: column; justify-content: center; - height: 100vh; - - &__container { - background-color: $MVP-White; - position: absolute; - top: 9.5514rem; - // top: 75px; - border-radius: 20px; - border: 4px solid #000; - box-sizing: border-box; - width: 70%; - //min-height: 70vh; - flex-direction: column; - overflow: hidden; - display: flex; - justify-content: center; - align-items: center; - } + align-items: center; + border-top: 3px solid $MVP-black; + border-right: 6px solid $MVP-black; + border-bottom: 6px solid $MVP-black; + border-left: 3px solid $MVP-black; + width: 100%; + padding: 1em; + gap: 4rem; - &__top-bar { - border-radius: 16px 16px 0px 0px; - background-color: $MVP-Yellow; - // border: 0px 0px 4px 0px solid #000; - width: 100%; - min-height: 5.5vh; - border-bottom: 4px solid #000; - } - &__middle-container { - padding: 3%; - background-color: $MVP-White; - width: 100%; - min-height: 10vh; - flex-direction: column; - - &__sub-container { - width: 100%; - text-align: center; - font-weight: 700; - } - - &__coffeemug-img { - width: 15%; - } - } + @include Desktop { + width: calc(100vw - 8rem); + padding: 6em; + gap: 1rem; - .welcome-message { - font-family: Corben-Bold; - font-size: 1.875rem; - font-weight: 700; } - .welcome-text { - font-family: Gilroy; - &--main { - font-size: 1.25rem; - } +} + +.promptpage__text-container { + display: flex; + flex-direction: column; + align-items: center; + gap: 2.5rem; + +} + +.welcome-message { + font-family: Corben; + font-size: 2rem; + font-weight: 700; + font-style: normal; + line-height: 2.5rem; +} + +.welcome-text { + font-family: Corben-Regular; + font-style: normal; + font-weight: 400; + text-align: center; + line-height: 1.5rem; + + &--main { + font-size: 1rem; } +} + +.button-container { + display: flex; + justify-content: center; + align-items: flex-start; + align-self: stretch; + gap: 1rem; - .text-container > * { - padding-top: 25px; + flex-direction: column; + + @include Desktop { + flex-direction: row; + padding: 4rem; } - .button-container { + button { display: flex; + padding: 0.625rem 3rem; justify-content: center; - gap: 50px; - padding-top: 50px; - } + align-items: center; + gap: 0.5rem; - &__bottom-bar { - margin-top: auto; - border-radius: 0px 0px 16px 16px; - background-color: #ffd22f; - width: 100%; - min-height: 5.5vh; - border-top: 4px solid #000; + } + } + +.loading-icon-container { + display: flex; + align-items: center; + gap: 0.5rem; +} \ No newline at end of file diff --git a/src/components/QuizPage/QuizPage.jsx b/src/pages/QuizPage/QuizPage.jsx similarity index 92% rename from src/components/QuizPage/QuizPage.jsx rename to src/pages/QuizPage/QuizPage.jsx index 272fa5e..a30f897 100644 --- a/src/components/QuizPage/QuizPage.jsx +++ b/src/pages/QuizPage/QuizPage.jsx @@ -3,8 +3,8 @@ import ProgressBar from "../../components/ProgressBar/ProgressBar"; import React, { useState, Suspense } from "react"; import QuizQuestions from "../../components/QuizQuestions/QuizQuestions"; import LoadingPage from "../LoadingPage/LoadingPage"; -import NoMatch from "../NoMatch/NoMatch"; -import NewMatchedUsers from "../NewMatchedUsers/NewMatchedUsers"; +import NoMatch from "../../components/NoMatch/NoMatch"; +import NewMatchedUsers from "../../components/NewMatchedUsers/NewMatchedUsers"; const QuizPage = ({ currentPage, setCurrentPage }) => { // ADD match response prop if match algo happens after sending questions diff --git a/src/components/QuizPage/QuizPage.scss b/src/pages/QuizPage/QuizPage.scss similarity index 100% rename from src/components/QuizPage/QuizPage.scss rename to src/pages/QuizPage/QuizPage.scss diff --git a/src/pages/TestPage/TestPage.jsx b/src/pages/TestPage/TestPage.jsx index 743b2d4..a843adc 100644 --- a/src/pages/TestPage/TestPage.jsx +++ b/src/pages/TestPage/TestPage.jsx @@ -1,34 +1,11 @@ import "./TestPage.scss"; -import Dropdown from "../../components/Dropdown/Dropdown"; -import ListWithCheckbox from "../../components/ListWithCheckbox/ListWithCheckbox"; -import DropdownCheckbox from "../../components/DropdownCheckbox/DropdownCheckbox"; -import PromptPage from "../PromptPage/PromptPage"; -import NoMatch from "../../components/NoMatch/NoMatch"; -import Box from '@mui/material/Box'; -import Button from '@mui/material/Button'; -import Typography from '@mui/material/Typography'; -// import Modal from '@mui/material/Modal'; +import Button from "@mui/material/Button"; import { useState } from "react"; -import Modal from 'react-modal'; -import { PopUpModal, PopUpStyle } from "../../components/PopUpModal/PopUpModal"; -import LoadingPage from "../../components/LoadingPage/LoadingPage"; - -const style = { - position: 'absolute', - top: '50%', - left: '50%', - transform: 'translate(-50%, -50%)', - width: 400, - bgcolor: 'background.paper', - border: '2px solid #000', - boxShadow: 24, - p: 4, -}; +import Modal from "react-modal"; +import { PopUpModal } from "../../components/PopUpModal/PopUpModal"; +import LoadingPage from "../LoadingPage/LoadingPage"; const TestPage = () => { - const [open, setOpen] = useState(false); - const handleOpen = () => setOpen(true); - const handleClose = () => setOpen(false); const [isModalOpen, setModalOpen] = useState(false); const handleOpenPostModal = () => { @@ -37,16 +14,10 @@ const TestPage = () => { const handleClosePostModal = () => { setModalOpen(false); - }; return (
- {/* - */} - {/* */} - {/* - */} - + { shouldCloseOnOverlayClick={false} > <> - - {/* + + {/* */} - hello this is the goal breakdown - - + hello this is the goal breakdown + +