Modul 03: Auth Helper & Reusable Layout
Modul 03: Auth Helper & Reusable Layout
Berikut adalah seluruh berkas kode program aktual yang digunakan dalam aplikasi SIPAS tanpa potongan atau placeholder. Kode dapat dipelajari dan diketikkan langsung pada Sublime Text 3.
1
Helper Otorisasi & Sesi (auth_helper.php)
Lokasi Berkas: application/helpers/auth_helper.php
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* auth_helper.php
* Helper untuk pengecekan session login dan role authorization
*/
if (!function_exists('is_logged_in')) {
/**
* Cek apakah user saat ini sedang login
*/
function is_logged_in() {
$CI =& get_instance();
return (bool) $CI->session->userdata('logged_in');
}
}
if (!function_exists('check_login')) {
/**
* Memastikan user sudah login, jika belum redirect ke /login
*/
function check_login() {
$CI =& get_instance();
if (!$CI->session->userdata('logged_in')) {
$CI->session->set_flashdata('error', 'Silakan login terlebih dahulu untuk mengakses sistem.');
redirect('login');
}
}
}
if (!function_exists('check_admin')) {
/**
* Memastikan user yang login adalah ADMIN
*/
function check_admin() {
check_login();
$CI =& get_instance();
if ($CI->session->userdata('role') !== 'admin') {
$CI->session->set_flashdata('error', 'Anda tidak memiliki akses ke halaman administrator.');
redirect('user/dashboard');
}
}
}
if (!function_exists('check_user')) {
/**
* Memastikan user yang login adalah USER / SISWA
*/
function check_user() {
check_login();
$CI =& get_instance();
if ($CI->session->userdata('role') !== 'user') {
redirect('admin/dashboard');
}
}
}
if (!function_exists('get_user_initials')) {
/**
* Mendapatkan inisial 2 huruf dari nama user untuk avatar
*/
function get_user_initials($name) {
$words = explode(' ', trim($name));
$initials = '';
if (isset($words[0])) {
$initials .= strtoupper(substr($words[0], 0, 1));
}
if (isset($words[1])) {
$initials .= strtoupper(substr($words[1], 0, 1));
}
return empty($initials) ? 'U' : $initials;
}
}
if (!function_exists('format_tanggal_indo')) {
/**
* Format tanggal Indonesia sederhana (contoh: 02 Sep 2026)
*/
function format_tanggal_indo($date_string) {
if (empty($date_string) || $date_string === '0000-00-00') {
return '—';
}
$bulan = [
1 => 'Jan', 2 => 'Feb', 3 => 'Mar', 4 => 'Apr',
5 => 'Mei', 6 => 'Jun', 7 => 'Jul', 8 => 'Agu',
9 => 'Sep', 10 => 'Okt', 11 => 'Nov', 12 => 'Des'
];
$time = strtotime($date_string);
$d = date('d', $time);
$m = (int) date('m', $time);
$y = date('Y', $time);
return $d . ' ' . (isset($bulan[$m]) ? $bulan[$m] : '') . ' ' . $y;
}
}
💡 Catatan: Baris komentar (// atau /*
*/) bersifat opsional/penjelas logika. Tidak wajib diketik semua agar lebih cepat.
2
Header Master Template (header.php)
Lokasi Berkas: application/views/layouts/header.php
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
?>
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?= isset($title) ? html_escape($title) : 'SIPAS Perpustakaan Digital' ?></title>
<!-- Bootstrap 5 Offline -->
<link rel="stylesheet" href="<?= base_url('assets/vendor/bootstrap/bootstrap.min.css') ?>">
<!-- Bootstrap Icons Offline -->
<link rel="stylesheet" href="<?= base_url('assets/vendor/bootstrap-icons/font/bootstrap-icons.min.css') ?>">
<!-- Custom CSS -->
<link rel="stylesheet" href="<?= base_url('assets/css/app.css') ?>">
</head>
<body class="bg-light">
💡 Catatan: Baris komentar (// atau /*
*/) bersifat opsional/penjelas logika. Tidak wajib diketik semua agar lebih cepat.
3
Bilah Navigasi Atas (navbar.php)
Lokasi Berkas: application/views/layouts/navbar.php
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
$user_name = $this->session->userdata('nama') ? $this->session->userdata('nama') : 'Pengguna';
$user_initials = get_user_initials($user_name);
$user_role = $this->session->userdata('role');
?>
<header class="app-topbar">
<div class="d-flex align-items-center gap-3">
<!-- Mobile Toggle Button -->
<button class="btn btn-light d-lg-none p-2 border-0" type="button" data-bs-toggle="offcanvas" data-bs-target="#mobileSidebar" aria-controls="mobileSidebar">
<i class="bi bi-list fs-4"></i>
</button>
<span class="d-none d-sm-inline fw-semibold text-secondary">
<?= $user_role === 'admin' ? 'Panel Administrator' : 'Portal Perpustakaan Siswa' ?>
</span>
</div>
<div class="d-flex align-items-center gap-3">
<div class="dropdown">
<button class="btn btn-light border-0 d-flex align-items-center gap-2 px-2 py-1" type="button" id="userDropdown" data-bs-toggle="dropdown" aria-expanded="false">
<div class="avatar-circle">
<?= $user_initials ?>
</div>
<div class="text-start d-none d-md-block" style="line-height: 1.2;">
<div class="fw-bold text-dark" style="font-size: 0.85rem;"><?= html_escape($user_name) ?></div>
<div class="text-muted" style="font-size: 0.72rem;"><?= ucfirst($user_role) ?></div>
</div>
<i class="bi bi-chevron-down ms-1 text-muted" style="font-size: 0.75rem;"></i>
</button>
<ul class="dropdown-menu dropdown-menu-end shadow-sm border mt-2" aria-labelledby="userDropdown">
<li class="px-3 py-2 border-bottom">
<div class="fw-bold text-dark"><?= html_escape($user_name) ?></div>
<div class="small text-muted">@<?= html_escape($this->session->userdata('username')) ?></div>
</li>
<?php if ($user_role === 'user'): ?>
<li><a class="dropdown-item py-2" href="<?= site_url('user/profil') ?>"><i class="bi bi-person me-2 text-muted"></i> Profil Saya</a></li>
<li><a class="dropdown-item py-2" href="<?= site_url('user/peminjaman') ?>"><i class="bi bi-journal-check me-2 text-muted"></i> Buku Saya</a></li>
<li><hr class="dropdown-divider"></li>
<?php endif; ?>
<li><a class="dropdown-item py-2 text-danger" href="<?= site_url('logout') ?>"><i class="bi bi-box-arrow-right me-2"></i> Keluar</a></li>
</ul>
</div>
</div>
</header>
💡 Catatan: Baris komentar (// atau /*
*/) bersifat opsional/penjelas logika. Tidak wajib diketik semua agar lebih cepat.
4
Sidebar Administrator (sidebar_admin.php)
Lokasi Berkas:
application/views/layouts/sidebar_admin.php
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
$current_page = $this->uri->segment(2);
$current_sub = $this->uri->segment(3);
?>
<!-- Desktop Sidebar -->
<aside class="app-sidebar d-none d-lg-flex">
<div class="sidebar-brand">
<div class="sidebar-brand-icon">
<i class="bi bi-book-half"></i>
</div>
<div>
<div class="sidebar-brand-text">SIPAS DIGITAL</div>
<span class="sidebar-brand-sub">Perpustakaan Ardli Sela</span>
</div>
</div>
<div class="sidebar-menu">
<div class="sidebar-heading">Menu Utama</div>
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link <?= ($current_page === 'dashboard' || empty($current_page)) ? 'active' : '' ?>" href="<?= site_url('admin/dashboard') ?>">
<i class="bi bi-grid"></i>
<span>Dashboard</span>
</a>
</li>
</ul>
<div class="sidebar-heading mt-3">Master Data</div>
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link <?= ($current_page === 'buku') ? 'active' : '' ?>" href="<?= site_url('admin/buku') ?>">
<i class="bi bi-book"></i>
<span>Data Buku</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link <?= ($current_page === 'anggota') ? 'active' : '' ?>" href="<?= site_url('admin/anggota') ?>">
<i class="bi bi-people"></i>
<span>Data Anggota</span>
</a>
</li>
</ul>
<div class="sidebar-heading mt-3">Transaksi</div>
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link <?= ($current_page === 'transaksi' && empty($this->input->get('status'))) ? 'active' : '' ?>" href="<?= site_url('admin/transaksi') ?>">
<i class="bi bi-arrow-left-right"></i>
<span>Semua Transaksi</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link <?= ($current_page === 'transaksi' && $this->input->get('status') === 'dipinjam') ? 'active' : '' ?>" href="<?= site_url('admin/transaksi?status=dipinjam') ?>">
<i class="bi bi-clock-history"></i>
<span>Peminjaman Aktif</span>
</a>
</li>
</ul>
</div>
<div class="sidebar-footer">
<div class="user-badge-container">
<div class="avatar-circle">
<?= get_user_initials($this->session->userdata('nama')) ?>
</div>
<div class="overflow-hidden" style="line-height: 1.2;">
<div class="fw-bold text-dark text-truncate" style="font-size: 0.85rem;"><?= html_escape($this->session->userdata('nama')) ?></div>
<div class="text-muted" style="font-size: 0.72rem;">Administrator</div>
</div>
</div>
<a href="<?= site_url('logout') ?>" class="btn btn-outline-danger btn-sm w-100 justify-content-center">
<i class="bi bi-box-arrow-right"></i> Keluar
</a>
</div>
</aside>
<!-- Mobile Offcanvas Sidebar -->
<div class="offcanvas offcanvas-start" tabindex="-1" id="mobileSidebar" aria-labelledby="mobileSidebarLabel">
<div class="offcanvas-header border-bottom">
<div class="d-flex align-items-center gap-2">
<div class="sidebar-brand-icon">
<i class="bi bi-book-half"></i>
</div>
<div>
<h6 class="offcanvas-title fw-bold" id="mobileSidebarLabel">SIPAS DIGITAL</h6>
<span class="small text-muted">Panel Administrator</span>
</div>
</div>
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body p-0 d-flex flex-column">
<div class="sidebar-menu flex-grow-1">
<div class="sidebar-heading">Menu Utama</div>
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link <?= ($current_page === 'dashboard' || empty($current_page)) ? 'active' : '' ?>" href="<?= site_url('admin/dashboard') ?>">
<i class="bi bi-grid"></i>
<span>Dashboard</span>
</a>
</li>
</ul>
<div class="sidebar-heading mt-3">Master Data</div>
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link <?= ($current_page === 'buku') ? 'active' : '' ?>" href="<?= site_url('admin/buku') ?>">
<i class="bi bi-book"></i>
<span>Data Buku</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link <?= ($current_page === 'anggota') ? 'active' : '' ?>" href="<?= site_url('admin/anggota') ?>">
<i class="bi bi-people"></i>
<span>Data Anggota</span>
</a>
</li>
</ul>
<div class="sidebar-heading mt-3">Transaksi</div>
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link <?= ($current_page === 'transaksi' && empty($this->input->get('status'))) ? 'active' : '' ?>" href="<?= site_url('admin/transaksi') ?>">
<i class="bi bi-arrow-left-right"></i>
<span>Semua Transaksi</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link <?= ($current_page === 'transaksi' && $this->input->get('status') === 'dipinjam') ? 'active' : '' ?>" href="<?= site_url('admin/transaksi?status=dipinjam') ?>">
<i class="bi bi-clock-history"></i>
<span>Peminjaman Aktif</span>
</a>
</li>
</ul>
</div>
<div class="sidebar-footer">
<a href="<?= site_url('logout') ?>" class="btn btn-outline-danger btn-sm w-100 justify-content-center">
<i class="bi bi-box-arrow-right"></i> Keluar
</a>
</div>
</div>
</div>
💡 Catatan: Baris komentar (// atau /*
*/) bersifat opsional/penjelas logika. Tidak wajib diketik semua agar lebih cepat.
5
Sidebar Anggota Siswa (sidebar_user.php)
Lokasi Berkas: application/views/layouts/sidebar_user.php
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
$current_page = $this->uri->segment(2);
?>
<!-- Desktop Sidebar -->
<aside class="app-sidebar d-none d-lg-flex">
<div class="sidebar-brand">
<div class="sidebar-brand-icon">
<i class="bi bi-book-half"></i>
</div>
<div>
<div class="sidebar-brand-text">SIPAS DIGITAL</div>
<span class="sidebar-brand-sub">Perpustakaan Ardli Sela</span>
</div>
</div>
<div class="sidebar-menu">
<div class="sidebar-heading">Menu Utama</div>
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link <?= ($current_page === 'dashboard' || empty($current_page)) ? 'active' : '' ?>" href="<?= site_url('user/dashboard') ?>">
<i class="bi bi-grid"></i>
<span>Dashboard</span>
</a>
</li>
</ul>
<div class="sidebar-heading mt-3">Perpustakaan</div>
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link <?= ($current_page === 'buku') ? 'active' : '' ?>" href="<?= site_url('user/buku') ?>">
<i class="bi bi-search"></i>
<span>Cari Buku</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link <?= ($current_page === 'peminjaman') ? 'active' : '' ?>" href="<?= site_url('user/peminjaman') ?>">
<i class="bi bi-journal-check"></i>
<span>Buku Saya</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link <?= ($current_page === 'riwayat') ? 'active' : '' ?>" href="<?= site_url('user/riwayat') ?>">
<i class="bi bi-clock-history"></i>
<span>Riwayat Peminjaman</span>
</a>
</li>
</ul>
<div class="sidebar-heading mt-3">Akun</div>
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link <?= ($current_page === 'profil') ? 'active' : '' ?>" href="<?= site_url('user/profil') ?>">
<i class="bi bi-person"></i>
<span>Profil Saya</span>
</a>
</li>
</ul>
</div>
<div class="sidebar-footer">
<div class="user-badge-container">
<div class="avatar-circle">
<?= get_user_initials($this->session->userdata('nama')) ?>
</div>
<div class="overflow-hidden" style="line-height: 1.2;">
<div class="fw-bold text-dark text-truncate" style="font-size: 0.85rem;"><?= html_escape($this->session->userdata('nama')) ?></div>
<div class="text-muted text-truncate" style="font-size: 0.72rem;"><?= html_escape($this->session->userdata('kelas')) ?></div>
</div>
</div>
<a href="<?= site_url('logout') ?>" class="btn btn-outline-danger btn-sm w-100 justify-content-center">
<i class="bi bi-box-arrow-right"></i> Keluar
</a>
</div>
</aside>
<!-- Mobile Offcanvas Sidebar -->
<div class="offcanvas offcanvas-start" tabindex="-1" id="mobileSidebar" aria-labelledby="mobileSidebarUserLabel">
<div class="offcanvas-header border-bottom">
<div class="d-flex align-items-center gap-2">
<div class="sidebar-brand-icon">
<i class="bi bi-book-half"></i>
</div>
<div>
<h6 class="offcanvas-title fw-bold" id="mobileSidebarUserLabel">SIPAS DIGITAL</h6>
<span class="small text-muted">Portal Siswa</span>
</div>
</div>
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body p-0 d-flex flex-column">
<div class="sidebar-menu flex-grow-1">
<div class="sidebar-heading">Menu Utama</div>
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link <?= ($current_page === 'dashboard' || empty($current_page)) ? 'active' : '' ?>" href="<?= site_url('user/dashboard') ?>">
<i class="bi bi-grid"></i>
<span>Dashboard</span>
</a>
</li>
</ul>
<div class="sidebar-heading mt-3">Perpustakaan</div>
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link <?= ($current_page === 'buku') ? 'active' : '' ?>" href="<?= site_url('user/buku') ?>">
<i class="bi bi-search"></i>
<span>Cari Buku</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link <?= ($current_page === 'peminjaman') ? 'active' : '' ?>" href="<?= site_url('user/peminjaman') ?>">
<i class="bi bi-journal-check"></i>
<span>Buku Saya</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link <?= ($current_page === 'riwayat') ? 'active' : '' ?>" href="<?= site_url('user/riwayat') ?>">
<i class="bi bi-clock-history"></i>
<span>Riwayat Peminjaman</span>
</a>
</li>
</ul>
<div class="sidebar-heading mt-3">Akun</div>
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link <?= ($current_page === 'profil') ? 'active' : '' ?>" href="<?= site_url('user/profil') ?>">
<i class="bi bi-person"></i>
<span>Profil Saya</span>
</a>
</li>
</ul>
</div>
<div class="sidebar-footer">
<a href="<?= site_url('logout') ?>" class="btn btn-outline-danger btn-sm w-100 justify-content-center">
<i class="bi bi-box-arrow-right"></i> Keluar
</a>
</div>
</div>
</div>
💡 Catatan: Baris komentar (// atau /*
*/) bersifat opsional/penjelas logika. Tidak wajib diketik semua agar lebih cepat.
6
Penampil Notifikasi Status (flash_message.php)
Lokasi Berkas:
application/views/layouts/flash_message.php
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
?>
<?php if ($this->session->flashdata('success')): ?>
<div class="alert alert-soft-success alert-dismissible fade show d-flex align-items-center mb-4 alert-auto-dismiss" role="alert">
<i class="bi bi-check-circle-fill me-2 fs-5 text-success"></i>
<div><?= $this->session->flashdata('success') ?></div>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php endif; ?>
<?php if ($this->session->flashdata('error')): ?>
<div class="alert alert-soft-danger alert-dismissible fade show d-flex align-items-center mb-4" role="alert">
<i class="bi bi-exclamation-triangle-fill me-2 fs-5 text-danger"></i>
<div><?= $this->session->flashdata('error') ?></div>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php endif; ?>
<?php if (validation_errors()): ?>
<div class="alert alert-soft-danger alert-dismissible fade show mb-4" role="alert">
<div class="fw-bold mb-1"><i class="bi bi-exclamation-circle-fill me-2"></i> Periksa kembali isian formulir:</div>
<div class="small ps-4"><?= validation_errors('<div class="mb-1">• ', '</div>') ?></div>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php endif; ?>
💡 Catatan: Baris komentar (// atau /*
*/) bersifat opsional/penjelas logika. Tidak wajib diketik semua agar lebih cepat.
7
Footer Master Template (footer.php)
Lokasi Berkas: application/views/layouts/footer.php
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
?>
<!-- Bootstrap Bundle with Popper Offline -->
<script src="<?= base_url('assets/vendor/bootstrap/bootstrap.bundle.min.js') ?>"></script>
<!-- Custom App JS -->
<script src="<?= base_url('assets/js/app.js') ?>"></script>
</body>
</html>
💡 Catatan: Baris komentar (// atau /*
*/) bersifat opsional/penjelas logika. Tidak wajib diketik semua agar lebih cepat.