Tutorial ini melanjutkan dari tutorial sebelumnya: Membuat Autentikasi JWT (JSON web token) dengan Laravel 7
Sebelumnya saya memposting tentang bagaimana membuat autentikasi jwt (json web token) dengan laravel, dan autentikasi dilakukan menggunakan postman untuk testing API nya.
Project tersebut akan digunakan sebagai backend dan dilanjutkan untuk membuat bagian frontend pada postingan ini.
Bagian frontend untuk halaman login, registrasi, maupun user dibuat menggunakan nuxt.js, dan memakai vuex untuk mengelola data.
Mengenai nuxt.js sendiri tidak dibahas disini, mari langsung kepembuatanya.
1. Instalasi Nuxt.js
Langkah awal kita lakukan instalasi nuxt. Silahkan gunakan perintah dibawah ini:
npx create-nuxt-app frontend
atau
yarn create nuxt-app frontend
Dokumentasi tentang instalasi ataupun lainnya bisa dilihat di situsnya nuxtjs.org.
2. Install Modul
Setelah proses instalasi selesai, kita lanjutkan menginstall modul yang digunakan.
npm install @nuxtjs/auth
Dokumentasi: auth.nuxtjs.org.
npm install @nuxtjs/axios
Dokumentasi: axios.nuxtjs.org.
3. Konfigurasi
Kemudian buka nuxt.config.js lalu tambahkan dan atau atur modul seperti berikut:
... modules: [ '@nuxtjs/axios', '@nuxtjs/auth' ], axios: { baseURL: 'http://localhost:8000/api' }, auth: { strategies: { local: { endpoints: { login: { url: 'login', method: 'post', propertyName: 'token' }, user: { url: 'user', method: 'get', propertyName: 'data' }, logout: false } } } }, ...
Yang kita lakukan diatas adalah:
Endpoints ditujukan sesuai dengan yang ada pada backend. Diatas diatur untuk login dan user sesuai route, method, dan nama properti dari data.
3. Aktivasi Vuex
Kita lanjutkan dengan mengaktifkan vuex pada nuxt. Untuk mengaktifkannya, kita buat file index.js pada direktori store.
Setelah file baru dibuat, secara otomatis mengaktifkan vuex.
Kemudian kita jalankan apliaksi.
npm run dev
Buka di browser dengan alamat http://localhost:3000/.
Pastikan telah menginstal / mengaktifkan Vue.js devtools pada browser lalu kita buka di dev tools browser.
Jika dilihat, modul yang digunakan telah membuat vuex store, terdapat state dan mutation disana.
Login User
Kita lanjutkan untuk membuat halaman dan form login.
Terlebih dahulu kita buka nuxt.config.js dan tambahkan css. Kita gunakan bootstrap dengan menambahkan link cdn pada bagian head.
//nuxt.config.js ... link: [ { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }, { rel: 'stylesheet', href: 'https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css' } ] ...
Kemudian kita buat file baru di direktori pages dengan nama login.vue dan copas form dibawah.
//login.vue <template> <div class="container"> <div class="row justify-content-md-center"> <div class="col-md-6"> <div class="card"> <div class="card-header"> Login </div> <div class="card-body"> <div class="alert alert-danger" v-for="(error, index) in errors" :key="index"> {{ error[0] }} </div> <form method="post" @submit.prevent="userLogin"> <div class="form-group"> <label for="email">Email address</label> <input type="email" v-model="login.email" class="form-control" placeholder="Enter email"> </div> <div class="form-group"> <label for="password">Password</label> <input type="password" v-model="login.password" class="form-control" placeholder="Password"> </div> <button type="submit" class="btn btn-primary">Submit</button> </form> </div> </div> </div> </div> </div> </template> <script> export default { middleware: 'guest', data() { return { login: { email: '', password: '' }, errors: null } }, methods: { async userLogin() { try { let response = await this.$auth.loginWith('local', { data: this.login }) console.log(response) this.$router.push('/'); } catch (e) { this.errors = e.response.data.errors } } } } </script>
Buat file baru pada direktori middleware dengan nama guest.js.
//middleware/guest.js export default function ({ store, redirect }) { if (store.state.auth.loggedIn) { return redirect('/') } }
Middleware guest akan mengecek status login user pada vuex. Jika properti loggedIn dalam kondisi true atau sudah login maka halaman login tidak dapat diakses.
Selanjutnya kita tambahkan juga komponen navbar untuk navigasi. Silahkan buat kembali file baru pada direktori components dengan nama Navbar.vue.
//Navbar.vue <template> <nav class="navbar navbar-expand-lg navbar-light bg-light"> <div class="container"> <nuxt-link class="navbar-brand" to="/">Laravel-Nuxt App</nuxt-link> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <ul class="navbar-nav ml-auto"> <li class="nav-item"> <nuxt-link class="nav-link" to="/login">Login</nuxt-link> </li> </ul> </div> </div> </nav> </template> <script> export default {} </script>
Lalu buka file default.vue yang terdapat pada direktori layouts, dan import komponen navbar.
//default.vue <template> <div> <Navbar/> <br> <nuxt/> </div> </template> <script> import Navbar from '~/components/Navbar' export default { components: { Navbar } } </script> <style> .navbar-nav .nav-item .nuxt-link-active{ color:black; } </style>
Sampai disini kita akan coba melakukan login user melalui halaman login.
Jangan lupa menjalankan kedua aplikasi pada terminal, npm run dev untuk frontend (nuxt) dan php artisan serve pada backend (laravel).
Sekarang buka halaman login dan coba melakukan login dengan user yang telah terdaftar sebelumnya.
Validasi ketika value kosong:
Ketika berhasil masuk, data disimpan dalam vuex dan ter-redirect ke homepage.
Untuk halaman index kita buat saja jumbotron.
//pages/index.vue <template> <div class="container"> <div class="jumbotron"> <h1 class="display-4">Hello, world!</h1> <p class="lead">This is a simple hero unit, a simple jumbotron-style component for calling extra attention to featured content or information.</p> <hr class="my-4"> <p>It uses utility classes for typography and spacing to space content out within the larger container.</p> <p class="lead"> <a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a> </p> </div> </div> </template>
Menampilkan User
Kita akan tampilkan user pada navbar, dan membuat validasi untuk mengecek status user apakah telah login apa belum, serta kita buat fungsi logout.
Kita akan akses data state pada vuex store.
Kita buka file index.js pada direktori store dan kita buat getters:
//store/index.js export const getters = { user(state) { return state.auth.user }, isLoggedIn(state) { return state.auth.loggedIn } }
Kita buat method user yang me-return properti user dan method isLoggedIn me-return properti loggedIn.
Selanjutnya buka file Navbar.vue dan update seperti dibawah.
//Navbar.vue <ul class="navbar-nav ml-auto"> <template v-if="isLoggedIn"> <li class="nav-item"> <nuxt-link class="nav-link" to="/user">{{ user.name }} <span class="sr-only">(current)</span></nuxt-link> </li> <li class="nav-item"> <a class="nav-link" @click="logout">Logout</a> </li> </template> <template v-else> <li class="nav-item"> <nuxt-link class="nav-link" to="/login">Login</nuxt-link> </li> </template> </ul> ... <script> import { mapGetters } from 'vuex' export default { computed: { ...mapGetters([ 'user', 'isLoggedIn' ]) }, methods: { async logout() { await this.$auth.logout(); } } } </script>
Diatas, kita import getters dan membuat method logout. Kita buat kondisi v-if v-else untuk menampilkan menu sesuai status atutentikasi user.
Selanjutnya kita buat halaman untuk user. Buat file baru pada direktori pages dengan nama user.vue.
Kita import getters dan memberi middleware 'auth'. Halaman akan dapat diakses jika sudah login.
//pages/user.vue <template> <div class="container"> <div class="jumbotron"> <h1 class="display-4">Hello, {{user.name}}!</h1> </div> </div> </template> <script> import { mapGetters } from 'vuex' export default { middleware: 'auth', computed: { ...mapGetters([ 'user' ]) } } </script>
Karena halaman user sudah ada, kita bisa buat redirect ke route user pada login.vue
//login.vue this.$router.push('/user');
Registrasi User
Kita lanjutkan untuk membuat halaman dan form registrasi user.
Buat file baru dengan nama register.vue pada direktori pages:
//pages/register.vue <template> <div class="container"> <div class="row justify-content-md-center"> <div class="col-md-6"> <div class="card"> <div class="card-header"> Register </div> <div class="card-body"> <div class="alert alert-danger" v-for="(error, index) in errors" :key="index"> {{ error[0] }} </div> <form method="post" @submit.prevent="register"> <div class="form-group"> <label for="email">Name</label> <input type="text" v-model="name" class="form-control" placeholder="Enter name"> </div> <div class="form-group"> <label for="email">Email address</label> <input type="email" v-model="email" class="form-control" placeholder="Enter email"> </div> <div class="form-group"> <label for="password">Password</label> <input type="password" v-model="password" class="form-control" placeholder="Password"> </div> <button type="submit" class="btn btn-primary">Submit</button> </form> </div> </div> </div> </div> </div > </template> <script> export default { middleware: 'guest', data() { return { name: '', email: '', password: '', errors: null } }, methods: { async register() { try { await this.$axios.post('register', { name: this.name, email: this.email, password: this.password }) this.$router.push('/login') } catch (e) { this.errors = e.response.data.errors } } } } </script>
Tambahkan menu pada navbar:
//Navbar.vue ... <li class="nav-item"> <nuxt-link class="nav-link" to="/register">Register</nuxt-link> </li> ...
Gambar diatas menampilkan validasi error, ketika pendaftaran user berhasil maka akan diarahkan ke halaman login. Silahkan coba melakukan pendaftaran user baru.