STUDY BUDDY-Your Study Companion
Tags: rebase01, gdsciiitkalyani
Published: 2024-04-20 16:13:27

## Study Buddy: 

## Team Details:
Team Lead:**Soaham Sur**
Role:Frontend Dev,UI/UX
Devfolio id:SoahamSur
Member:**Samridhi Mukhopadhyay**
Role:Frontend Dev,UI/UX
Devfolio id:samridhi171
Member:**Snehasis Mukhopadhyay**
Role:Frontend
Devfolio id:snehasis356


## Description of Project:

In the era of digital learning, having a reliable study companion can significantly enhance productivity and learning outcomes. The Study Buddy Web-App aims to provide just that, offering a suite of features designed to streamline study sessions and improve organization. In this article, we delve into the frontend features of the app, leveraging popular libraries and techniques within the React ecosystem.

## Submission Track: 
	Open Innovation
## Overview of My Submission:

_**->Why this Project?**_
The inspiration for this project comes from recognizing the common challenges students face in staying focused and productive during study sessions due to distractions in today's digital age. Drawing from the effectiveness of the Pomodoro Technique and the demand for customizable study tools, the proposal aims to offer a solution that addresses these challenges comprehensively. By incorporating features such as task schedular, todolist, , the project seeks to provide students with a tailored study experience that promotes discipline, motivation, and ultimately, academic success.


## Project WorkFlow:

**Pomodoro Timer:** The Pomodoro Timer is a cornerstone feature for enhancing study efficiency through time management. At its core, the timer operates as a countdown mechanism, typically set to 25-minute intervals (Pomodoro sessions), followed by short breaks. The structured approach of the Pomodoro Technique helps users maintain focus by breaking tasks into manageable chunks. By incorporating regular breaks, it promotes sustained concentration and combats mental fatigue, ultimately improving productivity and retention during study sessions.


![Pomodoro Timer](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8ar7i2yd35c1amriiaql.png)
DEMO:

![Pomodoro](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/62pso980n1alfjpxejjp.gif)

**Implementation:** We leverage **React's state management** to handle the timer's state, including the elapsed time, remaining duration, and timer status (running, paused, or stopped). The timer functionality is encapsulated within a React component, allowing for easy integration and reuse across the application. To enrich the user experience, we employ **Framer Motion** for fluid animations, providing visual feedback on timer progression. Additionally, the Npm circular progress bar library enhances visualization, displaying the elapsed time within a circular progress indicator.
**_Check Out the circular progress bar.Isn't it cool?_**
```
const Pomodoro = () => {
  const [workMinutes, setWorkMinutes] = useState(25);
  const [breakMinutes, setBreakMinutes] = useState(5);
  const [minutes, setMinutes] = useState(workMinutes);
  const [seconds, setSeconds] = useState(0);
  const [isActive, setIsActive] = useState(false);
  const [session, setSession] = useState("Work");
  const [progress, setProgress] = useState(100);

  useEffect(() => {
    let interval;

    if (isActive) {
      interval = setInterval(() => {
        if (seconds === 0) {
          if (minutes === 0) {
            new Audio("https://www.soundjay.com/button/beep-07.wav").play();
            if (session === "Work") {
              setSession("Break");
              setMinutes(breakMinutes);
            } else {
              setSession("Work");
              setMinutes(workMinutes);
            }
            setSeconds(0);
            setIsActive(false);
            return;
          } else {
            setMinutes((prev) => prev - 1);
            setSeconds(59);
          }
        } else {
          setSeconds((prev) => prev - 1);
        }

        // Calculate progress
        const totalSeconds =
          session === "Work" ? workMinutes * 60 : breakMinutes * 60;
        const remainingSeconds = minutes * 60 + seconds;
        setProgress((remainingSeconds / totalSeconds) * 100);
      }, 1000);
    } else {
      clearInterval(interval);
    }

    return () => clearInterval(interval);
  }, [isActive, minutes, seconds, session, breakMinutes, workMinutes]);

  const toggleTimer = () => {
    setIsActive(!isActive);
  };

  const resetTimer = () => {
    setMinutes(workMinutes);
    setSeconds(0);
    setIsActive(false);
    setSession("Work");
    setProgress(100);
  };

  const handleWorkChange = (e) => {
    const newWorkMinutes = Math.max(0, parseInt(e.target.value));
    setWorkMinutes(newWorkMinutes);
    if (session === "Work") {
      setMinutes(newWorkMinutes);
      setSeconds(0);
    }
  };

  const handleBreakChange = (e) => {
    const newBreakMinutes = Math.max(0, parseInt(e.target.value));
    setBreakMinutes(newBreakMinutes);
    if (session === "Break") {
      setMinutes(newBreakMinutes);
      setSeconds(0);
    }
  };

  const handleKeyPress = (e) => {
    if (e.key === "Enter") {
      resetTimer();
    }
  };

```


**Flash Cards:** Flashcards serve as a fundamental tool for active learning and retention. With our intuitive flashcard system, users can harness the power of spaced repetition, reinforcing learning through strategically timed reviews. Whether on-the-go or at a desk, our platform empowers learners to efficiently master new concepts and information. Our implementation allows users to **create**, **edit**, and **review** flashcards seamlessly, with support for persistent storage.

![FlashCards](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3ysluggt86rt9egy88cy.png)

![FlashCards](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/87ikjb2omzv287bqa51g.png)

DEMO:

![Demo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/50m7dbei56cv0j3ywyje.gif)

Implementation: Flashcard data is stored locally using **uselocalStorage** hook of react, ensuring that user-created content persists across sessions. React hooks, such as useState and useEffect, manage the flashcard state and lifecycle events. Each flashcard is represented as an object with properties for the question, answer, and additional metadata.  To facilitate user interactions, we utilize React hooks to handle state updates triggered by actions such as card flipping, editing, or deletion. The use of useState ensures reactive rendering, while useEffect enables side effects such as data retrieval or synchronization with external sources.

```
const Flashcards = () => {
  const [questionValue, setQuestionValue] = useState("");
  const [answerValue, setAnswerValue] = useState("");
  const [editMode, setEditMode] = useState(false);
  const [flashcards, setFlashcards] = useLocalStorage('flashcards', []);
  const [showFlashcardForm, setShowFlashcardForm] = useState(false);
  const [currentEditIndex, setCurrentEditIndex] = useState(null);

  const handleAddFlashcard = () => {
    setShowFlashcardForm(true);
    setQuestionValue("");
    setAnswerValue("");
    setEditMode(false); // Ensure edit mode is turned off when adding new flashcard
    setCurrentEditIndex(null); // Reset currentEditIndex
  };

  const handleCloseFlashcard = () => {
    setShowFlashcardForm(false);
    if (editMode) {
      setEditMode(false);
      setCurrentEditIndex(null);
    
    }
  };

  const handleSubmitQuestion = () => {
    const tempQuestion = questionValue.trim();
    const tempAnswer = answerValue.trim();

    if (!tempQuestion || !tempAnswer) {
      alert("Input fields cannot be empty!");
      return;
    }

    if (editMode) {
      const updatedFlashcards = [...flashcards];
      updatedFlashcards[currentEditIndex] = { question: tempQuestion, answer: tempAnswer };
      setFlashcards(updatedFlashcards);
      setEditMode(false);
      setCurrentEditIndex(null);
    } else {
      setFlashcards([...flashcards, { question: tempQuestion, answer: tempAnswer }]);
    }

    setShowFlashcardForm(false);
    setQuestionValue("");
    setAnswerValue("");
  };

  const handleEditFlashcard = (index) => {
    setEditMode(true);
    setCurrentEditIndex(index);
    setQuestionValue(flashcards[index].question);
    setAnswerValue(flashcards[index].answer);
    setShowFlashcardForm(true); // Show form when editing
  };

  const handleModifyElement = (index) => {
    if (!editMode) {
      const updatedFlashcards = [...flashcards];
      updatedFlashcards.splice(index, 1);
      setFlashcards(updatedFlashcards);
    }
  };

  const toggleAnswerVisibility = (index) => {
    const updatedFlashcards = [...flashcards];
    updatedFlashcards[index].showAnswer = !updatedFlashcards[index].showAnswer;
    setFlashcards(updatedFlashcards);
  };
```

**TodoList:**A to-do list is a powerful tool for organizing tasks and priorities, helping you stay focused and productive throughout the day. By jotting down tasks and crossing them off as you complete them, you can track progress and ensure nothing slips through the cracks. Whether on paper or digitally, a to-do list is a simple yet effective way to manage your time and responsibilities.Our implementation allows users to create, edit,check as finished todo and review todos seamlessly, with support for persistent storage.

![Todo List](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b5p290vsd3kw2gtilc61.png)


![Todo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h1ewi63ekeajfg700vk7.gif)

Implementation:. Each todo is assigned a unique identifier using **UUID**, facilitating efficient retrieval and manipulation. React state management handles todo data, while **useEffect** hooks enable asynchronous operations such as data fetching or updates. The use of **UUID** ensures that each task has a unique identifier, preventing conflicts or ambiguities when performing operations such as editing or deleting todos. 
**_Don't miss out our show finished todos feature😉 Get some motivation seeing your completed todos.Cheers!!_**

```
function Todolist() { 

  const [todo, setTodo] = useState("")
  const [todos, setTodos] = useState([])
  const [showFinished, setshowFinished] = useState(true)

  useEffect(() => {
    let todoString = localStorage.getItem("todos")
    if(todoString){
      let todos = JSON.parse(localStorage.getItem("todos")) 
      setTodos(todos)
    }
  }, [])
  

  const saveToLS = () => {
    localStorage.setItem("todos", JSON.stringify(todos))
  }

  const toggleFinished = (e) => {
    setshowFinished(!showFinished)
  }
  
  


  const handleEdit = (e, id)=>{ 
    let t = todos.filter(i=>i.id === id) 
    setTodo(t[0].todo)
    let newTodos = todos.filter(item=>{
      return item.id!==id
    }); 
    setTodos(newTodos) 
    saveToLS()
  }

  const handleDelete= (e, id)=>{  
    let newTodos = todos.filter(item=>{
      return item.id!==id
    }); 
    setTodos(newTodos) 
    saveToLS()
  }

  const handleAdd= ()=>{
    setTodos([...todos, {id: uuidv4(), todo, isCompleted: false}])
    setTodo("") 
    saveToLS()
  }
  
  const handleChange= (e)=>{ 
    setTodo(e.target.value)
  }

  const handleCheckbox = (e) => { 
    let id = e.target.name;  
    let index = todos.findIndex(item=>{
      return item.id === id;
    }) 
    let newTodos = [...todos];
    newTodos[index].isCompleted = !newTodos[index].isCompleted;
    setTodos(newTodos)
    saveToLS()
  }
  

```

Task Schedular:Effective task management is essential for organizing study sessions and tracking progress. The Task Scheduler feature provides users with tools to plan and prioritize their study tasks.

![task](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/046rljfzwq2vh3jdrxen.png)

![task sched](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h4hmtqgxb3g5e1ixzu8c.png)
DEMO:

![demo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dasmt19b0jc1l0bat5n0.gif)

Implementation:This feature is implemented using React js. It utilizes **useState**and **useEffect** hooks for state management and **localStorage** for persisting tasks. The application allows users to add, edit, and delete tasks, each associated with a deadline. **Framer Motion library** is used for animation effects like fadeIn. The UI updates dynamically based on user interactions, offering a seamless task management experience.
**_Don't miss out our special addition to this task schedular.
You can only add and schedule tasks only from the present date and time & not past_**

```
function App() {
  const [tasks, setTasks] = useState([]);
  const [taskInput, setTaskInput] = useState('');
  const [datetimeInput, setDatetimeInput] = useState('');
  const [editIndex, setEditIndex] = useState(null); // Track index of the task being edited
  const [editTaskInput, setEditTaskInput] = useState('');

  useEffect(() => {
    const storedTasks = JSON.parse(localStorage.getItem('tasks')) || [];
    setTasks(storedTasks);
  }, []);

  function getCurrentDateTime() {
    const now = new Date();
    const year = now.getFullYear();
    let month = now.getMonth() + 1;
    if (month < 10) month = '0' + month;
    let day = now.getDate();
    if (day < 10) day = '0' + day;
    let hours = now.getHours();
    if (hours < 10) hours = '0' + hours;
    let minutes = now.getMinutes();
    if (minutes < 10) minutes = '0' + minutes;
    return `${year}-${month}-${day}T${hours}:${minutes}`;
  }

  const addTask = () => {
    if (taskInput.trim() !== '' && datetimeInput !== '') {
      const newTasks = [...tasks, { task: taskInput.trim(), datetime: datetimeInput }];
      setTasks(newTasks);
      localStorage.setItem('tasks', JSON.stringify(newTasks));
      setTaskInput('');
      setDatetimeInput('');
    }
  };

  const deleteTask = (index) => {
    const updatedTasks = tasks.filter((_, i) => i !== index);
    setTasks(updatedTasks);
    localStorage.setItem('tasks', JSON.stringify(updatedTasks));
  };

  const editTask = (index) => {
    setEditIndex(index); // Set index of the task being edited
    setEditTaskInput(tasks[index].task); // Set input field value to the current task text
  };

  const saveEditedTask = (index) => {
    const updatedTasks = [...tasks];
    updatedTasks[index].task = editTaskInput;
    setTasks(updatedTasks);
    localStorage.setItem('tasks', JSON.stringify(updatedTasks));
    setEditIndex(null); // Reset editIndex after saving changes
  };

```


**UI Elements: **A visually appealing and intuitive user interface is paramount for enhancing user engagement and usability.


![ui](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uo0pkuyfo2ib60amhcs5.png)

Implementation: We incorporate **open-source UI** elements to maintain consistency and improve aesthetics across the application. **React Icons** provides a diverse library of icons for various actions and categories, enhancing visual hierarchy and navigation. Custom CSS styles ensure a cohesive and visually pleasing layout. Leveraging React Icons simplifies the integration of iconography within the application, reducing development time and ensuring a consistent design language. Custom CSS styles allow for fine-grained control over the appearance and layout of UI elements, enhancing the overall user experience.

**Cross-Page Navigation:** Seamless navigation between different sections of the application enhances user flow and accessibility. Streamlined pathways ensure users can navigate between tasks and information effortlessly, maintaining focus and enhancing overall user experience.
Implementation: We utilize **React Router DOM** to manage routing and navigation, defining routes for each page or section of the application. This enables users to navigate between the Pomodoro Timer, Flash Cards, Task Scheduler, and To-Do Lists effortlessly, with support for bookmarking and sharing specific sections. React Router DOM provides a declarative approach to handling routing and navigation within a React application, simplifying the implementation of complex navigation flows. By defining routes as components, we ensure that each page is encapsulated and can be easily integrated or modified.

**Responsive:** Our web application is responsive for all devices.

![responsive](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d4e3baobbk5ganabs9xq.png)


## Tech Stack:
The tech stack behind this project primarily revolves around **React.js**. React.js is a JavaScript library for building user interfaces, offering reusable components and a declarative approach to building UIs. Additionally, **Framer Motion library** is employed for animation effects, enhancing the user experience by providing smooth and engaging transitions. The use of React.js enables efficient **state management** through useState and useEffect hooks, facilitating **dynamic updates** and interactions within the application.

**Repository:** https://github.com/SoahamSur/Study-Buddy
**Deploy Link:** https://study-buddy-nine.vercel.app
**Demo:** https://youtu.be/x_xcylj6hLc

In conclusion, the frontend development of the Study Buddy involves a careful balance of functionality, usability, and aesthetics. By leveraging powerful capabilities of frontend technologies and integrating various libraries and techniques, we create a comprehensive study companion that empowers users to optimize their learning experience effectively. From the Pomodoro Timer for time management to Flash Cards for active recall and Task Scheduler for organization, each feature is meticulously designed to enhance productivity and facilitate learning. With a user-friendly interface and robust functionality, the Study Buddy Web App is poised to become an invaluable tool for students seeking to excel in their studies.