├── .browserslistrc
├── .gitignore
├── README.md
├── babel.config.js
├── db.json
├── jsconfig.json
├── package-lock.json
├── package.json
├── public
├── favicon.ico
└── index.html
├── screenshots
└── preview.gif
├── src
├── App.vue
├── components
│ ├── AddTask.vue
│ ├── Button.vue
│ ├── Footer.vue
│ ├── Header.vue
│ ├── Task.vue
│ └── Tasks.vue
├── main.js
├── router
│ └── index.js
├── services
│ └── tasksServices.js
├── styles
│ ├── AddTask.css
│ ├── App.css
│ └── Task.css
└── views
│ ├── About.vue
│ └── Home.vue
└── vue.config.js
/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 | not dead
4 | not ie 11
5 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 |
6 | # local env files
7 | .env.local
8 | .env.*.local
9 |
10 | # Log files
11 | npm-debug.log*
12 | yarn-debug.log*
13 | yarn-error.log*
14 | pnpm-debug.log*
15 |
16 | # Editor directories and files
17 | .idea
18 | .vscode
19 | *.suo
20 | *.ntvs*
21 | *.njsproj
22 | *.sln
23 | *.sw?
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Task Tracker
2 |
3 | It is a simple task tracker built with Vue JS. It enables you to create goals for yourself and set a day and a reminder to them.
4 |
5 | This project was inspired from [Traversy Media Vue JS Crash Course](https://youtu.be/qZXt1Aom3Cs) 🙌🏽❤️
6 |
7 | ## Preview
8 |
9 | 
10 |
11 | ## Project setup
12 |
13 | ```bash
14 | git clone https://github.com/abdullahalshawafi/Task-Tracker.git
15 | cd Task-Tracker/
16 | npm install
17 | ```
18 |
19 | ### Compile and hot-reloads for development
20 |
21 | ```bash
22 | npm run serve
23 | ```
24 |
25 | ### Compile and minify for production
26 |
27 | ```bash
28 | npm run build
29 | ```
30 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/cli-plugin-babel/preset'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/db.json:
--------------------------------------------------------------------------------
1 | {
2 | "tasks": [
3 | {
4 | "id": 1,
5 | "text": "Learn Vue",
6 | "day": "March 1st at 10:00 AM",
7 | "reminder": true
8 | },
9 | {
10 | "id": 2,
11 | "text": "Learn Vuex",
12 | "day": "April 1st at 11:00 PM",
13 | "reminder": false
14 | },
15 | {
16 | "id": 3,
17 | "text": "Learn Vue Router",
18 | "day": "May 1st at 12:00 PM",
19 | "reminder": true
20 | }
21 | ]
22 | }
--------------------------------------------------------------------------------
/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "module": "esnext",
5 | "baseUrl": "./",
6 | "moduleResolution": "node",
7 | "paths": {
8 | "@/*": [
9 | "src/*"
10 | ]
11 | },
12 | "lib": [
13 | "esnext",
14 | "dom",
15 | "dom.iterable",
16 | "scripthost"
17 | ]
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "task-tracker",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "backend": "json-server --watch db.json --port 4000",
7 | "serve": "concurrently \"npm run backend\" \"vue-cli-service serve\"",
8 | "build": "vue-cli-service build"
9 | },
10 | "dependencies": {
11 | "core-js": "^3.8.3",
12 | "vue": "^3.2.13",
13 | "vue-router": "^4.0.13"
14 | },
15 | "devDependencies": {
16 | "@vue/cli-plugin-babel": "~5.0.0",
17 | "@vue/cli-service": "~5.0.0",
18 | "concurrently": "^7.2.0",
19 | "json-server": "^0.17.0"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abdullahalshawafi/Task-Tracker/00aff46934ad83874d152bd88b4559bb977659be/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
12 | Task Tracker
13 |
14 |
15 |
16 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/screenshots/preview.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abdullahalshawafi/Task-Tracker/00aff46934ad83874d152bd88b4559bb977659be/screenshots/preview.gif
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
12 |
13 |
32 |
33 |
36 |
--------------------------------------------------------------------------------
/src/components/AddTask.vue:
--------------------------------------------------------------------------------
1 |
2 |
30 |
31 |
32 |
67 |
68 |
71 |
--------------------------------------------------------------------------------
/src/components/Button.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
20 |
--------------------------------------------------------------------------------
/src/components/Footer.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
16 |
--------------------------------------------------------------------------------
/src/components/Header.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
34 |
--------------------------------------------------------------------------------
/src/components/Task.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 | {{ task.text }}
8 |
9 |
10 |
{{ task.day }}
11 |
12 |
13 |
14 |
20 |
21 |
24 |
--------------------------------------------------------------------------------
/src/components/Tasks.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
21 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import { createApp } from "vue";
2 | import router from "./router";
3 | import App from "./App.vue";
4 |
5 | createApp(App).use(router).mount("#app");
6 |
--------------------------------------------------------------------------------
/src/router/index.js:
--------------------------------------------------------------------------------
1 | import { createRouter, createWebHistory } from "vue-router";
2 | import Home from "../views/Home.vue";
3 | import About from "../views/About.vue";
4 |
5 | const routes = [
6 | {
7 | path: "/",
8 | name: "Home",
9 | component: Home,
10 | },
11 | {
12 | path: "/about",
13 | name: "About",
14 | component: About,
15 | },
16 | ];
17 |
18 | const router = createRouter({
19 | history: createWebHistory(process.env.BASE_URL),
20 | routes,
21 | });
22 |
23 | export default router;
24 |
--------------------------------------------------------------------------------
/src/services/tasksServices.js:
--------------------------------------------------------------------------------
1 | export const createTask = async (task) => {
2 | const response = await fetch("api/tasks", {
3 | method: "POST",
4 | headers: {
5 | "Content-Type": "application/json",
6 | },
7 | body: JSON.stringify(task),
8 | });
9 |
10 | const newTask = await response.json();
11 |
12 | return newTask;
13 | };
14 |
15 | export const fetchTasks = async () => {
16 | const response = await fetch("api/tasks");
17 | const data = await response.json();
18 | return data;
19 | };
20 |
21 | export const toggleTaskReminder = async (task) => {
22 | await fetch(`api/tasks/${task.id}`, {
23 | method: "PATCH",
24 | headers: {
25 | "Content-Type": "application/json",
26 | },
27 | body: JSON.stringify({
28 | reminder: !task.reminder,
29 | }),
30 | });
31 | };
32 |
33 | export const removeTask = async (taskId) => {
34 | const response = await fetch(`api/tasks/${taskId}`, {
35 | method: "DELETE",
36 | });
37 |
38 | return response.status === 200;
39 | };
40 |
--------------------------------------------------------------------------------
/src/styles/AddTask.css:
--------------------------------------------------------------------------------
1 | .add-form {
2 | margin-bottom: 40px;
3 | }
4 |
5 | .form-control {
6 | margin: 20px 0;
7 | }
8 |
9 | .form-control label {
10 | display: block;
11 | }
12 |
13 | .form-control input {
14 | width: 100%;
15 | height: 40px;
16 | margin: 5px;
17 | padding: 3px 7px;
18 | font-size: 17px;
19 | }
20 |
21 | .form-control-check {
22 | display: flex;
23 | align-items: center;
24 | justify-content: space-between;
25 | }
26 |
27 | .form-control-check label {
28 | flex: 1;
29 | }
30 |
31 | .form-control-check input {
32 | flex: 2;
33 | height: 20px;
34 | }
--------------------------------------------------------------------------------
/src/styles/App.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Poppins:wght@300;400&display=swap");
2 |
3 | * {
4 | box-sizing: border-box;
5 | margin: 0;
6 | padding: 0;
7 | }
8 |
9 | body {
10 | font-family: "Poppins", sans-serif;
11 | }
12 |
13 | header {
14 | display: flex;
15 | justify-content: space-between;
16 | align-items: center;
17 | margin-bottom: 20px;
18 | }
19 |
20 | a {
21 | color: #333;
22 | }
23 |
24 | footer {
25 | margin-top: 30px;
26 | text-align: center;
27 | }
28 |
29 | .container {
30 | max-width: 500px;
31 | margin: 30px auto;
32 | overflow: auto;
33 | min-height: 300px;
34 | border: 1px solid steelblue;
35 | padding: 30px;
36 | border-radius: 5px;
37 | }
38 |
39 | .btn {
40 | display: inline-block;
41 | background: #000;
42 | color: #fff;
43 | border: none;
44 | padding: 10px 20px;
45 | margin: 5px;
46 | border-radius: 5px;
47 | cursor: pointer;
48 | text-decoration: none;
49 | font-size: 15px;
50 | font-family: inherit;
51 | }
52 |
53 | .btn:focus {
54 | outline: none;
55 | }
56 |
57 | .btn:active {
58 | transform: scale(0.98);
59 | }
60 |
61 | .btn-block {
62 | display: block;
63 | width: 100%;
64 | }
65 |
66 | .tasks-message {
67 | text-align: center;
68 | margin: 50px 0;
69 | font-size: 1.5rem;
70 | }
--------------------------------------------------------------------------------
/src/styles/Task.css:
--------------------------------------------------------------------------------
1 | .fas {
2 | color: red;
3 | }
4 |
5 | .task {
6 | background: #dbdbdb;
7 | margin: 5px;
8 | padding: 10px 20px;
9 | cursor: pointer;
10 | }
11 |
12 | .task.reminder {
13 | border-left: 5px solid green;
14 | }
15 |
16 | .task h3 {
17 | display: flex;
18 | align-items: center;
19 | justify-content: space-between;
20 | }
--------------------------------------------------------------------------------
/src/views/About.vue:
--------------------------------------------------------------------------------
1 |
2 | About
3 | Version 2.0.0
4 | This is a simple todo app built with Vue.js and Vue Router.
5 | Go back
6 |
7 |
8 |
14 |
--------------------------------------------------------------------------------
/src/views/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | Loading...
4 |
5 | There are no tasks yet. Set some goals for yourself!
6 |
7 |
13 |
14 |
15 |
71 |
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 | const { defineConfig } = require("@vue/cli-service");
2 | module.exports = defineConfig({
3 | transpileDependencies: true,
4 | devServer: {
5 | proxy: {
6 | "^/api": {
7 | target: "http://localhost:4000",
8 | changeOrigin: true,
9 | logLevel: "debug",
10 | pathRewrite: { "^/api": "" },
11 | },
12 | },
13 | },
14 | });
15 |
--------------------------------------------------------------------------------