đŸ’ģ Pemrograman Web 2
🎓 Pertemuan
Pertemuan 15: Integrasi Sistem & Finalisasi

MODUL PEMROGRAMAN WEBSITE 2

Mata Kuliah: Pemrograman Website 2
Kode MK: INF2419
SKS: 3 (Praktikum)
Semester: Genap 2025/2026
Program Studi: Informatika
Fakultas: FEBI / Saintek
Universitas: UIN K.H. Abdurrahman Wahid Pekalongan

Dosen Pengampu: Mohammad Reza Maulana, M.Kom
NIP: 199110082025051002

Pertemuan: 15 dari 16
Durasi: 150 menit (3 × 50 menit)
Studi Kasus Berkelanjutan: Sistem Manajemen Perpustakaan


PERTEMUAN 15

INTEGRASI SISTEM & FINALISASI

A. INFORMASI PERTEMUAN

AspekKeterangan
Capaian Pembelajaran Lulusan (CPL)CPL10: Mampu mendesain, mengimplementasikan, dan mengevaluasi solusi berbasis komputasi sesuai kebutuhan pengguna.
Capaian Pembelajaran Mata Kuliah (CPMK)CPMK10.1: Mampu mengembangkan dan mengevaluasi aplikasi web backend sesuai kebutuhan pengguna.
Sub-CPMKSub-CPMK10.1.1: Mengintegrasikan frontend dan backend menjadi sistem yang fungsional.
Sub-CPMK10.1.2: Menguji fungsionalitas aplikasi web backend berdasarkan skenario penggunaan.
Indikator PencapaianMahasiswa mampu:
1. Mengintegrasikan semua fitur sistem perpustakaan
2. Implementasi fitur pengembalian buku dengan perhitungan denda
3. Membuat dashboard dengan statistik dan grafik lengkap
4. Implementasi search dan filter global
5. Membuat laporan transaksi dengan filter
6. Melakukan testing dan debugging sistematis
7. Enhancement UI/UX untuk user experience yang baik
8. Membuat dokumentasi sistem yang lengkap
Alokasi Waktuâ€ĸ Teori: 60 menit
â€ĸ Praktikum: 90 menit
â€ĸ Total: 150 menit (3 × 50 menit)

B. PENDAHULUAN

1. Deskripsi Singkat

Pertemuan kelimabelas ini adalah puncak dari seluruh pembelajaran yang telah dilakukan sepanjang semester. Mahasiswa akan mengintegrasikan semua modul yang telah dibuat (Authentication, CRUD Buku, CRUD Anggota, Transaksi Peminjaman) menjadi satu sistem perpustakaan yang lengkap, fungsional, dan siap digunakan. Fokus pertemuan ini adalah pada finalisasi fitur-fitur yang belum selesai, enhancement UI/UX, testing menyeluruh, debugging, dan pembuatan dokumentasi sistem.

2. Keterkaitan dengan Pertemuan Lain

Pertemuan ini adalah integrasi dan finalisasi dari semua pembelajaran:

Rangkuman Perjalanan Pembelajaran (Pertemuan 1-15):

📚 FASE 1: FOUNDATION (Pertemuan 1-7)
├─ P1: Pengenalan Backend & Konsep Web Development
├─ P2: PHP Basics - Variables, Data Types, Operators
├─ P3: Control Flow - If/Else, Switch, Loops
├─ P4: Functions & Array
├─ P5: Form Handling & Superglobals
├─ P6: MySQL Database & SQL Queries
└─ P7: CRUD Native PHP/MySQL

🎓 P8: UTS (Mid-Semester Evaluation)

⚡ FASE 2: LARAVEL FOUNDATION (Pertemuan 9-10)
├─ P9: Pengenalan Laravel & MVC Concept
└─ P10: Database Migration & Eloquent Model

đŸ—ī¸ FASE 3: CRUD DEVELOPMENT (Pertemuan 11-13)
├─ P11: Controller & View (MVC Implementation)
├─ P12: CRUD Buku (Complete CRUD Pattern)
└─ P13: CRUD Anggota (Replikasi Pattern dengan DRY)

🔐 FASE 4: INTEGRATION & FINALIZATION (Pertemuan 14-15)
├─ P14: Authentication (Laravel Breeze) + Transaksi Peminjaman
└─ P15: **[SEKARANG]** INTEGRASI LENGKAP & FINALISASI
    ├─ Pengembalian Buku + Perhitungan Denda
    ├─ Dashboard Complete dengan Grafik
    ├─ Global Search & Advanced Filters
    ├─ Laporan & Analytics
    ├─ UI/UX Enhancement
    ├─ Testing & Bug Fixing
    └─ Documentation

đŸŽ¯ P16: UAS (Final Presentation & Evaluation)

3. Manfaat Pembelajaran

  1. Mampu mengintegrasikan multiple modules menjadi satu sistem yang kohesif
  2. Dapat melakukan testing dan debugging secara sistematis
  3. Terampil membuat dashboard informatif dengan visualisasi data
  4. Memahami pentingnya UI/UX yang baik untuk user experience
  5. Siap melakukan deployment aplikasi web ke production
  6. Memiliki portfolio project yang siap dipresentasikan di dunia kerja

4. Relevansi dengan Studi Kasus

Sistem Perpustakaan yang LENGKAP dan TERINTEGRASI:

┌─────────────────────────────────────────────────────┐
│       SISTEM MANAJEMEN PERPUSTAKAAN                  │
│                  (COMPLETE SYSTEM)                   │
├─────────────────────────────────────────────────────┤
│                                                      │
│  ✅ Authentication System (Login/Logout/Register)   │
│  ✅ CRUD Buku (Create, Read, Update, Delete)        │
│  ✅ CRUD Anggota (Create, Read, Update, Delete)     │
│  ✅ Transaksi Peminjaman (Auto Update Stok)         │
│  ✅ Pengembalian Buku (Perhitungan Denda)           │
│  ✅ Dashboard (Statistics + Charts)                 │
│  ✅ Global Search (Multi-Module)                    │
│  ✅ Laporan Transaksi (Filter + Export)             │
│  ✅ Notifikasi Keterlambatan                        │
│  ✅ Responsive Design (Mobile-Friendly)             │
│                                                      │
└─────────────────────────────────────────────────────┘

C. MATERI TEORI

1. System Integration Principles

a. Apa itu System Integration?

System Integration adalah proses menggabungkan berbagai subsistem atau komponen menjadi satu sistem yang bekerja secara kohesif dan berfungsi sebagai satu kesatuan.

Dalam Konteks Sistem Perpustakaan:

┌──────────────────────────────────────────────────┐
│     SISTEM TERINTEGRASI PERPUSTAKAAN              │
├──────────────────────────────────────────────────┤
│                                                   │
│  ┌────────────┐  ┌────────────┐  ┌────────────┐ │
│  │   BUKU     │  │  ANGGOTA   │  │ TRANSAKSI  │ │
│  │   (CRUD)   │  │   (CRUD)   │  │  PINJAM/   │ │
│  │            │  │            │  │  KEMBALI   │ │
│  └─────â”Ŧ──────┘  └──────â”Ŧ─────┘  └─────â”Ŧ──────┘ │
│        │                │               │        │
│        └────────────────┴───────────────┘        │
│                         │                        │
│                  ┌──────â–ŧ──────┐                 │
│                  │AUTHENTICATION│                 │
│                  │   (Breeze)   │                 │
│                  └──────â”Ŧ───────┘                 │
│                         │                        │
│                  ┌──────â–ŧ──────┐                 │
│                  │  DATABASE   │                 │
│                  │   (MySQL)   │                 │
│                  └──────â”Ŧ───────┘                 │
│                         │                        │
│                  ┌──────â–ŧ──────┐                 │
│                  │  DASHBOARD  │                 │
│                  │  & REPORTS  │                 │
│                  └─────────────┘                 │
│                                                   │
└──────────────────────────────────────────────────┘

b. Integration Checklist

✅ Data Layer:

  • Foreign keys terkonfigurasi dengan benar
  • Relasi Model (hasMany, belongsTo) sudah didefinisikan
  • Cascade delete berfungsi
  • Seeding data untuk testing tersedia

✅ Business Logic Layer:

  • Peminjaman update stok buku (-1)
  • Pengembalian restore stok buku (+1)
  • Denda dihitung otomatis (Rp 5.000/hari)
  • Validasi: Tidak bisa pinjam buku stok 0
  • Validasi: Hanya anggota aktif yang bisa pinjam

✅ UI/UX Layer:

  • Navigation bar konsisten
  • Flash messages di semua CRUD
  • Confirmation dialog untuk delete
  • Loading indicators untuk proses
  • Responsive untuk mobile

✅ Security Layer:

  • Middleware auth pada routes
  • CSRF token di semua forms
  • Input validation
  • XSS protection (Blade escaping)

2. Testing & Debugging Strategies

a. Jenis-Jenis Testing

1. Unit Testing:

  • Test individual functions/methods
  • Contoh: Test method generateKodeTransaksi()

2. Integration Testing:

  • Test modules working together
  • Contoh: Test peminjaman → update stok → save to database

3. User Acceptance Testing (UAT):

  • Test dari perspektif user
  • Simulasi penggunaan nyata

4. Manual Testing:

  • Click through aplikasi secara manual
  • Test semua fitur satu per satu

b. Testing Scenarios

Scenario 1: Happy Path - Peminjaman Berhasil

LANGKAH:
1. Login sebagai admin
2. Buka halaman transaksi → Create
3. Pilih anggota dengan status "Aktif"
4. Pilih buku yang stoknya > 0
5. Submit form

EXPECTED RESULT:
✅ Transaksi created
✅ Stok buku berkurang 1
✅ Redirect ke index transaksi
✅ Flash message muncul

Scenario 2: Edge Case - Stok Habis

LANGKAH:
1. Pilih buku dengan stok = 0
2. Submit form

EXPECTED RESULT:
✅ Error message "Stok buku habis"
✅ Transaksi TIDAK dibuat

c. Debugging Tools

1. Laravel Debug Bar:

composer require barryvdh/laravel-debugbar --dev

2. dd() dan dump():

dd($transaksi);  // Die and dump
dump($transaksi);  // Dump without dying

3. Laravel Log:

Log::info('Transaksi created', ['id' => $transaksi->id]);
Log::error('Failed', ['error' => $e->getMessage()]);

3. UI/UX Enhancement Principles

a. Prinsip Dasar UI/UX

1. Consistency (Konsistensi):

  • Warna yang sama untuk aksi yang sama
  • Typography konsisten
  • Button styles seragam
  • Spacing konsisten

2. Feedback (Umpan Balik):

  • Loading indicators
  • Success/error messages
  • Confirmation dialogs
  • Progress indicators

3. Accessibility:

  • Proper labels
  • Alt text
  • Keyboard navigation
  • Color contrast

4. Responsive Design:

  • Mobile-first approach
  • Touch-friendly buttons
  • Readable fonts

5. Performance:

  • Fast page loads
  • Minimal queries (eager loading)
  • Image optimization

4. Search & Filter Implementation

a. Global Search Strategy

public function search(Request $request)
{
    $keyword = $request->input('q');
    
    // Search in Buku
    $bukus = Buku::where('judul', 'like', "%{$keyword}%")
                 ->orWhere('pengarang', 'like', "%{$keyword}%")
                 ->limit(10)
                 ->get();
    
    // Search in Anggota
    $anggotas = Anggota::where('nama', 'like', "%{$keyword}%")
                       ->orWhere('email', 'like', "%{$keyword}%")
                       ->limit(10)
                       ->get();
    
    // Search in Transaksi
    $transaksis = Transaksi::where('kode_transaksi', 'like', "%{$keyword}%")
                            ->limit(10)
                            ->get();
    
    return view('search.results', compact('keyword', 'bukus', 'anggotas', 'transaksis'));
}

b. Advanced Filters

public function filter(Request $request)
{
    $query = Transaksi::query();
    
    // Filter by date range
    if ($request->tanggal_dari && $request->tanggal_sampai) {
        $query->whereBetween('tanggal_pinjam', [
            $request->tanggal_dari,
            $request->tanggal_sampai
        ]);
    }
    
    // Filter by status
    if ($request->status) {
        $query->where('status', $request->status);
    }
    
    $transaksis = $query->with(['anggota', 'buku'])->paginate(20);
    
    return view('transaksi.index', compact('transaksis'));
}

5. Documentation Best Practices

a. Code Documentation

/**
 * Create a new transaksi peminjaman buku.
 * 
 * This method handles the complete borrowing workflow:
 * 1. Validates that book stock is available
 * 2. Creates transaksi record
 * 3. Decrements book stock automatically
 * 
 * @param  \Illuminate\Http\Request  $request
 * @return \Illuminate\Http\RedirectResponse
 */
public function store(Request $request)
{
    // Implementation
}

b. README.md Structure

# Sistem Perpustakaan Laravel
 
## Deskripsi
Aplikasi manajemen perpustakaan berbasis web.
 
## Fitur
- Authentication
- CRUD Buku & Anggota
- Transaksi Peminjaman & Pengembalian
- Dashboard & Reports
 
## Tech Stack
- Laravel 12.x
- MySQL 8.x
- Bootstrap 5.3
 
## Instalasi
1. Clone repo
2. composer install
3. npm install
4. cp .env.example .env
5. php artisan key:generate
6. php artisan migrate --seed
7. php artisan serve

D. PRAKTIKUM

1. Tujuan Praktikum

  1. Melengkapi fitur pengembalian buku
  2. Membuat dashboard informatif
  3. Implementasi global search
  4. Membuat laporan transaksi
  5. Testing & bug fixing
  6. UI/UX enhancements
  7. Dokumentasi lengkap

2. PRAKTIKUM 1: Fitur Pengembalian Buku Lengkap

Tujuan

Melengkapi fitur pengembalian buku dengan perhitungan denda otomatis.

Langkah-langkah

a. Update TransaksiController — tambah method kembalikan dengan UI feedback

Buka file app/Http/Controllers/TransaksiController.php dan pastikan method kembalikan sudah ada (dari Pertemuan 14). Tambahkan pengecekan status:

// Di TransaksiController.php — tambahkan/update method kembalikan
public function kembalikan(string $id)
{
    try {
        DB::transaction(function () use ($id) {
            $transaksi = Transaksi::findOrFail($id);
 
            // Cek apakah sudah dikembalikan
            if ($transaksi->status === 'Dikembalikan') {
                throw new \Exception('Buku sudah dikembalikan sebelumnya.');
            }
 
            $tanggalDikembalikan = now();
            $denda = $this->hitungDenda($transaksi, $tanggalDikembalikan);
 
            $transaksi->update([
                'status' => 'Dikembalikan',
                'tanggal_dikembalikan' => $tanggalDikembalikan,
                'denda' => $denda,
            ]);
 
            $transaksi->buku->increment('stok');
        });
 
        return redirect()->route('transaksi.show', $id)
                         ->with('success', 'Buku berhasil dikembalikan!');
    } catch (\Exception $e) {
        return redirect()->back()
                         ->with('error', 'Gagal mengembalikan buku: ' . $e->getMessage());
    }
}

b. Update View resources/views/transaksi/show.blade.php

Tambahkan tombol pengembalian dengan konfirmasi SweetAlert2:

{{-- Di dalam card body detail transaksi --}}
@if($transaksi->status === 'Dipinjam')
    <button type="button" class="btn btn-success" id="btn-kembalikan">
        <i class="bi bi-arrow-return-left"></i> Kembalikan Buku
    </button>
 
    <form id="form-kembalikan" action="{{ route('transaksi.kembalikan', $transaksi->id) }}" method="POST" class="d-none">
        @csrf
        @method('PATCH')
    </form>
@else
    @if($transaksi->tanggal_dikembalikan <= $transaksi->tanggal_kembali)
        <div class="alert alert-success">
            <i class="bi bi-check-circle"></i> Dikembalikan tepat waktu pada
            {{ $transaksi->tanggal_dikembalikan->format('d M Y') }}
        </div>
    @else
        <div class="alert alert-warning">
            <i class="bi bi-exclamation-triangle"></i> Terlambat dikembalikan!
            Denda: Rp {{ number_format($transaksi->denda, 0, ',', '.') }}
        </div>
    @endif
@endif
 
@push('scripts')
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script>
document.getElementById('btn-kembalikan')?.addEventListener('click', function() {
    Swal.fire({
        title: 'Konfirmasi Pengembalian',
        text: 'Apakah Anda yakin ingin mengembalikan buku ini?',
        icon: 'question',
        showCancelButton: true,
        confirmButtonColor: '#198754',
        confirmButtonText: 'Ya, Kembalikan!',
        cancelButtonText: 'Batal'
    }).then((result) => {
        if (result.isConfirmed) {
            document.getElementById('form-kembalikan').submit();
        }
    });
});
</script>
@endpush

Key Features: ✅ Button "Kembalikan Buku" ✅ Konfirmasi dengan SweetAlert2 ✅ Perhitungan denda otomatis ✅ Update stok buku ✅ Status alert (tepat waktu/terlambat)


3. PRAKTIKUM 2: Enhanced Dashboard

Tujuan

Membuat dashboard informatif dengan statistik dan grafik.

Langkah-langkah

a. Update DashboardController

Buat file app/Http/Controllers/DashboardController.php:

<?php
 
namespace App\Http\Controllers;
 
use App\Models\Buku;
use App\Models\Anggota;
use App\Models\Transaksi;
use Carbon\Carbon;
 
class DashboardController extends Controller
{
    public function index()
    {
        // Statistik utama
        $stats = [
            'total_buku'        => Buku::count(),
            'total_anggota'     => Anggota::where('status', 'Aktif')->count(),
            'total_transaksi'   => Transaksi::count(),
            'sedang_dipinjam'   => Transaksi::where('status', 'Dipinjam')->count(),
            'terlambat'         => Transaksi::where('status', 'Dipinjam')
                                            ->where('tanggal_kembali', '<', now())->count(),
            'denda_bulan_ini'   => Transaksi::whereMonth('tanggal_dikembalikan', now()->month)
                                            ->sum('denda'),
            'transaksi_hari_ini'=> Transaksi::whereDate('tanggal_pinjam', today())->count(),
            'buku_tersedia'     => Buku::where('stok', '>', 0)->count(),
        ];
 
        // Data chart: transaksi 6 bulan terakhir
        $chartData = collect(range(5, 0))->map(function ($i) {
            $date = now()->subMonths($i);
            return [
                'bulan' => $date->translatedFormat('M Y'),
                'pinjam' => Transaksi::whereMonth('tanggal_pinjam', $date->month)
                                     ->whereYear('tanggal_pinjam', $date->year)->count(),
                'kembali' => Transaksi::whereMonth('tanggal_dikembalikan', $date->month)
                                      ->whereYear('tanggal_dikembalikan', $date->year)->count(),
            ];
        });
 
        // Top 5 buku populer
        $bukuPopuler = Buku::withCount('transaksis')
                           ->orderByDesc('transaksis_count')
                           ->take(5)->get();
 
        // Top 5 anggota aktif
        $anggotaAktif = Anggota::withCount('transaksis')
                               ->orderByDesc('transaksis_count')
                               ->take(5)->get();
 
        // Transaksi terbaru
        $recentTransaksi = Transaksi::with(['anggota', 'buku'])
                                    ->latest()->take(5)->get();
 
        return view('dashboard', compact(
            'stats', 'chartData', 'bukuPopuler',
            'anggotaAktif', 'recentTransaksi'
        ));
    }
}

b. Dashboard View dengan Chart.js

Buat file resources/views/dashboard.blade.php:

@extends('layouts.app')
@section('title', 'Dashboard')
 
@section('content')
<div class="container-fluid py-4">
    <h2 class="mb-4">Dashboard Perpustakaan</h2>
 
    {{-- Statistics Cards --}}
    <div class="row g-3 mb-4">
        @foreach([
            ['Total Buku', $stats['total_buku'], 'bi-book', 'primary'],
            ['Anggota Aktif', $stats['total_anggota'], 'bi-people', 'success'],
            ['Sedang Dipinjam', $stats['sedang_dipinjam'], 'bi-journal-arrow-up', 'info'],
            ['Terlambat', $stats['terlambat'], 'bi-exclamation-triangle', 'danger'],
            ['Transaksi Hari Ini', $stats['transaksi_hari_ini'], 'bi-calendar-check', 'warning'],
            ['Buku Tersedia', $stats['buku_tersedia'], 'bi-bookshelf', 'secondary'],
            ['Total Transaksi', $stats['total_transaksi'], 'bi-receipt', 'dark'],
            ['Denda Bulan Ini', 'Rp ' . number_format($stats['denda_bulan_ini'], 0, ',', '.'), 'bi-cash', 'danger'],
        ] as [$label, $value, $icon, $color])
        <div class="col-xl-3 col-md-6">
            <div class="card border-{{ $color }} h-100">
                <div class="card-body d-flex align-items-center">
                    <i class="bi {{ $icon }} fs-1 text-{{ $color }} me-3"></i>
                    <div>
                        <h6 class="text-muted mb-1">{{ $label }}</h6>
                        <h4 class="mb-0">{{ $value }}</h4>
                    </div>
                </div>
            </div>
        </div>
        @endforeach
    </div>
 
    {{-- Charts --}}
    <div class="row mb-4">
        <div class="col-lg-8">
            <div class="card">
                <div class="card-header">Transaksi 6 Bulan Terakhir</div>
                <div class="card-body">
                    <canvas id="chartTransaksi" height="100"></canvas>
                </div>
            </div>
        </div>
        <div class="col-lg-4">
            <div class="card">
                <div class="card-header">Top 5 Buku Populer</div>
                <div class="card-body">
                    <canvas id="chartBuku" height="200"></canvas>
                </div>
            </div>
        </div>
    </div>
 
    {{-- Recent Transactions --}}
    <div class="card">
        <div class="card-header">Transaksi Terbaru</div>
        <div class="card-body table-responsive">
            <table class="table table-hover">
                <thead>
                    <tr>
                        <th>Kode</th><th>Anggota</th><th>Buku</th>
                        <th>Tgl Pinjam</th><th>Status</th>
                    </tr>
                </thead>
                <tbody>
                    @foreach($recentTransaksi as $trx)
                    <tr>
                        <td>{{ $trx->kode_transaksi }}</td>
                        <td>{{ $trx->anggota->nama }}</td>
                        <td>{{ $trx->buku->judul }}</td>
                        <td>{{ $trx->tanggal_pinjam->format('d/m/Y') }}</td>
                        <td>
                            <span class="badge bg-{{ $trx->status === 'Dipinjam' ? 'warning' : 'success' }}">
                                {{ $trx->status }}
                            </span>
                        </td>
                    </tr>
                    @endforeach
                </tbody>
            </table>
        </div>
    </div>
</div>
 
@push('scripts')
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
// Line chart — Transaksi 6 bulan terakhir
new Chart(document.getElementById('chartTransaksi'), {
    type: 'line',
    data: {
        labels: @json($chartData->pluck('bulan')),
        datasets: [
            { label: 'Peminjaman', data: @json($chartData->pluck('pinjam')),
              borderColor: '#0d6efd', tension: 0.3 },
            { label: 'Pengembalian', data: @json($chartData->pluck('kembali')),
              borderColor: '#198754', tension: 0.3 }
        ]
    },
    options: { responsive: true }
});
 
// Pie chart — Buku Populer
new Chart(document.getElementById('chartBuku'), {
    type: 'pie',
    data: {
        labels: @json($bukuPopuler->pluck('judul')),
        datasets: [{
            data: @json($bukuPopuler->pluck('transaksis_count')),
            backgroundColor: ['#0d6efd','#198754','#ffc107','#dc3545','#6f42c1']
        }]
    },
    options: { responsive: true, plugins: { legend: { position: 'bottom' } } }
});
</script>
@endpush
@endsection

Key Features: ✅ 8 Statistics cards ✅ Line chart transaksi 6 bulan ✅ Pie chart per kategori ✅ Top 5 buku populer ✅ Top 5 anggota aktif ✅ Recent transactions table


4. PRAKTIKUM 3: Global Search

Implementasi SearchController

Buat file app/Http/Controllers/SearchController.php:

<?php
 
namespace App\Http\Controllers;
 
use Illuminate\Http\Request;
use App\Models\Buku;
use App\Models\Anggota;
use App\Models\Transaksi;
 
class SearchController extends Controller
{
    public function index(Request $request)
    {
        $keyword = $request->input('q');
        $results = ['buku' => collect(), 'anggota' => collect(), 'transaksi' => collect()];
 
        if ($keyword) {
            $results['buku'] = Buku::where('judul', 'LIKE', "%{$keyword}%")
                                   ->orWhere('penulis', 'LIKE', "%{$keyword}%")
                                   ->orWhere('isbn', 'LIKE', "%{$keyword}%")
                                   ->get();
 
            $results['anggota'] = Anggota::where('nama', 'LIKE', "%{$keyword}%")
                                         ->orWhere('email', 'LIKE', "%{$keyword}%")
                                         ->orWhere('nim', 'LIKE', "%{$keyword}%")
                                         ->get();
 
            $results['transaksi'] = Transaksi::with(['anggota', 'buku'])
                ->where('kode_transaksi', 'LIKE', "%{$keyword}%")
                ->orWhereHas('anggota', fn($q) => $q->where('nama', 'LIKE', "%{$keyword}%"))
                ->orWhereHas('buku', fn($q) => $q->where('judul', 'LIKE', "%{$keyword}%"))
                ->get();
        }
 
        return view('search.index', compact('keyword', 'results'));
    }
}

Tambahkan route di routes/web.php:

Route::get('/search', [SearchController::class, 'index'])->name('search');

Buat view resources/views/search/index.blade.php:

@extends('layouts.app')
@section('title', 'Pencarian')
 
@section('content')
<div class="container py-4">
    <h2>Hasil Pencarian: "{{ $keyword }}"</h2>
 
    <ul class="nav nav-tabs mb-3" role="tablist">
        <li class="nav-item">
            <a class="nav-link active" data-bs-toggle="tab" href="#tab-buku">
                Buku ({{ $results['buku']->count() }})
            </a>
        </li>
        <li class="nav-item">
            <a class="nav-link" data-bs-toggle="tab" href="#tab-anggota">
                Anggota ({{ $results['anggota']->count() }})
            </a>
        </li>
        <li class="nav-item">
            <a class="nav-link" data-bs-toggle="tab" href="#tab-transaksi">
                Transaksi ({{ $results['transaksi']->count() }})
            </a>
        </li>
    </ul>
 
    <div class="tab-content">
        {{-- Tab Buku --}}
        <div class="tab-pane fade show active" id="tab-buku">
            @forelse($results['buku'] as $buku)
                <div class="card mb-2">
                    <div class="card-body">
                        <h6>{!! str_ireplace($keyword, '<mark>'.$keyword.'</mark>', e($buku->judul)) !!}</h6>
                        <small class="text-muted">{{ $buku->penulis }} — Stok: {{ $buku->stok }}</small>
                    </div>
                </div>
            @empty
                <p class="text-muted">Tidak ada buku yang cocok.</p>
            @endforelse
        </div>
 
        {{-- Tab Anggota --}}
        <div class="tab-pane fade" id="tab-anggota">
            @forelse($results['anggota'] as $anggota)
                <div class="card mb-2">
                    <div class="card-body">
                        <h6>{!! str_ireplace($keyword, '<mark>'.$keyword.'</mark>', e($anggota->nama)) !!}</h6>
                        <small class="text-muted">{{ $anggota->nim }} — {{ $anggota->email }}</small>
                    </div>
                </div>
            @empty
                <p class="text-muted">Tidak ada anggota yang cocok.</p>
            @endforelse
        </div>
 
        {{-- Tab Transaksi --}}
        <div class="tab-pane fade" id="tab-transaksi">
            @forelse($results['transaksi'] as $trx)
                <div class="card mb-2">
                    <div class="card-body">
                        <h6>{{ $trx->kode_transaksi }}</h6>
                        <small>{{ $trx->anggota->nama }} — {{ $trx->buku->judul }}</small>
                    </div>
                </div>
            @empty
                <p class="text-muted">Tidak ada transaksi yang cocok.</p>
            @endforelse
        </div>
    </div>
</div>
@endsection

Tambahkan search box di resources/views/layouts/app.blade.php (di dalam navbar):

<form class="d-flex" action="{{ route('search') }}" method="GET">
    <input class="form-control me-2" type="search" name="q"
           placeholder="Cari buku, anggota, transaksi..." value="{{ request('q') }}">
    <button class="btn btn-outline-light" type="submit">
        <i class="bi bi-search"></i>
    </button>
</form>

Key Features: ✅ Search box di navigation ✅ Search 3 modules (Buku, Anggota, Transaksi) ✅ Results dalam tabs ✅ Keyword highlighting ✅ Empty state handling


5. PRAKTIKUM 4: Laporan Transaksi

Implementasi Laporan

Buat file app/Http/Controllers/LaporanController.php:

<?php
 
namespace App\Http\Controllers;
 
use Illuminate\Http\Request;
use App\Models\Transaksi;
use App\Models\Anggota;
use Carbon\Carbon;
 
class LaporanController extends Controller
{
    public function index(Request $request)
    {
        $query = Transaksi::with(['anggota', 'buku']);
 
        // Filter berdasarkan tanggal
        if ($request->filled('dari')) {
            $query->whereDate('tanggal_pinjam', '>=', $request->dari);
        }
        if ($request->filled('sampai')) {
            $query->whereDate('tanggal_pinjam', '<=', $request->sampai);
        }
 
        // Filter berdasarkan status
        if ($request->filled('status')) {
            $query->where('status', $request->status);
        }
 
        // Filter berdasarkan anggota
        if ($request->filled('anggota_id')) {
            $query->where('anggota_id', $request->anggota_id);
        }
 
        $transaksis = $query->latest()->get();
 
        // Statistik ringkasan
        $summary = [
            'total'          => $transaksis->count(),
            'dipinjam'       => $transaksis->where('status', 'Dipinjam')->count(),
            'dikembalikan'   => $transaksis->where('status', 'Dikembalikan')->count(),
            'total_denda'    => $transaksis->sum('denda'),
        ];
 
        $anggotas = Anggota::orderBy('nama')->get();
 
        return view('laporan.index', compact('transaksis', 'summary', 'anggotas'));
    }
}

Buat view resources/views/laporan/index.blade.php:

@extends('layouts.app')
@section('title', 'Laporan Transaksi')
 
@section('content')
<div class="container py-4">
    <h2>Laporan Transaksi</h2>
 
    {{-- Filter Form --}}
    <div class="card mb-4">
        <div class="card-body">
            <form method="GET" class="row g-3">
                <div class="col-md-3">
                    <label class="form-label">Dari Tanggal</label>
                    <input type="date" name="dari" class="form-control"
                           value="{{ request('dari') }}">
                </div>
                <div class="col-md-3">
                    <label class="form-label">Sampai Tanggal</label>
                    <input type="date" name="sampai" class="form-control"
                           value="{{ request('sampai') }}">
                </div>
                <div class="col-md-3">
                    <label class="form-label">Status</label>
                    <select name="status" class="form-select">
                        <option value="">Semua</option>
                        <option value="Dipinjam" {{ request('status') == 'Dipinjam' ? 'selected' : '' }}>Dipinjam</option>
                        <option value="Dikembalikan" {{ request('status') == 'Dikembalikan' ? 'selected' : '' }}>Dikembalikan</option>
                    </select>
                </div>
                <div class="col-md-3">
                    <label class="form-label">Anggota</label>
                    <select name="anggota_id" class="form-select">
                        <option value="">Semua</option>
                        @foreach($anggotas as $anggota)
                            <option value="{{ $anggota->id }}" {{ request('anggota_id') == $anggota->id ? 'selected' : '' }}>
                                {{ $anggota->nama }}
                            </option>
                        @endforeach
                    </select>
                </div>
                <div class="col-12">
                    <button type="submit" class="btn btn-primary">
                        <i class="bi bi-filter"></i> Filter
                    </button>
                    <a href="{{ route('laporan.index') }}" class="btn btn-secondary">Reset</a>
                    <button type="button" class="btn btn-success" onclick="window.print()">
                        <i class="bi bi-printer"></i> Cetak
                    </button>
                </div>
            </form>
        </div>
    </div>
 
    {{-- Summary Cards --}}
    <div class="row g-3 mb-4">
        <div class="col-md-3">
            <div class="card bg-primary text-white">
                <div class="card-body text-center">
                    <h6>Total Transaksi</h6>
                    <h3>{{ $summary['total'] }}</h3>
                </div>
            </div>
        </div>
        <div class="col-md-3">
            <div class="card bg-warning text-dark">
                <div class="card-body text-center">
                    <h6>Dipinjam</h6>
                    <h3>{{ $summary['dipinjam'] }}</h3>
                </div>
            </div>
        </div>
        <div class="col-md-3">
            <div class="card bg-success text-white">
                <div class="card-body text-center">
                    <h6>Dikembalikan</h6>
                    <h3>{{ $summary['dikembalikan'] }}</h3>
                </div>
            </div>
        </div>
        <div class="col-md-3">
            <div class="card bg-danger text-white">
                <div class="card-body text-center">
                    <h6>Total Denda</h6>
                    <h3>Rp {{ number_format($summary['total_denda'], 0, ',', '.') }}</h3>
                </div>
            </div>
        </div>
    </div>
 
    {{-- Tabel Laporan --}}
    <div class="card">
        <div class="card-body table-responsive">
            <table class="table table-striped table-hover">
                <thead class="table-dark">
                    <tr>
                        <th>No</th><th>Kode</th><th>Anggota</th><th>Buku</th>
                        <th>Tgl Pinjam</th><th>Tgl Kembali</th><th>Status</th><th>Denda</th>
                    </tr>
                </thead>
                <tbody>
                    @forelse($transaksis as $i => $trx)
                    <tr>
                        <td>{{ $i + 1 }}</td>
                        <td>{{ $trx->kode_transaksi }}</td>
                        <td>{{ $trx->anggota->nama }}</td>
                        <td>{{ $trx->buku->judul }}</td>
                        <td>{{ $trx->tanggal_pinjam->format('d/m/Y') }}</td>
                        <td>{{ $trx->tanggal_dikembalikan?->format('d/m/Y') ?? '-' }}</td>
                        <td>
                            <span class="badge bg-{{ $trx->status === 'Dipinjam' ? 'warning' : 'success' }}">
                                {{ $trx->status }}
                            </span>
                        </td>
                        <td>{{ $trx->denda ? 'Rp ' . number_format($trx->denda, 0, ',', '.') : '-' }}</td>
                    </tr>
                    @empty
                    <tr><td colspan="8" class="text-center text-muted">Tidak ada data transaksi.</td></tr>
                    @endforelse
                </tbody>
            </table>
        </div>
    </div>
</div>
 
{{-- Print CSS --}}
<style>
@media print {
    .card-body form, .btn, nav, footer { display: none !important; }
    .card { border: none !important; box-shadow: none !important; }
}
</style>
@endsection

Key Features: ✅ Filter: Date range, Status, Anggota ✅ Statistics summary ✅ Tabel laporan lengkap ✅ Print-friendly CSS ✅ Export Excel (optional)


6. PRAKTIKUM 5: Testing & Bug Fixing

Testing Checklist

Authentication:

  • Register berfungsi
  • Login berfungsi
  • Logout berfungsi
  • Protected routes redirect

CRUD Buku:

  • Create berfungsi
  • Read berfungsi
  • Update berfungsi
  • Delete berfungsi
  • Validation bekerja
  • Search berfungsi

CRUD Anggota:

  • All CRUD operations
  • Date picker functional
  • Email unique validation

Transaksi:

  • Peminjaman (stok -1)
  • Pengembalian (stok +1, denda)
  • Business rules validation

Dashboard:

  • Statistics akurat
  • Charts tampil data
  • Quick actions work

Search:

  • Results correct
  • Tabs berfungsi
  • Highlighting works

E. TUGAS AKHIR - PROJECT FINAL (100%)

Fitur Wajib (Harus ada & berfungsi sempurna)

  1. ✅ Authentication System

    • Login, Register, Logout
    • Password hashing
    • Middleware protection
  2. ✅ CRUD Buku Lengkap

    • Create, Read, Update, Delete
    • Validation
    • Search & Filter
  3. ✅ CRUD Anggota Lengkap

    • All CRUD operations
    • Date handling
    • Email & phone validation
  4. ✅ Transaksi Peminjaman

    • Form peminjaman
    • Auto update stok (-1)
    • Generate kode transaksi
    • Tanggal kembali auto (+7 hari)
  5. ✅ Pengembalian Buku

    • Update status
    • Perhitungan denda (Rp 5.000/hari)
    • Auto update stok (+1)
  6. ✅ Dashboard

    • Minimum 6 statistics
    • 2 charts (line + pie/bar)
    • Recent data tables
    • Quick actions
  7. ✅ Global Search

    • Search 3 modules
    • Results dalam tabs
    • Keyword highlighting
  8. ✅ Laporan Transaksi

    • Filter (date, status, anggota)
    • Statistics summary
    • Print-friendly

Fitur Tambahan (Pilih minimal 3 dari 6)

1. Notifikasi Terlambat (20%)

Spesifikasi:

  • Dashboard widget "Buku Terlambat"
  • Jumlah transaksi yang terlambat
  • List anggota yang terlambat
  • Badge "Terlambat X hari" di index transaksi
  • Alert di detail transaksi jika melewati tanggal kembali

Implementasi:

// Di DashboardController
$bukuTerlambat = Transaksi::where('status', 'Dipinjam')
                           ->where('tanggal_kembali', '<', now())
                           ->with(['anggota', 'buku'])
                           ->get();

2. Kategori Buku Management (15%)

Spesifikasi:

  • CRUD Kategori
  • Relasi Buku-Kategori (belongsTo)
  • Dropdown kategori di form buku
  • Filter buku per kategori

3. Export Data (20%)

Spesifikasi:

  • Export buku ke Excel
  • Export anggota ke Excel
  • Export laporan transaksi ke PDF

Library yang bisa digunakan:

composer require maatwebsite/excel
composer require barryvdh/laravel-dompdf

4. Dashboard Charts Advanced (15%)

Spesifikasi:

  • Pie chart kategori buku
  • Bar chart top 10 buku terpopuler
  • Line chart trend peminjaman
  • Donut chart status transaksi

5. Riwayat Peminjaman Anggota (15%)

Spesifikasi:

  • Di detail anggota, tampilkan riwayat semua peminjaman
  • Statistik: Total pinjam, Total denda
  • Timeline peminjaman
  • Filter by status

6. Advanced Search & Filter (15%)

Spesifikasi:

  • Filter buku: Range harga, Tahun terbit, Ketersediaan
  • Filter anggota: Range umur, Pekerjaan, Status
  • Filter transaksi: Multiple criteria
  • Save filter preferences

Enhancement Bonus (+20%)

1. Responsive Design (5%)

  • Mobile-friendly layout
  • Touch-friendly buttons (min 44x44px)
  • Hamburger menu untuk mobile
  • Responsive tables (scroll/stack)

2. Dark Mode Toggle (5%)

  • Switch dark/light mode
  • Simpan preference di localStorage
  • Consistent color scheme

3. Barcode/QR Code (5%)

  • Barcode untuk buku (simulation)
  • QR Code untuk kartu anggota
  • Scanner simulation (input manual)

4. Multi-Language (5%)

  • Indonesia & English
  • Language switcher
  • Translate semua UI text

5. Advanced Animations (Bonus)

  • Loading animations
  • Transition effects
  • Micro-interactions

Deliverables

1. Source Code (GitHub/GitLab)

  • Repository public/private
  • Commit history yang baik
  • Branch structure (main, develop)
  • .gitignore configured

2. Database (.sql file)

  • Export database lengkap
  • Include sample data
  • Clear table structure

3. README.md

  • Deskripsi project
  • Fitur lengkap dengan checklist
  • Screenshots (min 5)
  • Instalasi step-by-step
  • Tech stack
  • Author info

4. Video Demo (3-5 menit)

  • Format: MP4, max 100MB
  • Isi:
    • Intro (30s)
    • Demo fitur utama (2-3 menit)
    • Demo fitur tambahan (1 menit)
    • Closing (30s)
  • Upload ke YouTube/Google Drive

5. Dokumentasi (PDF)

  • User Manual (10-15 halaman)
  • Technical Documentation (5-10 halaman)
  • Include screenshots
  • Table of contents
  • Professional formatting

1. Fungsionalitas (40%)

  • Semua fitur wajib berfungsi 100%: 20%
  • Fitur tambahan berfungsi: 15%
  • No critical bugs: 5%

2. Code Quality (20%)

  • Clean code (DRY, SOLID): 8%
  • Best practices Laravel: 6%
  • Code organization: 4%
  • Comments & documentation: 2%

3. UI/UX (20%)

  • Tampilan menarik & profesional: 8%
  • User-friendly navigation: 6%
  • Consistent design: 4%
  • Responsive design: 2%

4. Testing (10%)

  • No bugs saat demo: 5%
  • Edge cases handled: 3%
  • Error messages jelas: 2%

5. Dokumentasi (10%)

  • README lengkap: 4%
  • Code comments: 3%
  • User manual: 3%

Bonus:

  • Enhancement features: +20%
  • Extra creativity: +10%
  • Total maksimal: 130%

Deadline & Submission

Deadline: Sebelum UAS (Pertemuan 16)

Cara Submit:

  1. Upload source code ke GitHub
  2. Export database (.sql)
  3. Upload video demo ke YouTube (unlisted)
  4. Compile semua dokumen di Google Drive folder
  5. Submit link Google Drive ke Ngaji UIN Gusdur atau Email dosen

Format Nama Folder: NIM_Nama_ProyekAkhir_WebProg2

Isi Folder:

ProyekAkhir/
├── README.md
├── perpustakaan-laravel/ (source code)
├── database.sql
├── screenshots/ (5-10 gambar)
├── UserManual.pdf
├── TechnicalDocs.pdf
└── video-demo-link.txt

Tips Pengerjaan

  1. Mulai dari fitur wajib - Pastikan semua bekerja 100%
  2. Testing berkala - Test setiap fitur setelah selesai
  3. Commit teratur - Commit setiap progress penting
  4. Dokumentasi sejak awal - Jangan tunggu akhir
  5. Minta feedback - Tunjukkan ke teman/dosen lebih awal
  6. Backup berkala - Push ke GitHub setiap hari
  7. UI/UX polish - Sisihkan waktu untuk beautify
  8. Video demo latihan - Rekam beberapa kali sampai smooth

F. EVALUASI

1. Kuis Singkat

Pilihan Ganda:

  1. System integration artinya:

    • A. Membuat sistem baru
    • B. Menggabungkan subsistem menjadi satu kesatuan
    • C. Menghapus sistem lama
    • D. Membeli sistem baru
  2. Eager loading di Laravel menggunakan:

    • A. load()
    • B. with()
    • C. get()
    • D. find()
  3. Method untuk debugging di Laravel:

    • A. print()
    • B. console.log()
    • C. dd()
    • D. debug()
  4. Chart.js digunakan untuk:

    • A. Membuat tabel
    • B. Membuat grafik
    • C. Membuat form
    • D. Membuat database
  5. Global search mencari di:

    • A. Satu tabel
    • B. Dua tabel
    • C. Semua tabel
    • D. Database lain
  6. Print CSS menggunakan media query:

    • A. @media screen
    • B. @media print
    • C. @media mobile
    • D. @media all
  7. withCount() digunakan untuk:

    • A. Hitung total data
    • B. Hitung relasi
    • C. Hitung kolom
    • D. Hitung row
  8. Method untuk highlight keyword:

    • A. highlight()
    • B. str_replace()
    • C. mark()
    • D. bold()
  9. Testing yang dilakukan user disebut:

    • A. Unit testing
    • B. Integration testing
    • C. UAT
    • D. Debug testing
  10. README.md ditulis dalam format:

    • A. HTML
    • B. Markdown
    • C. PHP
    • D. JSON

Essay:

  1. Jelaskan langkah-langkah system integration untuk sistem perpustakaan! Sebutkan minimal 4 aspek yang harus diintegrasikan. (15 poin)

Jawaban tersedia di dokumen kunci jawaban dosen.

  1. Apa perbedaan Unit Testing, Integration Testing, dan UAT? Berikan contoh untuk masing-masing! (15 poin)

Jawaban tersedia di dokumen kunci jawaban dosen.

  1. Jelaskan cara implementasi global search yang mencari di multiple tables! Sertakan minimal 3 tables yang dicari. (15 poin)

Jawaban tersedia di dokumen kunci jawaban dosen.

  1. Mengapa perlu ada laporan transaksi? Sebutkan minimal 5 informasi penting dalam laporan! (10 poin)

Jawaban tersedia di dokumen kunci jawaban dosen.

  1. Sebutkan 5 bug yang mungkin muncul saat integrasi sistem dan cara mengatasinya! (10 poin)

Jawaban tersedia di dokumen kunci jawaban dosen.


2. Checklist Kompetensi Final

NoKompetensiBelumCukupMahir
1System integration○○○
2Testing & debugging○○○
3Dashboard with charts○○○
4Global search○○○
5Reports generation○○○
6UI/UX enhancement○○○
7Code quality○○○
8Documentation○○○
9Problem solving○○○
10Project completion○○○

G. REFERENSI

1. Dokumentasi

2. Tools

3. Resources


H. PERSIAPAN UAS (PERTEMUAN 16)

Format UAS: Presentasi & Evaluasi Akhir

Yang Harus Disiapkan:

1. Sistem Perpustakaan Lengkap:

  • Semua fitur berfungsi 100%
  • No critical bugs
  • Data sample yang cukup
  • Database ter-setup dengan baik

2. Presentasi (10 menit):

Struktur Presentasi:

a. Opening (1 menit)

  • Perkenalan
  • Overview sistem

b. Arsitektur Sistem (2 menit)

  • Tech stack
  • Database schema
  • MVC flow
  • Integration overview

c. Demo Fitur Utama (4 menit)

  • Authentication
  • CRUD operations
  • Transaksi peminjaman & pengembalian
  • Dashboard & reports

d. Challenges & Solutions (2 menit)

  • 3 challenges terbesar
  • Bagaimana solve
  • Lessons learned

e. Closing (1 menit)

  • Summary
  • Future improvements
  • Q&A ready

3. Dokumentasi:

a. README.md

# Sistem Perpustakaan Laravel
 
## Screenshots
Screenshot halaman Login, Dashboard, CRUD Buku, CRUD Anggota,
Transaksi Peminjaman, Pengembalian, Laporan, Search, dll.
 
## Features
✅ All features with checklist
 
## Installation
Step-by-step guide
 
## Usage
User guide ringkas
 
## Tech Stack
Semua technology used
 
## Author
Your info

b. User Manual (PDF)

  • Cover
  • Daftar Isi
  • Pendahuluan
  • Petunjuk Penggunaan (dengan screenshots)
  • FAQ
  • Troubleshooting

c. Technical Documentation (PDF)

  • System Architecture
  • Database Schema
  • API Endpoints (jika ada)
  • Code Structure
  • Deployment Guide

4. Source Code:

  • Clean & well-organized
  • Commented (DocBlocks)
  • Follow PSR standards
  • No debug code (dd(), dump())
  • Proper .gitignore

1. Kelengkapan Fitur (30%)

  • Fitur wajib lengkap: 20%
  • Fitur tambahan: 10%

2. Kualitas Code (20%)

  • Clean code: 10%
  • Best practices: 10%

3. Presentasi (20%)

  • Clarity & structure: 10%
  • Demo smooth: 10%

4. Demo & Q&A (20%)

  • Live demo working: 15%
  • Jawab pertanyaan: 5%

5. Dokumentasi (10%)

  • README complete: 5%
  • User manual clear: 5%

Tips Sukses UAS:

Sebelum UAS:

  1. ✅ Test sistem berkali-kali
  2. ✅ Buat slide presentasi menarik
  3. ✅ Latih presentasi (timing!)
  4. ✅ Siapkan data dummy yang bagus
  5. ✅ Backup database & code
  6. ✅ List 10 possible questions & answers
  7. ✅ Screenshot semua fitur
  8. ✅ Video walkthrough untuk backup

Saat UAS:

  1. Datang lebih awal
  2. Test laptop & koneksi
  3. Buka sistem sebelum presentasi
  4. Tenang & confident
  5. Explain clearly
  6. Demo smooth (practice!)
  7. Handle error gracefully
  8. Jawab jujur jika tidak tahu

Pertanyaan yang Mungkin Ditanya:

  1. Jelaskan alur peminjaman buku dari form sampai database
  2. Bagaimana cara menghitung denda?
  3. Kenapa pakai Laravel Breeze, bukan buat manual?
  4. Apa challenge terbesar saat development?
  5. Bagaimana handle N+1 query problem?
  6. Jelaskan relasi antar tabel
  7. Bagaimana cara protect dari SQL injection?
  8. Kenapa pakai Eloquent, bukan query builder?
  9. Jelaskan MVC pattern di sistem Anda
  10. Future improvement apa yang ingin ditambahkan?

KESIMPULAN

🎉 Selamat! Anda telah menyelesaikan Pemrograman Website 2!

Pencapaian Anda:

Technical Skills: ✅ PHP Programming (Variables, Functions, OOP) ✅ Laravel Framework 12 (MVC, Eloquent, Blade) ✅ Database Management (MySQL, Migrations, Relationships) ✅ Frontend Development (HTML, CSS, Bootstrap, Chart.js) ✅ Authentication & Authorization (Laravel Breeze) ✅ CRUD Operations (Create, Read, Update, Delete) ✅ Business Logic Implementation ✅ API Integration ✅ Testing & Debugging ✅ Version Control (Git)

Soft Skills: ✅ Problem Solving ✅ Logical Thinking ✅ Project Management ✅ Documentation Writing ✅ Presentation Skills ✅ Time Management ✅ Self-Learning ✅ Attention to Detail

Portfolio Project:

Sistem Perpustakaan yang telah Anda bangun adalah:

  • ✅ Full-stack web application
  • ✅ Production-ready (with minor adjustments)
  • ✅ Portfolio-worthy project
  • ✅ Interview talking point
  • ✅ Real-world problem solver

Dapat digunakan untuk:

  1. Job Application - Tunjukkan di CV/Portfolio
  2. Interview - Demo saat interview
  3. Freelance - Base untuk project perpustakaan real
  4. Learning - Reference untuk belajar framework lain
  5. Teaching - Material untuk mengajar junior

Next Steps:

1. Polish Your Project:

  • Fix remaining bugs
  • Improve UI/UX
  • Add more features
  • Write comprehensive tests

2. Deploy to Production:

  • Heroku (free tier)
  • Railway.app
  • DigitalOcean
  • AWS EC2
  • Shared hosting (cpanel)

3. Expand Your Knowledge:

  • Laravel Advanced (Queues, Events, Broadcasting)
  • Vue.js / React untuk frontend
  • API Development (REST, GraphQL)
  • Testing (PHPUnit, Pest)
  • DevOps (Docker, CI/CD)

4. Build More Projects:

  • E-commerce
  • Blog/CMS
  • Booking System
  • Inventory Management
  • Social Media Clone

Final Words:

"The expert in anything was once a beginner."

Anda telah menempuh perjalanan panjang dari:

  • P1: Tidak tahu apa itu backend
  • P8: Sudah bisa CRUD native PHP
  • P16: Full-stack Laravel developer!

Keep learning, keep coding, keep growing! 🚀

Resources untuk Lanjut Belajar:

Official:

  • Laravel Documentation
  • Laravel News
  • Laracasts

Community:

  • Laravel Indonesia (Telegram)
  • Stack Overflow
  • GitHub Discussions

YouTube Channels:

  • Traversy Media
  • The Net Ninja
  • Laravel Daily
  • Codepolitan (Indonesia)
  • Web Programming UNPAS (Indonesia)

Practice Platforms:

  • LeetCode (algorithms)
  • HackerRank (PHP challenges)
  • Exercism (PHP track)
  • Laravel Challenges

Good luck untuk UAS dan karir Anda sebagai Web Developer! 🎓đŸ’ģ


End of Module - Pertemuan 15

Total Perjalanan:

  • 15 Pertemuan ✅
  • 6 Praktikum per pertemuan ≈ 90 Praktikum ✅
  • 1 UTS ✅
  • 1 Project Final ✅
  • 1 UAS (Upcoming) đŸŽ¯

Next: Pertemuan 16 - UAS (Presentasi & Evaluasi Akhir)


LAMPIRAN: Quick Reference

Artisan Commands Penting

# Server
php artisan serve                    # Run development server
php artisan serve --port=8080        # Custom port
 
# Database
php artisan migrate                  # Run migrations
php artisan migrate:fresh            # Drop all & re-run
php artisan migrate:fresh --seed     # Fresh + seed
php artisan db:seed                  # Run seeders
 
# Make Commands
php artisan make:controller NameController --resource
php artisan make:model Name -m       # With migration
php artisan make:request StoreName   # Form request
php artisan make:migration create_table_name
 
# Cache
php artisan config:clear
php artisan cache:clear
php artisan route:clear
php artisan view:clear
 
# Other
php artisan route:list               # List all routes
php artisan tinker                   # REPL
php artisan queue:work               # Process queues
php artisan storage:link             # Link storage

Git Commands

git init
git add .
git commit -m "Initial commit"
git branch -M main
git remote add origin [URL]
git push -u origin main
 
# Daily workflow
git add .
git commit -m "Add feature X"
git push
 
# Branching
git checkout -b feature-name
git checkout main
git merge feature-name

MySQL Quick Reference

-- Show databases
SHOW DATABASES;
 
-- Use database
USE perpustakaan;
 
-- Show tables
SHOW TABLES;
 
-- Describe table
DESC buku;
 
-- Select
SELECT * FROM buku WHERE stok > 0;
 
-- Insert
INSERT INTO buku (kode_buku, judul) VALUES ('BK-001', 'Laravel');
 
-- Update
UPDATE buku SET stok = stok - 1 WHERE id = 1;
 
-- Delete
DELETE FROM buku WHERE id = 1;

Laravel Blade Directives

{{-- Comments --}}
 
{{ $variable }}              {{-- Escaped output --}}
{!! $html !!}               {{-- Raw output --}}
 
@if($condition)
@elseif($other)
@else
@endif
 
@foreach($items as $item)
@endforeach
 
@forelse($items as $item)
@empty
@endforelse
 
@csrf                       {{-- CSRF token --}}
@method('PUT')              {{-- Method spoofing --}}
 
@auth                       {{-- If authenticated --}}
@endauth
 
@guest                      {{-- If not authenticated --}}
@endguest
 
@extends('layout')
@section('content')
@endsection
 
@include('partial')
 
@push('scripts')
@endpush

Bootstrap 5 Classes Cheat Sheet

<!-- Spacing -->
<div class="m-3">       <!-- Margin all sides -->
<div class="mt-3">      <!-- Margin top -->
<div class="p-3">       <!-- Padding all sides -->
<div class="px-3">      <!-- Padding left-right -->
 
<!-- Colors -->
<div class="bg-primary">
<div class="text-white">
<div class="text-success">
 
<!-- Display -->
<div class="d-none">
<div class="d-flex">
<div class="d-inline-block">
 
<!-- Buttons -->
<button class="btn btn-primary">
<button class="btn btn-success">
<button class="btn btn-sm">
 
<!-- Grid -->
<div class="row">
    <div class="col-md-6"></div>
    <div class="col-md-6"></div>
</div>
 
<!-- Alerts -->
<div class="alert alert-success">
<div class="alert alert-danger">

đŸŽ¯ Semua modul pembelajaran telah selesai! 🎓 Sistem perpustakaan siap untuk dipresentasikan! 🚀 Anda siap menjadi Laravel Developer!