├── .eslintrc.cjs ├── .github └── ISSUE_TEMPLATE │ └── user-stories.md ├── .gitignore ├── README.md ├── dist ├── assets │ ├── index-DVPIv-rT.css │ └── index-DaMzb0gm.js ├── index.html └── vite.svg ├── index.html ├── package-lock.json ├── package.json ├── public ├── logo.png └── vite.svg ├── readme-assets ├── am-i-responsive.png ├── c1a.png ├── c1b.png ├── c2a.png ├── c2b.png ├── c2c.png ├── d1.png ├── d2.png ├── d3.png ├── s1.png ├── s2.png ├── s3.png ├── test.png ├── wireframe-addtask.jpg ├── wireframe-dashboard.jpg ├── wireframe-edittask.jpg ├── wireframe-home.jpg └── wireframe-viewtask.jpg ├── src ├── App.css ├── App.jsx ├── CONSTANT.jsx ├── assets │ ├── icons │ │ └── FilterIcon.jsx │ └── react.svg ├── auth │ ├── Login.jsx │ └── Register.jsx ├── components │ ├── Footer.jsx │ ├── Header.jsx │ └── TakeMeToAdmin.jsx ├── contexts │ └── UserData.jsx ├── index.css ├── layout │ └── Layout.jsx ├── main.jsx └── views │ ├── AddNewTask.jsx │ ├── Dashboard.jsx │ ├── EditTask.jsx │ ├── Home.jsx │ ├── NotFound.jsx │ ├── Profile.jsx │ └── ViewTask.jsx ├── static.json └── vite.config.js /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { browser: true, es2020: true }, 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:react/recommended', 7 | 'plugin:react/jsx-runtime', 8 | 'plugin:react-hooks/recommended', 9 | ], 10 | ignorePatterns: ['dist', '.eslintrc.cjs'], 11 | parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }, 12 | settings: { react: { version: '18.2' } }, 13 | plugins: ['react-refresh'], 14 | rules: { 15 | 'react/jsx-no-target-blank': 'off', 16 | 'react-refresh/only-export-components': [ 17 | 'warn', 18 | { allowConstantExport: true }, 19 | ], 20 | }, 21 | } 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/user-stories.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: User Stories 3 | about: User stories template 4 | title: '' 5 | labels: Important 6 | assignees: Bashmdz 7 | 8 | --- 9 | 10 | As a **role** I can **capability** so that **received benefit** 11 | 12 | - Acceptance criteria 1 13 | 14 | - Acceptance criteria 2 15 | 16 | - Acceptance criteria 3 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist-ssr 12 | *.local 13 | 14 | # Editor directories and files 15 | .vscode/* 16 | !.vscode/extensions.json 17 | .idea 18 | .DS_Store 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | backup 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CalenTask 2 | 3 | ![CalenTask-responsiveness](readme-assets/am-i-responsive.png) 4 | 5 | ## Table of Contents 6 | 7 | - [Introduction and Project Goals](#introduction-and-project-goals) 8 | - [Wireframes](#wireframes) 9 | - [Features](#features) 10 | - [Technologies Used](#technologies-used) 11 | - [Color Schemes](#color-schemes) 12 | - [Fonts](#fonts) 13 | - [React Components](#react-components) 14 | - [Installation](#installation) 15 | - [Configuration](#configuration) 16 | - [Usage](#usage) 17 | - [Acknowledgments](#acknowledgments) 18 | - [Testing](#testing) 19 | - [Test Cases](#test-cases) 20 | - [Pages](#pages) 21 | - [Deployment](#deployment) 22 | - [CONSTANT.js](#constantjs) 23 | - [Future Functionalities](#future-functionalities) 24 | - [Logs](#logs) 25 | - [Enhancing User Experience with React](#enhancing-user-experience-with-react) 26 | 27 | ## Introduction and Project Goals 28 | 29 | CalenTask is a Task Management System designed to help users organize and track their tasks efficiently. It allows users to register, create tasks, assign them to other users, and monitor their progress through an intuitive calendar interface. 30 | 31 | ## Wireframes 32 | 33 | ### Home 34 | 35 | ![Home Wireframe](readme-assets/wireframe-home.jpg)
36 | Short description: Wireframe for the home page of CalenTask. 37 | 38 | ### Dashboard 39 | 40 | ![Dashboard Wireframe](readme-assets/wireframe-dashboard.jpg)
41 | Short description: Wireframe for the dashboard page of CalenTask, displaying a calendar view of tasks. 42 | 43 | ### Add New Task 44 | 45 | ![Add New Task Wireframe](readme-assets/wireframe-addtask.jpg)
46 | Short description: Wireframe for the add new task page of CalenTask, allowing users to create a new task. 47 | 48 | ### Edit Task 49 | 50 | ![Edit Task Wireframe](readme-assets/wireframe-edittask.jpg)
51 | Short description: Wireframe for the edit task page of CalenTask, enabling users to modify task details. 52 | 53 | ### View Task 54 | 55 | ![View Task Wireframe](readme-assets/wireframe-viewtask.jpg)
56 | Short description: Wireframe for the view task page of CalenTask, displaying detailed information about a task. 57 | 58 | ## Features 59 | 60 | - **Task Management**: Create, edit, and delete tasks with ease. 61 | - **Priority Levels**: Assign priority levels to tasks (Important, Medium, Low). 62 | - **Categorization**: Categorize tasks for better organization. 63 | - **Progress Tracking**: Monitor task progress (Open, In Progress, Done) at a glance. 64 | - **Date Management**: Set start and end dates for tasks. 65 | - **Attachments**: Attach files to tasks for additional context or reference. 66 | - **Calendar View**: View tasks on a calendar, with options for daily, weekly, monthly, and agenda views. 67 | - **User Assignment**: Assign tasks to other users for collaboration. 68 | 69 | ## Technologies Used 70 | 71 | - **Backend**: Django (Python) 72 | 73 | - Reason: Django is a powerful and popular web framework that provides a robust backend infrastructure for building scalable and secure applications. 74 | 75 | - **Frontend**: Bootstrap (HTML/CSS/JS), React (JavaScript) 76 | 77 | - Reason: Bootstrap is a widely-used CSS framework that offers a responsive and mobile-first design. React is a JavaScript library for building user interfaces, providing a component-based approach and efficient rendering. 78 | 79 | - **Calendar Component**: [react-big-calendar](https://www.npmjs.com/package/react-big-calendar) 80 | 81 | - Reason: react-big-calendar is a feature-rich and customizable calendar component for React, which provides the necessary functionality for displaying and managing tasks in a calendar format. 82 | 83 | - **Testing**: Placeholder for testing section 84 | - Reason: Testing is an essential part of software development to ensure the reliability and correctness of the application. Placeholder is used to indicate that the testing section is yet to be implemented. 85 | 86 | ## Color Schemes 87 | 88 | The color schemes used in CalenTask are well thought out and contribute to a visually appealing user interface. The following color scheme is used: 89 | 90 | - Body Text: #000000b3 91 | 92 | In addition, the priority levels of tasks are visually represented using different background colors: 93 | 94 | - Important: Red background with white text 95 | - Medium: Yellow background with black text 96 | - Low: Green background with white text 97 | 98 | This color scheme effectively communicates the importance of tasks and helps users quickly identify their priority levels. 99 | 100 | ## Fonts 101 | 102 | CalenTask utilizes the Roboto font, which is loaded using the Google Fonts API. The Roboto font is a popular choice for its clean and modern appearance, making it highly readable and suitable for both headings and body text. By using the Google Fonts API, the font is loaded efficiently and ensures consistent typography across different devices and browsers. 103 | 104 | The combination of the Roboto font and the chosen color scheme creates a visually pleasing and user-friendly interface in CalenTask. 105 | 106 | ## React Components 107 | 108 | ### Reusable 109 | 110 | 1. **Footer**: A reusable component that displays the footer section of the application. 111 | 112 | 2. **Header**: A reusable component that displays the header section of the application. 113 | 114 | ### Auth 115 | 116 | 1. **Login**: A component that handles the login functionality, allowing users to authenticate and access their accounts. 117 | 118 | 2. **Register**: A component that handles the registration functionality, allowing new users to create an account. 119 | 120 | ### Contexts 121 | 122 | 1. **UserData**: A context component that holds user personal information and the isLoggedIn session information. 123 | 124 | ### Layouts 125 | 126 | 1. **Layout**: A layout component that provides a consistent structure for rendering views. 127 | 128 | ### Views 129 | 130 | 1. **Home**: A view component that serves as the landing page for the application. 131 | 132 | 2. **Dashboard**: A view component that allows users to search for and view tasks in a calendar format. 133 | 134 | 3. **AddNewTask**: A view component that enables users to create a new task by providing relevant details. 135 | 136 | 4. **ViewTasks**: A view component that displays detailed information about a specific task and provides options to update or delete it. 137 | 138 | 5. **EditTask**: A view component that allows users to modify the details of an existing task. 139 | 140 | 6. **Profile**: A view component that allows users to view and edit their personal information. 141 | 142 | 7. **NotFound**: A view component that is displayed when a requested page is not found. 143 | 144 | ## Installation 145 | 146 | 1. Clone the repository. 147 | 2. Before running the project, go to `CONSTANT.js` and update the URLs in the `CONSTANT` object. 148 | 3. Install backend dependencies using `pip install -r requirements.txt`. 149 | 4. Install frontend dependencies using `npm install`. 150 | 5. Start the development server for the backend using `python manage.py runserver`. 151 | 6. Start the development server for the frontend using `npm start`. 152 | 153 | ## Configuration 154 | 155 | - Configure the database settings in `settings.py` according to your environment (e.g., PostgreSQL, MySQL). 156 | - Customize frontend UI components in the `src/components` directory. 157 | - Configure user authentication and permissions as needed. 158 | 159 | ## Usage 160 | 161 | 1. Register or login to your CalenTask account. 162 | 2. Create tasks by filling in the required fields and selecting options such as priority, category, and dates. 163 | 3. Assign tasks to other users if necessary. 164 | 4. View tasks on the calendar dashboard and navigate between different views (daily, weekly, monthly, agenda). 165 | 5. Click on a task to view more details or to edit/delete it (only available to the task owner). 166 | 6. Monitor task progress and update as necessary. 167 | 168 | ## Acknowledgments 169 | 170 | - Inspiration from wireframes and Bootstrap UI. 171 | - React Big Calendar npm package for calendar functionality. 172 | - Copilot for code suggestions and inspiration. 173 | 174 | ## Testing 175 | 176 | ### Lighthouse Testing 177 | 178 | ![Lighthouse Testing](readme-assets/test.png) 179 | 180 | - Description: Lighthouse is an open-source tool for auditing and improving the quality of web pages. It measures performance, accessibility, best practices, and SEO of a web application. The screenshot above shows the results of Lighthouse testing for CalenTask. 181 | 182 | ### Manual Testing 183 | 184 | - ![Calendar View](readme-assets/s1.png) _Calendar View showing tasks for the month._ 185 | 186 | - ![Task Details](readme-assets/s2.png) _Task Details page displaying task information._ 187 | 188 | - ![Edit Task](readme-assets/s3.png) _Edit Task page allowing users to modify task details._ 189 | 190 | ## Test Cases 191 | 192 | ### Case 1: _User Registration_ 193 | 194 | ![Registration Page](readme-assets/c1a.png) 195 | ![Dashboard Page](readme-assets/c1b.png) 196 | 197 | ### Steps: 198 | 199 | - _Click 'Add New Task'_ 200 | - _Fill task title, end-date, description_ 201 | - _Select priority, category, progress, additional users_ 202 | - _Click 'Add'_ 203 | 204 | ### Expected Output: 205 | 206 | _Task is created successfully and redirected to homepage._ 207 | 208 | ### Actual Results: 209 | 210 | _Task is created successfully and redirected to homepage._ 211 | 212 | ### Case 2: _Creation of Task_ 213 | 214 | ![Add New Task Page](readme-assets/c2a.png) 215 | ![Add New Task Page](readme-assets/c2b.png) 216 | ![Dashboard Page](readme-assets/c2c.png) 217 | 218 | ### Steps: 219 | 220 | - _Click register_ 221 | - _Fill name, email, password_ 222 | - _Click 'Register'_ 223 | 224 | ### Expected Output: 225 | 226 | _Account is created successfully and redirected to homepage._ 227 | 228 | ### Actual Results: 229 | 230 | _Account is created successfully and redirected to homepage._ 231 | 232 | ## Pages 233 | 234 | ### Home Page 235 | 236 | - Screenshot: ![Home Page](readme-assets/d1.png) 237 | - Description: The Home page serves as the landing page for CalenTask. It provides an overview of the application and may include login/register options. 238 | 239 | ### Dashboard Page 240 | 241 | - Screenshot: ![Dashboard Page](readme-assets/s1.png) 242 | - Description: The Dashboard page displays a calendar view of tasks, allowing users to visualize their tasks over different time periods (daily, weekly, monthly). 243 | 244 | ### Profile Page 245 | 246 | - Screenshot: ![Profile Page](readme-assets/d2.png) 247 | - Description: The Profile page allows users to view and edit their personal information, such as username, email, and profile picture. 248 | 249 | ### Add New Task Page 250 | 251 | - Screenshot: ![Add New Task Page](readme-assets/d3.png) 252 | - Description: The Add New Task page enables users to create a new task by providing details such as title, priority, category, start/end dates, and attachments. 253 | 254 | ### Edit Task Page 255 | 256 | - Screenshot: ![Edit Task Page](readme-assets/s3.png) 257 | - Description: The Edit Task page allows users to modify the details of an existing task, including title, priority, category, dates, and attachments. 258 | 259 | ### View Task Page 260 | 261 | - Screenshot: ![View Task Page](readme-assets/s2.png) 262 | - Description: The View Task page displays detailed information about a specific task, including its title, description, priority, category, dates, and attachments. 263 | 264 | ## Deployment 265 | 266 | CalenTask is deployed on Heroku using Node.js. As React has static files, the "serve" package is used. 267 | 268 | 1. Create a Heroku account and install the Heroku CLI. 269 | 2. Initialize a Git repository in your CalenTask project folder (`git init`). 270 | 3. Log in to Heroku CLI (`heroku login`) and create a new Heroku app (`heroku create`). 271 | 4. Set up Heroku PostgreSQL as the database (`heroku addons:create heroku-postgresql`). 272 | 5. Push your code to the Heroku remote (`git push heroku master`). 273 | 6. Run migrations and set up the database (`heroku run python manage.py migrate`). 274 | 7. Install the "serve" package (`npm install serve`). 275 | 8. Add a start script to your `package.json` file: `"start": "serve -s build"`. 276 | 9. Build your React app (`npm run build`). 277 | 10. Deploy your app to Heroku (`git push heroku master`). 278 | 11. Your CalenTask application should now be deployed and accessible via the provided Heroku app URL. 279 | 12. Your app should now be deployed and accessible via the provided Heroku URL. 280 | 281 | ## Future Functionalities 282 | 283 | ### Logs 284 | 285 | In the current implementation, the system saves logs for the creation, updation, and deletion of tasks. However, there is no interaction functionality for users to view these logs or receive notifications. 286 | 287 | A future functionality to be added is the ability for users to interact with the logs. This can include features such as: 288 | 289 | - Viewing a log history for each task, displaying the date and time of each action. 290 | - Notifying users when a task they are assigned to has been modified or deleted. 291 | - Providing a notification center where users can view all their notifications. 292 | 293 | Implementing these functionalities will enhance the user experience and improve the overall usability of the CalenTask Task Management System. 294 | 295 | ## Enhancing User Experience with React 296 | 297 | ### 1. Improved Performance 298 | 299 | By leveraging React's virtual DOM, our application achieves remarkable performance enhancements. React efficiently updates only the components that have changed, resulting in faster rendering times and a smoother user interface experience. Users will notice a significant reduction in page load times, especially when interacting with dynamic content. 300 | 301 | ### 2. Enhanced Interactivity 302 | 303 | React's component-based architecture facilitates the creation of highly interactive user interfaces. Through the use of reusable components, we've implemented seamless navigation, intuitive user interactions, and dynamic data updates. This enhances user engagement and provides a more enjoyable experience while navigating through our application. 304 | 305 | ### 3. Responsive Design 306 | 307 | With React's responsive design capabilities, our application adapts seamlessly to various screen sizes and devices. Whether users access the application on desktops, tablets, or mobile devices, they'll experience consistent functionality and visual appeal. This ensures optimal usability and accessibility across different platforms, contributing to an improved overall user experience. 308 | 309 | ### 4. Streamlined Development Workflow 310 | 311 | The declarative nature of React simplifies the development process, allowing us to focus more on building features and less on managing state and DOM manipulation. This streamlined workflow results in faster iterations, quicker bug fixes, and ultimately, a more polished end product. Users benefit from a more stable and reliable application, leading to increased satisfaction and retention. 312 | 313 | ### Conclusion 314 | 315 | In conclusion, the integration of React has been instrumental in enhancing the user experience within our application. From improved performance and enhanced interactivity to responsive design and streamlined development, React's features have contributed to a more engaging, efficient, and user-friendly experience for our audience. 316 | 317 | Thank you for exploring our project documentation. We hope you enjoy using our application! 318 | -------------------------------------------------------------------------------- /dist/assets/index-DVPIv-rT.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8";.App{width:100%;min-height:100vh;display:flex;justify-items:center;justify-content:space-between;flex-direction:column}.rbc-btn{color:inherit;font:inherit;margin:0}button.rbc-btn{overflow:visible;text-transform:none;-webkit-appearance:button;cursor:pointer}button[disabled].rbc-btn{cursor:not-allowed}button.rbc-input::-moz-focus-inner{border:0;padding:0}.rbc-calendar{-webkit-box-sizing:border-box;box-sizing:border-box;height:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch}.rbc-calendar *,.rbc-calendar *:before,.rbc-calendar *:after{-webkit-box-sizing:inherit;box-sizing:inherit}.rbc-abs-full,.rbc-row-bg{overflow:hidden;position:absolute;top:0;left:0;right:0;bottom:0}.rbc-ellipsis,.rbc-show-more,.rbc-row-segment .rbc-event-content,.rbc-event-label{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rbc-rtl{direction:rtl}.rbc-off-range{color:#999}.rbc-off-range-bg{background:#e6e6e6}.rbc-header{overflow:hidden;-webkit-box-flex:1;-ms-flex:1 0 0%;flex:1 0 0%;text-overflow:ellipsis;white-space:nowrap;padding:0 3px;text-align:center;vertical-align:middle;font-weight:700;font-size:90%;min-height:0;border-bottom:1px solid #ddd}.rbc-header+.rbc-header{border-left:1px solid #ddd}.rbc-rtl .rbc-header+.rbc-header{border-left-width:0;border-right:1px solid #ddd}.rbc-header>a,.rbc-header>a:active,.rbc-header>a:visited{color:inherit;text-decoration:none}.rbc-button-link{color:inherit;background:none;margin:0;padding:0;border:none;cursor:pointer;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text}.rbc-row-content{position:relative;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-user-select:none;z-index:4}.rbc-row-content-scrollable{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;height:100%}.rbc-row-content-scrollable .rbc-row-content-scroll-container{height:100%;overflow-y:scroll;-ms-overflow-style:none;scrollbar-width:none}.rbc-row-content-scrollable .rbc-row-content-scroll-container::-webkit-scrollbar{display:none}.rbc-today{background-color:#eaf6ff}.rbc-toolbar{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin-bottom:10px;font-size:16px}.rbc-toolbar .rbc-toolbar-label{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;padding:0 10px;text-align:center}.rbc-toolbar button{color:#373a3c;display:inline-block;margin:0;text-align:center;vertical-align:middle;background:none;background-image:none;border:1px solid #ccc;padding:.375rem 1rem;border-radius:4px;line-height:normal;white-space:nowrap}.rbc-toolbar button:active,.rbc-toolbar button.rbc-active{background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px #00000020;background-color:#e6e6e6;border-color:#adadad}.rbc-toolbar button:active:hover,.rbc-toolbar button:active:focus,.rbc-toolbar button.rbc-active:hover,.rbc-toolbar button.rbc-active:focus{color:#373a3c;background-color:#d4d4d4;border-color:#8c8c8c}.rbc-toolbar button:focus{color:#373a3c;background-color:#e6e6e6;border-color:#adadad}.rbc-toolbar button:hover{color:#373a3c;background-color:#e6e6e6;border-color:#adadad}.rbc-btn-group{display:inline-block;white-space:nowrap}.rbc-btn-group>button:first-child:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.rbc-btn-group>button:last-child:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.rbc-rtl .rbc-btn-group>button:first-child:not(:last-child){border-radius:0 4px 4px 0}.rbc-rtl .rbc-btn-group>button:last-child:not(:first-child){border-radius:4px 0 0 4px}.rbc-btn-group>button:not(:first-child):not(:last-child){border-radius:0}.rbc-btn-group button+button{margin-left:-1px}.rbc-rtl .rbc-btn-group button+button{margin-left:0;margin-right:-1px}.rbc-btn-group+.rbc-btn-group,.rbc-btn-group+button{margin-left:10px}@media (max-width: 767px){.rbc-toolbar{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}}.rbc-event,.rbc-day-slot .rbc-background-event{border:none;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-box-shadow:none;box-shadow:none;margin:0;padding:2px 5px;background-color:#3174ad;border-radius:5px;color:#fff;cursor:pointer;width:100%;text-align:left}.rbc-slot-selecting .rbc-event,.rbc-slot-selecting .rbc-day-slot .rbc-background-event,.rbc-day-slot .rbc-slot-selecting .rbc-background-event{cursor:inherit;pointer-events:none}.rbc-event.rbc-selected,.rbc-day-slot .rbc-selected.rbc-background-event{background-color:#265985}.rbc-event:focus,.rbc-day-slot .rbc-background-event:focus{outline:5px auto #3b99fc}.rbc-event-label{font-size:80%}.rbc-event-overlaps{-webkit-box-shadow:-1px 1px 5px 0px rgba(51,51,51,.5);box-shadow:-1px 1px 5px #33333380}.rbc-event-continues-prior{border-top-left-radius:0;border-bottom-left-radius:0}.rbc-event-continues-after{border-top-right-radius:0;border-bottom-right-radius:0}.rbc-event-continues-earlier{border-top-left-radius:0;border-top-right-radius:0}.rbc-event-continues-later{border-bottom-left-radius:0;border-bottom-right-radius:0}.rbc-row{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.rbc-row-segment{padding:0 1px 1px}.rbc-selected-cell{background-color:#0000001a}.rbc-show-more{background-color:#ffffff4d;z-index:4;font-weight:700;font-size:85%;height:auto;line-height:normal;color:#3174ad}.rbc-show-more:hover,.rbc-show-more:focus{color:#265985}.rbc-month-view{position:relative;border:1px solid #ddd;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-flex:1;-ms-flex:1 0 0px;flex:1 0 0;width:100%;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-user-select:none;height:100%}.rbc-month-header{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.rbc-month-row{display:-webkit-box;display:-ms-flexbox;display:flex;position:relative;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-flex:1;-ms-flex:1 0 0px;flex:1 0 0;-ms-flex-preferred-size:0px;flex-basis:0px;overflow:hidden;height:100%}.rbc-month-row+.rbc-month-row{border-top:1px solid #ddd}.rbc-date-cell{-webkit-box-flex:1;-ms-flex:1 1 0px;flex:1 1 0;min-width:0;padding-right:5px;text-align:right}.rbc-date-cell.rbc-now{font-weight:700}.rbc-date-cell>a,.rbc-date-cell>a:active,.rbc-date-cell>a:visited{color:inherit;text-decoration:none}.rbc-row-bg{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-flex:1;-ms-flex:1 0 0px;flex:1 0 0;overflow:hidden}.rbc-day-bg{-webkit-box-flex:1;-ms-flex:1 0 0%;flex:1 0 0%}.rbc-day-bg+.rbc-day-bg{border-left:1px solid #ddd}.rbc-rtl .rbc-day-bg+.rbc-day-bg{border-left-width:0;border-right:1px solid #ddd}.rbc-overlay{position:absolute;z-index:5;border:1px solid #e5e5e5;background-color:#fff;-webkit-box-shadow:0 5px 15px rgba(0,0,0,.25);box-shadow:0 5px 15px #00000040;padding:10px}.rbc-overlay>*+*{margin-top:1px}.rbc-overlay-header{border-bottom:1px solid #e5e5e5;margin:-10px -10px 5px;padding:2px 10px}.rbc-agenda-view{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-flex:1;-ms-flex:1 0 0px;flex:1 0 0;overflow:auto}.rbc-agenda-view table.rbc-agenda-table{width:100%;border:1px solid #ddd;border-spacing:0;border-collapse:collapse}.rbc-agenda-view table.rbc-agenda-table tbody>tr>td{padding:5px 10px;vertical-align:top}.rbc-agenda-view table.rbc-agenda-table .rbc-agenda-time-cell{padding-left:15px;padding-right:15px;text-transform:lowercase}.rbc-agenda-view table.rbc-agenda-table tbody>tr>td+td{border-left:1px solid #ddd}.rbc-rtl .rbc-agenda-view table.rbc-agenda-table tbody>tr>td+td{border-left-width:0;border-right:1px solid #ddd}.rbc-agenda-view table.rbc-agenda-table tbody>tr+tr{border-top:1px solid #ddd}.rbc-agenda-view table.rbc-agenda-table thead>tr>th{padding:3px 5px;text-align:left;border-bottom:1px solid #ddd}.rbc-rtl .rbc-agenda-view table.rbc-agenda-table thead>tr>th{text-align:right}.rbc-agenda-time-cell{text-transform:lowercase}.rbc-agenda-time-cell .rbc-continues-after:after{content:" »"}.rbc-agenda-time-cell .rbc-continues-prior:before{content:"« "}.rbc-agenda-date-cell,.rbc-agenda-time-cell{white-space:nowrap}.rbc-agenda-event-cell{width:100%}.rbc-time-column{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;min-height:100%}.rbc-time-column .rbc-timeslot-group{-webkit-box-flex:1;-ms-flex:1;flex:1}.rbc-timeslot-group{border-bottom:1px solid #ddd;min-height:40px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-flow:column nowrap;flex-flow:column nowrap}.rbc-time-gutter,.rbc-header-gutter{-webkit-box-flex:0;-ms-flex:none;flex:none}.rbc-label{padding:0 5px}.rbc-day-slot{position:relative}.rbc-day-slot .rbc-events-container{bottom:0;left:0;position:absolute;right:0;margin-right:10px;top:0}.rbc-day-slot .rbc-events-container.rbc-rtl{left:10px;right:0}.rbc-day-slot .rbc-event,.rbc-day-slot .rbc-background-event{border:1px solid #265985;display:-webkit-box;display:-ms-flexbox;display:flex;max-height:100%;min-height:20px;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-flow:column wrap;flex-flow:column wrap;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;overflow:hidden;position:absolute}.rbc-day-slot .rbc-background-event{opacity:.75}.rbc-day-slot .rbc-event-label{-webkit-box-flex:0;-ms-flex:none;flex:none;padding-right:5px;width:auto}.rbc-day-slot .rbc-event-content{width:100%;-webkit-box-flex:1;-ms-flex:1 1 0px;flex:1 1 0;word-wrap:break-word;line-height:1;height:100%;min-height:1em}.rbc-day-slot .rbc-time-slot{border-top:1px solid #f7f7f7}.rbc-time-view-resources .rbc-time-gutter,.rbc-time-view-resources .rbc-time-header-gutter{position:sticky;left:0;background-color:#fff;border-right:1px solid #ddd;z-index:10;margin-right:-1px}.rbc-time-view-resources .rbc-time-header{overflow:hidden}.rbc-time-view-resources .rbc-time-header-content{min-width:auto;-webkit-box-flex:1;-ms-flex:1 0 0px;flex:1 0 0;-ms-flex-preferred-size:0px;flex-basis:0px}.rbc-time-view-resources .rbc-time-header-cell-single-day{display:none}.rbc-time-view-resources .rbc-day-slot{min-width:140px}.rbc-time-view-resources .rbc-header,.rbc-time-view-resources .rbc-day-bg{width:140px;-webkit-box-flex:1;-ms-flex:1 1 0px;flex:1 1 0;-ms-flex-preferred-size:0 px;flex-basis:0 px}.rbc-time-header-content+.rbc-time-header-content{margin-left:-1px}.rbc-time-slot{-webkit-box-flex:1;-ms-flex:1 0 0px;flex:1 0 0}.rbc-time-slot.rbc-now{font-weight:700}.rbc-day-header{text-align:center}.rbc-slot-selection{z-index:10;position:absolute;background-color:#00000080;color:#fff;font-size:75%;width:100%;padding:3px}.rbc-slot-selecting{cursor:move}.rbc-time-view{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-flex:1;-ms-flex:1;flex:1;width:100%;border:1px solid #ddd;min-height:0}.rbc-time-view .rbc-time-gutter{white-space:nowrap;text-align:right}.rbc-time-view .rbc-allday-cell{-webkit-box-sizing:content-box;box-sizing:content-box;width:100%;height:100%;position:relative}.rbc-time-view .rbc-allday-cell+.rbc-allday-cell{border-left:1px solid #ddd}.rbc-time-view .rbc-allday-events{position:relative;z-index:4}.rbc-time-view .rbc-row{-webkit-box-sizing:border-box;box-sizing:border-box;min-height:20px}.rbc-time-header{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.rbc-time-header.rbc-overflowing{border-right:1px solid #ddd}.rbc-rtl .rbc-time-header.rbc-overflowing{border-right-width:0;border-left:1px solid #ddd}.rbc-time-header>.rbc-row:first-child{border-bottom:1px solid #ddd}.rbc-time-header>.rbc-row.rbc-row-resource{border-bottom:1px solid #ddd}.rbc-time-header-cell-single-day{display:none}.rbc-time-header-content{-webkit-box-flex:1;-ms-flex:1;flex:1;display:-webkit-box;display:-ms-flexbox;display:flex;min-width:0;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;border-left:1px solid #ddd}.rbc-rtl .rbc-time-header-content{border-left-width:0;border-right:1px solid #ddd}.rbc-time-header-content>.rbc-row.rbc-row-resource{border-bottom:1px solid #ddd;-ms-flex-negative:0;flex-shrink:0}.rbc-time-content{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex:1 0 0%;flex:1 0 0%;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;width:100%;border-top:2px solid #ddd;overflow-y:auto;position:relative}.rbc-time-content>.rbc-time-gutter{-webkit-box-flex:0;-ms-flex:none;flex:none}.rbc-time-content>*+*>*{border-left:1px solid #ddd}.rbc-rtl .rbc-time-content>*+*>*{border-left-width:0;border-right:1px solid #ddd}.rbc-time-content>.rbc-day-slot{width:100%;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-user-select:none}.rbc-current-time-indicator{position:absolute;z-index:3;left:0;right:0;height:1px;background-color:#74ad31;pointer-events:none}body{min-height:100vh} 2 | -------------------------------------------------------------------------------- /dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Calendar App 8 | 9 | 10 | 11 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /dist/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | CalenTask 8 | 9 | 10 | 11 | 17 | 18 | 19 |
20 | 21 | 22 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "calendar", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "start": "serve -s dist", 10 | "heroku-postbuild": "npm run build", 11 | "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", 12 | "preview": "vite preview" 13 | }, 14 | "dependencies": { 15 | "axios": "^1.6.7", 16 | "bootstrap": "^5.3.2", 17 | "moment": "^2.30.1", 18 | "react": "^18.2.0", 19 | "react-big-calendar": "^1.10.0", 20 | "react-bootstrap": "^2.10.1", 21 | "react-dom": "^18.2.0", 22 | "react-router-dom": "^6.22.0", 23 | "react-select": "^5.8.0", 24 | "serve": "^14.2.1" 25 | }, 26 | "devDependencies": { 27 | "@types/react": "^18.2.55", 28 | "@types/react-dom": "^18.2.19", 29 | "@vitejs/plugin-react-swc": "^3.5.0", 30 | "eslint": "^8.56.0", 31 | "eslint-plugin-react": "^7.33.2", 32 | "eslint-plugin-react-hooks": "^4.6.0", 33 | "eslint-plugin-react-refresh": "^0.4.5", 34 | "vite": "^5.1.0" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bashmdz/calendar-frontend/643fc56929d32cc9146bb997f54df1e680c15394/public/logo.png -------------------------------------------------------------------------------- /public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /readme-assets/am-i-responsive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bashmdz/calendar-frontend/643fc56929d32cc9146bb997f54df1e680c15394/readme-assets/am-i-responsive.png -------------------------------------------------------------------------------- /readme-assets/c1a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bashmdz/calendar-frontend/643fc56929d32cc9146bb997f54df1e680c15394/readme-assets/c1a.png -------------------------------------------------------------------------------- /readme-assets/c1b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bashmdz/calendar-frontend/643fc56929d32cc9146bb997f54df1e680c15394/readme-assets/c1b.png -------------------------------------------------------------------------------- /readme-assets/c2a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bashmdz/calendar-frontend/643fc56929d32cc9146bb997f54df1e680c15394/readme-assets/c2a.png -------------------------------------------------------------------------------- /readme-assets/c2b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bashmdz/calendar-frontend/643fc56929d32cc9146bb997f54df1e680c15394/readme-assets/c2b.png -------------------------------------------------------------------------------- /readme-assets/c2c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bashmdz/calendar-frontend/643fc56929d32cc9146bb997f54df1e680c15394/readme-assets/c2c.png -------------------------------------------------------------------------------- /readme-assets/d1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bashmdz/calendar-frontend/643fc56929d32cc9146bb997f54df1e680c15394/readme-assets/d1.png -------------------------------------------------------------------------------- /readme-assets/d2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bashmdz/calendar-frontend/643fc56929d32cc9146bb997f54df1e680c15394/readme-assets/d2.png -------------------------------------------------------------------------------- /readme-assets/d3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bashmdz/calendar-frontend/643fc56929d32cc9146bb997f54df1e680c15394/readme-assets/d3.png -------------------------------------------------------------------------------- /readme-assets/s1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bashmdz/calendar-frontend/643fc56929d32cc9146bb997f54df1e680c15394/readme-assets/s1.png -------------------------------------------------------------------------------- /readme-assets/s2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bashmdz/calendar-frontend/643fc56929d32cc9146bb997f54df1e680c15394/readme-assets/s2.png -------------------------------------------------------------------------------- /readme-assets/s3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bashmdz/calendar-frontend/643fc56929d32cc9146bb997f54df1e680c15394/readme-assets/s3.png -------------------------------------------------------------------------------- /readme-assets/test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bashmdz/calendar-frontend/643fc56929d32cc9146bb997f54df1e680c15394/readme-assets/test.png -------------------------------------------------------------------------------- /readme-assets/wireframe-addtask.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bashmdz/calendar-frontend/643fc56929d32cc9146bb997f54df1e680c15394/readme-assets/wireframe-addtask.jpg -------------------------------------------------------------------------------- /readme-assets/wireframe-dashboard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bashmdz/calendar-frontend/643fc56929d32cc9146bb997f54df1e680c15394/readme-assets/wireframe-dashboard.jpg -------------------------------------------------------------------------------- /readme-assets/wireframe-edittask.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bashmdz/calendar-frontend/643fc56929d32cc9146bb997f54df1e680c15394/readme-assets/wireframe-edittask.jpg -------------------------------------------------------------------------------- /readme-assets/wireframe-home.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bashmdz/calendar-frontend/643fc56929d32cc9146bb997f54df1e680c15394/readme-assets/wireframe-home.jpg -------------------------------------------------------------------------------- /readme-assets/wireframe-viewtask.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bashmdz/calendar-frontend/643fc56929d32cc9146bb997f54df1e680c15394/readme-assets/wireframe-viewtask.jpg -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | width: 100%; 3 | min-height: 100vh; 4 | display: flex; 5 | justify-items: center; 6 | justify-content: space-between; 7 | flex-direction: column; 8 | } 9 | -------------------------------------------------------------------------------- /src/App.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Routes, Route, BrowserRouter as Router } from "react-router-dom"; 3 | import Home from "./views/Home"; 4 | import Layout from "./layout/Layout"; 5 | import "./App.css"; 6 | import Register from "./auth/Register"; 7 | import Login from "./auth/Login"; 8 | import AddNewTask from "./views/AddNewTask"; 9 | import EditTask from "./views/EditTask"; 10 | import ViewTask from "./views/ViewTask"; 11 | import Dashboard from "./views/Dashboard"; 12 | import Profile from "./views/Profile"; 13 | import TakeMeToAdmin from "./components/TakeMeToAdmin"; 14 | import NotFound from "./views/NotFound"; // Import NotFound component 15 | 16 | function App() { 17 | return ( 18 |
19 | 20 | 21 | {/* Home */} 22 | 26 | 27 | 28 | } 29 | /> 30 | 31 | {/* Dashboard */} 32 | 36 | 37 | 38 | } 39 | /> 40 | 41 | {/* Profile */} 42 | 46 | 47 | 48 | } 49 | /> 50 | 51 | {/* Add New Task */} 52 | 56 | 57 | 58 | } 59 | /> 60 | 61 | {/* Edit Task */} 62 | 66 | 67 | 68 | } 69 | /> 70 | 71 | {/* View Task */} 72 | 76 | 77 | 78 | } 79 | /> 80 | 81 | {/* Register */} 82 | 86 | 87 | 88 | } 89 | /> 90 | 91 | {/* Login */} 92 | 96 | 97 | 98 | } 99 | /> 100 | 101 | {/* Admin */} 102 | } /> 103 | } /> 104 | 105 | {/* Not Found */} 106 | } /> 107 | 108 | 109 |
110 | ); 111 | } 112 | 113 | export default App; 114 | -------------------------------------------------------------------------------- /src/CONSTANT.jsx: -------------------------------------------------------------------------------- 1 | // Constants for server and client URLs 2 | export const CONSTANT = { 3 | server: "https://calender-app-bashar-e84fae186fa8.herokuapp.com/", // CHANGE WITH YOUR BACKEND LINK (/ is MUST IN END) 4 | admin: "https://calender-app-bashar-e84fae186fa8.herokuapp.com/admin/", // CHANGE WITH YOUR BACKEND LINK (/ is MUST IN END) 5 | client: "http://localhost:5173/", // CHANGE WITH YOUR FRONTEND LINK (/ is MUST IN END). 6 | }; 7 | 8 | // Brand name constant 9 | export const BRAND_NAME = "CalenTask"; 10 | 11 | // Check if user is logged in 12 | export const checkIsLoggedIn = () => { 13 | return sessionStorage.getItem("loggedin") && 14 | JSON.parse(sessionStorage.getItem("loggedin")).data 15 | ? true 16 | : false; 17 | }; 18 | 19 | // Generate error message 20 | export const getErrorMessage = (message) => { 21 | let toReturn = ""; 22 | for (const key in message) { 23 | toReturn += `[${capitalizeFirstLetter(key.split("_").join(" "))}]: ${ 24 | message[key][0] 25 | }\n`; 26 | } 27 | return toReturn; 28 | }; 29 | 30 | // Set error message 31 | export const setMessage = (text, color) => { 32 | let error = document.getElementById("error"); 33 | error.innerHTML = text; 34 | error.classList.add("text-" + color); 35 | error.style.display = "block"; 36 | }; 37 | 38 | // Reset error message 39 | export const resetMessage = () => { 40 | let error = document.getElementById("error"); 41 | error.innerText = ""; 42 | error.style.display = "none"; 43 | error.classList.remove("text-danger"); 44 | error.classList.remove("text-success"); 45 | }; 46 | 47 | // Check if error message is displayed 48 | export const isMessage = () => { 49 | let error = document.getElementById("error"); 50 | if (error.style.display === "none") { 51 | return false; 52 | } 53 | return true; 54 | }; 55 | 56 | // Capitalize the first letter of a string 57 | export const capitalizeFirstLetter = (string) => { 58 | return string.charAt(0).toUpperCase() + string.slice(1); 59 | }; 60 | -------------------------------------------------------------------------------- /src/assets/icons/FilterIcon.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export default function FilterIcon(props) { 4 | return ( 5 | 13 | 14 | 28 | 44 | 45 | 46 | ); 47 | } 48 | -------------------------------------------------------------------------------- /src/assets/react.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/auth/Login.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react"; 2 | import { useNavigate } from "react-router-dom"; 3 | import axios from "axios"; 4 | import { 5 | CONSTANT, 6 | setMessage, 7 | resetMessage, 8 | checkIsLoggedIn, 9 | } from "../CONSTANT"; 10 | 11 | const Login = () => { 12 | const navigate = useNavigate(); 13 | 14 | useEffect(() => { 15 | // Check if user is already logged in 16 | if (checkIsLoggedIn()) { 17 | navigate("/dashboard"); 18 | } 19 | }, []); 20 | 21 | const initialPayload = { 22 | email: "", 23 | password: "", 24 | }; 25 | const [payload, setPayload] = useState(initialPayload); 26 | 27 | const handleChange = (e) => { 28 | // Update payload state when input values change 29 | setPayload({ 30 | ...payload, 31 | [e.target.name]: e.target.value, 32 | }); 33 | }; 34 | 35 | const handleLogin = async (e) => { 36 | e.target.style.pointerEvents = "none"; 37 | e.target.innerHTML = 38 | '
Loading...
'; 39 | e.preventDefault(); 40 | resetMessage(); 41 | 42 | let allGood = true; 43 | 44 | if (!payload.email || !payload.password) { 45 | setMessage("Enter valid email and password.", "danger"); 46 | allGood = false; 47 | } 48 | 49 | if (allGood) { 50 | try { 51 | const response = await axios.post( 52 | CONSTANT.server + "authentication/validate", 53 | payload 54 | ); 55 | if (response.data) { 56 | let res = response.data; 57 | if (res.message) { 58 | setMessage(res.message, "danger"); 59 | } else { 60 | sessionStorage.setItem( 61 | "loggedin", 62 | JSON.stringify({ 63 | data: res, 64 | }) 65 | ); 66 | navigate("/dashboard"); 67 | } 68 | } 69 | } catch (error) { 70 | setMessage("System error!", "danger"); 71 | console.log(error); 72 | } 73 | } 74 | 75 | e.target.style.pointerEvents = "unset"; 76 | e.target.innerHTML = "Login"; 77 | }; 78 | 79 | return ( 80 |
81 |
82 |

Login

83 |
84 |
85 | 88 | 97 |
98 |
99 | 102 | 111 |
112 |
113 | 116 |
117 |
118 |
119 |
120 |
121 | ); 122 | }; 123 | 124 | export default Login; 125 | -------------------------------------------------------------------------------- /src/auth/Register.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react"; 2 | import { useNavigate } from "react-router-dom"; 3 | import axios from "axios"; 4 | import { 5 | CONSTANT, 6 | setMessage, 7 | resetMessage, 8 | checkIsLoggedIn, 9 | getErrorMessage, 10 | } from "../CONSTANT"; 11 | 12 | const Register = () => { 13 | const navigate = useNavigate(); 14 | 15 | useEffect(() => { 16 | // Redirect to dashboard if user is already logged in 17 | if (checkIsLoggedIn()) { 18 | navigate("/dashboard"); 19 | } 20 | }, []); 21 | 22 | const initPayload = { 23 | name: "", 24 | password: "", 25 | email: "", 26 | }; 27 | 28 | const [payload, setPayload] = useState(initPayload); 29 | 30 | const changePayload = (e) => { 31 | setPayload({ 32 | ...payload, 33 | [e.target.name]: e.target.value, 34 | }); 35 | }; 36 | 37 | const register = async (e) => { 38 | e.target.style.pointerEvents = "none"; 39 | e.target.innerHTML = 40 | '
Loading...
'; 41 | e.preventDefault(); 42 | resetMessage(); 43 | 44 | let allGood = true; 45 | 46 | if (!payload.name) { 47 | setMessage("Enter your name.", "danger"); 48 | allGood = false; 49 | } else if ( 50 | !payload.email || 51 | !/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(payload.email) 52 | ) { 53 | setMessage("Enter valid email.", "danger"); 54 | allGood = false; 55 | } else if (!payload.password) { 56 | setMessage("Enter valid password.", "danger"); 57 | allGood = false; 58 | } 59 | 60 | if (allGood) { 61 | try { 62 | const response = await axios.post( 63 | CONSTANT.server + "authentication/user", 64 | payload 65 | ); 66 | const res = response.data; 67 | if (res.message) { 68 | setMessage(getErrorMessage(res?.message), "danger"); 69 | } else { 70 | sessionStorage.setItem( 71 | "loggedin", 72 | JSON.stringify({ 73 | data: res, 74 | }) 75 | ); 76 | navigate("/dashboard"); 77 | } 78 | } catch (error) { 79 | setMessage("System error!", "danger"); 80 | console.log(error); 81 | } 82 | } 83 | 84 | e.target.style.pointerEvents = "unset"; 85 | e.target.innerHTML = "Register"; 86 | }; 87 | 88 | return ( 89 |
90 |
91 |

Registration

92 |
93 |
94 | 97 | 106 |
107 |
108 | 111 | 120 |
121 |
122 | 125 | 134 |
135 |
136 | 139 |
140 |
141 |
142 |
143 |
144 | ); 145 | }; 146 | 147 | export default Register; 148 | -------------------------------------------------------------------------------- /src/components/Footer.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Container } from "react-bootstrap"; 3 | import { BRAND_NAME } from "../CONSTANT"; 4 | 5 | // Footer component 6 | const Footer = () => { 7 | return ( 8 | // Footer section 9 | 14 | ); 15 | }; 16 | 17 | export default Footer; 18 | -------------------------------------------------------------------------------- /src/components/Header.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { Link } from "react-router-dom"; 3 | import { BRAND_NAME } from "../CONSTANT"; 4 | 5 | // Header component 6 | const Header = (props) => { 7 | const [isOpen, setIsOpen] = useState(false); 8 | 9 | // ListItem component 10 | const ListItem = (props) => { 11 | if (props?.to) { 12 | return ( 13 |
  • 14 | { 17 | setIsOpen(false); 18 | }} 19 | aria-current="page" 20 | to={props?.to || "/"} 21 | > 22 | {props?.label} 23 | 24 |
  • 25 | ); 26 | } 27 | return ( 28 |
  • 29 | 34 | {props?.label} 35 | 36 |
  • 37 | ); 38 | }; 39 | 40 | return ( 41 | 98 | ); 99 | }; 100 | 101 | export default Header; 102 | -------------------------------------------------------------------------------- /src/components/TakeMeToAdmin.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from "react"; 2 | import { CONSTANT } from "../CONSTANT"; 3 | 4 | export default function TakeMeToAdmin() { 5 | useEffect(() => { 6 | // Redirect to the admin page 7 | window.location.href = `${CONSTANT.admin}`; 8 | }, []); 9 | 10 | return
    ; 11 | } 12 | -------------------------------------------------------------------------------- /src/contexts/UserData.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | // Create a context for user data 4 | const UserData = React.createContext({ 5 | session: { 6 | personal: { 7 | id: "", // User ID 8 | email: "", // User email 9 | name: "", // User name 10 | }, 11 | isLoggedIn: false, // User login status 12 | }, 13 | setSession: () => {}, // Function to set user session 14 | setToast: () => {}, // Function to set toast message 15 | }); 16 | 17 | export default UserData; 18 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap"); 2 | 3 | body { 4 | min-height: 100vh; 5 | font-family: "Roboto", sans-serif; 6 | } 7 | 8 | @media (max-width: 576px) { 9 | .__HOME__BOX__ { 10 | width: 100% !important; 11 | } 12 | } 13 | 14 | .toast-css { 15 | right: 0 !important; 16 | left: auto !important; 17 | } 18 | -------------------------------------------------------------------------------- /src/layout/Layout.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | import Header from "../components/Header"; 3 | import Footer from "../components/Footer"; 4 | import { useLocation, useNavigate } from "react-router-dom"; 5 | import { Toast } from "react-bootstrap"; 6 | import UserData from "../contexts/UserData"; 7 | 8 | export default function Layout(props) { 9 | let navigate = useNavigate(); 10 | let location = useLocation(); 11 | 12 | // Initialize session state 13 | let __init_session = { 14 | personal: { 15 | id: "", 16 | email: "", 17 | name: "", 18 | }, 19 | isLoggedIn: false, 20 | }; 21 | const [session, setSession] = useState(__init_session); 22 | const [toast, setToast] = useState({ show: false, text: "", type: "" }); 23 | 24 | // Check if user is logged in on page load 25 | useEffect(() => { 26 | let sessionData = JSON.parse(sessionStorage.getItem("loggedin")); 27 | if (sessionData) { 28 | setSession({ 29 | ...__init_session, 30 | personal: sessionData.data, 31 | isLoggedIn: true, 32 | }); 33 | } 34 | }, [location]); 35 | 36 | // Redirect to signin page if user is not logged in 37 | useEffect(() => { 38 | if (!props?.auth && !session.isLoggedIn) { 39 | navigate("/signin"); 40 | } 41 | }, [session]); 42 | 43 | // Logout function 44 | const logout = async () => { 45 | sessionStorage.removeItem("loggedin"); 46 | setSession(__init_session); 47 | navigate("/signin"); 48 | }; 49 | 50 | const value = { session, setSession, setToast }; 51 | 52 | return ( 53 | <> 54 | 55 |
    60 |
    {props.children}
    61 |