├── .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 | ![preview](./screenshots/preview.gif) 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 | 12 | 13 | 32 | 33 | 36 | -------------------------------------------------------------------------------- /src/components/AddTask.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 67 | 68 | 71 | -------------------------------------------------------------------------------- /src/components/Button.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 20 | -------------------------------------------------------------------------------- /src/components/Footer.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 16 | -------------------------------------------------------------------------------- /src/components/Header.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 34 | -------------------------------------------------------------------------------- /src/components/Task.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 20 | 21 | 24 | -------------------------------------------------------------------------------- /src/components/Tasks.vue: -------------------------------------------------------------------------------- 1 | 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 | 7 | 8 | 14 | -------------------------------------------------------------------------------- /src/views/Home.vue: -------------------------------------------------------------------------------- 1 | 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 | --------------------------------------------------------------------------------