├── src ├── assets │ ├── main.css │ ├── tailwind.css │ └── previews │ │ ├── Logo.png │ │ ├── home.png │ │ ├── login.png │ │ └── dashboard.png ├── views │ ├── HomeView.vue │ ├── DashboardView.vue │ └── SigninView.vue ├── stores │ └── counter.ts ├── components │ ├── svg │ │ ├── Close.vue │ │ ├── Info.vue │ │ ├── LinkedIn.vue │ │ ├── Delete.vue │ │ ├── Twitter.vue │ │ └── Google.vue │ ├── EmptyCard.vue │ ├── Footer.vue │ ├── Hero.vue │ ├── Tasks.vue │ ├── Navbar.vue │ ├── TaskModal.vue │ └── TaskCard.vue ├── main.ts ├── App.vue ├── firebase.ts └── router │ └── index.ts ├── env.d.ts ├── .vscode ├── extensions.json └── settings.json ├── public ├── _redirects ├── riyad.jpg ├── favicon.ico ├── default-man.jpg ├── favicon-16x16.png ├── favicon-32x32.png ├── apple-touch-icon.png ├── android-chrome-192x192.png ├── android-chrome-512x512.png └── site.webmanifest ├── .eslintrc ├── postcss.config.js ├── tsconfig.config.json ├── tailwind.config.js ├── vite.config.ts ├── .gitignore ├── tsconfig.json ├── package.json ├── README.md └── index.html /src/assets/main.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["Vue.volar"] 3 | } 4 | -------------------------------------------------------------------------------- /public/_redirects: -------------------------------------------------------------------------------- 1 | # Redirects from what the browser requests to what we serve 2 | /* / 200 -------------------------------------------------------------------------------- /public/riyad.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nurRiyad/vuefire-todos/HEAD/public/riyad.jpg -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@antfu", 3 | "rules": { 4 | "no-console":"off" 5 | } 6 | } -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nurRiyad/vuefire-todos/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /src/assets/tailwind.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /public/default-man.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nurRiyad/vuefire-todos/HEAD/public/default-man.jpg -------------------------------------------------------------------------------- /public/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nurRiyad/vuefire-todos/HEAD/public/favicon-16x16.png -------------------------------------------------------------------------------- /public/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nurRiyad/vuefire-todos/HEAD/public/favicon-32x32.png -------------------------------------------------------------------------------- /public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nurRiyad/vuefire-todos/HEAD/public/apple-touch-icon.png -------------------------------------------------------------------------------- /src/assets/previews/Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nurRiyad/vuefire-todos/HEAD/src/assets/previews/Logo.png -------------------------------------------------------------------------------- /src/assets/previews/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nurRiyad/vuefire-todos/HEAD/src/assets/previews/home.png -------------------------------------------------------------------------------- /src/assets/previews/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nurRiyad/vuefire-todos/HEAD/src/assets/previews/login.png -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /public/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nurRiyad/vuefire-todos/HEAD/public/android-chrome-192x192.png -------------------------------------------------------------------------------- /public/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nurRiyad/vuefire-todos/HEAD/public/android-chrome-512x512.png -------------------------------------------------------------------------------- /src/assets/previews/dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nurRiyad/vuefire-todos/HEAD/src/assets/previews/dashboard.png -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": false, 3 | "editor.codeActionsOnSave": { 4 | "source.fixAll": "explicit" 5 | }, 6 | "cSpell.words": [ 7 | "vuefire" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /public/site.webmanifest: -------------------------------------------------------------------------------- 1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} -------------------------------------------------------------------------------- /src/views/HomeView.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /tsconfig.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.node.json", 3 | "ignoreDeprecations": "5.0", 4 | "include": ["vite.config.*", "vitest.config.*", "cypress.config.*", "playwright.config.*"], 5 | "compilerOptions": { 6 | "composite": true, 7 | "types": ["node"] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | darkMode: 'class', 4 | content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'], 5 | theme: { 6 | extend: {}, 7 | }, 8 | daisyui: { 9 | themes: ['dark'], 10 | }, 11 | 12 | plugins: [require('daisyui')], 13 | } 14 | -------------------------------------------------------------------------------- /src/stores/counter.ts: -------------------------------------------------------------------------------- 1 | import { computed, ref } from 'vue' 2 | import { defineStore } from 'pinia' 3 | 4 | export const useCounterStore = defineStore('counter', () => { 5 | const count = ref(0) 6 | const doubleCount = computed(() => count.value * 2) 7 | function increment() { 8 | count.value++ 9 | } 10 | 11 | return { count, doubleCount, increment } 12 | }) 13 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { URL, fileURLToPath } from 'node:url' 2 | 3 | import { defineConfig } from 'vite' 4 | import vue from '@vitejs/plugin-vue' 5 | 6 | // https://vitejs.dev/config/ 7 | export default defineConfig({ 8 | plugins: [vue()], 9 | resolve: { 10 | alias: { 11 | '@': fileURLToPath(new URL('./src', import.meta.url)), 12 | }, 13 | }, 14 | }) 15 | -------------------------------------------------------------------------------- /src/components/svg/Close.vue: -------------------------------------------------------------------------------- 1 | 17 | -------------------------------------------------------------------------------- /src/components/EmptyCard.vue: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /.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 | .DS_Store 12 | dist 13 | dist-ssr 14 | coverage 15 | *.local 16 | 17 | /cypress/videos/ 18 | /cypress/screenshots/ 19 | 20 | # Editor directories and files 21 | !.vscode/extensions.json 22 | .idea 23 | *.suo 24 | *.ntvs* 25 | *.njsproj 26 | *.sln 27 | *.sw? 28 | -------------------------------------------------------------------------------- /src/components/svg/Info.vue: -------------------------------------------------------------------------------- 1 | 16 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.web.json", 3 | "ignoreDeprecations": "5.0", 4 | "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], 5 | "compilerOptions": { 6 | "baseUrl": ".", 7 | "ignoreDeprecations": "5.0", 8 | "paths": { 9 | "@/*": ["./src/*"] 10 | } 11 | }, 12 | 13 | "references": [ 14 | { 15 | "path": "./tsconfig.config.json" 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /src/components/svg/LinkedIn.vue: -------------------------------------------------------------------------------- 1 | 14 | -------------------------------------------------------------------------------- /src/components/Footer.vue: -------------------------------------------------------------------------------- 1 | 15 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { createPinia } from 'pinia' 2 | import { createApp } from 'vue' 3 | 4 | import { autoAnimatePlugin } from '@formkit/auto-animate/vue' 5 | import { VueFire, VueFireAuth } from 'vuefire' 6 | import App from './App.vue' 7 | import router from './router' 8 | 9 | import { firebaseApp } from './firebase' 10 | 11 | import './assets/main.css' 12 | import './assets/tailwind.css' 13 | 14 | const app = createApp(App) 15 | 16 | app.use(createPinia()) 17 | app.use(router) 18 | app.use(VueFire, { 19 | firebaseApp, 20 | modules: [VueFireAuth()], 21 | }) 22 | app.use(autoAnimatePlugin) 23 | 24 | app.mount('#app') 25 | -------------------------------------------------------------------------------- /src/components/svg/Delete.vue: -------------------------------------------------------------------------------- 1 | 14 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 20 | 21 | 28 | -------------------------------------------------------------------------------- /src/components/svg/Twitter.vue: -------------------------------------------------------------------------------- 1 | 14 | -------------------------------------------------------------------------------- /src/firebase.ts: -------------------------------------------------------------------------------- 1 | import { initializeApp } from 'firebase/app' 2 | import { collection, getFirestore } from 'firebase/firestore' 3 | // ... other firebase imports 4 | 5 | export const firebaseApp = initializeApp({ 6 | // your application settings 7 | apiKey: 'AIzaSyAR84yRMSxqodyPoQbyYso0iNo6T--qZ7g', 8 | authDomain: 'personal-project-4ac6f.firebaseapp.com', 9 | projectId: 'personal-project-4ac6f', 10 | storageBucket: 'personal-project-4ac6f.appspot.com', 11 | messagingSenderId: '337096134393', 12 | appId: '1:337096134393:web:edd7878c77fc6add839c28', 13 | }) 14 | 15 | // used for the firestore refs 16 | const db = getFirestore(firebaseApp) 17 | 18 | // here we can export reusable database references 19 | export const todosRef = collection(db, 'todos') 20 | -------------------------------------------------------------------------------- /src/components/Hero.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 30 | -------------------------------------------------------------------------------- /src/components/svg/Google.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /src/router/index.ts: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHistory } from 'vue-router' 2 | import { getCurrentUser } from 'vuefire' 3 | 4 | const HomeView = () => import('@/views/HomeView.vue') 5 | const SigninView = () => import('@/views/SigninView.vue') 6 | const DashboardView = () => import('@/views/DashboardView.vue') 7 | 8 | const router = createRouter({ 9 | history: createWebHistory(import.meta.env.BASE_URL), 10 | routes: [ 11 | { 12 | meta: { requiresAuth: false }, 13 | path: '/', 14 | name: 'home', 15 | component: HomeView, 16 | }, 17 | { 18 | meta: { requiresAuth: true }, 19 | path: '/dashboard', 20 | name: 'dashboard', 21 | component: DashboardView, 22 | }, 23 | { 24 | meta: { requiresAuth: false }, 25 | path: '/signin', 26 | name: 'signin', 27 | component: SigninView, 28 | }, 29 | ], 30 | }) 31 | 32 | router.beforeEach(async (to) => { 33 | if (to.meta.requiresAuth) { 34 | const currentUser = await getCurrentUser() 35 | if (!currentUser) { 36 | return { 37 | path: '/signin', 38 | } 39 | } 40 | } 41 | }) 42 | 43 | export default router 44 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-todos", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "run-p type-check build-only", 8 | "preview": "vite preview", 9 | "build-only": "vite build", 10 | "type-check": "vue-tsc --noEmit", 11 | "lint": "eslint .", 12 | "lint:fix": "eslint . --fix" 13 | }, 14 | "dependencies": { 15 | "@formkit/auto-animate": "^0.8.1", 16 | "firebase": "^10.6.0", 17 | "pinia": "^2.1.7", 18 | "vue": "^3.3.8", 19 | "vue-router": "^4.2.5", 20 | "vuefire": "^3.1.18" 21 | }, 22 | "devDependencies": { 23 | "@antfu/eslint-config": "^0.35.3", 24 | "@rushstack/eslint-patch": "^1.1.4", 25 | "@types/node": "^18.11.12", 26 | "@vitejs/plugin-vue": "^4.0.0", 27 | "@vue/eslint-config-prettier": "^7.0.0", 28 | "@vue/eslint-config-typescript": "^11.0.0", 29 | "@vue/tsconfig": "^0.1.3", 30 | "autoprefixer": "^10.4.13", 31 | "daisyui": "^4.0.7", 32 | "eslint": "^8.35.0", 33 | "eslint-plugin-vue": "^9.3.0", 34 | "npm-run-all": "^4.1.5", 35 | "postcss": "^8.4.21", 36 | "tailwindcss": "^3.2.4", 37 | "typescript": "~4.7.4", 38 | "vite": "^4.0.0", 39 | "vue-tsc": "^1.0.12" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vuefire Todos 2 | 3 | Vue3, Vuefire, Firebase, Tailwindcss powered to-do app. Create, update, delete tasks with ease, and user authentication. Boss up your task game now! 4 | 5 | 6 | 7 | ## Demo 8 | 9 | https://vuefire-todos.netlify.app/ 10 | 11 | > Hosted on [Netlify](https://netlify.com/): 12 | 13 | 14 | ### Built with 15 | 16 |

17 | 18 |

19 | 20 | Vuefire Todos built with [Vue3](https://vuejs.org), [Vuefire](https://vuefire.vuejs.org/) [Vue-Router](https://router.vuejs.org/) & [Tailwind](https://tailwindcss.com/) 21 | 22 | 23 | ## Previews 24 | 25 |

26 | 27 | 28 | 29 | 30 |
31 | Live Demo 32 |
33 |

34 | 35 | 36 | ## Features 37 | 38 | - Client Side Rendering 39 | - Vite-based hot module replacement (HMR) dev environment 40 | - Deploys anywhere with zero config Netlify 41 | - Login with password less email link 42 | - Login with gmail 43 | - Route Protection 44 | - Dom change animation 45 | - Crate Task with description 46 | - Show task my it's status 47 | - Search task my title 48 | 49 | ## Build Setup 50 | 51 | **Requires Node.js 16+** 52 | 53 | ```bash 54 | # install dependencies 55 | yarn install 56 | 57 | # serve in dev mode, with hot reload at localhost:5173 58 | yarn run dev 59 | 60 | # build for production 61 | yarn run build 62 | 63 | # serve in production mode 64 | yarn run preview 65 | 66 | ``` 67 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Vuefire Todos 10 | 11 | 15 | 16 | 17 | 18 | 19 | 20 | 24 | 28 | 29 | 30 | 31 | 32 | 33 | 37 | 41 | 42 | 43 |
44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /src/components/Tasks.vue: -------------------------------------------------------------------------------- 1 | 49 | 50 | 76 | -------------------------------------------------------------------------------- /src/views/DashboardView.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 70 | -------------------------------------------------------------------------------- /src/components/Navbar.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 75 | -------------------------------------------------------------------------------- /src/components/TaskModal.vue: -------------------------------------------------------------------------------- 1 | 44 | 45 | 98 | -------------------------------------------------------------------------------- /src/components/TaskCard.vue: -------------------------------------------------------------------------------- 1 | 65 | 66 | 106 | -------------------------------------------------------------------------------- /src/views/SigninView.vue: -------------------------------------------------------------------------------- 1 | 95 | 96 | 146 | --------------------------------------------------------------------------------