Tujuan Praktikum
Setelah praktikum ini, mahasiswa mampu:
- Membuat tampilan dashboard untuk pegawai.
- Menghubungkan dashboard pegawai dengan data dari database.
- Menyediakan shortcut ke halaman profile dan presensi.
- Menyaring menu sesuai role pegawai.
Persiapan
Siapkan kebutuhan berikut:
- Project Java Web Starter
- Folder `src/java/controller`
- Folder `src/java/dao`
- Folder `src/java/model`
- Folder `web/WEB-INF/views/dashboard`
- File `web/WEB-INF/views/profile.jsp`
- File `web/WEB-INF/views/presensi.jsp`
- File `web/WEB-INF/views/partials/sidebar.jsp`
- File `src/java/controller/AuthFilter.java`
- File `web/assets/css/style.css`
- User pegawai yang sudah terhubung ke data pegawai
Konsep Singkat
Dashboard user adalah halaman utama untuk pegawai yang sedang login.
Alurnya seperti ini:
Login pegawai -> DashboardServlet.java -> dashboard/pegawai.jsp
Pada versi ini, DashboardServlet.java tidak hanya
untuk admin, tetapi juga bisa mengarah ke dashboard pegawai.
sidebar.jsp menampilkan menu yang berbeda sesuai
role.
AuthFilter.java membatasi halaman yang boleh dibuka
oleh pegawai.
Langkah 1 - Update File Dashboard
Di pertemuan ini, file yang diupdate adalah:
src/java/controller/DashboardServlet.java
web/WEB-INF/views/dashboard/pegawai.jsp
web/WEB-INF/views/partials/sidebar.jsp
src/java/controller/AuthFilter.java
Catatan:
DashboardDAO, PegawaiDAO, dan PresensiDAO tetap dipakai dari alur dashboard sebelumnya.
Di langkah ini kita fokus pada file yang berubah untuk dashboard pegawai.
Kalau folder dashboard belum ada, buat dulu di dalam
web/WEB-INF/views/.
1. src/java/controller/DashboardServlet.java
package controller;
import dao.DashboardDAO;
import dao.PegawaiDAO;
import dao.PresensiDAO;
import model.Pegawai;
import model.Presensi;
import model.User;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import java.io.IOException;
import java.sql.SQLException;
@WebServlet(name = "DashboardServlet", urlPatterns = {"/dashboard"})
public class DashboardServlet extends HttpServlet {
private static final String ADMIN_PAGE = "/WEB-INF/views/dashboard/admin.jsp";
private static final String PEGAWAI_PAGE = "/WEB-INF/views/dashboard/pegawai.jsp";
private final DashboardDAO dashboardDAO = new DashboardDAO();
private final PegawaiDAO pegawaiDAO = new PegawaiDAO();
private final PresensiDAO presensiDAO = new PresensiDAO();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
User user = getUserLogin(request);
request.setAttribute("activeMenu", "home");
try {
if (user != null && user.isPegawai()) {
showPegawaiDashboard(request, response, user);
return;
}
showAdminDashboard(request, response);
} catch (SQLException e) {
throw new ServletException("Gagal membuka dashboard.", e);
}
}
private void showAdminDashboard(HttpServletRequest request, HttpServletResponse response)
throws SQLException, ServletException, IOException {
request.setAttribute("totalPegawaiAktif", dashboardDAO.countPegawaiAktif());
request.setAttribute("totalBagian", dashboardDAO.countBagian());
request.setAttribute("totalUserAktif", dashboardDAO.countUserAktif());
request.setAttribute("totalDatangHariIni", dashboardDAO.countPresensiDatangHariIni());
request.setAttribute("totalPulangHariIni", dashboardDAO.countPresensiPulangHariIni());
request.setAttribute("totalBelumPresensiHariIni", dashboardDAO.countPresensiBelumHariIni());
request.setAttribute("pegawaiByBagian", dashboardDAO.findPegawaiByBagian());
request.setAttribute("presensiLastSevenDays", dashboardDAO.findPresensiLastSevenDays());
request.setAttribute("presensiTodayStatus", dashboardDAO.findAdminTodayStatus());
forwardToLayout(request, response, ADMIN_PAGE);
}
private void showPegawaiDashboard(HttpServletRequest request, HttpServletResponse response, User user)
throws SQLException, ServletException, IOException {
if (user.getPegawaiId() == null || user.getPegawaiId() <= 0) {
request.setAttribute("message", "Akun ini belum terhubung ke data pegawai.");
forwardToLayout(request, response, PEGAWAI_PAGE);
return;
}
Pegawai pegawai = pegawaiDAO.findById(user.getPegawaiId());
Presensi presensiHariIni = presensiDAO.findTodayByPegawaiId(user.getPegawaiId());
request.setAttribute("pegawai", pegawai);
request.setAttribute("presensiHariIni", presensiHariIni);
request.setAttribute("hadirBulanIni", dashboardDAO.countPresensiBulanIni(user.getPegawaiId()));
request.setAttribute("pulangBulanIni", dashboardDAO.countPulangBulanIni(user.getPegawaiId()));
request.setAttribute("presensiMonthStatus", dashboardDAO.findPegawaiMonthStatus(user.getPegawaiId()));
request.setAttribute("presensiLastSevenDays", dashboardDAO.findPegawaiLastSevenDays(user.getPegawaiId()));
forwardToLayout(request, response, PEGAWAI_PAGE);
}
private User getUserLogin(HttpServletRequest request) {
HttpSession session = request.getSession(false);
if (session == null) {
return null;
}
Object user = session.getAttribute("userLogin");
return user instanceof User ? (User) user : null;
}
private void forwardToLayout(HttpServletRequest request, HttpServletResponse response,
String contentPage) throws ServletException, IOException {
request.setAttribute("contentPage", contentPage);
request.getRequestDispatcher("/index.jsp").forward(request, response);
}
}
2. web/WEB-INF/views/dashboard/pegawai.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<div class="page-header">
<h2>Dashboard Pegawai</h2>
</div>
<c:if test="${not empty message}">
<div class="info"><c:out value="${message}"/></div>
</c:if>
<c:if test="${not empty pegawai}">
<div class="stats-grid">
<div class="stat-card">
<span>Nama Pegawai</span>
<strong><c:out value="${pegawai.namaPegawai}"/></strong>
</div>
<div class="stat-card">
<span>Bagian</span>
<strong><c:out value="${pegawai.bagianNama}"/></strong>
</div>
<div class="stat-card">
<span>Hadir Bulan Ini</span>
<strong>${hadirBulanIni}</strong>
</div>
<div class="stat-card">
<span>Pulang Tercatat</span>
<strong>${pulangBulanIni}</strong>
</div>
</div>
<div class="dashboard-grid">
<div class="card">
<h3>Presensi Hari Ini</h3>
<div class="presensi-status">
<div>
<span>Jam Datang</span>
<strong><c:out value="${presensiHariIni.jamMasuk}" default="-"/></strong>
</div>
<div>
<span>Jam Pulang</span>
<strong><c:out value="${presensiHariIni.jamPulang}" default="-"/></strong>
</div>
</div>
<div class="quick-actions">
<a href="${pageContext.request.contextPath}/presensi" class="btn btn-add">Buka Presensi</a>
<a href="${pageContext.request.contextPath}/profile" class="btn btn-secondary">Profile</a>
</div>
</div>
<div class="card">
<h3>Ringkasan Bulan Ini</h3>
<div class="chart-list">
<c:forEach var="item" items="${presensiMonthStatus}">
<div class="chart-row">
<div class="chart-row__meta">
<span><c:out value="${item.label}"/></span>
<strong>${item.value}</strong>
</div>
<div class="chart-track">
<div class="chart-fill chart-fill--green" style="width: ${item.percent}%"></div>
</div>
</div>
</c:forEach>
</div>
</div>
</div>
<div class="card">
<h3>Presensi 7 Hari Terakhir</h3>
<c:choose>
<c:when test="${empty presensiLastSevenDays}">
<div class="info">Belum ada data presensi 7 hari terakhir.</div>
</c:when>
<c:otherwise>
<div class="bar-chart">
<c:forEach var="item" items="${presensiLastSevenDays}">
<div class="bar-chart__item">
<div class="bar-chart__bar" style="height: ${item.percent}%">
<span>${item.value}</span>
</div>
<small><c:out value="${item.label}"/></small>
</div>
</c:forEach>
</div>
</c:otherwise>
</c:choose>
</div>
</c:if>
3. web/WEB-INF/views/partials/sidebar.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<nav id="sidebar">
<ul>
<li class="${requestScope.activeMenu == 'home' ? 'active' : ''}">
<a href="${pageContext.request.contextPath}/dashboard">
Home
</a>
</li>
<c:choose>
<c:when test="${sessionScope.userLogin.role == 'pegawai'}">
<li class="${requestScope.activeMenu == 'profile' ? 'active' : ''}">
<a href="${pageContext.request.contextPath}/profile">
Profile
</a>
</li>
<li class="${requestScope.activeMenu == 'presensi' ? 'active' : ''}">
<a href="${pageContext.request.contextPath}/presensi">
Presensi
</a>
</li>
</c:when>
<c:otherwise>
<li class="${requestScope.activeMenu == 'bagian' ? 'active' : ''}">
<a href="${pageContext.request.contextPath}/bagian">
Entry Data Bagian
</a>
</li>
<li class="${requestScope.activeMenu == 'pegawai' ? 'active' : ''}">
<a href="${pageContext.request.contextPath}/pegawai">
Entry Data Pegawai
</a>
</li>
<li class="${requestScope.activeMenu == 'users' ? 'active' : ''}">
<a href="${pageContext.request.contextPath}/users">
Manajemen User
</a>
</li>
</c:otherwise>
</c:choose>
</ul>
</nav>
4. src/java/controller/AuthFilter.java
package controller;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import model.User;
import java.io.IOException;
/**
* Filter untuk memastikan semua halaman hanya bisa diakses
* oleh user yang sudah login.
*
* Pengecualian (URL yang boleh diakses tanpa login):
* - /login
* - /assets/* (CSS, JS, gambar)
*/
@WebFilter(filterName = "AuthFilter", urlPatterns = {"/*"})
public class AuthFilter implements Filter {
// URL yang boleh diakses tanpa login
private static final String[] PUBLIC_URLS = {
"/login",
"/assets/",
"/db-status"
};
private static final String[] PEGAWAI_URLS = {
"/",
"/index.jsp",
"/dashboard",
"/profile",
"/presensi",
"/logout",
"/db-status"
};
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// Tidak ada inisialisasi khusus
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpReq = (HttpServletRequest) request;
HttpServletResponse httpRes = (HttpServletResponse) response;
String requestURI = httpReq.getRequestURI();
String contextPath = httpReq.getContextPath();
// Cek apakah URL ini termasuk public (tidak butuh login)
String pathWithoutContext = requestURI.substring(contextPath.length());
for (String publicUrl : PUBLIC_URLS) {
if (pathWithoutContext.startsWith(publicUrl)) {
chain.doFilter(request, response); // lolos tanpa cek session
return;
}
}
HttpSession session = httpReq.getSession(false);
boolean sudahLogin = (session != null)
&& (session.getAttribute("userLogin") != null);
if (!sudahLogin) {
httpRes.sendRedirect(contextPath + "/login");
return;
}
User user = (User) session.getAttribute("userLogin");
if (user != null && user.isPegawai() && !isPegawaiUrl(pathWithoutContext)) {
httpRes.sendRedirect(contextPath + "/index.jsp");
return;
}
chain.doFilter(request, response);
}
private boolean isPegawaiUrl(String path) {
for (String allowedPath : PEGAWAI_URLS) {
if ("/".equals(allowedPath) && "/".equals(path)) {
return true;
}
if (!"/".equals(allowedPath) && path.startsWith(allowedPath)) {
return true;
}
}
return false;
}
@Override
public void destroy() {
// Cleanup jika diperlukan
}
}
Langkah 2 - Pastikan Integrasi Role Pegawai
Setelah file dashboard pegawai ditulis, cek bahwa alur role pegawai benar-benar tersambung.
Hal yang perlu dicek:
- dashboard pegawai menampilkan nama, bagian, dan ringkasan presensi
- menu sidebar untuk pegawai hanya `Home`, `Profile`, dan `Presensi`
- tombol shortcut mengarah ke `/profile` dan `/presensi`
- `AuthFilter.java` membatasi URL sesuai role pegawai
- `web/index.jsp` tetap menjadi layout utama
Jika tampilan kartu atau grafik perlu penyesuaian, update juga
web/assets/css/style.css.
Pengujian
Lakukan pengujian berikut:
- Login sebagai pegawai.
- Buka
/dashboard. - Pastikan dashboard pegawai tampil.
- Cek apakah nama dan bagian pegawai muncul.
- Coba buka menu admin, lalu lihat apakah akses ditolak.
Troubleshooting
| Masalah | Penyebab | Solusi |
|---|---|---|
| Dashboard tidak sesuai role | User login bukan pegawai | Login menggunakan akun pegawai |
| Nama pegawai tidak tampil | User belum terhubung ke data pegawai | Hubungkan akun ke pegawai terlebih dahulu |
| Menu profile dan presensi tidak muncul | Sidebar membaca role yang salah |
Pastikan session user berisi role pegawai
|
| Akses ke menu lain ditolak | AuthFilter membatasi URL |
Gunakan URL yang sesuai dengan role |
Tugas Praktikum
- Login sebagai pegawai lalu screenshot dashboard.
- Buka halaman profile dari dashboard.
- Buka halaman presensi dari dashboard.
Kesimpulan
Dashboard user adalah versi dashboard yang khusus untuk pegawai. Satu servlet yang sama bisa dipakai untuk admin dan pegawai, tetapi view, menu, dan data yang ditampilkan berbeda sesuai role.