WA

Laravel Dataviz

Deskripsi:

Studi kasus mendalam bagaimana mempersiapkan perintah SQL dari database sampai menampilkan dalam 25+ macam visualisasi.

Artikel terkait:

promo banner literasikode.004.jpeg
promo banner literasikode.001.jpeg
promo banner literasikode.002.jpeg
promo banner literasikode.003.jpeg

Daftar Isi
Project Briefing
·
Desain Database
··
Tabel bookings
··
Tabel guests
··
Tabel rooms
··
Tabel satisfactions
··
Tabel services
·
Menyiapkan Migration
··
Migration bookings
··
Migration guests
··
Migration rooms
··
Migration satisfactions
··
Migration services
··
Mengeksekusi Migration
·
Membuat dan Mengkonfigurasikan Model-Model yang Diperlukan
··
Model Booking
··
Model Guest
··
Model Room
··
Model Satisfaction
··
Model Service
Fundamental Grafik
Occupancy Rate / Booking Rate
Demography
Behaviour
Satisfaction
Sentuhan Akhir
Sample Materi

↓ ↓ ↓

Project Briefing

Di ebook ini kita akan diajak bersimulasi menjadi seorang fullstack developer
yang memiliki client yaitu Hana Hotel.

Hana Hotel sudah beroperasi sejak tahun 2016 sampai sekarang. Kamu mendapatkan
sebuah permintaan yaitu membuat dashboard berbasis web yang akan menampilkan
beberapa ukuran penting yang menunjukan performa hotel.

Hotel ini sudah memiliki sistem informasi tersendiri, tugasmu berfokus
mengembangkan fitur dashboard.

Kamu akan diberikan struktur database dan data dari sistem tersebut yang memuat
data bookings dari tahun 2016 sampai tahun 2020, data tamu, kepuasan tamu,
layanan yang tersedia, dan kamar hotel.

Dari tabel-tabel tersebut kamu harus membuat beberapa visualisasi antara lain:

  • Average Occupancy Rate per Month
  • Average Occupancy Rate per Quarter
  • Average Occupancy Rate YoY
  • Average Occupancy Rate per Month By Room Category
  • Average Occupancy Rate per Quarter by Room Category
  • Average Occupancy Rate YoY by Room Category
  • Average Occupancy Rate per Month by Bed Type
  • Average Occupancy Rate per Quarter by Bed Type
  • Average Occupancy Rate YoY by Bed Type
  • Tamu Berdasarkan Usia All Time
  • Tamu Berdasarkan Usia (Donut)
  • Tamu Berdasarkan Usia - Bulanan
  • Tamu Berdasarkan Usia - Kuartal
  • Tamu Berdasarkan Usia - Tahun ke Tahun
  • Tamu Berdasarkan Tipe All Time
  • Tamu Berdasarkan Tipe All Time (Donut)
  • Tamu Berdasarkan Tipe - Bulanan
  • Tamu Berdasarkan Tipe - Kuartal
  • Tamu Berdasarkan Tipe - Tahun ke Tahun
  • Grafik Tipe Kamar Pilihan
  • Grafik Tipe Kamar Pilihan Berdasarkan Orgin
  • Grafik Tipe Kamar Pilihan Berdasarkan Rentang Usia
  • Grafik Tipe Kamar Pilihan Berdasarkan Tipe Tamu
  • Grafik Lama Menginap Pilihan
  • Grafik Lama Menginap Pilihan Berdasarkan Orgin
  • Grafik Lama Menginap Pilihan Berdasarkan Rentang Usia
  • Grafik Lama Menginap Pilihan Berdasarkan Tipe Tamu
  • Guest Satisfaction & Score Count
  • Classified Satisfaction
  • Satisfaction Month to Month
  • Satisfaction by Services
  • Satisfaction Year to Year
  • Menampilkan Presentase pada Demogrpahy By Age Range
  • Menampilkan Presentase pada Demography By Guest Type
  • Menampilkan Presentase pada Behaviour Room Selection
  • Menampilkan Presentase pada Behaviour Stay Duration

Di sini kamu akan mempelajari bagaimana caranya mengekstrak informasi dari
tabel-tabel yang tersedia menjadi sebuah data yang siap divisualisasikan.

Mulai dari menyiapkan perintah SQL, mengolahnya dengan Laravel dan tentu
menampilkannya dalam bentuk berbagai macam grafik yang sesuai untuk
masing-masing data tersebut.

Grafik yang akan kita gunakan antara lain:

  • Pie Chart
  • Bar Chart
  • Horizontal Bar Chart
  • Donut Chart
  • Radial Chart
  • Polar Area Chart
  • Line Chart
  • Area Chart
  • Heat Map Chart
  • Radar Chart

Selain itu kita juga akan membuat grafik-grafik tersebut bisa difilter
berdasarkan tahu maupun rentang tahun ke tahun tertentu.

Dalam menerapkan fitur-fitur tersebut di Laravel kita akan menggunakan pola
Repository dan kita tidak akan meninggalkan kenyamanan Laravel.

Apakah kamu siap menerima tantangan tersebut?

Persyaratan Sistem

Dalam menuliskan panduan ini, saya menggunakan framework Laravel dan beberapa
tool maupun package yang diperlukan. Untuk kelancaran dalam mengikuti panduan
ini, pastikan kamu menggunakan versi yang sama atau lebih baru:

  • Composer versi 2.0.7
  • NodeJS versi minimal 12.14
  • Laravel Framework versi 8.x
  • MySQL 8.0.1 ke atas

Sebelum memulai mempraktikkan apa yang ada di panduan ini, kamu harus sudah
memasang composer dan NodeJS di komputermu.

NodeJS diperlukan untuk melakukan build terhadap asset javascript yang
digunakan untuk view.

Desain Database

Kamu memperoleh informasi mengenai struktur database yang digunakan oleh Hana
hotel, database tersebut berisi beberapa tabel penting untuk pengembangan
dashboard ini, yaitu:

  • bookings
  • guests
  • rooms
  • satisfactions
  • services

Desain dari kelima tabel tersebut adalah sebagai berikut:

ch01-06-erd.png

Di sini kamu akan mengekstrak informasi dari kelima tabel yang kelihatannya
cukup sederhana ini menjadi visualisasi sesuai daftar yang telah disebutkan di
atas.

Tabel bookings

Tabel ini merupakan tabel transaksi yang berisi informasi terkait pemesanan
seperti:

  • identitas tamu
  • tanggal kedatangan tamu
  • tanggal kepergian tamu
  • durasi menginap
  • informasi kamar yang digunakan

Struktur dari tabel bookings adalah sebagai berikut:

ch01-01-bookings-table-structure.png

Tabel guests

Tabel ini memuat seluruh tamu yang pernah menginap di Hana Hotel. Informasi di
tabel ini meliputi:

  • title gelar tamu ("Mr", "Mrs" , dsb)
  • first_name cukup jelas
  • last_name cukup jelas
  • email cukup jelas
  • birth_date cukup jelas
  • origin asal tamu (foreign | domestic)
  • type kategori tamu (family | solo | business | couple)

ch01-02-guests-table-structure.png

Tabel rooms

Tabel rooms berisi tipe kamar yang dimiliki oleh Hana Hotel. Terdapat 50 kamar
dengan kategori yaitu:

  • standard
  • superior
  • deluxe
  • junior suite
  • suite

Masing-masing kategori tersebut bisa memiliki jenis kasur yang berbeda (bed
type) yaitu:

  • king size
  • twin size

Struktur tabel rooms adalah sebagai berikut:

ch01-03-rooms-table-structure.png

Tabel satisfactions

Tabel satisfactions memuat data kepuasan tamu hotel yang berkunjung. Di akhir
hari menginap, setiap tamu mengisi kepuasan terhadap layanan-layanan yang ada di
hotel.

Nilai kepuasan tersebut dari angka 1 - 10, dimana angka 1 tidak puas dan semakin
mendekati angka 10 semakin puas terhadap layanan-layanan di hotel.

Struktur dari tabel satisfactions adalah sebagai berikut:

ch01-04-satisfactions.png

Tabel services

Tabel service merupakan tabel yang berisi layanan-layanan yang tersedia di
Hana hotel, antara lain:

  • cleaness (kebersihan)
  • hospitality (keramahan)
  • parking lot (tempat parkir)
  • food (makanan)
  • fitness center (pusat kebugaran)
  • location (lokasi)
  • property (kondisi properti)

Struktur dari tabel services adalah sebagai berikut:

ch01-05-services-table-structure.png

Membuat Projek Laravel

Pertama kita buat dulu projek Laravel baru, pastikan Laravel yang diinstall
adalah versi 8.x

Jalankan perintah berikut di terminalmu:

composer create-project laravel/laravel=8.* laravel-dataviz --prefer-dist

Setelah itu kita masuk ke project yang baru dibuat:

cd laravel-dataviz

Menyiapkan Migration

Dari kelima tabel di atas kita akan membuat berkas-berkas migration di Laravel.

Jangan lupa ubah dulu konfigurasi sambungan ke database pada file .env, isi dengan
data sesuai keinginanmu.

Migration bookings

Jalankan perintah:

php artisan make:migration create_bookings_table

Kemudian buka berkas yang tergenerate dan jadikan seperti ini:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateBookingsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('bookings', function (Blueprint $table) {
            $table->id();
            $table->integer('duration');
            $table->date('start_date');
            $table->date('end_date');
            $table->string('guest_title');
            $table->string('guest_firstname');
            $table->string('guest_lastname');
            $table->string('guest_email');
            $table->string('guest_age');
            $table->enum('guest_origin', ['foreign', 'domestic']);
            $table->enum('guest_type', ['family', 'solo', 'business', 'couple']);
            $table->enum('room_category', ['standard', 'superior', 'deluxe', 'junior suite', 'suite']);
            $table->enum('room_bed', ['twin', 'king']);
            $table->integer('room_price');
            $table->unsignedBigInteger('guest_id');
            $table->unsignedBigInteger('room_id');
            $table->timestamps();

            $table
                ->foreign('guest_id')
                ->references('id')
                ->on('guests')
                ->onDelete('cascade')
                ->onUpdate('cascade');

            $table
                ->foreign('room_id')
                ->references('id')
                ->on('rooms')
                ->onDelete('cascade')
                ->onUpdate('cascade');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::disableForeignKeyConstraints();
        Schema::dropIfExists('bookings');
    }
}

Migration guests

Jalankan perintah berikut:

php artisan make:migration create_guests_table

Lalu buka berkas yang tergenerate dan jadikan seperti ini:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateGuestsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('guests', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->string('first_name');
            $table->string('last_name');
            $table->string('email');
            $table->date('birth_date');
            $table->enum('origin', ['foreign', 'domestic']);
            $table->enum('type', ['family', 'solo', 'business', 'couple']);
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('guests');
    }
}

Migration rooms

Jalankan perintah berikut:

php artisan make:migration create_rooms_table

Lalu buka berkas yang tergenerate dan jadikan seperti ini:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateRoomsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('rooms', function (Blueprint $table) {
            $table->id();
            $table->enum('category', ['standard', 'superior', 'deluxe', 'junior suite', 'suite']);
            $table->enum('bed_type', ['twin', 'king']);
            $table->integer('price');
            $table->integer('number');
            $table->boolean('is_available');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('rooms');
    }
}

Migration satisfactions

Jalankan perintah berikut:

php artisan make:migration create_satisfactions_table

Lalu buka berkas yang tergenerate dan jadikan seperti ini:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateSatisfactionsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('satisfactions', function (Blueprint $table) {
            $table->id();
            $table->integer('score');
            $table->unsignedBigInteger('guest_id');
            $table->unsignedBigInteger('service_id');
            $table->unsignedBigInteger('booking_id');
            $table->timestamps();

            $table
                ->foreign('guest_id')
                ->references('id')
                ->on('guests')
                ->onDelete('cascade')
                ->onUpdate('cascade');

            $table
                ->foreign('service_id')
                ->references('id')
                ->on('services')
                ->onDelete('cascade')
                ->onUpdate('cascade');

            $table
                ->foreign('booking_Id')
                ->references('id')
                ->on('bookings')
                ->onDelete('cascade')
                ->onUpdate('cascade');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::disableForeignKeyConstraints();
        Schema::dropIfExists('satisfactions');
    }
}

Migration services

Jalankan perintah berikut:

php artisan make:migration create_services_table

Lalu buka berkas yang tergenerate dan jadikan seperti ini:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateServicesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('services', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('services');
    }
}

Mengeksekusi Migration

Terakhir kita jalankan perintah ini:

php artisan migrate

Percuma capek-capek bikin berkas-berkas migration di atas kalau lupa
menjalankan perintah ini :p

Kenapa saya tidak menjelaskan tentang migration di atas? Jawabannya karena
ebook ini memang bukan ditujukan untuk pemula Laravel sekali.

Jadi diasumsikan materi migration di atas sudah pada paham apa maksud dan
tujuannya, jika kok kamu belum tahu sama sekali, kamu berarti harus mempelajari
terlebih dahulu materi dasar Laravel di https://bit.ly/buku-laravel-vue

Mengimport berkas SQL ke database

Download file SQL di sini https://gist.github.com/azamuddin/93ccb82c83c98d507f6ee443dc6d285a

Lalu import ke database yang kamu gunakan untuk projek latihan di ebook ini.

Membuat dan Mengkonfigurasikan Model-Model yang Diperlukan

Kita perlu membuat model-model untuk merepresentasikan entitas yang ada di database.

Model Booking

Jalankan perintah berikut:

php artisan make:model Booking

Model Guest

Jalankan perintah berikut:

php artisan make:model Guest

Model Room

Jalankan perintah berikut:

php artisan make:model Room

Model Satisfaction

Jalankan perintah berikut:

php artisan make:model Satisfaction

Model Service

Jalankan perintah berikut:

php artisan make:model Service

Khusus untuk model Satisfaction jadikan seperti ini:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Satisfaction extends Model
{
    use HasFactory;

    public function guest(){
        return $this->belongsTo(Guest::class, 'guest_id');
    }

    public function booking(){
        return $this->belongsTo(Booking::class, 'booking_id');
    }

    public function service(){
        return $this->belongsTo(Service::class, 'service_id');
    }
}

app/Models/Satisfaction.php

Memasang Package untuk Grafik

Kita akan menggunakan Larapex yang sudah tersedia package khusus untuk
Laravelnya yaitu arielmejiadev/larapex-charts

Jalankan perintah berikut:

composer require arielmejiadev/larapex-charts=2.1.0

Publish config

Setelah itu kita perlu mempublikasikan konfigurasi dari package
larapex-charts, Jalankan perintah berikut:

php artisan vendor:publish --tag=larapex-charts-config

Kemudian akan muncul pesan kurang lebih seperti berikut:

Copied File [/vendor/arielmejiadev/larapex-charts/config/larapex-charts.php] To [/config/larapex-charts.php]

Sekarang kita siap untuk melanjutkan ke bab berikutnya.

Sentuhan Akhir

Menyesuaikan Style Dasar Dari Layout

Buka berkas resources/views/layouts/dashboard.blade.php kemudian hapus
kode yang mengekstends ke layouts.app. Yaitu hapus kode ini:

@extends('layouts.app')

Kemudian hapus juga kode pengapit section, yaitu @section('content') dan @endsection:

Hapus!

@section('content') 

{{-- view di sini --}}

@endsection

Ganti bagian atas berkas, yaitu yang tadinya @section('content') dengan kode
<head> yang kita ambil dari layouts.app ini:

<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- CSRF Token -->
    <meta name="csrf-token" content="{{ csrf_token() }}">

    <title>{{ config('app.name', 'Laravel') }}</title>

    <!-- Scripts -->
    <script src="{{ asset('js/app.js') }}" defer></script>

    <!-- Fonts -->
    <link rel="dns-prefetch" href="//fonts.gstatic.com">
    <link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet">

    <!-- Styles -->
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>

Dan dibagian paling akhir berkas, di paling bawah kita tambahkan penutup
<body> dan <html> ini:

</body>
</html>

Menyesuaikan Sidebar

Setelah itu kita ubah kode berikut:

<div class="container-fluid">
    <div class="row">
        <div class="col-md-2">

Menjadi seperti berikut:

<div class="container-fluid">
    <div class="row">
        <div class="col-md-2 p-4 bg-white shadow-sm">

Dengan kode di atas kita mengubah warna background dari sidebar menjadi putih
dan memiliki sedikit shadow serta memberi padding 4px untuk semua sisi.

Menyesuaikan Section Konten Utama

Kemudian kita sesuaikan kode berikut ini:

<div class="col-md-10">
    @yield('main-content')
</div>

Menjadi seperti ini:

<div class="col-md-10 p-4">
    @yield('main-content')
</div>

Kode di atas menambahkan padding 4px di setiap sisi dari konten utama dashboard.

Menyesuaikan Menu Item di Sidebar

Setelah itu kita ubah class untuk tiap-tiap menu di sidebar, dari yang tadinya
seperti ini:

<div class="mb-3">
    <div class="bg-secondary text-white p-2 rounded hover:text-black">
        Occupancy Rate <br/> 
    </div>
    <div class="bg-light p-1 rounded">
        <a href="{{url('/occupancy-rate')}}">Overview</a>
    </div>
    <div class="bg-light p-1 rounded">
        <a href="{{url('/occupancy-rate/room')}}">By room category</a>
    </div>
    <div class="bg-light p-1 rounded">
        <a href="{{url('/occupancy-rate/bed')}}">By bed ype</a>
    </div>
</div>

Menjadi seperti ini:

<div class="mb-3">
    <div class="text-white px-1 py-2 rounded text-xl bg-primary mb-1">
        Occupancy Rate 
    </div>
    <div class="ml-4 px-2 py-1 rounded">
        <a class="text-dark" href="{{url('/occupancy-rate')}}">Overview</a>
    </div>
    <div class="ml-4 px-2 py-1 rounded">
        <a class="text-dark" href="{{url('/occupancy-rate/room')}}">By room category</a>
    </div>
    <div class="ml-4 px-2 py-1 rounded">
        <a class="text-dark" href="{{url('/occupancy-rate/bed')}}">By bed type</a>
    </div>
</div>

Dengan kode di atas kita mengubah tampilan menu dari yang tadinya seperti ini:

ch07-01-sidebar-item-before.png

Menjadi seperti ini:

ch07-02-sidebar-item-after.png

Silahkan ganti seluruh menu item agar memiliki style demikian.

Memberikan Ikon

Kita akan menggunakan ikon dari https://css.gg

Kode ikon untuk Occupancy Rate adalah ini:

<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M16.2426 6.34319C16.6331 5.95266 17.2663 5.95266 17.6568 6.34319C18.0474 6.73371 18.0474 7.36688 17.6568 7.7574L7.75734 17.6569C7.36681 18.0474 6.73365 18.0474 6.34313 17.6569C5.9526 17.2664 5.9526 16.6332 6.34313 16.2427L16.2426 6.34319Z" fill="currentColor" /><path d="M9.87866 9.87872C9.09761 10.6598 7.83128 10.6598 7.05023 9.87872C6.26918 9.09767 6.26918 7.83134 7.05023 7.05029C7.83128 6.26924 9.09761 6.26924 9.87866 7.05029C10.6597 7.83134 10.6597 9.09767 9.87866 9.87872Z" fill="currentColor" /><path d="M14.1213 16.9498C14.9023 17.7308 16.1687 17.7308 16.9497 16.9498C17.7308 16.1687 17.7308 14.9024 16.9497 14.1214C16.1687 13.3403 14.9023 13.3403 14.1213 14.1214C13.3403 14.9024 13.3403 16.1687 14.1213 16.9498Z" fill="currentColor" /></svg>

Kode ikon untuk Demography adalah ini:

<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M8 11C10.2091 11 12 9.20914 12 7C12 4.79086 10.2091 3 8 3C5.79086 3 4 4.79086 4 7C4 9.20914 5.79086 11 8 11ZM8 9C9.10457 9 10 8.10457 10 7C10 5.89543 9.10457 5 8 5C6.89543 5 6 5.89543 6 7C6 8.10457 6.89543 9 8 9Z" fill="currentColor" /><path d="M11 14C11.5523 14 12 14.4477 12 15V21H14V15C14 13.3431 12.6569 12 11 12H5C3.34315 12 2 13.3431 2 15V21H4V15C4 14.4477 4.44772 14 5 14H11Z" fill="currentColor" /><path d="M22 11H16V13H22V11Z" fill="currentColor" /><path d="M16 15H22V17H16V15Z" fill="currentColor" /><path d="M22 7H16V9H22V7Z" fill="currentColor" /></svg>

Kode ikon untuk Behaviour adalah berikut ini:

<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M12 6V4H20V20H12V18H8V16H4V8H8V6H12ZM14 6H18V18H14V6ZM12 8H10V16H12V8ZM8 10V14H6V10H8Z" fill="currentColor" /></svg>

Kode ikon untuk Satisfaction adalah ini:

<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M19 9C19 11.3787 17.8135 13.4804 16 14.7453V22H13.4142L12 20.5858L10.5858 22H8V14.7453C6.18652 13.4804 5 11.3787 5 9C5 5.13401 8.13401 2 12 2C15.866 2 19 5.13401 19 9ZM17 9C17 11.7614 14.7614 14 12 14C9.23858 14 7 11.7614 7 9C7 6.23858 9.23858 4 12 4C14.7614 4 17 6.23858 17 9ZM10 19.7573L12 17.7573L14 19.7574V15.7101C13.3663 15.8987 12.695 16 12 16C11.305 16 10.6337 15.8987 10 15.7101V19.7573Z" fill="currentColor" /></svg>

Kode-kode ikon svg tersbut kita dapatkan dari https://css.gg, kamu pilih salah
satu ikon klik, nanti di sidebar kanan pilih SVG dan kita bisa copas untuk
mendapatkannya.

Selain SVG, juga bisa diunduh dalam bentu kode CSS atau unduh berkas.

Setelah itu kita sisipkan kode ikon tersebut di masing-masing menu item, misalnya untuk occupancy rate menjadi seperti ini:

<div class="text-white px-1 py-2 rounded text-xl bg-primary mb-1">
    <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M16.2426 6.34319C16.6331 5.95266 17.2663 5.95266 17.6568 6.34319C18.0474 6.73371 18.0474 7.36688 17.6568 7.7574L7.75734 17.6569C7.36681 18.0474 6.73365 18.0474 6.34313 17.6569C5.9526 17.2664 5.9526 16.6332 6.34313 16.2427L16.2426 6.34319Z" fill="currentColor" /><path d="M9.87866 9.87872C9.09761 10.6598 7.83128 10.6598 7.05023 9.87872C6.26918 9.09767 6.26918 7.83134 7.05023 7.05029C7.83128 6.26924 9.09761 6.26924 9.87866 7.05029C10.6597 7.83134 10.6597 9.09767 9.87866 9.87872Z" fill="currentColor" /><path d="M14.1213 16.9498C14.9023 17.7308 16.1687 17.7308 16.9497 16.9498C17.7308 16.1687 17.7308 14.9024 16.9497 14.1214C16.1687 13.3403 14.9023 13.3403 14.1213 14.1214C13.3403 14.9024 13.3403 16.1687 14.1213 16.9498Z" fill="currentColor" /></svg>
  Occupancy Rate 
</div>

Silahkan kamu sesuaikan untuk item Behaviour, Demography dan Satisfaction ya.

Active Item

Selanjutnya kita ingin agar item aktif memiliki background hitam dengan teks
putih.

Misalnya jika kita mengeklik menu laporan Demography > By Guest Type,
maka tampilan menu sidebar akan terlihat seperti ini:

ch07-03-sidebar-item-active.png

Untuk melakukan itu pada setiap item link, kita akan ubah dari seperti ini:

<div class="ml-4 px-2 py-1 rounded">
  <a class="text-dark" href="{{url('/occupancy-rate')}}">Overview</a>

Menjadi seperti ini:

<div class="ml-4 px-2 py-1 rounded {{$path == 'occupancy-rate' ? 'bg-dark' : ''}}">
  <a class="{{$path == 'occupancy-rate' ? 'text-white' : 'text-dark'}}" href="{{url('/occupancy-rate')}}">Overview</a>

Dari mana variabel $path yang dipakai pada kode di atas? Kita harus menangkapnya
terlebih dahulu dari \Request::path(), pada bagian atas berkas kita deklarasikan dulu:

@php 
  $path = \Request::path();
@endphp

Kamu paham kan maksud dari kode {{$path == 'occupancy-rate' ? 'bg-dark' : ''}} dan
kode {{$path == 'occupancy-rate' ? 'text-white' : 'text-dark'}}.

Kode tersebut mendeteksi path yang sedang aktif dari URL, jika ternyata
sesuai dengan kriteria yang kita gunakan, dalam contoh di atas adalah occupancy-rate,
maka kita berikan class yang mengindikasikan item sedang aktif, yaitu kita gunakan
bg-dark pada item wrapper dan pada <a> atau link kita berikan teks berwarna putih.

Silahkan sesuaikan semua menu yang ada di sidebar dengan cara yang sama seperti
pada contoh di atas, tinggal kamu sesuaikan saja kriteria $path nya yaitu
sesuai dengan URL / path pada item masing-masing.

User yang Sedang Login

Selanjutnya kita akan berikan slot untuk user yang sedang login, tambahkan kode berikut ini:


  <div class="rounded bg-light px-2 py-3 mb-5">
      <span>
        <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M15 4H21V10H15V4Z" fill="currentColor" /><path d="M3 12C3 16.9706 7.02944 21 12 21C16.9706 21 21 16.9706 21 12H17C17 14.7614 14.7614 17 12 17C9.23858 17 7 14.7614 7 12H3Z" fill="currentColor" /><path d="M6 10C7.65685 10 9 8.65685 9 7C9 5.34315 7.65685 4 6 4C4.34315 4 3 5.34315 3 7C3 8.65685 4.34315 10 6 10Z" fill="currentColor" /></svg>
      </span>
      <span class="h5">
          Muhammad Azamuddin
      </span>
  </div>

Letakkan kode tersebut di atas kode menu item pertama yaitu Occupancy Rate,
alias di bawah kode ini:

<div class="col-md-2 p-4 bg-white shadow-sm">

Jika sudah kamu akan melihat slot untuk menampilkan user yang sedang login
seperti ini:

ch07-04-logged-in-user-slot.png

Tentu untuk otentikasi diluar lingkup bahasan ebook ini seperti yang sudah
ditegaskan di awal. Kamu bisa mengimplementasikan sendiri karena diasumsikan
kamu sudah memahami dasar Laravel.

Jika belum, silahkan kamu pelajari secara detail di ebook saya sebelumnya di
https://bit.ly/buku-laravel-vue

Jika sudah maka kamu akan melihat tampilan dashboard dengan sidebar yang
sudah lebih cantik seperti ini:

ch07-05-polished-sidebar.png

Kode pada view layout/dashboard.php sekarang terlihat seperti ini:

@php 
  $path = \Request::path();
@endphp
<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- CSRF Token -->
    <meta name="csrf-token" content="{{ csrf_token() }}">

    <title>{{ config('app.name', 'Laravel') }}</title>

    <!-- Scripts -->
    <script src="{{ asset('js/app.js') }}" defer></script>

    <!-- Fonts -->
    <link rel="dns-prefetch" href="//fonts.gstatic.com">
    <link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet">

    <!-- Styles -->
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
<div class="container-fluid">
    <div class="row">
        <div class="col-md-2 p-4 bg-white shadow-sm">

                <div class="rounded bg-light px-2 py-3 mb-5">
                    <span>
                      <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M15 4H21V10H15V4Z" fill="currentColor" /><path d="M3 12C3 16.9706 7.02944 21 12 21C16.9706 21 21 16.9706 21 12H17C17 14.7614 14.7614 17 12 17C9.23858 17 7 14.7614 7 12H3Z" fill="currentColor" /><path d="M6 10C7.65685 10 9 8.65685 9 7C9 5.34315 7.65685 4 6 4C4.34315 4 3 5.34315 3 7C3 8.65685 4.34315 10 6 10Z" fill="currentColor" /></svg>
                    </span>
                    <span class="h5">
                        Muhammad Azamuddin
                    </span>
                </div>

                <div class="mb-3">
                    <div class="text-white px-1 py-2 rounded text-xl bg-primary mb-1">
                      <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M16.2426 6.34319C16.6331 5.95266 17.2663 5.95266 17.6568 6.34319C18.0474 6.73371 18.0474 7.36688 17.6568 7.7574L7.75734 17.6569C7.36681 18.0474 6.73365 18.0474 6.34313 17.6569C5.9526 17.2664 5.9526 16.6332 6.34313 16.2427L16.2426 6.34319Z" fill="currentColor" /><path d="M9.87866 9.87872C9.09761 10.6598 7.83128 10.6598 7.05023 9.87872C6.26918 9.09767 6.26918 7.83134 7.05023 7.05029C7.83128 6.26924 9.09761 6.26924 9.87866 7.05029C10.6597 7.83134 10.6597 9.09767 9.87866 9.87872Z" fill="currentColor" /><path d="M14.1213 16.9498C14.9023 17.7308 16.1687 17.7308 16.9497 16.9498C17.7308 16.1687 17.7308 14.9024 16.9497 14.1214C16.1687 13.3403 14.9023 13.3403 14.1213 14.1214C13.3403 14.9024 13.3403 16.1687 14.1213 16.9498Z" fill="currentColor" /></svg>
                        Occupancy Rate 
                    </div>
                    <div class="ml-4 px-2 py-1 rounded">
                        <a class="text-dark" href="{{url('/occupancy-rate')}}">Overview</a>
                    </div>
                    <div class="ml-4 px-2 py-1 rounded">
                        <a class="text-dark" href="{{url('/occupancy-rate/room')}}">By room category</a>
                    </div>
                    <div class="ml-4 px-2 py-1 rounded">
                        <a class="text-dark" href="{{url('/occupancy-rate/bed')}}">By bed type</a>
                    </div>
                </div>


              <div class="mb-3">
                  <div class="text-white px-1 py-2 rounded text-xl bg-primary mb-1">
                    <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M8 11C10.2091 11 12 9.20914 12 7C12 4.79086 10.2091 3 8 3C5.79086 3 4 4.79086 4 7C4 9.20914 5.79086 11 8 11ZM8 9C9.10457 9 10 8.10457 10 7C10 5.89543 9.10457 5 8 5C6.89543 5 6 5.89543 6 7C6 8.10457 6.89543 9 8 9Z" fill="currentColor" /><path d="M11 14C11.5523 14 12 14.4477 12 15V21H14V15C14 13.3431 12.6569 12 11 12H5C3.34315 12 2 13.3431 2 15V21H4V15C4 14.4477 4.44772 14 5 14H11Z" fill="currentColor" /><path d="M22 11H16V13H22V11Z" fill="currentColor" /><path d="M16 15H22V17H16V15Z" fill="currentColor" /><path d="M22 7H16V9H22V7Z" fill="currentColor" /></svg>
                      Demography
                  </div>
                  <div class="ml-4 px-2 py-1 rounded {{$path == 'demography' ? 'bg-dark' : ''}}">
                      <a class="{{$path == 'demography' ? 'text-white' : 'text-dark'}}" href="{{url('/demography')}}">By Age Range</a>
                  </div>
                  <div class="ml-4 px-2 py-1 rounded {{$path == 'demography/guest-type' ? 'bg-dark' : ''}}">
                      <a class="{{$path == 'demography/guest-type' ? 'text-white' : 'text-dark'}}" href="{{url('/demography/guest-type')}}">By Guest Type</a>
                  </div>
                  <div class="ml-4 px-2 py-1 rounded {{$path == 'demography/origin' ? 'bg-dark' : ''}}">
                      <a class="{{$path == 'demography/origin' ? 'text-white' : 'text-dark'}}" href="{{url('/demography/origin')}}">By Origin</a>
                  </div>
              </div>
              <div class="mb-3">
                  <div class="text-white px-1 py-2 rounded text-xl bg-primary mb-1">
                    <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M12 6V4H20V20H12V18H8V16H4V8H8V6H12ZM14 6H18V18H14V6ZM12 8H10V16H12V8ZM8 10V14H6V10H8Z" fill="currentColor" /></svg>
                      Behaviour
                  </div>
                  <div class="ml-4 px-2 py-1 rounded {{$path == 'behaviour/rooms' ? 'bg-dark' : ''}}">
                      <a class="{{$path == 'behaviour/rooms' ? 'text-white' : 'text-dark'}}" href="{{url('/behaviour/rooms')}}">Room Selection</a>
                  </div>
                  <div class="ml-4 px-2 py-1 rounded {{$path == 'behaviour/duration' ? 'bg-dark' : ''}}">
                      <a class="{{$path == 'behaviour/duration' ? 'text-white' : 'text-dark'}}" href="{{url('/behaviour/duration')}}">Stay Duration</a>
                  </div>
              </div>
              <div class="mb-3">
                  <div class="text-white px-1 py-2 rounded text-xl bg-primary mb-1">
                    <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M19 9C19 11.3787 17.8135 13.4804 16 14.7453V22H13.4142L12 20.5858L10.5858 22H8V14.7453C6.18652 13.4804 5 11.3787 5 9C5 5.13401 8.13401 2 12 2C15.866 2 19 5.13401 19 9ZM17 9C17 11.7614 14.7614 14 12 14C9.23858 14 7 11.7614 7 9C7 6.23858 9.23858 4 12 4C14.7614 4 17 6.23858 17 9ZM10 19.7573L12 17.7573L14 19.7574V15.7101C13.3663 15.8987 12.695 16 12 16C11.305 16 10.6337 15.8987 10 15.7101V19.7573Z" fill="currentColor" /></svg>
                      Satisfaction
                  </div>
                  <div class="ml-4 px-2 py-1 rounded {{$path == 'satisfactions' ? 'bg-dark' : ''}}">
                      <a class="{{$path == 'satisfactions' ? 'text-white' : 'text-dark'}}" href="{{url('/satisfactions')}}">Satisfaction</a>
                  </div>
              </div>

          </div>

          <div class="col-md-10 p-4">
              @yield('main-content')
          </div>
      </div>
  </div>
</body>
</html>

Menampilkan Presentase pada Demography By Age Range

Kita akan menampilkan presentase tamu yang masuk dalam kelompok rentang usia
tertentu.

Tampilannya seperti ini:

ch07-06-age-range-presentage.png

Untuk melakukan itu pertama kita perlu sedikit memodifikasi method
byAge pada repository Demography.

Saat ini method byAge menghasilkan data seperti berikut:

ch07-07-by-age-before.png

Kita perlu membuat hasilnya agar memiliki properti percentage seperti ini:

ch07-08-by-age-after.png

Menyesuaikan Method byAge

Untuk melakukannya, buka berkas app/Repositories/Demography.php, pada method
byAge sebelum mengembalikan $data, kita buat dulu variabel $allCount untuk
menyimpan seluruh count dari $data:

$allCount = $data->sum('count');

Kemudian kita buat fungsi untuk menambahkan properti percentage pada
tiap-tiap item di dalam $data:

$addPercentage = function($item) use($allCount) {
    if($allCount == 0){
        $item->percentage = 0;
    } else {
        $item->percentage = $item->count / $allCount * 100;
        $item->percentage = number_format((float)$item->percentage, "2");
    }
    return $item;
};

Lalu kita gunakan fungsi $addPercentage tersebut di dalam method map
yang dimiliki oleh Collection $data seperti ini:

$data = $data->map($addPercentage);

Sehingga sekarang fungsi byAge terlihat seperti berikut:

public function byAge(){
    $data = DB::select("
        SELECT 
        age_range,
        COUNT(id) count
        FROM (
               SELECT
                *,
                CASE
                        WHEN guest_age < 20 THEN '< 20'
                        WHEN guest_age BETWEEN 20 and 29 THEN '20 - 29'
                        WHEN guest_age BETWEEN 30 and 39 THEN '30 - 39'
                        WHEN guest_age BETWEEN 40 and 49 THEN '40 - 49'
                        WHEN guest_age BETWEEN 50 and 59 THEN '50 - 59'
                        WHEN guest_age >= 60 THEN '> 60'
                        WHEN guest_age IS NULL THEN 'Not Filled In (NULL)'
                END as age_range
                FROM bookings
            ) bookings 
        GROUP BY age_range 
        ORDER BY age_range
    ");

    $data = collect($data ? $data : []);

    $allCount = $data->sum('count');

    $addPercentage = function($item) use($allCount) {
        if($allCount == 0){
            $item->percentage = 0;
        } else {
            $item->percentage = $item->count / $allCount * 100;
            $item->percentage = number_format((float)$item->percentage, "2");
        }
        return $item;
    };

    $data = $data->map($addPercentage);

    return $data;
}

Menyesuaikan DemographyController

Berikutnya kita akan menyesuaikan DemographyController, silahkan buka
berkasi controller tersebut.

Setelah itu pada method index, kita akan menyimpan data dari method byAge
yang sudah kita sesuaikan tadi, dalam variabel $dg_by_age_data seperti ini:

$dg_by_age_data = $this->demography->byAge();

Kemudian kita sekalian melakukan refactor terhadap pengisian data dan
label pada grafik $dg_by_age yang sebelumnya seperti ini:

$dg_by_age->addData('Count', $this->demography->byAge()->pluck('count')->toArray());
$dg_by_age->setLabels($this->demography->byAge()->pluck('age_range')->toArray());

Menjadi seperti berikut:

$dg_by_age->addData('Count', $dg_by_age_data->pluck('count')->toArray());
$dg_by_age->setLabels($dg_by_age_data->pluck('age_range')->toArray());

Dan terakhir kita kirimkan juga variabel $dg_by_age_data ke view:

return view(
    'demography.index', 
    compact(
        'dg_by_age',
        'dg_by_age_donut', 
        'dg_by_age_by_month', 
        'dg_by_age_by_quarter', 
        'dg_by_age_by_year', 
        'dg_by_age_data'    )
);

Menyesuaikan View

Setelah kita melakukan penyesuaian pada repository dan controller,
selanjutnya silahkan buka berkas resources/views/demography/index.blade.php.

Pertama kita tambahkan dulu judul halaman yaitu Demography By Age Range
dengan kode ini:

<div class="row">
    <h2 class="p-3">Demography By Age Range</h2>
</div>

Letakkan kode tersebut di bawah kode ini:

@section('main-content')

Kemudian di bawah kode yang baru saja ditambahkan, tambahkan lagi kode berikut
ini untuk menampilkan presentase masing-masing rentang usia yang berasal
dari perulangan terhadap variabel $dg_by_age_data:

<div class="row">
    <div class="col-md-12">
        <div class="text-center pb-5">
            @foreach($dg_by_age_data as $item)
                <div class="d-inline-block bg-white m-2 rounded  text-center py-2 px-5">
                    <div class="h6">
                        {{$item->age_range}} th 
                    </div>
                    <div class="h3">
                        {{$item->percentage}}%
                    </div>
                </div>
            @endforeach
        </div>
    </div>
</div>

Jika sudah silahkan kamu buka kembali http://localhost:8181/demography,
maka kamu akan melihat tampilan sebagai berikut:

ch07-09-demography-after-by-age-percentage.png

Menampilkan Presentase pada Demography By Guest Type

Kita akan melakukan hal yang sama seperti pada bahasan sebelumnya, yaitu
menambahkan informasi presentase demografi dalam kelompok.

Kali ini dalam kelompok tipe tamu / guest type.

Menyesuaikan Repository

Pertama, buka berkas repository Demography kembali, dan
ubah method byGuestType agar menghasilkan properti percentage pada
setiap item dari nilai kembaliannya.

Kodenya adalah sebagai berikut:

public function byGuestType(){
    $data = DB::select("
        SELECT 
        guest_type,
        COUNT(id) count 
        FROM bookings 
        GROUP BY bookings.guest_type
    ");

    $data = collect($data ? $data : []);

    $allCount = $data->sum('count');

    $addPercentage = function($item) use($allCount) {
        if($allCount == 0){
            $item->percentage = 0;
        } else {
            $item->percentage = $item->count / $allCount * 100;
            $item->percentage = number_format((float)$item->percentage, "2");
        }
        return $item;
    };

    $data = $data->map($addPercentage);

    return $data;
}

Menyesuaikan Controller

Setelah method di repository disesuaikan, sekarang buka berkas
app/Http/Controllers/DemographyController.php,

Pada action byGuestType, kita akan mengambil data dari method di
repository yang baru kita sesuaikan ke dalam variabel $dg_by_type_data:

$dg_by_type_data = $this->demography->byGuestType();

Kemudian kita ubah juga kode berikut ini:

$dg_by_age->addData('Count', $this->demography->byAge()->pluck('count')->toArray());
$dg_by_age->setLabels($this->demography->byAge()->pluck('age_range')->toArray());

Menjadi seperti berikut:

$dg_by_type->addData('Count', $dg_by_type_data->pluck('count')->toArray());
$dg_by_type->setLabels($dg_by_type_data->pluck('guest_type')->toArray());

Setelah itu kita juga mengirimkan variabel $dg_by_type_data ke view terkait:

return view(
    'demography.guest-type', 
    compact(
        'dg_by_type',
        'dg_by_type_donut', 
        'dg_by_type_by_month', 
        'dg_by_type_by_quarter', 
        'dg_by_type_by_year', 
        'dg_by_type_data'    )
);

Menampilkan Presentase pada View

Buka berkas app/resources/demography/guest-type.blade.php,
sama seperti sebelumnya kita akan menambahkan judul untuk halaman dan menampilkan
kartu berisi informasi presentase masing-masing kelompok tipe tamu.

Kodenya adalah sebagai berikut:

<div class="row">
    <h2 class="p-3">Demography By Guest Type</h2>
</div>

<div class="row">
    <div class="col-md-12">
        <div class="text-center pb-5">
            @foreach($dg_by_type_data as $item)
                <div class="d-inline-block bg-white m-2 rounded  text-center py-2 px-5">
                    <div class="h6">
                        {{$item->guest_type}}
                    </div>
                    <div class="h3">
                        {{$item->percentage}}%
                    </div>
                </div>
            @endforeach
        </div>
    </div>
</div>

Letakkan kode tersebut di bawah kode @section('main-content').

Setelah itu silahkan buka http://localhost:8181/demography/guest-type
kamu akan melihat tampilan halaman seperti berikut:

ch07-10-demography-after-by-guest-type-percentage.png

Menampilkan Presentase pada Behaviour Room Selection

Menyesuaikan Repository

Kita perlu menyesuaikan method rooms pada repository Behaviour supaya
mengembalikan item yang memiliki properti percentage dari yang sebelumnya
hanya memiliki properti count dan room_category.

Caranya adalah seperti yang sudah kita lakukan pada repository Demography,
masih ingat kan?

Kode akhir dari method rooms yang sudah disesuaikan adalah sebagai berikut:

public function rooms(int $year = NULL){

    $data = DB::table('bookings')
        ->select([DB::raw('COUNT(id) count'), 'room_category'])
        ->groupBy('room_category')
        ->orderBy('room_category');

    if($year){
        $data = $data->whereYear('start_date', '=', $year);
    }

    $data = $data->get();

    $allCount = $data->sum('count');

    $addPercentage = function($item) use ($allCount) {

        if($allCount == 0){
            $item->percentage = 0; 
        } else {
            $item->percentage = $item->count / $allCount * 100;
            $item->percentage = number_format((float)$item->percentage, 2);
        }

        return $item;
    };

    return $data->map($addPercentage);
}

Menyesuaikan Controller

Setelah itu buka berkas BehaviourController, dan pada action rooms,
kita akan menyimpan data dari method rooms dari repository behaviour
ke dalam variabel $rooms_overview_data:

$rooms_overview_data = $this->behaviour->rooms($year);

Kemudian kita refactor kode pengisian data dan label terhadap grafik
$rooms_overview dengan memanfaatkan variabel yang baru saja kita buat
menjadi seperti ini:

$rooms_overview->setLabels($rooms_overview_data->pluck('room_category')->toArray());
$rooms_overview->addData($rooms_overview_data->pluck('count')->toArray());

Setelah itu kita kirimkan juga variabel $rooms_overview_data ke view terkait:

return view(
    'behaviour.rooms', 
    compact(
        'rooms_overview',
        'rooms_by_age', 
        'rooms_by_guest_type', 
        'rooms_by_guest_origin', 
        'rooms_overview_data'
    )
);

Menyesuaikan View

Kemudian buka berkas resources/views/behaviour/rooms.blade.php,
dan tambahkan koda berikut ini, di bawah kode row untuk judul halaman:

<div class="row">
    <div class="col-md-12">
        <div class="text-center pb-5">
            @foreach($rooms_overview_data as $item)
                <div class="d-inline-block bg-white m-2 rounded  text-center py-2 px-5">
                    <div class="h6">
                        {{$item->room_category}}
                    </div>
                    <div class="h3">
                        {{$item->percentage}}%
                    </div>
                </div>
            @endforeach
        </div>
    </div>
</div>

Jika sudah silahkan buka http://localhost:8181/behaviour/rooms maka kamu
akan melihat tampilan ini:

ch07-11-behaviour-after-by-rooms-percentage.png

Menampilkan Presentase pada Behaviour Stay Duration

Kita juga akan menampilkan presentase durasi menginap secara umum di dalam
dashboard Behaviour > Stay Duration

Menyesuaikan Repository

Untuk melakukannya, pertama kita sesuaikan dulu method duration pada
repository Behaviour agar setiap item dalam $data memiliki properti
percetage.

Caranya sama seperti sebelumnya, berikut hasil method yang sudah disesuaikan:

public function duration(int $year = NULL){

    $data = DB::table('bookings')
        ->select(['duration', DB::raw('COUNT(id) count')])
        ->groupBy('duration')
        ->orderBy('duration');

    if($year){
        $data = $data->whereYear('start_date', '=', $year);
    }

    $data = $data->get();

    $allCount = $data->sum('count');

    $addPercentage = function($item) use ($allCount) {

        if($allCount == 0){
            $item->percentage = 0; 
        } else {
            $item->percentage = $item->count / $allCount * 100;
            $item->percentage = number_format((float)$item->percentage, 2);
        }

        return $item;
    };

    return $data->map($addPercentage);

}

Menyesuaikan Controller

Selanjutnya kita simpan data dari method duration repository Behaviour
ke dalam variabel $duration_overview_data:

$duration_overview_data = $this->behaviour->duration($year);

Kemudian kita kita refactor sekalian pengisian data dan label ke dalam
grafik $duration_overview menjadi seperti ini:

$duration_overview->addData($duration_overview_data->pluck('count')->toArray());
$duration_overview->setLabels($duration_overview_data->pluck('duration')->map($addNights)->toArray());

Dan terkhir kita kirimkan variabel $duration_overview_data ke view terkait:

return view(
    'behaviour.duration', 
    compact(
        'duration_overview', 
        'duration_by_age', 
        'duration_by_guest_origin',
        'duration_by_guest_type', 
        'duration_overview_data'
    )
);

Menyesuaikan View

Kemudian buka berkas resources/views/behaviour/duration.blade.php dan
tambahkan kode berikut ini di bawah kode untuk judul halaman:

<div class="row">
    <div class="col-md-12">
        <div class="text-center pb-5">
            @foreach($duration_overview_data as $item)
                <div class="d-inline-block bg-white m-2 rounded  text-center py-2 px-5">
                    <div class="h6">
                        {{$item->duration}} night(s)
                    </div>
                    <div class="h3">
                        {{$item->percentage}}%
                    </div>
                </div>
            @endforeach
        </div>
    </div>
</div>

Jika sudah silahkan buka http://localhost:8181/behaviour/duration maka
kamu akan melihat tampilan presentase berikut:

ch07-12-behaviour-after-by-duration-percentage.png

Restyling Chart

Kita akan menyempurnakan tampilan chart pada konfigurasi-konfigurasi yang
masih bisa kita tweak.

Occupancy Rate > Overview

Yang pertama pada halaman Occupancy Rate > Overview. Kita buka dulu
berkas app/Http/Controllers/OcupancyRateController.php, pada bagian atas
action index, kita buat fungsi $numberFloat berikut:

$numberFloat = function($item){
    return number_format((float)$item, 2);
};

Fungsi ini akan kita gunakan untuk mengubah format presentase agar hanya memiliki
dua angka di belakang koma.

Kalau kamu perhatikan sekarang pada grafik occupancy rate, format presentase nya
masih belum diformat secara baik seperti ini:

ch07-13-unformatted-occupancy-rate.png

Menjadi:

ch07-14-formatted-occupancy-rate.png

Ubah kode pengisian data untuk grafik $occupancy_by_year agar memanfaatkan
fungsi $numberFloat seperti ini:

$occupancy_by_year->addData("Occupancy Rate", $this->occupancyRate->byYear($start_year, $end_year)->pluck('occupancy_rate')->map($numberFloat)->toArray());

Kemudian juga untuk grafik $occupancy_by_month dan $occupancy_by_quarter
seperti ini:

$occupancy_by_month->addData($year, $this->occupancyRate->byMonth($year)->pluck('occupancy_rate')->map($numberFloat)->toArray());
$occupancy_by_quarter->addData($year, $this->occupancyRate->byQuarter($year)->pluck('occupancy_rate')->map($numberFloat)->toArray());

Berikutnya kita juga ingin mengaktifka grid, pada ketiga objek grafik di atas
kita panggil method setGrid():

$occupancy_by_year->setGrid();
$occupancy_by_month->setGrid();
$occupancy_by_quarter->setGrid();

Sekarang tampilan grafik akan menjadi seperti ini:

ch07-15-occupancy-overview-datagrid.png

Selanjutnya kita juga ingin mengaktifkan data label, silahkan panggil method
setDataLabels pada tiga grafik di atas:

$occupancy_by_year->setDataLabels();
$occupancy_by_month->setDataLabels();
$occupancy_by_quarter->setDataLabels();

Maka kamu sekarang akan melihat data label marker di grafik:

ch07-16-occupancy-overview-datalabels.png

Occupancy Rate > By Room Category

Untuk halaman ini, kita akan mengaktifkan grid untuk tiga grafik yang ada.

Buka berkas app/Http/Controllers/OccupancyRateController.php kemudian
pada method room tambahkan kode ini:

$occupancy_by_year_by_room->setGrid();
$occupancy_by_month_by_room->setGrid();
$occupancy_by_quarter_by_room->setGrid();

Kemudian kita juga akan melakukan formatting desimal, buat fungsi $numberFloat
seperti sebelumnya:

$numberFloat = function($item){
    return number_format((float)$item, 2);
};

Kemudian jadikan kode untuk mengisi grafik menjadi seperti berikut:

$categories
    ->each(function($category) use
        ($occupancy_by_month_by_room, $occupancy_by_quarter_by_room, $month_year, $quarter_year, $occupancy_by_year_by_room, $start_year, $end_year, $numberFloat)
    {

        $occupancy_by_month_by_room
            ->addData($category, $this->occupancyRate->byMonthByRoom($category, $month_year)->pluck('occupancy_rate')->map($numberFloat)->toArray());
        $occupancy_by_quarter_by_room
            ->addData($category, $this->occupancyRate->byQuarterByRoom($category, $quarter_year)->pluck('occupancy_rate')->map($numberFloat)->toArray());
        $occupancy_by_year_by_room
            ->addData("Occupancy Rate", $this->occupancyRate->byYearByRoom($category, $start_year, $end_year)->pluck('occupancy_rate')->map($numberFloat)->toArray());

    });

Jika sudah silahkan buka http://localhost:8184/occupancy-rate/room?start=2016&end=2021&quarter_year=2020&month_year=2020
kamu akan mendapati tampilan grafik seperti ini:

ch07-17-occupancy-by-room-adjustment.png

Tema Grafik

Saya telah menyiapkan beberapa warna atau tema untuk grafik yang bisa kamu pakai.

Cara penggunaannya masih ingat kan? Tinggal panggil setColors dengan daftar
warna pada tema yang kamu inginkan pada masing-masing objek grafik yang kamu buat.

Berikut beberapaa tema yang bisa kamu pakai:

Tema 1

ch07-18-tema-grafik-1.png

Kode warna:

$chart->setColors(["#693c72", "#c15050", "#d97642", "#d49d42", "#9b3675"]);

Tema 2

ch07-19-tema-grafik-2.png

Kode warna:

$chart->setColors(["#1f441e", "#cee6b4", "#9ecca4", "#9b3675", "#f6c065"]);

Tema 3

ch07-20-tema-grafik-3.png

Kode warna:

$chart->setColors(["#ff75a0", "#fce38a", "#eaffd0", "#95e1d3", "#cee6b4"]);

Tema 4

Kode warna:

ch07-21-tema-grafik-4.png

$chart->setColors(["#09015f", "#af0069", "#55b3b1", "#f6c065", "#d97642"]);

Tema 5

ch07-22-tema-grafik-5.png

Kode warna:

$chart->setColors(["#865858", "#8e7f7f", "#bbbbbb", "#e2d5d5", "#eac8af"]);

Penutup

Demikianlah materi yang dapat kami sampaikan. Kita telah belajar banyak tentang
visualisasi data menggunakan Laravel dengan package Larapex.

Mulai dari fundamental grafik dengan Larapex sampai belajar banyak studi
kasus pembuatan grafik dengan tema perhotelan.

Mudah-mudahan materi yang terdapat di ebook ini dapat memberikan manfaat bagi
kita semua.