├── Nuxt-3-Firebase-Todo-App ├── .gitignore ├── README.md ├── app.vue ├── assets │ └── css │ │ └── main.css ├── components │ ├── Icons │ │ └── TrashIcon.vue │ ├── Loader.vue │ ├── Navbar.vue │ └── TodoAppComponent.vue ├── composables │ ├── useFirebase.ts │ ├── useFirebaseDb.ts │ └── useState.ts ├── layouts │ └── default.vue ├── nuxt.config.ts ├── package-lock.json ├── package.json ├── pages │ ├── Register.vue │ ├── dashboard.vue │ └── index.vue ├── plugins │ ├── auth.ts │ ├── firebaseAuth.client.ts │ └── firebaseDb.client.ts ├── postcss.config.js ├── server │ ├── api │ │ ├── auth.ts │ │ └── me.ts │ └── middleware │ │ └── user-middleware.ts ├── tailwind.config.js ├── tsconfig.json └── yarn.lock ├── Nuxt-FullStack-Todo-App ├── .gitignore ├── README.md ├── Types │ └── todo.interface.ts ├── app.vue ├── assets │ └── main.css ├── components │ ├── Loader.vue │ ├── Navbar.vue │ └── TodoApp.vue ├── composables │ ├── useToast.ts │ └── useTodoStore.ts ├── layouts │ └── default.vue ├── nuxt.config.ts ├── package-lock.json ├── package.json ├── pages │ └── index.vue ├── plugins │ └── toast.client.ts ├── postcss.config.js ├── server │ ├── api │ │ └── todos │ │ │ ├── [id].delete.ts │ │ │ ├── [id].put.ts │ │ │ ├── create.post.ts │ │ │ └── index.ts │ ├── db │ │ └── index.ts │ ├── models │ │ └── Todo.model.ts │ └── validation.ts ├── tailwind.config.js ├── tsconfig.json └── yarn.lock ├── Nuxt3-Blog ├── .gitignore ├── README.md ├── app.vue ├── assets │ └── main.css ├── components │ ├── AppLoadingBar.vue │ ├── Navbar.vue │ ├── Toc.vue │ └── content │ │ ├── Alert.vue │ │ ├── List.vue │ │ └── Wrong.vue ├── content │ └── blog │ │ └── index.md ├── layouts │ └── default.vue ├── nuxt.config.ts ├── package.json ├── pages │ ├── [...slug].vue │ └── index.vue ├── postcss.config.js ├── public │ └── img │ │ └── image.jpg ├── tailwind.config.js ├── tsconfig.json └── yarn.lock ├── Project Images ├── Netflix-Login-Page.png ├── Nuxt3-Blog.png ├── Nuxt3-Firebase-Login-Page.png ├── Nuxt3-Mongodb-Home-Page.png ├── Vue-Coinbase-Coins.png ├── Vue-Coinbase-Hero.png ├── Vue-Instagram-Home-Page.png ├── Vue-Instagram-Login-Page.png ├── Vue-Pinia-Store.png ├── Vue-Whatsapp-Chat-Page.png └── Vue-Whatsapp-Login-Page.png ├── README.md ├── Vue-Coinbase ├── .gitignore ├── .vscode │ └── extensions.json ├── README.md ├── index.html ├── package-lock.json ├── package.json ├── postcss.config.cjs ├── public │ └── vite.svg ├── src │ ├── App.vue │ ├── Types │ │ ├── coins.interface.ts │ │ └── news.interface.ts │ ├── assets │ │ ├── css │ │ │ └── style.css │ │ └── image │ │ │ ├── coinbase.png │ │ │ └── hero-bg.png │ ├── components │ │ ├── CoinCard.vue │ │ ├── Hero.vue │ │ ├── Icon │ │ │ └── Coin.vue │ │ ├── Loader.vue │ │ ├── Navbar-Top.vue │ │ ├── Navbar.vue │ │ ├── NewsCard.vue │ │ └── Tables.vue │ ├── composables │ │ ├── useFormat.ts │ │ └── usePriceChange.ts │ ├── main.ts │ ├── router │ │ └── index.ts │ ├── utils │ │ ├── coinApi.ts │ │ └── newsApi.ts │ ├── views │ │ ├── CoinView.vue │ │ ├── Home.vue │ │ └── NewsView.vue │ └── vite-env.d.ts ├── tailwind.config.cjs ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts ├── Vue-Instagram-Clone ├── .gitignore ├── .vscode │ └── extensions.json ├── README.md ├── index.html ├── package-lock.json ├── package.json ├── postcss.config.cjs ├── public │ └── vite.svg ├── src │ ├── App.vue │ ├── components │ │ ├── ColorModeSwitch.vue │ │ ├── CommentsComponent.vue │ │ ├── FeedComponent.vue │ │ ├── FeedInput.vue │ │ ├── FeedStories.vue │ │ ├── FeedStory.vue │ │ ├── LoginForm.vue │ │ ├── Navbar.vue │ │ ├── NavbarIcons.vue │ │ ├── PostComponent.vue │ │ ├── ProfileComponent.vue │ │ ├── ProfileImageComponent.vue │ │ ├── RegisterForm.vue │ │ ├── SuggestionComponent.vue │ │ ├── SuggestionProfileImageComponent.vue │ │ └── SuggestionsComponent.vue │ ├── firebaseConfig.js │ ├── main.js │ ├── router │ │ └── index.js │ ├── stores │ │ └── authStore.js │ ├── style.css │ └── views │ │ ├── Feed.vue │ │ ├── Login.vue │ │ ├── Profile.vue │ │ └── Register.vue ├── tailwind.config.cjs ├── vite.config.js └── yarn.lock ├── Vue-Netflix-Clone ├── .gitignore ├── .vscode │ └── extensions.json ├── README.md ├── index.html ├── package-lock.json ├── package.json ├── postcss.config.js ├── public │ └── favicon.ico ├── src │ ├── App.vue │ ├── assets │ │ ├── css │ │ │ └── index.css │ │ └── images │ │ │ ├── Netflix-BG.jpg │ │ │ ├── Netflix-Header.png │ │ │ ├── Netflix-Icon.png │ │ │ └── Netflix-avatar.png │ ├── axios │ │ └── axios.js │ ├── components │ │ ├── Banner.vue │ │ ├── Header.vue │ │ ├── Loader.vue │ │ ├── Navbar.vue │ │ ├── Row.vue │ │ └── __tests__ │ │ │ ├── Header.spec.js │ │ │ ├── authStore.spec.js │ │ │ └── movieStore.spec.js │ ├── main.js │ ├── requests │ │ └── requests.js │ ├── router │ │ └── index.js │ ├── stores │ │ ├── authStore.js │ │ └── movieStore.js │ ├── supabaseConfig.js │ └── views │ │ ├── Home.vue │ │ ├── List.vue │ │ ├── Login.vue │ │ ├── Movie.vue │ │ └── Register.vue ├── tailwind.config.js ├── vite.config.js ├── vitest.config.js └── yarn.lock ├── Vue-Pinia-Store ├── .gitignore ├── .vscode │ └── extensions.json ├── README.md ├── index.html ├── package-lock.json ├── package.json ├── postcss.config.js ├── public │ └── favicon.ico ├── src │ ├── App.vue │ ├── assets │ │ ├── css │ │ │ └── index.css │ │ └── svg │ │ │ └── Pinia.svg │ ├── components │ │ ├── Loader.vue │ │ ├── Navbar.vue │ │ ├── Product_Cards.vue │ │ └── Product_Loader.vue │ ├── main.js │ ├── router │ │ └── index.js │ ├── stores │ │ └── productStore.js │ └── views │ │ ├── Cart.vue │ │ ├── Home.vue │ │ └── Product.vue ├── tailwind.config.js ├── vite.config.js └── yarn.lock └── Vue-Whatsapp-Clone ├── .gitignore ├── .vscode └── extensions.json ├── README.md ├── index.html ├── package-lock.json ├── package.json ├── postcss.config.cjs ├── public └── vite.svg ├── src ├── App.vue ├── assets │ ├── Placeholder.png │ ├── robot.gif │ └── whatsapp-logo.png ├── components │ ├── ChatHeader.vue │ ├── Loader.vue │ ├── MessageContainer.vue │ ├── MessageInput.vue │ ├── Navbar.vue │ └── Sidebar.vue ├── firebaseConfig.js ├── main.js ├── router │ └── index.js ├── store │ └── authStore.js ├── style.css └── views │ ├── Chat.vue │ ├── Login.vue │ ├── Profile.vue │ └── Register.vue ├── tailwind.config.cjs ├── vite.config.js └── yarn.lock /Nuxt-3-Firebase-Todo-App/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log* 3 | .nuxt 4 | .nitro 5 | .cache 6 | .output 7 | .env 8 | dist 9 | -------------------------------------------------------------------------------- /Nuxt-3-Firebase-Todo-App/README.md: -------------------------------------------------------------------------------- 1 | # Nuxt 3 Minimal Starter 2 | 3 | Look at the [nuxt 3 documentation](https://v3.nuxtjs.org) to learn more. 4 | 5 | ## Setup 6 | 7 | Make sure to install the dependencies: 8 | 9 | ```bash 10 | # yarn 11 | yarn install 12 | 13 | # npm 14 | npm install 15 | 16 | # pnpm 17 | pnpm install --shamefully-hoist 18 | ``` 19 | 20 | ## Development Server 21 | 22 | Start the development server on http://localhost:3000 23 | 24 | ```bash 25 | npm run dev 26 | ``` 27 | 28 | ## Production 29 | 30 | Build the application for production: 31 | 32 | ```bash 33 | npm run build 34 | ``` 35 | 36 | Locally preview production build: 37 | 38 | ```bash 39 | npm run preview 40 | ``` 41 | 42 | Checkout the [deployment documentation](https://v3.nuxtjs.org/guide/deploy/presets) for more information. 43 | -------------------------------------------------------------------------------- /Nuxt-3-Firebase-Todo-App/app.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /Nuxt-3-Firebase-Todo-App/assets/css/main.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap'); 2 | @tailwind base; 3 | @tailwind components; 4 | @tailwind utilities; 5 | 6 | @layer base { 7 | body { 8 | @apply bg-[#151515] font-Roboto text-white 9 | } 10 | } 11 | 12 | @layer components { 13 | .grid-layout { 14 | @apply grid place-items-center 15 | } 16 | 17 | .flex-between { 18 | @apply flex justify-between items-center 19 | } 20 | 21 | .flex-layout { 22 | @apply flex justify-between items-center px-4 23 | } 24 | 25 | .flex-center { 26 | @apply flex items-center 27 | } 28 | 29 | .label { 30 | @apply text-white block 31 | } 32 | 33 | .input-style { 34 | @apply appearance-none py-2 px-2 mt-2 w-full rounded-md focus:outline-none focus:ring-1 focus:ring-green-500 bg-gray-400/30 text-white placeholder-gray-400 35 | } 36 | 37 | .error { 38 | @apply font-bold text-red-500 py-2 39 | } 40 | } -------------------------------------------------------------------------------- /Nuxt-3-Firebase-Todo-App/components/Icons/TrashIcon.vue: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | -------------------------------------------------------------------------------- /Nuxt-3-Firebase-Todo-App/components/Loader.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Nuxt-3-Firebase-Todo-App/components/Navbar.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /Nuxt-3-Firebase-Todo-App/components/TodoAppComponent.vue: -------------------------------------------------------------------------------- 1 | 41 | 42 | 76 | 77 | -------------------------------------------------------------------------------- /Nuxt-3-Firebase-Todo-App/composables/useFirebase.ts: -------------------------------------------------------------------------------- 1 | import { useLoadingState, useFirebaseUser } from './useState'; 2 | import { doc, setDoc, getFirestore } from "firebase/firestore"; 3 | import { getAuth, createUserWithEmailAndPassword, signInWithEmailAndPassword, onAuthStateChanged, signOut } from "firebase/auth"; 4 | export const registerUser = async (email: string, password: string) => { 5 | const auth = getAuth(); 6 | const db = getFirestore(); 7 | const response = await createUserWithEmailAndPassword(auth, email, password); 8 | await setDoc(doc(db, "users", response.user.uid), { 9 | id: response.user.uid, 10 | email: response.user.email 11 | }); 12 | return response; 13 | } 14 | 15 | export const loginUser = async (email: string, password: string) => { 16 | const auth = getAuth(); 17 | const response = await signInWithEmailAndPassword(auth, email, password) 18 | return response; 19 | } 20 | 21 | export const initUser = async () => { 22 | const firebaseUser = useFirebaseUser(); 23 | const loadingState = useLoadingState(); 24 | const auth = getAuth(); 25 | firebaseUser.value = auth.currentUser; 26 | const router = useRouter(); 27 | const userCookie: any = useCookie("userCookie"); 28 | onAuthStateChanged(auth, (user) => { 29 | if (user) { 30 | router.push("/dashboard") 31 | } else { 32 | router.push("/") 33 | }; 34 | loadingState.value = false; 35 | firebaseUser.value = user; 36 | userCookie.value = user; 37 | 38 | $fetch("/api/auth", { 39 | method: "POST", 40 | body: { user }, 41 | }); 42 | }); 43 | }; 44 | 45 | export const signOutUser = async () => { 46 | const auth = getAuth(); 47 | await signOut(auth); 48 | } 49 | -------------------------------------------------------------------------------- /Nuxt-3-Firebase-Todo-App/composables/useFirebaseDb.ts: -------------------------------------------------------------------------------- 1 | import { 2 | collection, addDoc, getFirestore, Timestamp 3 | } from "firebase/firestore"; 4 | import { getAuth } from "@firebase/auth"; 5 | export const addTodo = async (todo: string, completed: boolean) => { 6 | const auth = getAuth(); 7 | const db = getFirestore() 8 | const docRef = collection(db, "todos"); 9 | await addDoc(docRef, { 10 | id: auth?.currentUser?.uid, 11 | todo, 12 | completed, 13 | createdAt: Timestamp.fromDate(new Date()) 14 | }); 15 | }; -------------------------------------------------------------------------------- /Nuxt-3-Firebase-Todo-App/composables/useState.ts: -------------------------------------------------------------------------------- 1 | export const useFirebaseUser = () => useState("firebaseUser", () => { }); 2 | export const useLoadingState = () => useState("loadingState", () => true); 3 | -------------------------------------------------------------------------------- /Nuxt-3-Firebase-Todo-App/layouts/default.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Nuxt-3-Firebase-Todo-App/nuxt.config.ts: -------------------------------------------------------------------------------- 1 | // https://v3.nuxtjs.org/api/configuration/nuxt.config 2 | export default defineNuxtConfig({ 3 | modules: [ 4 | "@nuxtjs/tailwindcss" 5 | ], 6 | runtimeConfig: { 7 | FIREBASE_API_KEY: "AIzaSyA2EoYFdCCTCQ7FXyF9VX-DjdFpQ8h5GzU", 8 | FIREBASE_AUTH_DOMAIN: "nuxt-firebase-b75fb.firebaseapp.com", 9 | FIREBASE_PROJECT_ID: "nuxt-firebase-b75fb", 10 | FIREBASE_STORAGE_BUCKET: "nuxt-firebase-b75fb.appspot.com", 11 | FIREBASE_MESSAGING_SENDER_ID: "218542199251", 12 | FIREBASE_APP_ID: "1:218542199251:web:377bedd62925789a5b9f26", 13 | public: { 14 | FIREBASE_API_KEY: "AIzaSyA2EoYFdCCTCQ7FXyF9VX-DjdFpQ8h5GzU", 15 | FIREBASE_AUTH_DOMAIN: "nuxt-firebase-b75fb.firebaseapp.com", 16 | FIREBASE_PROJECT_ID: "nuxt-firebase-b75fb", 17 | FIREBASE_STORAGE_BUCKET: "nuxt-firebase-b75fb.appspot.com", 18 | FIREBASE_MESSAGING_SENDER_ID: "218542199251", 19 | FIREBASE_APP_ID: "1:218542199251:web:377bedd62925789a5b9f26", 20 | } 21 | }, 22 | 23 | css: [ 24 | "@/assets/css/main.css" 25 | ] 26 | }) 27 | -------------------------------------------------------------------------------- /Nuxt-3-Firebase-Todo-App/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "build": "nuxt build", 5 | "dev": "nuxt dev", 6 | "generate": "nuxt generate", 7 | "preview": "nuxt preview", 8 | "postinstall": "nuxt prepare" 9 | }, 10 | "devDependencies": { 11 | "nuxt": "3.0.0-rc.11" 12 | }, 13 | "dependencies": { 14 | "@nuxtjs/tailwindcss": "^5.3.3", 15 | "@vuelidate/core": "^2.0.0", 16 | "@vuelidate/validators": "^2.0.0", 17 | "firebase": "^9.10.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Nuxt-3-Firebase-Todo-App/pages/Register.vue: -------------------------------------------------------------------------------- 1 | 29 | -------------------------------------------------------------------------------- /Nuxt-3-Firebase-Todo-App/pages/dashboard.vue: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /Nuxt-3-Firebase-Todo-App/pages/index.vue: -------------------------------------------------------------------------------- 1 | 26 | -------------------------------------------------------------------------------- /Nuxt-3-Firebase-Todo-App/plugins/auth.ts: -------------------------------------------------------------------------------- 1 | export default defineNuxtPlugin(() => { 2 | addRouteMiddleware('auth', () => { 3 | const { $auth } = useNuxtApp() 4 | if (!$auth?.currentUser?.uid) { 5 | return navigateTo("/") 6 | } 7 | }) 8 | }) -------------------------------------------------------------------------------- /Nuxt-3-Firebase-Todo-App/plugins/firebaseAuth.client.ts: -------------------------------------------------------------------------------- 1 | import { initializeApp } from "firebase/app"; 2 | import { getAuth } from "@firebase/auth"; 3 | export default defineNuxtPlugin((nuxtApp) => { 4 | const config = useRuntimeConfig() 5 | const firebaseConfig = { 6 | apiKey: config.public.FIREBASE_API_KEY, 7 | authDomain: config.public.FIREBASE_AUTH_DOMAIN, 8 | projectId: config.public.FIREBASE_PROJECT_ID, 9 | storageBucket: config.public.FIREBASE_STORAGE_BUCKET, 10 | messagingSenderId: config.public.FIREBASE_MESSAGING_SENDER_ID, 11 | appId: config.public.FIREBASE_APP_ID 12 | }; 13 | const app = initializeApp(firebaseConfig); 14 | initUser(); 15 | const auth = getAuth(app); 16 | nuxtApp.vueApp.provide('auth', auth); 17 | nuxtApp.provide('auth', auth); 18 | }) 19 | -------------------------------------------------------------------------------- /Nuxt-3-Firebase-Todo-App/plugins/firebaseDb.client.ts: -------------------------------------------------------------------------------- 1 | import { initializeApp } from "firebase/app"; 2 | import { getFirestore } from "@firebase/firestore"; 3 | export default defineNuxtPlugin((nuxtApp) => { 4 | const config = useRuntimeConfig() 5 | const firebaseConfig = { 6 | apiKey: config.public.FIREBASE_API_KEY, 7 | authDomain: config.public.FIREBASE_AUTH_DOMAIN, 8 | projectId: config.public.FIREBASE_PROJECT_ID, 9 | storageBucket: config.public.FIREBASE_STORAGE_BUCKET, 10 | messagingSenderId: config.public.FIREBASE_MESSAGING_SENDER_ID, 11 | appId: config.public.FIREBASE_APP_ID 12 | }; 13 | const app = initializeApp(firebaseConfig); 14 | const db = getFirestore(app); 15 | nuxtApp.vueApp.provide('db', db); 16 | nuxtApp.provide('db', db); 17 | }) 18 | -------------------------------------------------------------------------------- /Nuxt-3-Firebase-Todo-App/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /Nuxt-3-Firebase-Todo-App/server/api/auth.ts: -------------------------------------------------------------------------------- 1 | import type { IncomingMessage, ServerResponse } from "http"; 2 | export default async (req: IncomingMessage, res: ServerResponse) => { 3 | // @ts-ignore 4 | if (req.method !== "POST") return "Must be a post request"; 5 | 6 | // @ts-ignore 7 | const { user } = await useBody(req); 8 | 9 | // @ts-ignore 10 | req.user = user; 11 | return { updated : true } 12 | } -------------------------------------------------------------------------------- /Nuxt-3-Firebase-Todo-App/server/api/me.ts: -------------------------------------------------------------------------------- 1 | import type { IncomingMessage, ServerResponse } from "http"; 2 | export default async (req: IncomingMessage, res: ServerResponse) => { 3 | // @ts-ignore 4 | const user = req.user; 5 | return user ? user : "User is signed out"; 6 | } -------------------------------------------------------------------------------- /Nuxt-3-Firebase-Todo-App/server/middleware/user-middleware.ts: -------------------------------------------------------------------------------- 1 | import type { IncomingMessage, ServerResponse } from "http"; 2 | export default async (req: IncomingMessage, res: ServerResponse) => { 3 | // @ts-ignore 4 | const userCookie = useCookie(req, "userCookie"); 5 | // @ts-ignore 6 | req.user = userCookie; 7 | } -------------------------------------------------------------------------------- /Nuxt-3-Firebase-Todo-App/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: [], 4 | theme: { 5 | extend: { 6 | fontFamily: { 7 | "Roboto": "Roboto" 8 | } 9 | }, 10 | }, 11 | plugins: [], 12 | } 13 | -------------------------------------------------------------------------------- /Nuxt-3-Firebase-Todo-App/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // https://v3.nuxtjs.org/concepts/typescript 3 | "extends": "./.nuxt/tsconfig.json" 4 | } 5 | -------------------------------------------------------------------------------- /Nuxt-FullStack-Todo-App/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log* 3 | .nuxt 4 | .nitro 5 | .cache 6 | .output 7 | .env 8 | dist 9 | -------------------------------------------------------------------------------- /Nuxt-FullStack-Todo-App/README.md: -------------------------------------------------------------------------------- 1 | # Nuxt 3 Minimal Starter 2 | 3 | Look at the [nuxt 3 documentation](https://v3.nuxtjs.org) to learn more. 4 | 5 | ## Setup 6 | 7 | Make sure to install the dependencies: 8 | 9 | ```bash 10 | # yarn 11 | yarn install 12 | 13 | # npm 14 | npm install 15 | 16 | # pnpm 17 | pnpm install --shamefully-hoist 18 | ``` 19 | 20 | ## Development Server 21 | 22 | Start the development server on http://localhost:3000 23 | 24 | ```bash 25 | npm run dev 26 | ``` 27 | 28 | ## Production 29 | 30 | Build the application for production: 31 | 32 | ```bash 33 | npm run build 34 | ``` 35 | 36 | Locally preview production build: 37 | 38 | ```bash 39 | npm run preview 40 | ``` 41 | 42 | Checkout the [deployment documentation](https://v3.nuxtjs.org/guide/deploy/presets) for more information. 43 | -------------------------------------------------------------------------------- /Nuxt-FullStack-Todo-App/Types/todo.interface.ts: -------------------------------------------------------------------------------- 1 | export interface TodoInterface { 2 | id: string, 3 | todo: string 4 | } -------------------------------------------------------------------------------- /Nuxt-FullStack-Todo-App/app.vue: -------------------------------------------------------------------------------- 1 | 8 | 15 | -------------------------------------------------------------------------------- /Nuxt-FullStack-Todo-App/assets/main.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap'); 2 | @tailwind base; 3 | @tailwind components; 4 | @tailwind utilities; 5 | 6 | @layer base { 7 | body { 8 | @apply bg-[#151515] font-Roboto text-white 9 | } 10 | } 11 | 12 | @layer components { 13 | .grid-layout { 14 | @apply grid place-items-center 15 | } 16 | 17 | .flex-between { 18 | @apply flex justify-between items-center 19 | } 20 | 21 | .flex-layout { 22 | @apply flex justify-between items-center px-4 23 | } 24 | 25 | .flex-center { 26 | @apply flex items-center 27 | } 28 | 29 | .label { 30 | @apply text-white block 31 | } 32 | 33 | .input-style { 34 | @apply appearance-none py-2 px-2 mt-2 w-full rounded-md focus: outline-none focus:ring-1 focus:ring-green-500 bg-gray-400/30 text-white placeholder-gray-400 35 | } 36 | 37 | .error { 38 | @apply font-bold text-red-500 py-2 39 | } 40 | } -------------------------------------------------------------------------------- /Nuxt-FullStack-Todo-App/components/Loader.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Nuxt-FullStack-Todo-App/components/Navbar.vue: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /Nuxt-FullStack-Todo-App/components/TodoApp.vue: -------------------------------------------------------------------------------- 1 | 30 | 74 | 75 | -------------------------------------------------------------------------------- /Nuxt-FullStack-Todo-App/composables/useToast.ts: -------------------------------------------------------------------------------- 1 | import { useToast as toasty } from "vue-toastification"; 2 | export default function () { 3 | const toast = toasty(); 4 | return toast; 5 | }; 6 | -------------------------------------------------------------------------------- /Nuxt-FullStack-Todo-App/composables/useTodoStore.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from "pinia"; 2 | import { TodoInterface } from "~~/Types/todo.interface"; 3 | import useToast from "./useToast"; 4 | export const useTodoStore = defineStore({ 5 | id: "todoStore", 6 | state: () => ({ 7 | todos: [] as TodoInterface[], 8 | stateLoading: false, 9 | todosLoading: false, 10 | }), 11 | 12 | actions: { 13 | // get all the todos from the db 14 | async getAllTodos() { 15 | try { 16 | this.todosLoading = true; 17 | const data = await $fetch("/api/todos"); 18 | this.todos = data; 19 | this.todosLoading = false; 20 | return data as TodoInterface[] 21 | } catch (err) { 22 | useToast().error(err.message) 23 | } 24 | }, 25 | 26 | async createTodo(task: string, complete: boolean) { 27 | try { 28 | this.stateLoading = true; 29 | await $fetch("/api/todos/create", { 30 | method: "POST", 31 | body: { task, complete } 32 | }); 33 | 34 | await this.getAllTodos(); 35 | this.stateLoading = false; 36 | useToast().success("Todo created successfully") 37 | } catch (err) { 38 | useToast().error(err.message) 39 | } 40 | }, 41 | 42 | async updateTodo(id: string, complete: boolean) { 43 | try { 44 | await $fetch(`/api/todos/${id}`, { 45 | method: "PUT", 46 | body: { complete } 47 | }); 48 | await this.getAllTodos(); 49 | useToast().success("Todo successfully updated"); 50 | } catch (err) { 51 | useToast().error(err.message) 52 | } 53 | }, 54 | 55 | async deleteTodo(id: string) { 56 | try { 57 | await $fetch(`/api/todos/${id}`, { 58 | method: "DELETE", 59 | body: { id } 60 | }); 61 | await this.getAllTodos(); 62 | useToast().success("Todo successfully deleted") 63 | } catch (err) { 64 | useToast().error(err.message) 65 | } 66 | }, 67 | } 68 | 69 | }) -------------------------------------------------------------------------------- /Nuxt-FullStack-Todo-App/layouts/default.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Nuxt-FullStack-Todo-App/nuxt.config.ts: -------------------------------------------------------------------------------- 1 | // https://v3.nuxtjs.org/api/configuration/nuxt.config 2 | export default defineNuxtConfig({ 3 | modules: ["@nuxtjs/tailwindcss", "@pinia/nuxt", "nuxt-icon"], 4 | runtimeConfig: { 5 | MONGO_URI: process.env.MONGO_URI 6 | }, 7 | 8 | // register nitro plugin 9 | nitro: { 10 | plugins: ["@/server/db/index.ts"] 11 | }, 12 | css: ["@/assets/main.css"], 13 | 14 | // transpile packages 15 | build: { 16 | transpile: ["vue-toastification"] 17 | } 18 | }); 19 | -------------------------------------------------------------------------------- /Nuxt-FullStack-Todo-App/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "build": "nuxt build", 5 | "dev": "nuxt dev", 6 | "generate": "nuxt generate", 7 | "preview": "nuxt preview", 8 | "postinstall": "nuxt prepare" 9 | }, 10 | "devDependencies": { 11 | "@nuxtjs/tailwindcss": "^5.3.3", 12 | "autoprefixer": "^10.4.12", 13 | "nuxt": "3.0.0-rc.11", 14 | "nuxt-icon": "^0.1.6", 15 | "postcss": "^8.4.17", 16 | "tailwindcss": "^3.1.8" 17 | }, 18 | "dependencies": { 19 | "@pinia/nuxt": "^0.4.2", 20 | "joi": "^17.6.2", 21 | "mongoose": "^6.13.6", 22 | "pinia": "^2.0.22", 23 | "vue-toastification": "^2.0.0-rc.5" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Nuxt-FullStack-Todo-App/pages/index.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Nuxt-FullStack-Todo-App/plugins/toast.client.ts: -------------------------------------------------------------------------------- 1 | import Toast from "vue-toastification"; 2 | import "vue-toastification/dist/index.css"; 3 | export default defineNuxtPlugin((nuxtApp) => { 4 | nuxtApp.vueApp.use(Toast); 5 | }); -------------------------------------------------------------------------------- /Nuxt-FullStack-Todo-App/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /Nuxt-FullStack-Todo-App/server/api/todos/[id].delete.ts: -------------------------------------------------------------------------------- 1 | import TodoModel from "~~/server/models/Todo.model"; 2 | 3 | export default defineEventHandler(async (event) => { 4 | const id = event.context.params.id; 5 | 6 | try { 7 | await TodoModel.findByIdAndDelete(id); 8 | return { 9 | message: "Todo successfully deleted" 10 | } 11 | } catch (err) { 12 | throw createError({ 13 | message: err.message 14 | }) 15 | } 16 | }); 17 | -------------------------------------------------------------------------------- /Nuxt-FullStack-Todo-App/server/api/todos/[id].put.ts: -------------------------------------------------------------------------------- 1 | import TodoModel from "~~/server/models/Todo.model"; 2 | export default defineEventHandler(async (event) => { 3 | const body = await useBody(event) 4 | const id = event.context.params.id; 5 | try { 6 | await TodoModel.findByIdAndUpdate(id, body); 7 | return { 8 | message: "Todo successfully updated" 9 | } 10 | } catch (err) { 11 | throw createError({ 12 | message: err.message 13 | }) 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /Nuxt-FullStack-Todo-App/server/api/todos/create.post.ts: -------------------------------------------------------------------------------- 1 | import { TodoSchema } from "~~/server/validation"; 2 | import TodoModel from "~~/server/models/Todo.model"; 3 | 4 | export default defineEventHandler(async (event) => { 5 | // get data from body 6 | const body = await useBody(event); 7 | 8 | // validate the data gotten from the body 9 | let { error } = TodoSchema.validate(body); 10 | 11 | if (error) { 12 | throw createError({ 13 | message: error.message, 14 | statusCode: 400, 15 | fatal: false 16 | 17 | }) 18 | }; 19 | 20 | try { 21 | await TodoModel.create(body); 22 | 23 | return { 24 | message: "Todo created" 25 | } 26 | } catch (err) { 27 | throw createError({ 28 | message: error.message 29 | }) 30 | } 31 | 32 | }) -------------------------------------------------------------------------------- /Nuxt-FullStack-Todo-App/server/api/todos/index.ts: -------------------------------------------------------------------------------- 1 | import TodoModel from "~~/server/models/Todo.model"; 2 | 3 | export default defineEventHandler(async (event) => { 4 | // return all the todos from the db 5 | return await TodoModel.find().sort({"createdAt": -1}); 6 | }) -------------------------------------------------------------------------------- /Nuxt-FullStack-Todo-App/server/db/index.ts: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose"; 2 | import { Nitro } from "nitropack"; 3 | export default async (_nitroApp: Nitro) => { 4 | const config = useRuntimeConfig(); 5 | try { 6 | const conn = await mongoose.connect(config.MONGO_URI) 7 | console.log(`MongoDB connected: ${conn.connection.host}`) 8 | } catch (err) { 9 | console.log(err.message); 10 | process.exit(1); 11 | } 12 | } -------------------------------------------------------------------------------- /Nuxt-FullStack-Todo-App/server/models/Todo.model.ts: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose"; 2 | 3 | const schema: mongoose.Schema = new mongoose.Schema({ 4 | task: { 5 | type: String, 6 | required: true 7 | }, 8 | 9 | complete: { 10 | type: Boolean, 11 | default: false 12 | } 13 | }, { 14 | timestamps: true 15 | }); 16 | 17 | export default mongoose.model("Todo", schema) -------------------------------------------------------------------------------- /Nuxt-FullStack-Todo-App/server/validation.ts: -------------------------------------------------------------------------------- 1 | import Joi from "joi"; 2 | 3 | // Todo validation 4 | export const TodoSchema = Joi.object({ 5 | task: Joi.string().min(3).required(), 6 | complete: Joi.bool() 7 | }); -------------------------------------------------------------------------------- /Nuxt-FullStack-Todo-App/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: [ 4 | "./components/**/*.{js,vue,ts}", 5 | "./layouts/**/*.vue", 6 | "./pages/**/*.vue", 7 | "./plugins/**/*.{js,ts}", 8 | "./nuxt.config.{js,ts}", 9 | ], 10 | theme: { 11 | extend: { 12 | fontFamily: { 13 | "Roboto": "Roboto" 14 | } 15 | }, 16 | }, 17 | plugins: [], 18 | }; 19 | -------------------------------------------------------------------------------- /Nuxt-FullStack-Todo-App/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // https://v3.nuxtjs.org/concepts/typescript 3 | "extends": "./.nuxt/tsconfig.json" 4 | } 5 | -------------------------------------------------------------------------------- /Nuxt3-Blog/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log* 3 | .nuxt 4 | .nitro 5 | .cache 6 | .output 7 | .env 8 | dist 9 | -------------------------------------------------------------------------------- /Nuxt3-Blog/README.md: -------------------------------------------------------------------------------- 1 | # Nuxt 3 Minimal Starter 2 | 3 | Look at the [nuxt 3 documentation](https://v3.nuxtjs.org) to learn more. 4 | 5 | ## Setup 6 | 7 | Make sure to install the dependencies: 8 | 9 | ```bash 10 | # yarn 11 | yarn install 12 | 13 | # npm 14 | npm install 15 | 16 | # pnpm 17 | pnpm install --shamefully-hoist 18 | ``` 19 | 20 | ## Development Server 21 | 22 | Start the development server on http://localhost:3000 23 | 24 | ```bash 25 | npm run dev 26 | ``` 27 | 28 | ## Production 29 | 30 | Build the application for production: 31 | 32 | ```bash 33 | npm run build 34 | ``` 35 | 36 | Locally preview production build: 37 | 38 | ```bash 39 | npm run preview 40 | ``` 41 | 42 | Checkout the [deployment documentation](https://v3.nuxtjs.org/guide/deploy/presets) for more information. 43 | -------------------------------------------------------------------------------- /Nuxt3-Blog/app.vue: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /Nuxt3-Blog/assets/main.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap'); 2 | @tailwind base; 3 | @tailwind components; 4 | @tailwind utilities; 5 | 6 | @layer base { 7 | body { 8 | @apply bg-[#151515] font-Roboto text-white 9 | } 10 | } 11 | 12 | @layer components { 13 | .grid-layout { 14 | @apply grid place-items-center 15 | } 16 | 17 | .flex-between { 18 | @apply flex justify-between items-center 19 | } 20 | 21 | .flex-layout { 22 | @apply flex justify-between items-center px-4 23 | } 24 | 25 | .flex-center { 26 | @apply flex items-center 27 | } 28 | } -------------------------------------------------------------------------------- /Nuxt3-Blog/components/AppLoadingBar.vue: -------------------------------------------------------------------------------- 1 | 74 | 75 | 86 | 87 | -------------------------------------------------------------------------------- /Nuxt3-Blog/components/Navbar.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Nuxt3-Blog/components/Toc.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 21 | 22 | 37 | 38 | -------------------------------------------------------------------------------- /Nuxt3-Blog/components/content/Alert.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | -------------------------------------------------------------------------------- /Nuxt3-Blog/components/content/List.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | -------------------------------------------------------------------------------- /Nuxt3-Blog/components/content/Wrong.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | -------------------------------------------------------------------------------- /Nuxt3-Blog/layouts/default.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Nuxt3-Blog/nuxt.config.ts: -------------------------------------------------------------------------------- 1 | // https://v3.nuxtjs.org/api/configuration/nuxt.config 2 | export default defineNuxtConfig({ 3 | modules: ["@nuxtjs/tailwindcss", "@nuxt/content", "nuxt-icon"], 4 | css: ["@/assets/main.css"], 5 | }); 6 | -------------------------------------------------------------------------------- /Nuxt3-Blog/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "build": "nuxt build", 5 | "dev": "nuxt dev", 6 | "generate": "nuxt generate", 7 | "preview": "nuxt preview", 8 | "postinstall": "nuxt prepare" 9 | }, 10 | "devDependencies": { 11 | "@nuxt/content": "^2.1.1", 12 | "@nuxtjs/tailwindcss": "^5.3.5", 13 | "@tailwindcss/line-clamp": "^0.4.2", 14 | "@tailwindcss/typography": "^0.5.7", 15 | "nuxt": "3.0.0-rc.11", 16 | "nuxt-icon": "^0.1.6" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Nuxt3-Blog/pages/[...slug].vue: -------------------------------------------------------------------------------- 1 | 5 | 36 | -------------------------------------------------------------------------------- /Nuxt3-Blog/pages/index.vue: -------------------------------------------------------------------------------- 1 | 15 | 60 | -------------------------------------------------------------------------------- /Nuxt3-Blog/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /Nuxt3-Blog/public/img/image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selemondev/8-Awesome-Vue-Projects/a33fa2f765a6ae802bb90481bcac94a5f5f032d3/Nuxt3-Blog/public/img/image.jpg -------------------------------------------------------------------------------- /Nuxt3-Blog/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: [ 4 | "./components/**/*.{js,vue,ts}", 5 | "./layouts/**/*.vue", 6 | "./pages/**/*.vue", 7 | "./plugins/**/*.{js,ts}", 8 | "./nuxt.config.{js,ts}", 9 | ], 10 | theme: { 11 | extend: { 12 | fontFamily: { 13 | "Roboto": "Roboto" 14 | } 15 | }, 16 | }, 17 | plugins: [require("@tailwindcss/typography"), require("@tailwindcss/line-clamp")], 18 | }; 19 | -------------------------------------------------------------------------------- /Nuxt3-Blog/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // https://v3.nuxtjs.org/concepts/typescript 3 | "extends": "./.nuxt/tsconfig.json" 4 | } 5 | -------------------------------------------------------------------------------- /Project Images/Netflix-Login-Page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selemondev/8-Awesome-Vue-Projects/a33fa2f765a6ae802bb90481bcac94a5f5f032d3/Project Images/Netflix-Login-Page.png -------------------------------------------------------------------------------- /Project Images/Nuxt3-Blog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selemondev/8-Awesome-Vue-Projects/a33fa2f765a6ae802bb90481bcac94a5f5f032d3/Project Images/Nuxt3-Blog.png -------------------------------------------------------------------------------- /Project Images/Nuxt3-Firebase-Login-Page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selemondev/8-Awesome-Vue-Projects/a33fa2f765a6ae802bb90481bcac94a5f5f032d3/Project Images/Nuxt3-Firebase-Login-Page.png -------------------------------------------------------------------------------- /Project Images/Nuxt3-Mongodb-Home-Page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selemondev/8-Awesome-Vue-Projects/a33fa2f765a6ae802bb90481bcac94a5f5f032d3/Project Images/Nuxt3-Mongodb-Home-Page.png -------------------------------------------------------------------------------- /Project Images/Vue-Coinbase-Coins.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selemondev/8-Awesome-Vue-Projects/a33fa2f765a6ae802bb90481bcac94a5f5f032d3/Project Images/Vue-Coinbase-Coins.png -------------------------------------------------------------------------------- /Project Images/Vue-Coinbase-Hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selemondev/8-Awesome-Vue-Projects/a33fa2f765a6ae802bb90481bcac94a5f5f032d3/Project Images/Vue-Coinbase-Hero.png -------------------------------------------------------------------------------- /Project Images/Vue-Instagram-Home-Page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selemondev/8-Awesome-Vue-Projects/a33fa2f765a6ae802bb90481bcac94a5f5f032d3/Project Images/Vue-Instagram-Home-Page.png -------------------------------------------------------------------------------- /Project Images/Vue-Instagram-Login-Page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selemondev/8-Awesome-Vue-Projects/a33fa2f765a6ae802bb90481bcac94a5f5f032d3/Project Images/Vue-Instagram-Login-Page.png -------------------------------------------------------------------------------- /Project Images/Vue-Pinia-Store.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selemondev/8-Awesome-Vue-Projects/a33fa2f765a6ae802bb90481bcac94a5f5f032d3/Project Images/Vue-Pinia-Store.png -------------------------------------------------------------------------------- /Project Images/Vue-Whatsapp-Chat-Page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selemondev/8-Awesome-Vue-Projects/a33fa2f765a6ae802bb90481bcac94a5f5f032d3/Project Images/Vue-Whatsapp-Chat-Page.png -------------------------------------------------------------------------------- /Project Images/Vue-Whatsapp-Login-Page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selemondev/8-Awesome-Vue-Projects/a33fa2f765a6ae802bb90481bcac94a5f5f032d3/Project Images/Vue-Whatsapp-Login-Page.png -------------------------------------------------------------------------------- /Vue-Coinbase/.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 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /Vue-Coinbase/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["Vue.volar"] 3 | } 4 | -------------------------------------------------------------------------------- /Vue-Coinbase/README.md: -------------------------------------------------------------------------------- 1 | # Vue 3 + TypeScript + Vite 2 | 3 | This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 ` 12 | 13 | 14 | -------------------------------------------------------------------------------- /Vue-Coinbase/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-crypto-dashboard", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vue-tsc --noEmit && vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "@heroicons/vue": "^2.0.11", 13 | "axios": "^0.27.2", 14 | "dayjs": "^1.11.5", 15 | "millify": "^5.0.1", 16 | "vue": "^3.2.37", 17 | "vue-router": "^4.1.5", 18 | "vue3-smooth-scroll": "^0.8.1" 19 | }, 20 | "devDependencies": { 21 | "@tailwindcss/line-clamp": "^0.4.2", 22 | "@vitejs/plugin-vue": "^3.1.0", 23 | "autoprefixer": "^10.4.12", 24 | "postcss": "^8.4.16", 25 | "tailwindcss": "^3.1.8", 26 | "typescript": "^4.6.4", 27 | "vite": "^3.1.0", 28 | "vue-tsc": "^0.40.4" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Vue-Coinbase/postcss.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /Vue-Coinbase/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Vue-Coinbase/src/App.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /Vue-Coinbase/src/Types/coins.interface.ts: -------------------------------------------------------------------------------- 1 | 2 | export interface ICoin { 3 | uuid: string; 4 | symbol: string; 5 | name: string; 6 | color: null | string; 7 | iconUrl: string; 8 | marketCap: string; 9 | price: string; 10 | listedAt: number; 11 | tier: number; 12 | change: string; 13 | rank: number; 14 | sparkline: string[]; 15 | lowVolume: boolean; 16 | coinrankingUrl: string; 17 | "24hVolume": string; 18 | btcPrice: string; 19 | } 20 | -------------------------------------------------------------------------------- /Vue-Coinbase/src/Types/news.interface.ts: -------------------------------------------------------------------------------- 1 | export interface INews { 2 | name: string; 3 | url: string; 4 | description: string; 5 | about?: About[]; 6 | datePublished: string; 7 | category?: Category; 8 | } 9 | 10 | export interface About { 11 | _type: AboutType; 12 | readLink: string; 13 | name: string; 14 | } 15 | 16 | export enum AboutType { 17 | Thing = "Thing", 18 | } 19 | 20 | export enum Category { 21 | Business = "Business", 22 | ScienceAndTechnology = "ScienceAndTechnology", 23 | } 24 | 25 | 26 | -------------------------------------------------------------------------------- /Vue-Coinbase/src/assets/css/style.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Inter&display=swap'); 2 | @tailwind base; 3 | @tailwind components; 4 | @tailwind utilities; 5 | 6 | 7 | @layer base { 8 | body { 9 | @apply min-h-screen w-full font-Inter bg-[#030922] text-white 10 | } 11 | } 12 | 13 | @layer components { 14 | .grid-center { 15 | @apply grid place-items-center 16 | } 17 | 18 | .flex-center { 19 | @apply flex justify-center items-center 20 | } 21 | 22 | .flex-between { 23 | @apply flex justify-between items-center 24 | } 25 | 26 | .flex-around { 27 | @apply flex justify-around items-center 28 | } 29 | 30 | .mobile-li-tags, 31 | .tags { 32 | @apply p-1 font-bold cursor-pointer text-white transition duration-200 ease-in 33 | } 34 | 35 | .active { 36 | @apply text-blue-500 37 | } 38 | 39 | .box1, 40 | .box2, 41 | .box3 { 42 | margin: 5px; 43 | width: 35px; 44 | height: 3px; 45 | background-color: #fff; 46 | transition: all 400ms cubic-bezier(.84, .06, .52, 1.8); 47 | } 48 | 49 | .sidebar { 50 | height: 100%; 51 | width: 250px; 52 | top: -0.2%; 53 | left: 0; 54 | position: fixed; 55 | z-index: 50; 56 | background: #000; 57 | display: inline-block; 58 | list-style: none; 59 | transition: all 0.5s; 60 | } 61 | 62 | .sidebar li { 63 | margin: 10px; 64 | } 65 | 66 | .sidebar li a { 67 | text-decoration: none; 68 | font-size: 20px; 69 | } 70 | 71 | .rotate .box1 { 72 | transform: rotate(40deg) translate(8px, 3px); 73 | } 74 | 75 | .rotate .box3 { 76 | transform: rotate(-45deg) translate(8px, -5px); 77 | } 78 | 79 | .rotate .box2 { 80 | opacity: 0; 81 | } 82 | 83 | .navbar-li-tag { 84 | @apply cursor-pointer hover:text-blue-800 transition duration-200 ease-in 85 | } 86 | 87 | .animated-content { 88 | animation: scrolling 20s linear infinite; 89 | } 90 | 91 | .animated-content:hover { 92 | animation-play-state: paused; 93 | } 94 | 95 | .animated-content li { 96 | width: 20%; 97 | } 98 | 99 | .content:before, 100 | .content:after { 101 | position: absolute; 102 | top: 0; 103 | width: 10rem; 104 | height: 3em; 105 | content: ""; 106 | z-index: 1; 107 | } 108 | 109 | .content:before { 110 | left: 0; 111 | background: linear-gradient(to right, #111 0%, transparent 100%); 112 | } 113 | 114 | .content:after { 115 | right: 0; 116 | background: linear-gradient(to left, #111 0%, transparent 100%); 117 | } 118 | 119 | @keyframes scrolling { 120 | 0% { 121 | transform: translateX(0); 122 | } 123 | 124 | 100% { 125 | transform: translateX(-200%); 126 | } 127 | } 128 | } -------------------------------------------------------------------------------- /Vue-Coinbase/src/assets/image/coinbase.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selemondev/8-Awesome-Vue-Projects/a33fa2f765a6ae802bb90481bcac94a5f5f032d3/Vue-Coinbase/src/assets/image/coinbase.png -------------------------------------------------------------------------------- /Vue-Coinbase/src/assets/image/hero-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selemondev/8-Awesome-Vue-Projects/a33fa2f765a6ae802bb90481bcac94a5f5f032d3/Vue-Coinbase/src/assets/image/hero-bg.png -------------------------------------------------------------------------------- /Vue-Coinbase/src/components/CoinCard.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | -------------------------------------------------------------------------------- /Vue-Coinbase/src/components/Hero.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | -------------------------------------------------------------------------------- /Vue-Coinbase/src/components/Icon/Coin.vue: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /Vue-Coinbase/src/components/Loader.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /Vue-Coinbase/src/components/Navbar-Top.vue: -------------------------------------------------------------------------------- 1 | 18 | -------------------------------------------------------------------------------- /Vue-Coinbase/src/components/Navbar.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 78 | 79 | -------------------------------------------------------------------------------- /Vue-Coinbase/src/components/NewsCard.vue: -------------------------------------------------------------------------------- 1 | 33 | -------------------------------------------------------------------------------- /Vue-Coinbase/src/composables/useFormat.ts: -------------------------------------------------------------------------------- 1 | import millify from "millify"; 2 | const format = (value: number | string | any) => { 3 | return millify(value) 4 | }; 5 | export default format; -------------------------------------------------------------------------------- /Vue-Coinbase/src/composables/usePriceChange.ts: -------------------------------------------------------------------------------- 1 | const priceChanged = (value: string | number | any) => { 2 | if (value.toString().includes("-")) { 3 | return value; 4 | } else { 5 | return "" 6 | } 7 | }; 8 | 9 | export default priceChanged; -------------------------------------------------------------------------------- /Vue-Coinbase/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import "./assets/css/style.css"; 3 | import App from './App.vue' 4 | import router from "./router"; 5 | import VueSmoothScroll from 'vue3-smooth-scroll'; 6 | const app = createApp(App) 7 | app.use(router) 8 | app.use(VueSmoothScroll) 9 | app.mount('#app') 10 | -------------------------------------------------------------------------------- /Vue-Coinbase/src/router/index.ts: -------------------------------------------------------------------------------- 1 | import { createRouter , createWebHistory } from "vue-router"; 2 | import Home from "../views/Home.vue"; 3 | const routes = [ 4 | { 5 | path: "/", 6 | name: "Home", 7 | component: Home 8 | }, 9 | 10 | { 11 | path: "/coinView", 12 | name: "CoinView", 13 | component: () => import("../views/CoinView.vue") 14 | }, 15 | 16 | { 17 | path: "/newsView", 18 | name: "NewsView", 19 | component: () => import("../views/NewsView.vue") 20 | } 21 | ]; 22 | 23 | const router = createRouter({ 24 | history: createWebHistory(import.meta.env.BASE_URL), 25 | linkActiveClass: 'active', 26 | routes 27 | }); 28 | 29 | 30 | export default router; -------------------------------------------------------------------------------- /Vue-Coinbase/src/utils/coinApi.ts: -------------------------------------------------------------------------------- 1 | export const options = { 2 | method: 'GET', 3 | headers: { 4 | 'X-RapidAPI-Key': '1750abdb2cmshd17289e6b27b806p1d2308jsncd5b6d529efc', 5 | 'X-RapidAPI-Host': 'coinranking1.p.rapidapi.com' 6 | } 7 | }; 8 | export const newsOptions = { 9 | method: 'GET', 10 | headers: { 11 | 'X-BingApis-SDK': 'true', 12 | 'X-RapidAPI-Key': '1750abdb2cmshd17289e6b27b806p1d2308jsncd5b6d529efc', 13 | 'X-RapidAPI-Host': 'bing-news-search1.p.rapidapi.com' 14 | } 15 | }; 16 | 17 | export const useFetch = async (url:string, options:any) => { 18 | const response = await fetch(url, options); 19 | const data = await response.json(); 20 | return data; 21 | } 22 | -------------------------------------------------------------------------------- /Vue-Coinbase/src/utils/newsApi.ts: -------------------------------------------------------------------------------- 1 | export const newsOptions = { 2 | method: 'GET', 3 | headers: { 4 | 'X-BingApis-SDK': 'true', 5 | 'X-RapidAPI-Key': '1750abdb2cmshd17289e6b27b806p1d2308jsncd5b6d529efc', 6 | 'X-RapidAPI-Host': 'bing-news-search1.p.rapidapi.com' 7 | } 8 | } 9 | 10 | export const useFetch = async (url:string, options:any) => { 11 | const response = await fetch(url, options); 12 | const data = await response.json(); 13 | return data; 14 | } -------------------------------------------------------------------------------- /Vue-Coinbase/src/views/CoinView.vue: -------------------------------------------------------------------------------- 1 | 20 | -------------------------------------------------------------------------------- /Vue-Coinbase/src/views/Home.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | -------------------------------------------------------------------------------- /Vue-Coinbase/src/views/NewsView.vue: -------------------------------------------------------------------------------- 1 | 18 | 31 | -------------------------------------------------------------------------------- /Vue-Coinbase/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module '*.vue' { 4 | import type { DefineComponent } from 'vue' 5 | const component: DefineComponent<{}, {}, any> 6 | export default component 7 | } 8 | -------------------------------------------------------------------------------- /Vue-Coinbase/tailwind.config.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"], 4 | darkMode: "class", 5 | theme: { 6 | extend: { 7 | fontFamily: { 8 | 'Inter': 'Inter' 9 | } 10 | }, 11 | }, 12 | plugins: [ 13 | require('@tailwindcss/line-clamp'), 14 | ], 15 | }; 16 | -------------------------------------------------------------------------------- /Vue-Coinbase/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "module": "ESNext", 6 | "moduleResolution": "Node", 7 | "strict": true, 8 | "jsx": "preserve", 9 | "sourceMap": true, 10 | "resolveJsonModule": true, 11 | "isolatedModules": true, 12 | "esModuleInterop": true, 13 | "lib": ["ESNext", "DOM"], 14 | "skipLibCheck": true 15 | }, 16 | "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], 17 | "references": [{ "path": "./tsconfig.node.json" }] 18 | } 19 | -------------------------------------------------------------------------------- /Vue-Coinbase/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["vite.config.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /Vue-Coinbase/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import vue from '@vitejs/plugin-vue' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [vue()] 7 | }) 8 | -------------------------------------------------------------------------------- /Vue-Instagram-Clone/.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 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /Vue-Instagram-Clone/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["Vue.volar"] 3 | } 4 | -------------------------------------------------------------------------------- /Vue-Instagram-Clone/README.md: -------------------------------------------------------------------------------- 1 | # Vue 3 + Vite 2 | 3 | This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 ` 12 | 13 | 14 | -------------------------------------------------------------------------------- /Vue-Instagram-Clone/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-instagram-clone", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "@faker-js/faker": "^7.6.0", 13 | "@iconify/vue": "^4.0.0", 14 | "@vuelidate/core": "^2.0.0", 15 | "@vuelidate/validators": "^2.0.0", 16 | "@vueuse/core": "^9.4.0", 17 | "firebase": "^9.13.0", 18 | "pinia": "^2.0.23", 19 | "tailwind-scrollbar-hide": "^1.1.7", 20 | "vue": "^3.2.41", 21 | "vue-router": "^4.1.6", 22 | "vue-timeago3": "^2.3.0", 23 | "vue-toastification": "^2.0.0-rc.5", 24 | "vue3-emoji-picker": "^1.1.4" 25 | }, 26 | "devDependencies": { 27 | "@vitejs/plugin-vue": "^3.2.0", 28 | "autoprefixer": "^10.4.13", 29 | "postcss": "^8.4.18", 30 | "tailwindcss": "^3.2.1", 31 | "vite": "^3.2.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Vue-Instagram-Clone/postcss.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /Vue-Instagram-Clone/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Vue-Instagram-Clone/src/App.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /Vue-Instagram-Clone/src/components/ColorModeSwitch.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | -------------------------------------------------------------------------------- /Vue-Instagram-Clone/src/components/CommentsComponent.vue: -------------------------------------------------------------------------------- 1 | 24 | -------------------------------------------------------------------------------- /Vue-Instagram-Clone/src/components/FeedComponent.vue: -------------------------------------------------------------------------------- 1 | 23 | -------------------------------------------------------------------------------- /Vue-Instagram-Clone/src/components/FeedStories.vue: -------------------------------------------------------------------------------- 1 | 18 | -------------------------------------------------------------------------------- /Vue-Instagram-Clone/src/components/FeedStory.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /Vue-Instagram-Clone/src/components/LoginForm.vue: -------------------------------------------------------------------------------- 1 | 43 | 44 | -------------------------------------------------------------------------------- /Vue-Instagram-Clone/src/components/Navbar.vue: -------------------------------------------------------------------------------- 1 | 14 | -------------------------------------------------------------------------------- /Vue-Instagram-Clone/src/components/NavbarIcons.vue: -------------------------------------------------------------------------------- 1 | 18 | -------------------------------------------------------------------------------- /Vue-Instagram-Clone/src/components/ProfileImageComponent.vue: -------------------------------------------------------------------------------- 1 | 11 | 21 | -------------------------------------------------------------------------------- /Vue-Instagram-Clone/src/components/SuggestionComponent.vue: -------------------------------------------------------------------------------- 1 | 14 | -------------------------------------------------------------------------------- /Vue-Instagram-Clone/src/components/SuggestionProfileImageComponent.vue: -------------------------------------------------------------------------------- 1 | 32 | -------------------------------------------------------------------------------- /Vue-Instagram-Clone/src/components/SuggestionsComponent.vue: -------------------------------------------------------------------------------- 1 | 34 | 35 | -------------------------------------------------------------------------------- /Vue-Instagram-Clone/src/firebaseConfig.js: -------------------------------------------------------------------------------- 1 | import { initializeApp } from "firebase/app"; 2 | import { getAuth } from "firebase/auth"; 3 | import { getFirestore } from "firebase/firestore"; 4 | import { getStorage } from "firebase/storage"; 5 | const firebaseConfig = { 6 | apiKey: "AIzaSyBRJGxOCLOJ9po2qh0JIO9r3jAvfjfIHNE", 7 | authDomain: "nuxt-instagram-clone.firebaseapp.com", 8 | projectId: "nuxt-instagram-clone", 9 | storageBucket: "nuxt-instagram-clone.appspot.com", 10 | messagingSenderId: "1084219948983", 11 | appId: "1:1084219948983:web:8422a0fc3709ee89ee3232" 12 | }; 13 | 14 | const app = initializeApp(firebaseConfig); 15 | const auth = getAuth(app); 16 | const db = getFirestore(app); 17 | const storage = getStorage(app); 18 | export { 19 | auth, 20 | db, 21 | storage 22 | } -------------------------------------------------------------------------------- /Vue-Instagram-Clone/src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | import router from './router' 4 | import timeago from 'vue-timeago3'; 5 | import { createPinia } from 'pinia'; 6 | import Toast, { POSITION } from "vue-toastification"; 7 | import "vue-toastification/dist/index.css"; 8 | import "./style.css"; 9 | const app = createApp(App); 10 | app.use(createPinia()) 11 | app.use(timeago) 12 | app.use(router) 13 | app.use(Toast, { 14 | position: POSITION.TOP_CENTER 15 | }); 16 | app.mount('#app') -------------------------------------------------------------------------------- /Vue-Instagram-Clone/src/router/index.js: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHistory } from "vue-router"; 2 | import { auth } from "../firebaseConfig"; 3 | import { onAuthStateChanged } from "firebase/auth"; 4 | import Login from "../views/Login.vue"; 5 | const routes = [ 6 | { 7 | path: "/", 8 | name: "login", 9 | component: Login, 10 | meta: { 11 | auth: false, 12 | } 13 | }, 14 | 15 | { 16 | path: "/register", 17 | name: "register", 18 | component: () => import("../views/Register.vue"), 19 | meta: { 20 | auth: false, 21 | } 22 | }, 23 | 24 | { 25 | path: "/profile", 26 | name: "profile", 27 | component: () => import("../views/Profile.vue"), 28 | meta: { 29 | auth: true, 30 | } 31 | }, 32 | 33 | { 34 | path: "/feed", 35 | name: "feed", 36 | component: () => import("../views/Feed.vue"), 37 | meta: { 38 | auth: true, 39 | } 40 | } 41 | ]; 42 | 43 | const router = createRouter({ 44 | history: createWebHistory(import.meta.env.BASE_URL), 45 | routes: routes 46 | }); 47 | 48 | 49 | const currentUser = () => { 50 | return new Promise((resolve, reject) => { 51 | const unsubscribe = onAuthStateChanged(auth, (user) => { 52 | unsubscribe(); 53 | resolve(user); 54 | }, 55 | reject 56 | ) 57 | }) 58 | }; 59 | 60 | router.beforeEach(async (to, from, next) => { 61 | if (to.matched.some((record) => record.meta.auth)) { 62 | if (await currentUser()) { 63 | next(); 64 | } else { 65 | next("/"); 66 | } 67 | } else { 68 | next(); 69 | } 70 | }); 71 | 72 | export default router; -------------------------------------------------------------------------------- /Vue-Instagram-Clone/src/stores/authStore.js: -------------------------------------------------------------------------------- 1 | import { defineStore, acceptHMRUpdate } from "pinia"; 2 | import { auth, db } from "../firebaseConfig"; 3 | import { createUserWithEmailAndPassword, signInWithEmailAndPassword, signOut } from "firebase/auth"; 4 | import { setDoc, doc, Timestamp, updateDoc } from "firebase/firestore"; 5 | export const useAuthStore = defineStore({ 6 | id: "auth", 7 | state: () => ({ 8 | userToken: JSON.parse(localStorage.getItem("token")), 9 | userImage: JSON.parse(localStorage.getItem("profile")), 10 | username: JSON.parse(localStorage.getItem("username")) 11 | }), 12 | 13 | actions: { 14 | async registerUser(username, email, password) { 15 | const response = await createUserWithEmailAndPassword(auth, email, password); 16 | this.userToken = response?.user?.uid; 17 | await setDoc(doc(db, "users", response.user.uid), { 18 | id: response.user.uid, 19 | email: response.user.email, 20 | username: username, 21 | avatar: "", 22 | avatarPath: "", 23 | createdAt: Timestamp.fromDate(new Date()), 24 | online: true, 25 | }); 26 | localStorage.setItem("token", JSON.stringify(this.userToken)); 27 | }, 28 | 29 | async loginUser(email,password) { 30 | const response = await signInWithEmailAndPassword(auth, email, password); 31 | this.userToken = response?.user?.uid; 32 | await updateDoc(doc(db, "users", response.user.uid), { 33 | online: true 34 | }); 35 | localStorage.setItem("token", JSON.stringify(this.userToken)); 36 | }, 37 | 38 | async signOutUser() { 39 | await signOut(auth); 40 | this.userToken = null; 41 | localStorage.removeItem("token"); 42 | localStorage.removeItem("profile"); 43 | }, 44 | 45 | async saveProfileImage(profile) { 46 | this.userImage = profile; 47 | localStorage.setItem("profile", JSON.stringify(this.userImage)); 48 | }, 49 | 50 | async saveUsername(username) { 51 | this.username = username; 52 | localStorage.setItem("username", JSON.stringify(this.username)); 53 | } 54 | } 55 | }); 56 | 57 | if (import.meta.hot) { 58 | import.meta.hot.accept(acceptHMRUpdate(useAuthStore, import.meta.hot)) 59 | } -------------------------------------------------------------------------------- /Vue-Instagram-Clone/src/style.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap'); 2 | @tailwind base; 3 | @tailwind components; 4 | @tailwind utilities; 5 | 6 | @layer base { 7 | body { 8 | @apply w-full min-h-screen font-Roboto bg-white dark:bg-gray-900 9 | } 10 | } 11 | 12 | @layer components { 13 | .grid-center { 14 | @apply grid place-items-center 15 | } 16 | 17 | .flex-center { 18 | @apply flex justify-center items-center 19 | } 20 | 21 | .flex-between { 22 | @apply flex justify-between items-center 23 | } 24 | 25 | .flex-around { 26 | @apply flex justify-around items-center 27 | } 28 | 29 | .navbar-btn { 30 | @apply py-2 px-4 rounded-md bg-[#ec5761] hover:bg-[#E5515B] text-white transition duration-200 ease-in 31 | } 32 | 33 | .form-label { 34 | @apply block mt-2 dark:text-white 35 | } 36 | 37 | .form-input { 38 | @apply appearance-none py-2 px-2 w-full border border-gray-300 mt-2 rounded-md focus:outline-none focus:ring-1 focus:ring-[#E5515B] placeholder-gray-500 dark:bg-gray-600 dark:placeholder-gray-200 dark:border dark:border-gray-600 dark:text-gray-200 39 | } 40 | 41 | .form-btn { 42 | @apply w-full py-2 text-white bg-[#ec5761] hover:bg-[#E5515B] rounded-md transition-effect 43 | } 44 | 45 | .error { 46 | @apply text-red-500 my-2 font-bold dark:font-normal 47 | } 48 | 49 | .transition-effect { 50 | @apply transition duration-200 ease-in 51 | } 52 | 53 | .navbar-search { 54 | @apply appearance-none focus:outline-none py-1.5 px-2 w-28 rounded-md bg-gray-200 placeholder-gray-500 focus:ring-1 focus:ring-[#ec5761] dark:text-white dark:bg-gray-800 lg:w-72 55 | } 56 | 57 | .icon-style { 58 | @apply w-6 h-6 md:w-9 md:h-9 59 | } 60 | } -------------------------------------------------------------------------------- /Vue-Instagram-Clone/src/views/Feed.vue: -------------------------------------------------------------------------------- 1 | 2 | 5 | 10 | -------------------------------------------------------------------------------- /Vue-Instagram-Clone/src/views/Login.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /Vue-Instagram-Clone/src/views/Profile.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /Vue-Instagram-Clone/src/views/Register.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /Vue-Instagram-Clone/tailwind.config.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"], 4 | darkMode: "class", 5 | theme: { 6 | extend: { 7 | fontFamily: { 8 | "Roboto": "Roboto" 9 | } 10 | }, 11 | }, 12 | plugins: [require("tailwind-scrollbar-hide")], 13 | }; 14 | -------------------------------------------------------------------------------- /Vue-Instagram-Clone/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import vue from '@vitejs/plugin-vue' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [vue()] 7 | }) 8 | -------------------------------------------------------------------------------- /Vue-Netflix-Clone/.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 | .env 17 | 18 | /cypress/videos/ 19 | /cypress/screenshots/ 20 | 21 | # Editor directories and files 22 | .vscode/* 23 | !.vscode/extensions.json 24 | .idea 25 | *.suo 26 | *.ntvs* 27 | *.njsproj 28 | *.sln 29 | *.sw? 30 | -------------------------------------------------------------------------------- /Vue-Netflix-Clone/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"] 3 | } 4 | -------------------------------------------------------------------------------- /Vue-Netflix-Clone/README.md: -------------------------------------------------------------------------------- 1 | # Vue Netflix Clone 2 | 3 | This project is built using [Vue 3](https://vuejs.org/) , [Pinia](https://pinia.vuejs.org/), [TailwindCss](https://tailwindcss.com/), [Movie-Trailer](https://www.npmjs.com/package/movie-trailer), [Vueuse](https://vueuse.org/), [Vuelidate](https://vuelidate-next.netlify.app), [Vue-Toastification](https://github.com/Maronato/vue-toastification/tree/next), [Supabase](https://supabase.com/) and [Youtube-Component](https://www.npmjs.com/package/youtube-vue3). 4 | 5 | ## Recommended IDE Setup 6 | 7 | [VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). 8 | 9 | ## Customize configuration 10 | 11 | See [Vite Configuration Reference](https://vitejs.dev/config/). 12 | 13 | ## Project Setup 14 | 15 | Get your TMDB API Key from [TMDB](https://developers.themoviedb.org/3) 16 | 17 | ```sh 18 | npm install 19 | ``` 20 | 21 | ### Compile and Hot-Reload for Development 22 | 23 | ```sh 24 | npm run dev 25 | ``` 26 | 27 | ### Compile and Minify for Production 28 | 29 | ```sh 30 | npm run build 31 | ``` 32 | -------------------------------------------------------------------------------- /Vue-Netflix-Clone/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Netflix App 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Vue-Netflix-Clone/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-netflix-clone", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "vite build", 7 | "preview": "vite preview --port 4173", 8 | "test:unit": "vitest --environment jsdom", 9 | "vitest:ui": "vitest --ui" 10 | }, 11 | "dependencies": { 12 | "@heroicons/vue": "^2.0.4", 13 | "@supabase/supabase-js": "^1.35.6", 14 | "@tailwindcss/line-clamp": "^0.4.0", 15 | "@vuelidate/core": "^2.0.0-alpha.44", 16 | "@vuelidate/validators": "^2.0.0-alpha.31", 17 | "@vueuse/core": "^9.1.1", 18 | "axios": "^0.27.2", 19 | "jsdom": "^20.0.1", 20 | "movie-trailer": "^2.1.0", 21 | "pinia": "^2.0.17", 22 | "tailwind-scrollbar-hide": "^1.1.7", 23 | "vue": "^3.2.37", 24 | "vue-router": "^4.1.3", 25 | "vue-toastification": "^2.0.0-rc.5", 26 | "youtube-vue3": "^0.1.15" 27 | }, 28 | "devDependencies": { 29 | "@testing-library/vue": "^6.6.1", 30 | "@vitejs/plugin-vue": "^3.0.1", 31 | "@vitest/ui": "^0.24.1", 32 | "autoprefixer": "^10.4.8", 33 | "postcss": "^8.4.16", 34 | "tailwindcss": "^3.1.8", 35 | "vite": "^3.0.4", 36 | "vitest": "^0.24.1" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Vue-Netflix-Clone/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /Vue-Netflix-Clone/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selemondev/8-Awesome-Vue-Projects/a33fa2f765a6ae802bb90481bcac94a5f5f032d3/Vue-Netflix-Clone/public/favicon.ico -------------------------------------------------------------------------------- /Vue-Netflix-Clone/src/App.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | -------------------------------------------------------------------------------- /Vue-Netflix-Clone/src/assets/css/index.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap'); 2 | @tailwind base; 3 | @tailwind components; 4 | @tailwind utilities; 5 | 6 | @layer base { 7 | body { 8 | @apply bg-[#141414] font-Roboto 9 | } 10 | } 11 | 12 | @layer components { 13 | .grid-layout { 14 | @apply grid place-items-center 15 | } 16 | 17 | .flex-between { 18 | @apply flex justify-between items-center 19 | } 20 | 21 | .flex-layout { 22 | @apply flex justify-between items-center px-4 23 | } 24 | 25 | .flex-center { 26 | @apply flex items-center 27 | } 28 | 29 | .label { 30 | @apply text-white block 31 | } 32 | 33 | .input-style { 34 | @apply appearance-none py-2 px-2 mt-2 w-full rounded-md focus:outline-none focus:ring-1 focus:ring-red-500 bg-gray-400/30 text-white placeholder-gray-400 35 | } 36 | 37 | .error { 38 | @apply font-bold text-red-500 py-2 39 | } 40 | 41 | .navbarLink { 42 | @apply text-white cursor-pointer hover:text-red-500 transition duration-200 ease-in 43 | } 44 | 45 | .icon-style { 46 | @apply w-6 h-6 text-white 47 | } 48 | 49 | .btn { 50 | @apply flex items-center gap-x-2 rounded-md px-5 py-1 text-sm font-bold transition duration-200 ease-in hover:text-white md:mt-5 md:py-2.5 md:px-8 md:text-xl; 51 | } 52 | .box1, 53 | .box2, 54 | .box3 { 55 | margin: 5px; 56 | width: 35px; 57 | height: 3px; 58 | background-color: #fff; 59 | transition: all 400ms cubic-bezier(.84, .06, .52, 1.8); 60 | } 61 | 62 | .sidebar { 63 | height: 100%; 64 | width: 250px; 65 | top: -0.2%; 66 | left: 0; 67 | position: fixed; 68 | z-index: 50; 69 | background: #000; 70 | display: inline-block; 71 | list-style: none; 72 | transition: all 0.5s; 73 | } 74 | 75 | .sidebar li { 76 | margin: 10px; 77 | } 78 | 79 | .sidebar li a { 80 | text-decoration: none; 81 | font-size: 20px; 82 | } 83 | 84 | .rotate .box1 { 85 | transform: rotate(40deg) translate(8px, 3px); 86 | } 87 | 88 | .rotate .box3 { 89 | transform: rotate(-45deg) translate(8px, -5px); 90 | } 91 | 92 | .rotate .box2 { 93 | opacity: 0; 94 | } 95 | 96 | } -------------------------------------------------------------------------------- /Vue-Netflix-Clone/src/assets/images/Netflix-BG.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selemondev/8-Awesome-Vue-Projects/a33fa2f765a6ae802bb90481bcac94a5f5f032d3/Vue-Netflix-Clone/src/assets/images/Netflix-BG.jpg -------------------------------------------------------------------------------- /Vue-Netflix-Clone/src/assets/images/Netflix-Header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selemondev/8-Awesome-Vue-Projects/a33fa2f765a6ae802bb90481bcac94a5f5f032d3/Vue-Netflix-Clone/src/assets/images/Netflix-Header.png -------------------------------------------------------------------------------- /Vue-Netflix-Clone/src/assets/images/Netflix-Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selemondev/8-Awesome-Vue-Projects/a33fa2f765a6ae802bb90481bcac94a5f5f032d3/Vue-Netflix-Clone/src/assets/images/Netflix-Icon.png -------------------------------------------------------------------------------- /Vue-Netflix-Clone/src/assets/images/Netflix-avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selemondev/8-Awesome-Vue-Projects/a33fa2f765a6ae802bb90481bcac94a5f5f032d3/Vue-Netflix-Clone/src/assets/images/Netflix-avatar.png -------------------------------------------------------------------------------- /Vue-Netflix-Clone/src/axios/axios.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | const instance = axios.create({ 3 | baseURL:"https://api.themoviedb.org/3", 4 | }); 5 | export default instance; -------------------------------------------------------------------------------- /Vue-Netflix-Clone/src/components/Banner.vue: -------------------------------------------------------------------------------- 1 | 16 | -------------------------------------------------------------------------------- /Vue-Netflix-Clone/src/components/Header.vue: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /Vue-Netflix-Clone/src/components/Loader.vue: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /Vue-Netflix-Clone/src/components/Row.vue: -------------------------------------------------------------------------------- 1 | 24 | -------------------------------------------------------------------------------- /Vue-Netflix-Clone/src/components/__tests__/Header.spec.js: -------------------------------------------------------------------------------- 1 | import Header from "../Header.vue" 2 | import { render } from "@testing-library/vue"; 3 | describe("Header", () => { 4 | it("Should render a navigation button", () => { 5 | const { getByText } = render(Header); 6 | const button = getByText("Sign In"); 7 | expect(button).toBeTruthy(); 8 | }) 9 | }) -------------------------------------------------------------------------------- /Vue-Netflix-Clone/src/components/__tests__/authStore.spec.js: -------------------------------------------------------------------------------- 1 | import { createPinia, setActivePinia } from "pinia"; 2 | import { useAuthStore } from "../../stores/authStore"; 3 | 4 | // Here we are testing the authStore and making sure that before any logic is executed, the store is empty. 5 | describe("Test authStore", () => { 6 | beforeEach(() => { 7 | setActivePinia(createPinia()); 8 | }); 9 | test("The authStore state properties should all be empty", () => { 10 | const authStore = useAuthStore(); 11 | expect(authStore.userData).toBe(null) 12 | expect(authStore.registerErrorMsg).toBe("") 13 | expect(authStore.registerLoading).toBe(false) 14 | expect(authStore.loginErrorMsg).toBe("") 15 | expect(authStore.loginLoading).toBe(false) 16 | expect(authStore.logOutErrorMsg).toBe("") 17 | expect(authStore.logOutLoading).toBe(false) 18 | }) 19 | }) -------------------------------------------------------------------------------- /Vue-Netflix-Clone/src/components/__tests__/movieStore.spec.js: -------------------------------------------------------------------------------- 1 | import { setActivePinia, createPinia } from "pinia"; 2 | import { useMovieStore } from "../../stores/movieStore"; 3 | describe("Test movieStore", () => { 4 | beforeEach(() => { 5 | setActivePinia(createPinia()); 6 | }); 7 | test("The movieStore should be empty", () => { 8 | const movieStore = useMovieStore(); 9 | expect(movieStore.movies).toStrictEqual([]); 10 | expect(movieStore.movieExists).toBe(false); 11 | }) 12 | }) -------------------------------------------------------------------------------- /Vue-Netflix-Clone/src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import { createPinia } from 'pinia' 3 | import App from './App.vue'; 4 | import router from './router'; 5 | import Toast, { POSITION } from "vue-toastification"; 6 | import "vue-toastification/dist/index.css"; 7 | import "./assets/css/index.css"; 8 | const app = createApp(App) 9 | app.use(createPinia()) 10 | app.use(router) 11 | app.use(Toast, { 12 | position: POSITION.TOP_CENTER 13 | }); 14 | app.mount('#app') 15 | -------------------------------------------------------------------------------- /Vue-Netflix-Clone/src/requests/requests.js: -------------------------------------------------------------------------------- 1 | const API_KEY = "63ef9c1da41cd3c843dcec9ed2264b73" 2 | const requests = { 3 | fetchTrending:`/trending/all/week?api_key=${API_KEY}&language=en-US`, 4 | fetchNetflixOriginals:`/discover/tv?api_key=${API_KEY}&with_networks=213`, 5 | fetchTopRated:`/movie/top_rated?api_key=${API_KEY}&language=en-US`, 6 | fetchActionMovies:`/discover/movie?api_key=${API_KEY}&with_genres=28`, 7 | fetchComedyMovies:`/discover/movie?api_key=${API_KEY}&with_genres=35`, 8 | fetchHorrorMovies:`/discover/movie?api_key=${API_KEY}&with_genres=27`, 9 | fetchAnimationMovies:`/discover/movie?api_key=${API_KEY}&with_genres=16`, 10 | fetchDocumentaries:`/discover/movie?api_key=${API_KEY}&with_genres=99`, 11 | } 12 | export default requests; -------------------------------------------------------------------------------- /Vue-Netflix-Clone/src/router/index.js: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHistory } from 'vue-router' 2 | import Login from '../views/Login.vue'; 3 | import { useAuthStore } from '../stores/authStore'; 4 | const routes = [ 5 | { 6 | path: '/', 7 | name: 'login', 8 | component: Login, 9 | meta: { 10 | auth: false 11 | } 12 | }, 13 | { 14 | path: '/register', 15 | name: 'register', 16 | component: () => import('../views/Register.vue'), 17 | meta: { 18 | auth: false, 19 | } 20 | }, 21 | { 22 | path: '/home', 23 | name: 'home', 24 | component: () => import("../views/Home.vue"), 25 | meta: { 26 | auth: true 27 | } 28 | }, 29 | { 30 | path: '/movie/:id', 31 | name: 'movie', 32 | component: () => import("../views/Movie.vue"), 33 | meta: { 34 | auth: true 35 | } 36 | }, 37 | { 38 | path: '/list', 39 | name: 'list', 40 | component: () => import("../views/List.vue"), 41 | meta: { 42 | auth: true 43 | } 44 | }, 45 | ]; 46 | const router = createRouter({ 47 | history: createWebHistory(import.meta.env.BASE_URL), 48 | routes: routes 49 | }); 50 | 51 | const currentUser = () => { 52 | return new Promise((resolve, reject) => { 53 | const authStore = useAuthStore(); 54 | const token = authStore.userData; 55 | resolve(token); 56 | reject 57 | }) 58 | } 59 | 60 | router.beforeEach( async (to, from, next) => { 61 | if(to.matched.some((record) => record.meta.auth)) { 62 | if(await currentUser()) { 63 | next(); 64 | } else { 65 | next("/") 66 | } 67 | } else { 68 | next(); 69 | } 70 | }) 71 | 72 | 73 | export default router; 74 | 75 | -------------------------------------------------------------------------------- /Vue-Netflix-Clone/src/stores/authStore.js: -------------------------------------------------------------------------------- 1 | import { defineStore, acceptHMRUpdate } from "pinia"; 2 | import { supabase } from "../supabaseConfig"; 3 | export const useAuthStore = defineStore({ 4 | id: "auth", 5 | state:() => ({ 6 | userData: JSON.parse(localStorage.getItem("user")), 7 | registerErrorMsg: "", 8 | registerLoading: false, 9 | loginErrorMsg: "", 10 | loginLoading: false, 11 | logOutLoading: false, 12 | logOutErrorMsg: "", 13 | }), 14 | 15 | actions: { 16 | async registerUser(email, password) { 17 | this.registerLoading = true; 18 | const { error } = await supabase.auth.signUp({ 19 | email: email, 20 | password: password 21 | }); 22 | const auth = supabase.auth.user(); 23 | this.userData = auth.id; 24 | this.registerLoading = false; 25 | localStorage.setItem("user", JSON.stringify(this.userData)); 26 | this.registerErrorMsg = error?.message; 27 | }, 28 | 29 | async loginUser(email, password) { 30 | this.loginLoading = true; 31 | const { error } = await supabase.auth.signIn({ 32 | email: email, 33 | password: password 34 | }); 35 | 36 | const auth = supabase.auth.user(); 37 | this.userData = auth.id; 38 | this.loginLoading = false; 39 | localStorage.setItem("user", JSON.stringify(this.userData)); 40 | this.loginErrorMsg = error?.message; 41 | }, 42 | 43 | async logOut() { 44 | this.logOutLoading = true; 45 | const { error } = await supabase.auth.signOut(); 46 | this.userData = null; 47 | this.logOutLoading = false; 48 | localStorage.removeItem("user"); 49 | this.logOutErrorMsg = error?.message; 50 | }, 51 | } 52 | }); 53 | 54 | if( import.meta.hot ) { 55 | import.meta.hot.accept(acceptHMRUpdate(useAuthStore, import.meta.hot)); 56 | } 57 | -------------------------------------------------------------------------------- /Vue-Netflix-Clone/src/stores/movieStore.js: -------------------------------------------------------------------------------- 1 | import { defineStore, acceptHMRUpdate } from "pinia"; 2 | import { useStorage } from "@vueuse/core"; 3 | export const useMovieStore = defineStore({ 4 | id: "movie", 5 | state:() => ({ 6 | movies: useStorage("movies", []), 7 | movieExists: false, 8 | }), 9 | 10 | getters: { 11 | MoviesExist: (state) => (movie) => { 12 | const movieId = state.movies.find((i) => i.title === movie.title); 13 | return movieId ? state.movieExists = true : state.movieExists = false; 14 | } 15 | }, 16 | 17 | actions: { 18 | addMovie(movie) { 19 | const movieId = this.movies.find((i) => i.title === movie.title); 20 | console.log(movieId); 21 | if (movieId) { 22 | movieId.exists = true; 23 | } else { 24 | this.movies.push({...movie, exists: false }) 25 | localStorage.setItem("movies", JSON.stringify(movie)); 26 | } 27 | }, 28 | 29 | removeMovie(movie) { 30 | this.movieExists = false; 31 | this.movies = this.movies.filter((i) => i.id !== movie.id); 32 | } 33 | } 34 | }); 35 | 36 | if( import.meta.hot ) { 37 | import.meta.hot.accept(acceptHMRUpdate(useMovieStore, import.meta.hot)); 38 | } -------------------------------------------------------------------------------- /Vue-Netflix-Clone/src/supabaseConfig.js: -------------------------------------------------------------------------------- 1 | import { createClient } from '@supabase/supabase-js' 2 | const supabaseUrl = "https://maibsiymodtnkvrzhgst.supabase.co"; 3 | const supabaseAnonKey = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Im1haWJzaXltb2R0bmt2cnpoZ3N0Iiwicm9sZSI6ImFub24iLCJpYXQiOjE2NjQ1MzI1MTMsImV4cCI6MTk4MDEwODUxM30.z221LolPH7AVf_vuaj12Zvv1a-2kvPGl8kgpm9ShVvg" 4 | export const supabase = createClient(supabaseUrl, supabaseAnonKey); -------------------------------------------------------------------------------- /Vue-Netflix-Clone/src/views/Home.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 31 | -------------------------------------------------------------------------------- /Vue-Netflix-Clone/src/views/List.vue: -------------------------------------------------------------------------------- 1 | 12 | -------------------------------------------------------------------------------- /Vue-Netflix-Clone/src/views/Login.vue: -------------------------------------------------------------------------------- 1 | 40 | -------------------------------------------------------------------------------- /Vue-Netflix-Clone/src/views/Register.vue: -------------------------------------------------------------------------------- 1 | 42 | -------------------------------------------------------------------------------- /Vue-Netflix-Clone/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: [ 4 | "./index.html", 5 | "./src/**/*.{vue,js,ts,jsx,tsx}", 6 | ], 7 | theme: { 8 | extend: { 9 | fontFamily: { 10 | "Roboto": "Roboto" 11 | } 12 | }, 13 | }, 14 | plugins: [ 15 | require('@tailwindcss/line-clamp'), 16 | require('tailwind-scrollbar-hide') 17 | ] 18 | } -------------------------------------------------------------------------------- /Vue-Netflix-Clone/vite.config.js: -------------------------------------------------------------------------------- 1 | import { fileURLToPath, URL } 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 | test: { 9 | globals: true 10 | }, 11 | plugins: [vue()], 12 | resolve: { 13 | alias: { 14 | '@': fileURLToPath(new URL('./src', import.meta.url)) 15 | } 16 | } 17 | }) 18 | -------------------------------------------------------------------------------- /Vue-Netflix-Clone/vitest.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import Vue from '@vitejs/plugin-vue' 3 | 4 | export default defineConfig({ 5 | plugins: [ 6 | Vue(), 7 | ], 8 | test: { 9 | globals: true, 10 | environment: 'jsdom', 11 | }, 12 | }) -------------------------------------------------------------------------------- /Vue-Pinia-Store/.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/* 22 | !.vscode/extensions.json 23 | .idea 24 | *.suo 25 | *.ntvs* 26 | *.njsproj 27 | *.sln 28 | *.sw? 29 | -------------------------------------------------------------------------------- /Vue-Pinia-Store/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"] 3 | } 4 | -------------------------------------------------------------------------------- /Vue-Pinia-Store/README.md: -------------------------------------------------------------------------------- 1 | # Vue Pinia Store 2 | 3 | This project is built using [Vue 3](https://vuejs.org/) , [Pinia](https://pinia.vuejs.org/), [TailwindCss](https://tailwindcss.com/), [Vue-Toastification](https://github.com/Maronato/vue-toastification/tree/next), [Fake-Store-API](https://fakestoreapi.com) and [Vueuse](https://vueuse.org/). 4 | 5 | ## Recommended IDE Setup 6 | 7 | [VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). 8 | 9 | ## Customize configuration 10 | 11 | See [Vite Configuration Reference](https://vitejs.dev/config/). 12 | 13 | ## Project Setup 14 | 15 | ```sh 16 | npm install 17 | ``` 18 | 19 | ### Compile and Hot-Reload for Development 20 | 21 | ```sh 22 | npm run dev 23 | ``` 24 | 25 | ### Compile and Minify for Production 26 | 27 | ```sh 28 | npm run build 29 | ``` 30 | -------------------------------------------------------------------------------- /Vue-Pinia-Store/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Pinia Store 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Vue-Pinia-Store/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-pinia-store", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "vite build", 7 | "preview": "vite preview --port 4173" 8 | }, 9 | "dependencies": { 10 | "@heroicons/vue": "^2.0.7", 11 | "@tailwindcss/line-clamp": "^0.4.0", 12 | "@vueuse/core": "^9.1.1", 13 | "axios": "^0.30.0", 14 | "pinia": "^2.0.17", 15 | "tailwind-scrollbar-hide": "^1.1.7", 16 | "vue": "^3.2.37", 17 | "vue-router": "^4.1.3", 18 | "vue-toastification": "^2.0.0-rc.5" 19 | }, 20 | "devDependencies": { 21 | "@vitejs/plugin-vue": "^3.0.1", 22 | "autoprefixer": "^10.4.8", 23 | "postcss": "^8.4.16", 24 | "tailwindcss": "^3.1.8", 25 | "vite": "^3.0.4" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Vue-Pinia-Store/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /Vue-Pinia-Store/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selemondev/8-Awesome-Vue-Projects/a33fa2f765a6ae802bb90481bcac94a5f5f032d3/Vue-Pinia-Store/public/favicon.ico -------------------------------------------------------------------------------- /Vue-Pinia-Store/src/App.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /Vue-Pinia-Store/src/assets/css/index.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap'); 2 | @tailwind base; 3 | @tailwind components; 4 | @tailwind utilities; 5 | 6 | @layer base { 7 | body { 8 | @apply font-Roboto; 9 | } 10 | } 11 | 12 | 13 | @layer components { 14 | .flex-center { 15 | @apply flex justify-center items-center 16 | } 17 | 18 | .flex-around { 19 | @apply flex justify-around items-center 20 | } 21 | 22 | .flex-between { 23 | @apply flex justify-between items-center 24 | } 25 | 26 | .grid-center { 27 | @apply grid place-items-center 28 | } 29 | } -------------------------------------------------------------------------------- /Vue-Pinia-Store/src/components/Loader.vue: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /Vue-Pinia-Store/src/components/Navbar.vue: -------------------------------------------------------------------------------- 1 | 16 | -------------------------------------------------------------------------------- /Vue-Pinia-Store/src/components/Product_Cards.vue: -------------------------------------------------------------------------------- 1 | 26 | -------------------------------------------------------------------------------- /Vue-Pinia-Store/src/components/Product_Loader.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Vue-Pinia-Store/src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue'; 2 | import { createPinia } from 'pinia'; 3 | import App from './App.vue'; 4 | import router from './router'; 5 | import Toast, { POSITION } from "vue-toastification"; 6 | import "vue-toastification/dist/index.css"; 7 | import "./assets/css/index.css"; 8 | const app = createApp(App) 9 | app.use(createPinia()) 10 | app.use(router) 11 | app.use(Toast, { 12 | position: POSITION.TOP_CENTER 13 | }); 14 | app.mount('#app') 15 | -------------------------------------------------------------------------------- /Vue-Pinia-Store/src/router/index.js: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHistory } from 'vue-router' 2 | import Home from '../views/Home.vue'; 3 | const router = createRouter({ 4 | history: createWebHistory(import.meta.env.BASE_URL), 5 | routes: [ 6 | { 7 | path: '/', 8 | name: 'home', 9 | component: Home 10 | }, 11 | { 12 | path: '/cart', 13 | name: 'cart', 14 | component: () => import('../views/Cart.vue') 15 | }, 16 | { 17 | path: '/product/:id', 18 | name: 'product', 19 | component: () => import('../views/Product.vue') 20 | }, 21 | ] 22 | }) 23 | 24 | export default router 25 | -------------------------------------------------------------------------------- /Vue-Pinia-Store/src/stores/productStore.js: -------------------------------------------------------------------------------- 1 | import { defineStore, acceptHMRUpdate } from "pinia"; 2 | import axios from "axios"; 3 | import { useStorage } from "@vueuse/core" 4 | export const useProductStore = defineStore({ 5 | id: "store", 6 | state: () => ({ 7 | products: [], 8 | cart: useStorage("cart", []), 9 | loading: false, 10 | }), 11 | 12 | getters: { 13 | cartQuantity: (state) => { 14 | return state.cart?.length; 15 | }, 16 | 17 | itemQuantity: (state) => (product) => { 18 | const item = state.cart.find((item) => item.id === product.id); 19 | return item?.quantity; 20 | }, 21 | 22 | productTotal: (state) => { 23 | return state.cart.reduce((val, item) => val + item.quantity * item.price, 0) 24 | } 25 | }, 26 | 27 | actions: { 28 | async fetchProducts() { 29 | this.loading = true; 30 | const response = await axios.get("https://fakestoreapi.com/products"); 31 | this.loading = false; 32 | response.data.map((product) => { 33 | this.products.push(product); 34 | }); 35 | }, 36 | 37 | addToCart(product) { 38 | const item = this.cart.find((item) => item.id === product.id); 39 | if ( item ) { 40 | item.quantity++; 41 | } else { 42 | this.cart.push({...product, quantity: 1}); 43 | }; 44 | }, 45 | 46 | removeFromCart(product) { 47 | const item = this.cart.find((item) => item.id === product.id); 48 | if(item) { 49 | if( item.quantity > 1) { 50 | item.quantity--; 51 | } else { 52 | this.cart = this.cart.filter((item) => item.id !== product.id); 53 | } 54 | }; 55 | } 56 | }, 57 | }); 58 | 59 | if (import.meta.hot) { 60 | import.meta.hot.accept(acceptHMRUpdate(useProductStore, import.meta.hot)); 61 | } 62 | -------------------------------------------------------------------------------- /Vue-Pinia-Store/src/views/Cart.vue: -------------------------------------------------------------------------------- 1 | 10 | -------------------------------------------------------------------------------- /Vue-Pinia-Store/src/views/Home.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /Vue-Pinia-Store/src/views/Product.vue: -------------------------------------------------------------------------------- 1 | 29 | -------------------------------------------------------------------------------- /Vue-Pinia-Store/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | /** @type {import('tailwindcss').Config} */ 3 | module.exports = { 4 | content: [ 5 | "./index.html", 6 | "./src/**/*.{vue,js,ts,jsx,tsx}", 7 | ], 8 | theme: { 9 | extend: { 10 | fontFamily: { 11 | "Roboto": "Roboto" 12 | } 13 | }, 14 | }, 15 | plugins: [ 16 | require('@tailwindcss/line-clamp'), 17 | require('tailwind-scrollbar-hide') 18 | 19 | ] 20 | } -------------------------------------------------------------------------------- /Vue-Pinia-Store/vite.config.js: -------------------------------------------------------------------------------- 1 | import { fileURLToPath, URL } 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 | -------------------------------------------------------------------------------- /Vue-Whatsapp-Clone/.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 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /Vue-Whatsapp-Clone/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["Vue.volar"] 3 | } 4 | -------------------------------------------------------------------------------- /Vue-Whatsapp-Clone/README.md: -------------------------------------------------------------------------------- 1 | # Vue 3 + Vite 2 | 3 | This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 ` 8 | Whatsapp 9 | 10 | 11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Vue-Whatsapp-Clone/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-whatsapp-clone", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "@heroicons/vue": "^2.0.8", 13 | "@vuelidate/core": "^2.0.0-alpha.44", 14 | "@vuelidate/validators": "^2.0.0-alpha.31", 15 | "@vueuse/core": "^9.3.0", 16 | "firebase": "^9.9.3", 17 | "pinia": "^2.0.21", 18 | "vue": "^3.2.37", 19 | "vue-router": "^4.1.5", 20 | "vue-timeago3": "^2.3.0", 21 | "vue3-emoji-picker": "^1.1.4" 22 | }, 23 | "devDependencies": { 24 | "@vitejs/plugin-vue": "^3.0.3", 25 | "autoprefixer": "^10.4.8", 26 | "postcss": "^8.4.16", 27 | "tailwindcss": "^3.1.8", 28 | "vite": "^3.0.7" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Vue-Whatsapp-Clone/postcss.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /Vue-Whatsapp-Clone/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Vue-Whatsapp-Clone/src/App.vue: -------------------------------------------------------------------------------- 1 | 11 | 21 | 22 | -------------------------------------------------------------------------------- /Vue-Whatsapp-Clone/src/assets/Placeholder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selemondev/8-Awesome-Vue-Projects/a33fa2f765a6ae802bb90481bcac94a5f5f032d3/Vue-Whatsapp-Clone/src/assets/Placeholder.png -------------------------------------------------------------------------------- /Vue-Whatsapp-Clone/src/assets/robot.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selemondev/8-Awesome-Vue-Projects/a33fa2f765a6ae802bb90481bcac94a5f5f032d3/Vue-Whatsapp-Clone/src/assets/robot.gif -------------------------------------------------------------------------------- /Vue-Whatsapp-Clone/src/assets/whatsapp-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/selemondev/8-Awesome-Vue-Projects/a33fa2f765a6ae802bb90481bcac94a5f5f032d3/Vue-Whatsapp-Clone/src/assets/whatsapp-logo.png -------------------------------------------------------------------------------- /Vue-Whatsapp-Clone/src/components/ChatHeader.vue: -------------------------------------------------------------------------------- 1 | 18 | -------------------------------------------------------------------------------- /Vue-Whatsapp-Clone/src/components/Loader.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Vue-Whatsapp-Clone/src/components/MessageContainer.vue: -------------------------------------------------------------------------------- 1 | 16 | -------------------------------------------------------------------------------- /Vue-Whatsapp-Clone/src/components/Navbar.vue: -------------------------------------------------------------------------------- 1 | 11 | -------------------------------------------------------------------------------- /Vue-Whatsapp-Clone/src/components/Sidebar.vue: -------------------------------------------------------------------------------- 1 | 37 | -------------------------------------------------------------------------------- /Vue-Whatsapp-Clone/src/firebaseConfig.js: -------------------------------------------------------------------------------- 1 | import { initializeApp } from "firebase/app"; 2 | import { getStorage } from "firebase/storage"; 3 | import { getAuth } from "firebase/auth"; 4 | import { getFirestore } from "firebase/firestore"; 5 | const firebaseConfig = { 6 | apiKey: "AIzaSyDneo6YRuBq4diuhs12EOqKbXJB2Oi6GWM", 7 | authDomain: "vue-whatsapp-clone-73d03.firebaseapp.com", 8 | projectId: "vue-whatsapp-clone-73d03", 9 | storageBucket: "vue-whatsapp-clone-73d03.appspot.com", 10 | messagingSenderId: "481853368573", 11 | appId: "1:481853368573:web:cddd87d0618ea373eaf694" 12 | }; 13 | 14 | // Initialize Firebase 15 | const app = initializeApp(firebaseConfig); 16 | const auth = getAuth(app); 17 | const db = getFirestore(app); 18 | const storage = getStorage(app); 19 | 20 | export { 21 | auth, 22 | db, 23 | storage 24 | } -------------------------------------------------------------------------------- /Vue-Whatsapp-Clone/src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue'; 2 | import { createPinia } from "pinia"; 3 | import App from './App.vue'; 4 | import router from './router'; 5 | import timeago from 'vue-timeago3'; 6 | import './style.css'; 7 | const pinia = createPinia(); 8 | const app = createApp(App); 9 | app.use(pinia); 10 | app.use(timeago); 11 | app.use(router); 12 | app.mount('#app') 13 | -------------------------------------------------------------------------------- /Vue-Whatsapp-Clone/src/router/index.js: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHistory } from "vue-router"; 2 | import Login from "../views/Login.vue"; 3 | import Register from "../views/Register.vue"; 4 | import { onAuthStateChanged } from "firebase/auth"; 5 | import { auth } from "../firebaseConfig"; 6 | const routes = [ 7 | { 8 | path: "/", 9 | name: "login", 10 | component: Login, 11 | meta: { 12 | auth: false, 13 | } 14 | }, 15 | { 16 | path: "/register", 17 | name: "register", 18 | component: Register, 19 | meta: { 20 | auth: false, 21 | } 22 | }, 23 | { 24 | path: "/profile", 25 | name: "profile", 26 | component: () => import("../views/Profile.vue"), 27 | meta: { 28 | auth: true, 29 | } 30 | }, 31 | { 32 | path:"/chat", 33 | name: "chat", 34 | component: () => import("../views/Chat.vue"), 35 | meta: { 36 | auth: true, 37 | } 38 | } 39 | ] 40 | const router = createRouter({ 41 | history: createWebHistory(import.meta.env.BASE_URL), 42 | routes 43 | }); 44 | 45 | 46 | const currentUser = () => { 47 | return new Promise((resolve, reject) => { 48 | const unsubscribe = onAuthStateChanged(auth, (user) => { 49 | unsubscribe(); 50 | resolve(user); 51 | }, 52 | reject 53 | ) 54 | }) 55 | }; 56 | 57 | router.beforeEach( async (to,from,next) => { 58 | if(to.matched.some((record) => record.meta.auth)) { 59 | if(await currentUser()) { 60 | next(); 61 | } else { 62 | next("/"); 63 | } 64 | } else { 65 | next(); 66 | } 67 | }); 68 | export default router; -------------------------------------------------------------------------------- /Vue-Whatsapp-Clone/src/store/authStore.js: -------------------------------------------------------------------------------- 1 | import { defineStore, acceptHMRUpdate } from "pinia"; 2 | import { 3 | createUserWithEmailAndPassword, 4 | signInWithEmailAndPassword, 5 | signOut, 6 | } from "firebase/auth"; 7 | import { auth, db } from "../firebaseConfig"; 8 | import { setDoc, Timestamp, updateDoc, doc } from "firebase/firestore"; 9 | import { useStorage } from "@vueuse/core"; 10 | export const useAuthStore = defineStore({ 11 | id: "auth", 12 | state: () => ({ 13 | userData: useStorage("user", ""), 14 | registerLoading: false, 15 | loginLoading: false, 16 | registerError: "", 17 | loginError: "", 18 | }), 19 | 20 | actions: { 21 | async registerUser(username, email, password) { 22 | this.registerLoading = true; 23 | try { 24 | const response = await createUserWithEmailAndPassword( 25 | auth, 26 | email, 27 | password 28 | ); 29 | await setDoc(doc(db, "users", response.user.uid), { 30 | uid: response.user.uid, 31 | username, 32 | email, 33 | avatar: "", 34 | avatarPath: "", 35 | bio: "", 36 | createdAt: Timestamp.fromDate(new Date()), 37 | online: true, 38 | }); 39 | this.userData = response.user.uid; 40 | this.registerLoading = false; 41 | } catch (err) { 42 | this.registerError = err.message; 43 | this.registerLoading = false; 44 | } 45 | }, 46 | 47 | async loginUser(email, password) { 48 | this.loginLoading = true; 49 | try { 50 | const response = await signInWithEmailAndPassword( 51 | auth, 52 | email, 53 | password 54 | ); 55 | await updateDoc(doc(db, "users", response.user.uid), { 56 | online: true, 57 | }); 58 | this.userData = response.user.uid; 59 | this.loginLoading = false; 60 | } catch (err) { 61 | this.loginError = err.message; 62 | this.loginLoading = false; 63 | } 64 | }, 65 | async logOut() { 66 | await signOut(auth); 67 | this.userData = null; 68 | localStorage.removeItem("user"); 69 | }, 70 | }, 71 | }); 72 | 73 | if (import.meta.hot) { 74 | import.meta.hot.accept(acceptHMRUpdate(useAuthStore, import.meta.hot)); 75 | } 76 | -------------------------------------------------------------------------------- /Vue-Whatsapp-Clone/src/style.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap'); 2 | @tailwind base; 3 | @tailwind components; 4 | @tailwind utilities; 5 | 6 | @layer base { 7 | body { 8 | @apply min-h-screen w-full font-Roboto bg-gray-900 9 | } 10 | } 11 | 12 | @layer components { 13 | .grid-center { 14 | @apply grid place-items-center 15 | } 16 | 17 | .flex-center { 18 | @apply flex justify-center items-center 19 | } 20 | 21 | .flex-around { 22 | @apply flex justify-around items-center 23 | } 24 | 25 | .flex-between { 26 | @apply flex justify-between items-center 27 | } 28 | 29 | .navbar-btn { 30 | @apply py-1.5 px-6 bg-green-500 hover:bg-green-600 transition duration-200 ease-in rounded-md text-white 31 | } 32 | 33 | .form-label { 34 | @apply block mt-2 text-white 35 | } 36 | 37 | .form-input { 38 | @apply appearance-none py-2 px-2 w-full border border-gray-500 mt-2 rounded-md focus:outline-none focus:ring-1 focus:ring-green-500 bg-gray-400/30 text-white placeholder-gray-400 39 | } 40 | 41 | .form-btn { 42 | @apply py-2 px-6 w-full bg-green-500 hover:bg-green-600 rounded-md text-white font-bold transition duration-200 ease-in 43 | } 44 | 45 | .error { 46 | @apply font-bold text-red-500 mt-2 47 | } 48 | 49 | .input-style { 50 | @apply py-1.5 px-4 w-full rounded-full bg-gray-400/30 focus:outline-none focus:ring-1 focus:ring-gray-400 text-white placeholder-gray-400 md:py-2.5 51 | } 52 | } -------------------------------------------------------------------------------- /Vue-Whatsapp-Clone/src/views/Login.vue: -------------------------------------------------------------------------------- 1 | 50 | -------------------------------------------------------------------------------- /Vue-Whatsapp-Clone/src/views/Register.vue: -------------------------------------------------------------------------------- 1 | 51 | -------------------------------------------------------------------------------- /Vue-Whatsapp-Clone/tailwind.config.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"], 4 | darkMode: "class", 5 | theme: { 6 | extend: { 7 | fontFamily: { 8 | Roboto: "Roboto", 9 | }, 10 | }, 11 | }, 12 | plugins: [], 13 | }; 14 | -------------------------------------------------------------------------------- /Vue-Whatsapp-Clone/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import vue from '@vitejs/plugin-vue' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [vue()] 7 | }) 8 | --------------------------------------------------------------------------------