├── .env.example ├── .gitignore ├── README.md ├── babel.config.js ├── netlify.toml ├── package-lock.json ├── package.json ├── postcss.config.js ├── public ├── favicon.ico └── index.html ├── src ├── App.vue ├── assets │ └── css │ │ ├── app.css │ │ └── custom.css ├── components │ ├── ChatList.vue │ ├── ChatMessage.vue │ ├── ChatRoom.vue │ ├── Credits.vue │ ├── Home.vue │ ├── Login.vue │ ├── Nav.vue │ ├── User.vue │ └── UserProfile.vue ├── firebase.js └── main.js ├── tailwind.config.js └── vue.config.js /.env.example: -------------------------------------------------------------------------------- 1 | NODE_ENV=production 2 | 3 | VUE_APP_NAME=Qevoxo 4 | VUE_APP_ENV=production 5 | VUE_APP_DEBUG=false 6 | 7 | VUE_APP_FIREBASE_API= 8 | VUE_APP_FIREBASE_AUTH_DOMAIN= 9 | VUE_APP_FIREBASE_PROJECT_ID= 10 | VUE_APP_FIREBASE_DATABASE_URL= 11 | VUE_APP_FIREBASE_STORAGE_BUCKET= 12 | VUE_APP_FIREBASE_MESSAGING_SENDER_ID= 13 | VUE_APP_FIREBASE_APP_ID= 14 | VUE_APP_FIREBASE_MEASUREMENT_ID= 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | 15 | # Editor directories and files 16 | .idea 17 | .vscode 18 | *.suo 19 | *.ntvs* 20 | *.njsproj 21 | *.sln 22 | *.sw? 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # qevoxo 2 | 3 | Project is a work in progress. 4 | 5 | ## Project setup 6 | ``` 7 | npm install 8 | ``` 9 | 10 | ### Compiles and hot-reloads for development 11 | ``` 12 | npm run serve 13 | ``` 14 | 15 | ### Compiles and minifies for production 16 | ``` 17 | npm run build 18 | ``` 19 | 20 | ### Lints and fixes files 21 | ``` 22 | npm run lint 23 | ``` 24 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | command = "npm run build" 3 | publish = "dist" 4 | 5 | [[redirects]] 6 | from = "/*" 7 | to = "/index.html" 8 | status = 200 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "qevoxo", 3 | "version": "1.2.0", 4 | "private": false, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "@vue/composition-api": "^1.0.0-beta.6", 12 | "core-js": "^3.6.5", 13 | "firebase": "^7.17.1", 14 | "vue": "^2.6.11", 15 | "vue-router": "^3.3.4", 16 | "vuefire": "^2.2.3" 17 | }, 18 | "devDependencies": { 19 | "@fortawesome/fontawesome-free": "^5.13.0", 20 | "@fullhuman/postcss-purgecss": "^2.2.0", 21 | "@tailwindcss/custom-forms": "^0.2.1", 22 | "@vue/cli-plugin-babel": "~4.4.0", 23 | "@vue/cli-plugin-eslint": "~4.4.0", 24 | "@vue/cli-service": "~4.4.0", 25 | "babel-eslint": "^10.1.0", 26 | "eslint": "^6.7.2", 27 | "eslint-plugin-vue": "^6.2.2", 28 | "moment": "^2.26.0", 29 | "simplebar-vue": "^1.5.1", 30 | "tailwindcss": "^1.5", 31 | "vue-template-compiler": "^2.6.11" 32 | }, 33 | "eslintConfig": { 34 | "root": true, 35 | "env": { 36 | "node": true 37 | }, 38 | "extends": [ 39 | "plugin:vue/essential", 40 | "eslint:recommended" 41 | ], 42 | "parserOptions": { 43 | "parser": "babel-eslint" 44 | }, 45 | "rules": {} 46 | }, 47 | "browserslist": [ 48 | "> 1%", 49 | "last 2 versions", 50 | "not dead" 51 | ] 52 | } 53 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | const autoprefixer = require('autoprefixer'); 2 | const tailwindcss = require('tailwindcss'); 3 | const postcssPurgecss = require(`@fullhuman/postcss-purgecss`); 4 | 5 | const purgecss = postcssPurgecss({ 6 | content: [ 7 | './public/**/*.html', 8 | './src/**/*.vue', 9 | ], 10 | 11 | defaultExtractor: content => content.match(/[\w-/:]+(? 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 31 | 32 | -------------------------------------------------------------------------------- /src/assets/css/app.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | 3 | a { 4 | @apply .text-blue-500; 5 | } 6 | 7 | a:hover, 8 | a:focus { 9 | @apply .text-blue-600; 10 | } 11 | 12 | @tailwind components; 13 | 14 | @import './custom.css'; 15 | 16 | @tailwind utilities; 17 | -------------------------------------------------------------------------------- /src/assets/css/custom.css: -------------------------------------------------------------------------------- 1 | .btn { 2 | @apply .inline-block; 3 | @apply .px-4; 4 | @apply .py-0; 5 | @apply .leading-10; 6 | @apply .whitespace-no-wrap; 7 | @apply .rounded-lg; 8 | @apply .text-center; 9 | @apply .text-sm; 10 | @apply .font-medium; 11 | @apply .transition; 12 | @apply .ease-in-out; 13 | @apply .duration-150; 14 | @apply .shadow; 15 | } 16 | 17 | .btn:focus { 18 | @apply .outline-none; 19 | @apply .shadow-outline; 20 | } 21 | 22 | .btn.btn-primary { 23 | @apply .bg-blue-500; 24 | @apply .text-white; 25 | } 26 | 27 | .btn.btn-primary:hover { 28 | @apply .bg-blue-600; 29 | @apply .text-white; 30 | } 31 | 32 | .btn.btn-primary:focus { 33 | @apply .bg-blue-600; 34 | @apply .text-white; 35 | } 36 | 37 | .btn.btn-secondary { 38 | @apply .bg-white; 39 | @apply .text-gray-600; 40 | @apply .shadow; 41 | } 42 | 43 | .btn.btn-secondary:hover { 44 | @apply .text-gray-700; 45 | } 46 | 47 | .btn.btn-secondary:focus { 48 | @apply .text-gray-700; 49 | } 50 | 51 | .btn.btn-danger { 52 | @apply .bg-red-500; 53 | @apply .text-white; 54 | } 55 | 56 | .btn.btn-danger:hover { 57 | @apply .bg-red-600; 58 | @apply .text-white; 59 | } 60 | 61 | .btn.btn-danger:focus { 62 | @apply .bg-red-600; 63 | @apply .text-white; 64 | } 65 | -------------------------------------------------------------------------------- /src/components/ChatList.vue: -------------------------------------------------------------------------------- 1 | 54 | 55 | 100 | -------------------------------------------------------------------------------- /src/components/ChatMessage.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 28 | -------------------------------------------------------------------------------- /src/components/ChatRoom.vue: -------------------------------------------------------------------------------- 1 | 72 | 73 | 137 | 138 | 143 | -------------------------------------------------------------------------------- /src/components/Credits.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 20 | -------------------------------------------------------------------------------- /src/components/Home.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 26 | 27 | -------------------------------------------------------------------------------- /src/components/Login.vue: -------------------------------------------------------------------------------- 1 | 50 | 51 | 88 | 89 | -------------------------------------------------------------------------------- /src/components/Nav.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 49 | -------------------------------------------------------------------------------- /src/components/User.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 32 | -------------------------------------------------------------------------------- /src/components/UserProfile.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 47 | -------------------------------------------------------------------------------- /src/firebase.js: -------------------------------------------------------------------------------- 1 | import firebase from 'firebase/app'; 2 | import 'firebase/firestore'; 3 | import 'firebase/auth'; 4 | import 'firebase/storage'; 5 | 6 | const firebaseConfig = { 7 | apiKey: process.env.VUE_APP_FIREBASE_API, 8 | authDomain: process.env.VUE_APP_FIREBASE_AUTH_DOMAIN, 9 | projectId: process.env.VUE_APP_FIREBASE_PROJECT_ID, 10 | databaseURL: process.env.VUE_APP_FIREBASE_DATABASE_URL, 11 | storageBucket: process.env.VUE_APP_FIREBASE_STORAGE_BUCKET, 12 | messagingSenderId: process.env.VUE_APP_FIREBASE_MESSAGING_SENDER_ID, 13 | appId: process.env.VUE_APP_FIREBASE_APP_ID, 14 | measurementId: process.env.VUE_APP_FIREBASE_MEASUREMENT_ID, 15 | }; 16 | 17 | firebase.initializeApp(firebaseConfig); 18 | 19 | export const db = firebase.firestore(); 20 | export const auth = firebase.auth(); 21 | export const storage = firebase.storage(); 22 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import App from './App.vue'; 3 | import { firestorePlugin } from 'vuefire'; 4 | import VueRouter from 'vue-router'; 5 | import VueCompositionApi from '@vue/composition-api'; 6 | 7 | import './assets/css/app.css'; 8 | import '@fortawesome/fontawesome-free/js/all.js'; 9 | 10 | Vue.use(VueCompositionApi); 11 | Vue.use(VueRouter); 12 | Vue.use(firestorePlugin); 13 | 14 | Vue.config.productionTip = false; 15 | 16 | import Home from './components/Home'; 17 | import ChatRoom from './components/ChatRoom'; 18 | 19 | const router = new VueRouter({ 20 | mode: 'history', 21 | routes: [ 22 | { 23 | path: '/', 24 | component: Home, 25 | name: 'home' 26 | }, 27 | { 28 | path: '/chats/:id', 29 | component: ChatRoom, 30 | name: 'chat' 31 | } 32 | ] 33 | }); 34 | 35 | new Vue({ 36 | router, 37 | render: h => h(App), 38 | }).$mount('#app') 39 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | theme: { 3 | customForms: theme => ({ 4 | default: { 5 | input: { 6 | borderRadius: theme('borderRadius.lg'), 7 | backgroundColor: theme('colors.gray.100'), 8 | '&:focus': { 9 | backgroundColor: theme('colors.white'), 10 | } 11 | }, 12 | textarea: { 13 | borderRadius: theme('borderRadius.md'), 14 | backgroundColor: theme('colors.gray.100'), 15 | '&:focus': { 16 | backgroundColor: theme('colors.white'), 17 | } 18 | }, 19 | select: { 20 | borderRadius: theme('borderRadius.md'), 21 | boxShadow: theme('boxShadow.none'), 22 | backgroundColor: theme('colors.gray.100'), 23 | '&:focus': { 24 | backgroundColor: theme('colors.white'), 25 | } 26 | }, 27 | checkbox: { 28 | backgroundColor: theme('colors.gray.100'), 29 | width: theme('spacing.6'), 30 | height: theme('spacing.6'), 31 | }, 32 | radio: { 33 | backgroundColor: theme('colors.gray.100'), 34 | width: theme('spacing.6'), 35 | height: theme('spacing.6'), 36 | }, 37 | }, 38 | }), 39 | typography: theme => ({ 40 | default: { 41 | css: { 42 | color: theme('colors.gray.600'), 43 | a: { 44 | color: '#0366D6', 45 | '&:hover': { 46 | color: '#035CC1', 47 | }, 48 | }, 49 | }, 50 | }, 51 | }), 52 | extend: { 53 | colors: { 54 | blue: { 55 | 100: '#E6F0FB', 56 | 200: '#C0D9F5', 57 | 300: '#9AC2EF', 58 | 400: '#4F94E2', 59 | 500: '#0366D6', 60 | 600: '#035CC1', 61 | 700: '#023D80', 62 | 800: '#012E60', 63 | 900: '#011F40', 64 | }, 65 | } 66 | } 67 | }, 68 | variants: {}, 69 | plugins: [ 70 | require('@tailwindcss/custom-forms'), 71 | ], 72 | } 73 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | chainWebpack: config => { 3 | config 4 | .plugin('html') 5 | .tap(args => { 6 | args[0].title = 'Qevoxo | Web Walkie Talkie' 7 | return args 8 | }) 9 | } 10 | } 11 | --------------------------------------------------------------------------------