Login/cadastro com firebase + Vue JS #PASSO 2️⃣ (cadastro)

jacksonsantin

Jackson Dhanyel Santin

Posted on October 25, 2024

Login/cadastro com firebase + Vue JS #PASSO 2️⃣ (cadastro)

Primeiramente, mostrarei a estrutura da pasta SRC no meu projeto Vue JS.

.
├── src
│   └── assets
│       └── images
|           └── imagem_logo_google.png
│   └── module
│       └── login
|           └── component
|               └── formLogin.vue
|           └── controller
|               └── loginController.js
|           └── view
|               └── login.vue
│       └── register
|           └── component
|               └── formRegister.vue
|           └── controller
|               └── registerController.js
|           └── view
|               └── register.vue
│   └── router
│       └── index.js
│   └── App.vue
│   └── main.js
Enter fullscreen mode Exit fullscreen mode

Vamos lá as explicações:

  • A pasta assets é onde ficam as imagens do meu projeto, no caso, é onde eu coloquei a imagem da logo do Google para depois podermos utilizar para implementar a opção de login pelo Google;
  • A pasta module é onde eu tem os módulos do projeto, no caso eu separei cada módulo com pastas e dentro de cada pasta criei outras sub-pastas com os arquivos para melhor organização;

    • Dentro das pasta login e register eu criei as sub-pastas:

    component: onde tem o HTML das telas;
    controller: onde ficarão as funções que vamos executar na tela;
    view: onde eu chamo a tela criada no component e atribuo a prop controller para ela.

  • A pasta router tem as rotas do nosso projeto;

  • O arquivo App.vue apenas está chamando as rotas do projeto e definindo alguns estilos CSS padrão em todas as telas;

  • Por fim, o arquivo main.js que é onde eu chamo as configurações SDK que o firebase nos forneceu e algumas outras importações que o próprio Vue JS cria.


Inicialmente, antes de qualquer coisa, vamos instalar as libs que vamos ocupar, no caso o vue-router e o firebase executando no terminal os comandos abaixo:

$ npm install vue-router
Enter fullscreen mode Exit fullscreen mode

Após

$ npm install firebase
Enter fullscreen mode Exit fullscreen mode

Agora, vamos começar adicionando o SDK que o firebase nos forneceu no arquivo main.js, então vamos nos atentar a essa estrutura abaixo:

.
├── src
│   └── main.js
Enter fullscreen mode Exit fullscreen mode
import { createApp } from 'vue'
import App from './App.vue'
import vuetify from './plugins/vuetify'
import { initializeApp } from 'firebase/app'

const firebaseConfig = {
  apiKey: "AIzaSyA_Bq3nqLfRUWXsqtkpzietY5eu0ewFtzA",
  authDomain: "login-app-8c263.firebaseapp.com",
  projectId: "login-app-8c263",
  storageBucket: "login-app-8c263.appspot.com",
  messagingSenderId: "854129813359",
  appId: "1:854129813359:web:02f776146a0c34be906a9a"
}

initializeApp(firebaseConfig)

const app = createApp(App)

app.use(vuetify).mount('#app')
Enter fullscreen mode Exit fullscreen mode
Note que estou usando Vue com Vuetify para facilitar na criação dos componentes, mas você pode utilizar Tailwind ou qualquer outro framework desejado.

Agora, vamos criar a rota do projeto e configurar no arquivo App.vue, então, vamos focar nessa estrutura abaixo.

.
├── src
│   └── router
│       └── index.js
│   └── App.vue
Enter fullscreen mode Exit fullscreen mode

Primeiramente vamos ao arquivo index.js e adicionar o seguinte:

1  | import { createRouter, createWebHistory } from 'vue-router'
2  | import Register from '@/module/register/view/register.vue'
3  |
4  | const router = createRouter({
5  | history: createWebHistory(),
6  | routes: [
7  |   {
8  |     path: '/cadastro',
9  |     name: 'Register',
10 |     component: Register
11 |   }
12 | ]
13 | })
14 |
15 | export default router

Enter fullscreen mode Exit fullscreen mode
Linha Explicação
1 Importa as funções createRouter e createWebHistory da biblioteca vue-router. createRouter é usado para configurar o roteador, e createWebHistory define o modo de histórico do navegador para gerenciar URLs de forma limpa (sem o símbolo #).
2 Importa o componente Register, que representa a página de registro, localizado na pasta especificada. Este componente será carregado quando o usuário acessar a rota correspondente.
4/13
  • Cria uma instância do roteador (router) com createRouter. Aqui, history define o modo de histórico (createWebHistory) e routes define as rotas disponíveis.
  • A rota { path: '/cadastro', name: 'Register', component: Register } configura o caminho /cadastro para carregar o componente Register. name é um nome opcional para a rota, que facilita a navegação programática.
15 Exporta a rota como o módulo padrão, para que ele possa ser importado e usado no aplicativo Vue.

Agora vamos chamar a rota no arquivo App.vue da seguinte forma:

<template>
  <v-app>
    <v-main class="bg-grey-lighten-3">
      <router-view />
    </v-main>
  </v-app>
</template>
Enter fullscreen mode Exit fullscreen mode

Por fim, vamos adicionar a rota no nosso arquivo main.js para que a aplicação possa utilizá-la.

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import vuetify from './plugins/vuetify'
import { initializeApp } from 'firebase/app'

const firebaseConfig = {
  apiKey: "AIzaSyA_Bq3nqLfRUWXsqtkpzietY5eu0ewFtzA",
  authDomain: "login-app-8c263.firebaseapp.com",
  projectId: "login-app-8c263",
  storageBucket: "login-app-8c263.appspot.com",
  messagingSenderId: "854129813359",
  appId: "1:854129813359:web:02f776146a0c34be906a9a"
}

initializeApp(firebaseConfig)

const app = createApp(App)

app.use(router).use(vuetify).mount('#app')
Enter fullscreen mode Exit fullscreen mode

Agora, vamos partir pra criação do nosso componente de cadastro de fato, suas funções e a chamada dele, então, vamos focar nessa estrutura.

.
├── src
│   └── module
│       └── register
|           └── component
|               └── formRegister.vue
|           └── controller
|               └── registerController.js
|           └── view
|               └── register.vue
Enter fullscreen mode Exit fullscreen mode

Arquivo formRegister.vue.

<template>
  <div class="d-flex justify-center align-center fill-height">
    <v-card class="mx-auto px-6 py-8" max-width="400" min-width="400">
      <v-form :disabled="controller.loading.value" :readonly="controller.loading.value">
        <h1 class="text-center mb-3">Crie uma conta</h1>
        <v-text-field
          class="mb-2"
          label="E-mail"
          variant="underlined"
          clearable
          :rules="[controller.regras.required, controller.regras.validEmail]"
          v-model="controller.email.value"
        ></v-text-field>

        <v-text-field
          label="Senha"
          placeholder="Informe sua senha"
          variant="underlined"
          clearable
          @click:append-inner="controller.showPassword.value = !controller.showPassword.value"
          :append-inner-icon="controller.showPassword.value ? 'mdi-eye' : 'mdi-eye-off'"
          :type="controller.showPassword.value ? 'text' : 'password'"
          :rules="[
            controller.regras.required,
            (v) => (v && v.length >= 6) || 'A senha deve ter no mínimo 6 caracteres'
          ]"
          v-model="controller.password.value"
        ></v-text-field>

        <br />

        <v-btn
          color="#5865f2"
          size="large"
          type="submit"
          variant="elevated"
          block
          :loading="controller.loading.value"
          :disabled="
            !controller.password.value ||
            controller.password.value.length < 6 ||
            controller.loading.value
          "
          @click="controller.register"
        >
          Cadastrar
        </v-btn>

        <br />

        <v-divider class="mx-10"></v-divider>

        <div class="d-flex justify-center mt-3">
          <button @click="controller.signInWithGoogle">
            <v-avatar :image="logoGoogle"></v-avatar>
          </button>
        </div>

        <p class="text-center mt-5">Já possui uma conta? <a href="/login">Login</a></p>
      </v-form>
    </v-card>
  </div>
</template>

<script setup>
import logoGoogle from '../../../assets/images/imagem_logo_google.png'

const { controller } = defineProps({
  controller: { type: Object, required: true }
})
</script>
Enter fullscreen mode Exit fullscreen mode

Arquivo registerController.js.

import { ref } from 'vue'
import {
  getAuth,
  createUserWithEmailAndPassword,
  GoogleAuthProvider,
  signInWithPopup
} from 'firebase/auth'
import { useRouter } from 'vue-router'

const registerController = () => {
  const email = ref('')
  const password = ref('')
  const loading = ref(false)
  const showPassword = ref(false)
  const regras = {
    required: (v) => !!v || 'Obrigatório',
    validEmail: (v) => {
    if (v.length > 0) {
      const pattern =
        /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
      return pattern.test(v) || 'E-mail inválido'
    }

    return true
  },
  }
  const router = useRouter()

  // Essa função é responsável por criar um usuário com o firebase apenas informando o e-mail e senha
  const register = async () => {
    try {
      loading.value = true

      const auth = getAuth()
      await createUserWithEmailAndPassword(auth, email.value, password.value)

      alert("Usuário criado com sucesso!")

      router.push('/')
    } catch (error) {
      alert(error)
    } finally {
      loading.value = false
    }
  }


  // Essa função é responsável por criar um usuário com o firebase utilizando o provedor Google
  const signInWithGoogle = async () => {
    try {
      loading.value = true

      const provider = new GoogleAuthProvider()
      await signInWithPopup(getAuth(), provider)

      alert("Usuário criado com sucesso!")

      router.push('/')
    } catch (error) {
      alert(error)
    } finally {
      loading.value = false
    }
  }

  return {
    email,
    password,
    loading,
    showPassword,
    regras,
    register,
    signInWithGoogle
  }
}

export { registerController }
Enter fullscreen mode Exit fullscreen mode

Arquivo register.vue.

<template>
  <form-register :controller="controller" />
</template>

<script setup>
import { registerController } from "../controller/registerController";
import FormRegister from "../component/formRegister.vue"
const controller = registerController();
</script>
Enter fullscreen mode Exit fullscreen mode

Então, até o momento já adicionamos o código para integrar o SDK no firebase ao nosso projeto no arquivo main.js, configuramos as rotas no router/index.js e chamamos a rota no main.js e no App.vue, criamos o componente da tela de cadatro no arquivo formRegister.vue, criamos as funções no arquivo registerController.js e chamamos a tela e a prop do controller no arquivo register.vue, em teoria, agora, se você acessar sua aplicação no /cadastro já deve aparecer o formulário conforme abaixo:

tela_cadastro

💖 💪 🙅 🚩
jacksonsantin
Jackson Dhanyel Santin

Posted on October 25, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related