├── .babelrc
├── .gitignore
├── README.md
├── Untitled.png
├── arc.png
├── classdiagramfrontend.jpg
├── design.png
├── jest.config.ts
├── package-lock.json
├── package.json
├── public
├── favicon.ico
├── index.html
├── logo192.png
├── logo512.png
├── manifest.json
└── robots.txt
├── schemadiagram.jpg
├── src
├── App.tsx
├── Goalify-logos.jpeg
├── components
│ ├── AboutUs.tsx
│ ├── HeaderNavBar.css
│ ├── HeaderNavBar.tsx
│ ├── Profile.tsx
│ ├── account_setup
│ │ ├── Login.css
│ │ ├── Login.tsx
│ │ └── Register.tsx
│ ├── common
│ │ ├── Footer.css
│ │ ├── Footer.tsx
│ │ ├── LogoFooter.tsx
│ │ └── utilities.tsx
│ └── dashboard
│ │ ├── Dashboard.tsx
│ │ ├── Goal.css
│ │ ├── Goal.tsx
│ │ ├── GoalsList.css
│ │ ├── GoalsList.tsx
│ │ ├── MilestoneList.css
│ │ ├── MilestoneList.tsx
│ │ └── statistics
│ │ ├── GoalStats.tsx
│ │ └── Stats.tsx
├── hooks
│ └── useAuth.ts
├── index.css
├── index.tsx
├── react-app-env.d.ts
├── redux
│ ├── account_setup
│ │ ├── actions.ts
│ │ ├── reducer.ts
│ │ └── type.d.ts
│ └── store.ts
├── reportWebVitals.ts
├── setupTests.ts
├── test
│ ├── componenets
│ │ └── account_setup
│ │ │ └── Login.test.tsx
│ └── setupTests.js
├── testcases
│ └── samples.tsx
└── tsInterfaces
│ └── interfaces.tsx
├── tsconfig.json
└── usecasediagram.jpg
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "@babel/preset-env",
4 | "@babel/preset-react",
5 | "@babel/preset-typescript"
6 | ],
7 | "plugins": []
8 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Goalify
2 | ## Table of Contents
3 | 1. [ Introdution. ](#intro)
4 | 2. [ Business Goals and Objectives ](#business)
5 | 3. [ Requirements ](#req)
6 | 4. [ Project Glossary ](#glossary)
7 | 5. [ Technical Stack ](#techstack)
8 | 6. [ Stakeholders Roles. ](#stake)
9 | 7. [ User Stories ](#stories)
10 | 8. [ Design Documentation ](#design)
11 | 9. [ Architecture And Diagrams ](#arc)
12 | 10. [ Run the App ](#run-app)
13 | 11. [ Demo ](#demo)
14 | 12. [ Authors ](#auth)
15 |
16 |
17 | ## 1. Introdution
18 | Goalify is a web application used by users to set their goals, track their progress and achievements, view statistics on their progress, and share that with other users who would also be posting their progress creating some kind of a motivational feedback loop.
19 |
20 |
21 | ## 2. Business Goals and Objectives
22 | The problem: the lack of motivation to get up and pursue whatever any of us is trying to achieve has been a problem for almost everyone.
23 |
24 | Solution: Create an application to assist people put forward objectives and keep tabs on their development towards those objectives. It gives an organized method to follow and track objective advancement through highlights like dashboards and progress bars. Additionally, the platform is a magnificent apparatus for inspiration.
25 |
26 | The app allows users to stay focused on the most critical aspects of their goals. It aids in the identification of potential roadblocks as well as ideas for overcoming them. It can assist in setting more realistic goals and maintaining a happy attitude along the way. Most importantly, uses can share that with other users who would also be posting their progress creating some kind of a motivational feedback loop.
27 |
28 | Competition: There are many apps out there made for the purpose of tracking goals but they all lack in the social side.
29 |
30 |
31 | ## 3. Requirements
32 | ### 3.1. Functioanl Requirements
33 | - Account setup.
34 | - Creating goals.
35 | - Logging daily progress.
36 | - Specifying milestones and tracking them.
37 | - Generating statistics on progress.
38 | - Share goals, progress, achievements and stats.
39 | ### 3.2. Non-Functioanl Requirements
40 | - **Privacy**: Users’ data should be completely safe and private unless it’s shared by the user. This requirement will be met by having two types of data (private and public). This will be enforced by the middle-ware.
41 | - **Security**: We will meet this requirement by using a middle-ware server as a security abstraction between the front-end and the back-end. Servers must be secured against:
42 | - cross-site scripting attacks
43 | - cross-site injections
44 | - insecure connections to the servers
45 | - MIME-sniffing
46 | - Clickjacking
47 | - **Simplicity**: UI should be easy to use without complications as it will be used by young adults and designed for daily use. We will meet this requirement by keeping a minimal and intuitive design in the front-end.
48 | - **Scalability**: The platform should be able to handle an increasing amount of users which at some point could hit millions. This can be handled by the middle-ware by load balancing between the back-end micro services.
49 | - **Extensibility**: The source code of the platform should be able to handle additional features. The developers will meet this by following software engineering design principles such as *S.O.L.I.D.* and *KISS*.
50 |
51 |
52 | ## 4. Project Glossary
53 | - Middle-ware: An intermediate server acting as an interface between the front-end and the back-end.
54 | - Core server: The server which stores all data other the users' credentials.
55 | - Goal: A desired ambition that a person aims to achieve.
56 | - Milestone: Partial actions and achievements necessary to make progress toward a particular goal.
57 | - Discover page: A page where latest public goals are published.
58 | - Private goal: A goal only visible by its creator.
59 | - Public goal: A goal that can visible on the discover page.
60 | - Access token: An access token contains the security credentials for a login session and identifies the user.
61 | - Authentication request: A request sent from the frontend to the middleware to check if the user is granted an access token.
62 |
63 |
64 | ## 5. Technical Stack
65 | - front-end client: ReactJS + Typescript
66 | - user-proxy middleware: Node ExpressJs + Typescript
67 | - user accounts database: MongoDB
68 | - core-server: Python Flask
69 | - main database: MySQL
70 |
71 |
72 |
73 | ## 6. Stakeholders Roles
74 | Stakeholder's Name | Roles | Responsibilities
75 | | :---: | :--- | :---
76 | Users | Suggest new features, Report existing bugs. | Contact technical support to report bugs and problems. Provide feedback to improve the website.
77 | Board of executives | Direct and lead the project. | Choosing the main functions of the project. Managing and organizing the whole project. Take lead in Decision Making.
78 | Investors | Providing financial support to the development process. | Determining if some features are worth the funding. Deciding the amount of money to spend on certain features.
79 | Developers | Develop and maintain the platform. | Fixing bugs. Adding features. Unit testing.
80 | Project owners | Manage the project. | Accept or reject the project, and provide high level business requirements.
81 | QA testers | Assures the quality of the new features. | End to end testing.
82 |
83 |
84 |
85 | ## 7. User Stoires
86 | User Type | User Story Title | User stories
87 | | :--- | :---: | :---
88 | Web User | Registration | As a user, I can register on the website by entering my email and password and confirming the password so that I can log in to the platform.
89 | Web User | Login | As a user, I want to able to log in to the website by entering my confidentials (email, password) so that I can use the platform.
90 | Web User | Change confidentials | As a user, I want to be able to change my confidentials (email, password) in order to keep my account safe.
91 | Web User | Profile | As a user, I should be able to upload my profile picture and add a nickname to my account.
92 | Web User | Creating goals | As a user, I want to be able to add new goals so that I can have an organized to-do list.
93 | Web User | Edit goals | As a user, I want to be able to edit my goals so that I can adjust my goals to new circumstances.
94 | Web User | Creating milestones | As a user, I want to be able to create milestones in a specific goal so that I can divide my goal into small achievable steps.
95 | Web User | Publish goals | As a user, I want to be able to publish my goals so I can share my progress.
96 | Web User | View public goals | As a user, I want to be able to view other people's public goals so I can be more motiviated to achieve my own goals.
97 | Web User | Progress tracking | As a user, I should be able to update my progress in any of my goals so that I can view the progression.
98 | Web User | Statistics | As a user, I want to generate stats about my progress so that I could have a better understanding of my performance.
99 |
100 |
101 | ## 8. Design Documentation:
102 | We decided to have one client web app used by users. Another administration interface might be introduced in the future.
103 |
104 | We are using ReactJS as our frontend framework since it’s simple and efficient. Typescript and linter were added to make sure the code is easily debugged, easily read, and as clean as possible. Using Redux to store and organize the data retrieved from the backend, making it available to all of the frontend components.
105 |
106 | Unit tests using Jest and Enzyme were added to make sure that future changes won’t break the existing code. The SOLID principle was followed to make each of our components visible and with clear responsibilities, each of our components does only one thing at a time.
107 |
108 | That client communicates with the backend microservices using a middleware/proxy called user-proxy, which is a Node ExpressJS app responsible for load-balancing and assuring the safety of the backend servers and microservices as well as the user’s data since such data might be sensitive. Typescript and Linter were also added to the middleware for the same purpose explained above. SOLID was also followed, as each of our API middlewares has only one clear job.
109 |
110 | User authentication will be done by user-proxy which communicates with its own MongoDB database, this was done to make sure that no one can access any of the backend microservices and databases unless they’re authored and have access to the exact resource they’re trying to access. A middleware function will be called before any of the API middle-points checking the authority of the accessor.
111 |
112 | Here’s a sample diagram of the flow of a test post request to the endpoint/test:
113 |
114 | 
115 |
116 | After all of the user authentications are handled by the middleware, the valid requests are sent to the core server.
117 |
118 | We have decided to use Flask as the main framework for the core server because of its flexibility and the compatibility it embraces with the latest technologies. Moreover, it is easy and highly scalable on simple projects. Principles such as KISS and SOLID were followed during the development to make the process of debugging and adding new features simpler and more efficient. The core server is connected to a MySQL database, which stores all data except for the users’ credentials. MySQL was selected as it is secure, flexible, and easy to set up.
119 |
120 | Showing how we applied SOLID to our front-end, we only let our classes have a single responsibilty. For example class `addGoalModal` is only resposible for adding a new goal. Class `DbClickField` only shows some text that can be edited by pressing twice on the text, and so on. We followed Liskov substitution principle by using typescript since it can easily swap components if they share the same contract. We followed interface segregation principle by having multiple interfaces (e.g. `goal`, `milestone`) instead of designing a single interface to substitute them all. We followed dependency inversion principle by making sure that child classes depended on abstraction from parent classes, for example the `GoalsList` sends functions to the class `GoalItem` and these functions will be used by the child class to edit the goal. `GoalItem` doesn't depend on the implementation of the funtions from `GoalsList`. Those functions can be edited without affecting the child class.
121 |
122 | We followed KISS principle by not over-engineering anything and using the simplest methods to achieve objectives. We don't for example use any advanced techniques in react in our front-end such as Compound Components, Props Getters, and State Reducer.
123 |
124 |
125 | ## 9. Architecture And Diagrams
126 |
127 | Architecture:
128 |
129 | 
130 |
131 |
132 | Front-End Class Diagram:
133 |
134 | 
135 |
136 |
137 | Use Case Diagram:
138 |
139 | 
140 |
141 |
142 | Schema Diagram:
143 |
144 | 
145 |
146 |
147 | Sequence Diagram:
148 |
149 | 
150 |
151 |
152 | ## 10. Run the App
153 | To run the app without any errors, you need to first run the `Core-server`, then the `Middleware`, and finally the `front-end`.
154 | ### Core-server
155 | This parts explains how to run the core server on Ubuntu 20.04 or higher and python 3.8 or higher.
156 | #### Database
157 | As prevoiusly mentioned, the core server uses MySQL as its main database. So you need to install MySQL using the following steps.
158 | 1. You need to update the package index on your server if you’ve not done so recently using the command below.
159 | ```
160 | $ sudo apt update
161 | ```
162 |
163 | 2. Install the mysql-server package:
164 | ```
165 | $ sudo apt install mysql-server
166 | ```
167 |
168 | 3. Then you need to access the MySQL shell as the root user using the following command:
169 | ```
170 | $ sudo mysql
171 | ```
172 | NOTE: If you already had installed MySQL and enabled password authentication for root, you will need to use a different command to access the MySQL shell. The command to use in that case:
173 | ```
174 | $ mysql -u root -p
175 | ```
176 | This will enable you to access the MySQL shell after entering the password you set.
177 |
178 | 4. Now you need to create a database called 'goalify'. Type this command in the MySQL shell.
179 | ```
180 | > CREATE DATABASE goalify;
181 | ```
182 |
183 | 5. Create a user for this database to be used by the core server using the following command:
184 | ```
185 | > CREATE USER 'newuser'@'localhost' IDENTIFIED BY 'password';
186 | ```
187 | NOTE: keep `newuser` and `password` as they are. Otherwise you will need to change the user and the password in `db.yaml` file.
188 |
189 | 6. Finally granting the new user a full access to the newly created database 'goalify'.
190 | ```
191 | > GRANT ALL PRIVILEGES ON goalify.* TO 'newuser'@'localhost';
192 | ```
193 |
194 | #### Python
195 | All of the dependencies and necessary modules used are listed in the file `requirements.txt` you need to run the following command in the terminal in the project directory:
196 | ```
197 | pip install -r requirements.txt
198 | ```
199 | Now you can run the core server using the command in the project directory:
200 | ```
201 | python app.py
202 | ```
203 | This will make the app run on the localhost (127.0.0.1) and the port 3001. If you would like to change that, you can modify `app.py` file and change the values of `IP` and `PORT`.
204 | ### Middleware
205 | 1. You need to install `npm`:
206 | ```
207 | sudo apt install npm
208 | ```
209 | 2. You need to `cd` to the directory of the `user-proxy` and install node modules
210 |
211 | ```bash
212 | $ npm install
213 | ```
214 |
215 | 3. Run the development server
216 |
217 | ```bash
218 | $ npm run dev
219 | ```
220 |
221 | ### Frontend
222 | 1. You need to install `npm`:
223 | ```
224 | sudo apt install npm
225 | ```
226 | 2. You need to `cd` to the directory of the `front-end` repo and run:
227 | ```
228 | npm install
229 | ```
230 | 3. Now, to run the app use the following command:
231 | ```
232 | npm start
233 | ```
234 |
235 |
236 | ## 11. Demo
237 | [Here](https://youtu.be/ixyBmpZGab0) you can find a link to a video-demo of goalify with some explanations on how the platform works.
238 |
239 |
240 | ## 12. Authors
241 | This project was created and is maintained by: Hasan Khadra, Mahmood Darwish, Mohamad Dwik, Mohammad Shahin.
242 |
--------------------------------------------------------------------------------
/Untitled.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Goalify/front-end/28774210e489d82e97b0ec30412296f71eb75d0f/Untitled.png
--------------------------------------------------------------------------------
/arc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Goalify/front-end/28774210e489d82e97b0ec30412296f71eb75d0f/arc.png
--------------------------------------------------------------------------------
/classdiagramfrontend.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Goalify/front-end/28774210e489d82e97b0ec30412296f71eb75d0f/classdiagramfrontend.jpg
--------------------------------------------------------------------------------
/design.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Goalify/front-end/28774210e489d82e97b0ec30412296f71eb75d0f/design.png
--------------------------------------------------------------------------------
/jest.config.ts:
--------------------------------------------------------------------------------
1 | // jest.config.ts
2 | import type {Config} from '@jest/types';
3 |
4 | // Sync object
5 | export const config: Config.InitialOptions = {
6 | verbose: true,
7 | };
8 |
9 | // Or async function
10 | export default async (): Promise => {
11 | return {
12 | verbose: true,
13 | };
14 | };
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "front-end",
3 | "version": "0.1.0",
4 | "jest": {
5 | "name": "my-project",
6 | "jest": {
7 | "verbose": true
8 | }
9 | },
10 | "private": true,
11 | "dependencies": {
12 | "@testing-library/jest-dom": "^5.11.4",
13 | "@testing-library/react": "^11.1.0",
14 | "@testing-library/user-event": "^12.1.10",
15 | "@types/node": "^12.0.0",
16 | "@types/react": "^17.0.0",
17 | "@types/react-dom": "^17.0.0",
18 | "axios": "^0.21.4",
19 | "axios-mock-adapter": "^1.20.0",
20 | "bootstrap": "^5.1.1",
21 | "enzyme": "^3.11.0",
22 | "js-cookie": "^3.0.1",
23 | "mdbreact": "^5.1.0",
24 | "rc-footer": "^0.6.6",
25 | "react": "^17.0.2",
26 | "react-bootstrap": "^2.0.0-rc.0",
27 | "react-dom": "^17.0.2",
28 | "react-hot-toast": "^2.1.1",
29 | "react-redux": "^7.2.5",
30 | "react-router-dom": "^5.3.0",
31 | "react-scripts": "4.0.3",
32 | "react-test-renderer": "^17.0.2",
33 | "redux": "^4.1.1",
34 | "redux-thunk": "^2.3.0",
35 | "simple-react-footer": "^1.0.2",
36 | "styled-components": "^5.3.1",
37 | "ts-node": "^10.2.1",
38 | "typescript": "^4.1.2",
39 | "universal-cookie": "^4.0.4",
40 | "web-vitals": "^1.0.1"
41 | },
42 | "scripts": {
43 | "start": "react-scripts start",
44 | "build": "react-scripts build",
45 | "test": "jest",
46 | "eject": "react-scripts eject"
47 | },
48 | "eslintConfig": {
49 | "extends": [
50 | "react-app",
51 | "react-app/jest"
52 | ]
53 | },
54 | "browserslist": {
55 | "production": [
56 | ">0.2%",
57 | "not dead",
58 | "not op_mini all"
59 | ],
60 | "development": [
61 | "last 1 chrome version",
62 | "last 1 firefox version",
63 | "last 1 safari version"
64 | ]
65 | },
66 | "devDependencies": {
67 | "@babel/preset-typescript": "^7.15.0",
68 | "@types/enzyme": "^3.10.9",
69 | "@types/jest": "^27.0.1",
70 | "@types/react-redux": "^7.1.18",
71 | "@types/react-router-dom": "^5.3.0",
72 | "@types/react-test-renderer": "^17.0.1",
73 | "@types/redux": "^3.6.0",
74 | "@types/redux-mock-store": "^1.0.3",
75 | "@types/redux-persist": "^4.3.1",
76 | "@types/redux-thunk": "^2.1.0",
77 | "@wojtekmaj/enzyme-adapter-react-17": "^0.6.3",
78 | "babel-core": "^6.26.3",
79 | "babel-polyfill": "^6.26.0",
80 | "babel-preset-es2015": "^6.24.1",
81 | "babel-preset-stage-0": "^6.24.1",
82 | "fetch-mock": "^9.11.0",
83 | "html-loader": "^2.1.2",
84 | "redux-mock-store": "^1.5.4",
85 | "redux-persist": "^6.0.0",
86 | "regenerator-runtime": "^0.13.9"
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Goalify/front-end/28774210e489d82e97b0ec30412296f71eb75d0f/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
27 | React App
28 |
29 |
30 |
31 |
32 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Goalify/front-end/28774210e489d82e97b0ec30412296f71eb75d0f/public/logo192.png
--------------------------------------------------------------------------------
/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Goalify/front-end/28774210e489d82e97b0ec30412296f71eb75d0f/public/logo512.png
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/schemadiagram.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Goalify/front-end/28774210e489d82e97b0ec30412296f71eb75d0f/schemadiagram.jpg
--------------------------------------------------------------------------------
/src/App.tsx:
--------------------------------------------------------------------------------
1 | import Dashboard from './components/dashboard/Dashboard'
2 | import Footer from './components/common/Footer';
3 | import AboutUs from './components/AboutUs';
4 | import Profile from './components/Profile';
5 | import { Route, Switch, Redirect } from 'react-router-dom';
6 | import Login from './components/account_setup/Login';
7 | import Register from './components/account_setup/Register';
8 | import HeaderNavBar from './components/HeaderNavBar';
9 | import { useSelector } from 'react-redux';
10 | import { useAuth } from './hooks/useAuth';
11 |
12 |
13 | function App(){
14 | const auth = useAuth();
15 | const user = useSelector((state: UserState) => state.user);
16 | return