Dokumentasi lengkap aplikasi CRUD berbasis web yang digunakan sebagai bahan penjelasan project UTS. Seluruh penjelasan disusun dalam Bahasa Indonesia dengan gaya yang mudah diikuti namun tetap teknis.
- Tech Stack
- Ringkasan Proyek
- Tujuan & Manfaat
- Akun Demo
- Alur Penggunaan Singkat
- Panduan Penggunaan Aplikasi
- Fitur Utama Secara Mendalam
- Pendekatan Teknis & Arsitektur
- Struktur Folder
- Cara Menjalankan Proyek
- Penjelasan File Penting
- Frontend: HTML5, CSS3, Vanilla JavaScript (ES6+)
- Data Storage: localStorage, sessionStorage
- Libraries: jsPDF, jsPDF-AutoTable, SheetJS (XLSX.js)
- Security: SHA-256 Hashing via Web Crypto API
- Deployment: GitHub Pages / Vercel (static hosting)
Proyek ini dikembangkan sebagai bagian dari penilaian Ujian Tengah Semester (UTS) mata kuliah Pemrograman Web di Program Studi Teknik Informatika Universitas Hasanuddin.
Aplikasi ini merupakan dashboard CRUD (Create, Read, Update, Delete) berbasis web untuk mengelola data mahasiswa Fakultas Teknik Universitas Hasanuddin. Seluruh logika berjalan di sisi klien menggunakan HTML5, CSS3, dan JavaScript, tanpa framework maupun backend. Data disimpan pada localStorage, sehingga aplikasi dapat dipakai secara offline setelah dibuka. Proyek ini menonjolkan:
- Validasi NIM khusus Fakultas Teknik (awalan
Ddan kode departemen sah). - Pengelolaan data mahasiswa yang kaya atribut (foto, IPK, catatan, NIM, prodi, dsb.).
- Fitur pencarian, filter, dan pengurutan multi-kriteria dengan feedback real-time.
- Import CSV/XLSX/JSON menggunakan SheetJS, serta ekspor PDF lengkap foto dengan jsPDF.
- Pengalaman pengguna (UX) yang rapi: custom dropdown, indikator statistik total data dan rata-rata ipk sederhana, dan dukungan aksesibilitas.
- Pembelajaran Web Programming: memahami bagaimana membangun aplikasi CRUD tanpa framework dan bagaimana konsep dasar dari pembuatan website from scratch.
- Simulasi Sistem Akademik: mencontoh cara kampus mengelola data mahasiswa, mulai dari validasi data hingga pelaporan.
- Bahan Dokumentasi: dokumentasi ini memudahkan penjelasan arsitektur, fitur, dan alur data kepada dosen pengampuh mata kuliah.
- Email:
admin@example.com - Kata sandi:
Admin@123 - Password disimpan dalam bentuk hash SHA-256 pada client-side untuk memastikan praktik penyimpanan yang lebih aman.
- Jalankan server statis lokal dan buka
src/pages/index.html. - Halaman beranda mengenali status login:
- Jika belum login, tombol menuju halaman login.
- Jika sudah login, tombol langsung menuju dasbor.
- Masuk menggunakan akun demo.
- Gunakan dasbor untuk menambah, mengedit, menghapus, menyaring, atau mengekspor data.
- Keluar melalui tombol
Logout(membersihkan sesi padasessionStorage).
🌐 Demo Online: data-mahasiswa.fajrifarid.com
- Akses Aplikasi: Buka
src/pages/index.htmldi browser atau kunjungi data-mahasiswa.fajrifarid.com - Masuk ke Sistem: Klik tombol "Masuk ke Dasbor"
- Login: Gunakan akun demo:
- Email:
admin@example.com - Password:
Admin@123
- Email:
- Isi Form: Lengkapi form "Data Mahasiswa" di bagian atas dasbor
- Input NIM: Ketik NIM mahasiswa (contoh:
D121231001) - sistem otomatis mengisi Program Studi dan Angkatan - Upload Foto (opsional): Klik "Pilih Foto" untuk mengunggah foto dari komputer
- Simpan: Klik tombol "Simpan" - data akan muncul di tabel
Mengedit Data:
- Klik tombol "Edit" pada baris yang ingin diubah
- Form akan terisi otomatis, ubah data yang diperlukan
- Klik "Perbarui" untuk menyimpan perubahan
Menghapus Data:
- Centang checkbox data yang ingin dihapus
- Klik "Hapus Terpilih" dan konfirmasi
- Pencarian: Ketik nama/NIM/angkatan/dsb di kotak pencarian
- Filter Program Studi: Pilih program studi dari dropdown
- Filter Angkatan: Pilih tahun angkatan (batas angkatan cuman dalam rentang 2000-2025)
- Reset Filter: Klik "Reset Filter" untuk menghapus semua filter
- Pilih File: Klik "Upload CSV/XLSX" atau "Upload JSON"
- Unggah: Pilih file dari folder
data/(contoh:mahasiswa_20_data.json) - Lihat Hasil: Sistem akan menampilkan laporan import (berhasil/gagal/duplikat) berupa alert
- Download Log Error (opsional): Jika ada data yang gagal diimpor, sistem akan menanyakan apakah Anda ingin mengunduh file log error untuk melihat detail kesalahan
- Terapkan Filter (opsional): Filter data sesuai kebutuhan
- Export: Klik "Export PDF"
- Download: File PDF akan terunduh dengan nama otomatis berdasarkan filter aktif
- Hashing di Browser: Password user di-hash menggunakan Web Crypto API (
crypto.subtle.digest). Jika API tidak tersedia (misal browser lama), tersedia fallback SHA-256 manual sehingga fitur tetap berjalan. - Penyimpanan Sesi: Setelah login, info user tersimpan pada
sessionStoragemenggunakan keycrud_active_user. Data berisi email, nama, dan timestamp login. - Pengamanan Halaman & Logika Sesi:
login.jsmencegah user yang sudah login mengakses kembali halaman login dengan melakukan redirect otomatis ke dasbor.dasbor.jsmemeriksa validitas sesi saat halaman dimuat menggunakancheckActiveUser(). Jika sesi tidak valid atau tidak ditemukan, sistem akan:- Menambahkan kelas CSS
app-lockedke elemen<body>yang menyembunyikan seluruh konten halaman. - Menampilkan overlay loading dengan pesan "Memeriksa sesi..." selama proses validasi.
- Melakukan redirect otomatis ke
login.htmljika sesi tidak valid. - Hanya menampilkan konten dasbor (menghapus kelas
app-locked) jika sesi terverifikasi valid.
- Menambahkan kelas CSS
- Mengapa
sessionStorage?: Dipilih karena sifatnya yang otomatis terhapus saat tab browser ditutup, memberikan keamanan tambahan untuk aplikasi yang mengelola data sensitif. Berbeda denganlocalStorageyang persisten hingga dihapus manual,sessionStoragememastikan user harus login ulang setiap membuka aplikasi di tab/window baru.
- Aksesibilitas Form Login: Terdapat tombol show/hide password dengan ikon mata dan atribut ARIA agar pengguna mengetahui status tombol.
- Field Wajib vs Opsional:
- Field wajib: Nama, NIM, Program Studi, Angkatan, Alamat, Email, IPK, dan Jenis Kelamin.
- Field opsional: Catatan dan Foto (upload dari perangkat lokal).
- Validasi form akan menolak penyimpanan jika ada field wajib yang kosong dengan menampilkan pesan error spesifik.
- Upload Foto Lokal:
- Foto diambil dari perangkat pengguna menggunakan input
type="file"dengan acceptimage/*. - File yang dipilih dikonversi menjadi Data URL menggunakan
FileReaderAPI dan disimpan langsung dilocalStorage. - Mendukung format umum: JPG, PNG, GIF, WebP dengan validasi ukuran maksimal (biasanya dibatasi agar tidak melebihi kapasitas localStorage).
- Pratinjau foto langsung ditampilkan setelah upload berhasil.
- Foto diambil dari perangkat pengguna menggunakan input
- Mode Tambah vs Edit: form menyimpan state
data-mode. Saat mengedit, tombol berubah menjadiPerbarui, field diisi ulang, dan fokus diarahkan ke field Nama. - Tombol Reset: mengembalikan seluruh field ke nilai default, termasuk menghapus pesan error, mengosongkan catatan, dan mengembalikan foto placeholder.
- Auto-increment ID: Setiap data tersimpan dalam array
data. VariabelautoIdmemastikan ID unik auto-increment berdasarkan ID tertinggi yang ada.
- Validasi NIM Fakultas Teknik (
validateNIMFakultasTeknik):- NIM harus diawali
Ddan memiliki 10 karakter. - Karakter 2–4 merujuk kode departemen yang dipetakan pada objek
FAKULTAS_TEKNIK_CODES. - Karakter 5–6 adalah kode tahun angkatan (misal
23menjadi 2023). - Karakter 7–10 adalah nomor urut empat digit.
- NIM harus diawali
- Feedback Real-time: Saat mengetik NIM, aplikasi langsung menampilkan pesan valid/invalid tepat di bawah input dengan indikator visual (warna hijau untuk valid, merah untuk invalid).
- Validasi Field Wajib:
- Semua field wajib divalidasi saat penyimpanan dengan menampilkan pesan error spesifik.
- Email divalidasi menggunakan regex pattern untuk memastikan format yang benar.
- IPK hanya menerima nilai numerik antara 0.00–4.00 dengan validasi format dua desimal.
- Normalisasi Data (
normalizeMahasiswaRecord):- NIM dikonversi ke huruf besar otomatis.
- Program studi dan angkatan otomatis diisi berdasarkan NIM bila user tidak memasukkan nilai.
- IPK diformat ke dua desimal (misal: 3.5 menjadi 3.50).
- Nilai teks di-escape dengan
escapeHtmlsaat ditampilkan pada tabel untuk mencegah XSS.
- Cek Duplikasi (
isDuplicateEntry): mencegah penyimpanan data dengan kombinasi nama/NIM yang sudah ada dengan menampilkan peringatan yang jelas.
- Render Dinamis: Fungsi
render()menyiapkan tabel berdasarkanfilteredData, menerapkan pagination, dan menjaga state checkbox terpilih. - Pencarian Multi-field: Input pencarian memfilter data berdasarkan nama, NIM, prodi, angkatan, alamat, email, IPK, catatan, hingga jenis kelamin. Nilai pencarian disimpan di URL (
?search=) agar dapat dibagikan. - Filter Dinamis Program Studi & Angkatan:
populateAngkatanFilter()danpopulateProdiFilter()membuat daftar opsi berdasarkan data yang ada saat ini.- Filter selalu sinkron dengan data aktual - jika ada data baru dengan prodi/angkatan baru, opsi filter otomatis bertambah.
- Filter angkatan dan program studi menggunakan dropdown kustom (HTML + ul/li) dengan sinkronisasi ke elemen
<select hidden>.
- Indikator Filter Aktif:
- Bagian toolbar menampilkan filter yang sedang aktif (pencarian, program studi, angkatan, sorting).
- Tombol "Reset Filter" untuk menghapus semua filter dan mengembalikan tampilan ke data lengkap.
- Jumlah data terfilter ditampilkan real-time (misal: "Menampilkan 15 dari 50 data").
- Pengurutan:
- Mendukung nama, NIM, angkatan, jurusan, dan IPK (ascending/descending).
- Ikon sort di dropdown memanfaatkan aset SVG kustom dengan indikator arah pengurutan.
- Pagination: Pengguna bisa memilih 10/25/50/100 data per halaman. Tombol navigasi menampilkan ellipsis saat jumlah halaman banyak.
- Aksi Massal: Checkbox di header memungkinkan seleksi massal, dengan state
indeterminatesaat sebagian baris terpilih. Tersedia tombolHapus TerpilihdanHapus Semuadengan konfirmasi.
- Import CSV/XLSX:
- Menggunakan SheetJS (
xlsx.full.min.js). - Sistem mengenali berbagai alias kolom melalui
IMPORT_FIELD_ALIASES(misalProgram Studi,jurusan,program_studiakan dipetakan ke kolom internalprogramStudi). - Setiap baris import divalidasi dengan pipeline yang sama seperti input manual.
- Laporan hasil import menampilkan jumlah data berhasil, duplikat, dan gagal berikut detail error (maksimal 5 baris, sisanya diringkas).
- Download Log Error: Jika terdapat data yang gagal divalidasi, sistem menawarkan opsi download file log error dalam format teks yang berisi detail lengkap setiap kesalahan validasi.
- Menggunakan SheetJS (
- Import JSON:
- Mendukung struktur array langsung atau objek dengan properti
data/mahasiswa. - Berguna untuk memigrasikan data dari aplikasi lain atau hasil ekspor custom.
- Download Log Error: Sama seperti CSV/XLSX, tersedia opsi download log error jika ada data yang gagal divalidasi.
- Mendukung struktur array langsung atau objek dengan properti
- Export PDF:
- Memakai jsPDF 2.5.1 + plugin
jspdf-autotable. - Header PDF menuliskan filter aktif, jumlah data, dan timestamp lengkap beserta zona waktu Indonesia (WIB/WITA/WIT) berdasarkan offset lokal.
- Kolom foto ikut diekspor. Fungsi
prepareFotoForPdfmengonversi gambar menjadi data URL dan menyesuaikan ukuran agar proporsional. - Nama file disusun dinamis berdasarkan filter dan timestamp (
data_mahasiswa_filter_xxx_angkatan_xxx_sort_xxx_YYYYMMDD_HHmm.pdf).
- Memakai jsPDF 2.5.1 + plugin
- Panel Informasi Real-time:
- Jumlah data yang sedang terlihat berdasarkan filter aktif (misal: "Menampilkan 15 dari 50 data").
- Total keseluruhan data yang tersimpan di localStorage.
- Rata-rata IPK untuk data yang sedang terfilter dan rata-rata IPK keseluruhan data.
- Perhitungan dilakukan oleh
calculateAverageIpk()dengan pembulatan dua desimal.
- Indikator Filter Aktif:
- Menampilkan filter yang sedang diterapkan (pencarian, program studi, angkatan, pengurutan).
- Tombol "Reset Semua Filter" untuk mengembalikan tampilan ke kondisi awal tanpa filter.
- Update Otomatis: Informasi statistik langsung berubah setiap kali filter diterapkan, data ditambah/diedit/dihapus, atau ketika melakukan import data baru.
- Custom Select:
- Fungsi
setupCustomSelectmengubah<select>standar menjadi tombol interaktif dengan daftar opsi yang konsisten di semua browser. - Menambahkan atribut
aria-haspopup,aria-expanded, dan label teks agar mudah dinavigasi keyboard.
- Fungsi
- Kontrol Foto:
- Pengunggahan foto menampilkan pratinjau instan, validasi tipe/ukuran, dan pesan error yang mudah dipahami.
- Tautan foto di tabel membuka gambar pada tab baru dengan
rel="noopener noreferrer".
- Tampilan Saat Data Kosong:
- Menampilkan ilustrasi
no-data.svgdan pesan persuasif agar pengguna langsung mengisi data.
- Menampilkan ilustrasi
- Feedback Form:
- Fungsi
showFormFeedbackdanshowNimRealtimeFeedbackmemberikan informasi keberhasilan atau kesalahan tepat di lokasi input.
- Fungsi
- Performa:
- Semua script dimuat menggunakan atribut
defersehingga parsing HTML tidak terhambat. - Hanya halaman yang membutuhkan fitur tertentu yang memuat script terkait.
- Semua script dimuat menggunakan atribut
- Proyek statis multi-halaman (
index.html,login.html,dasbor.html). - Tidak ada proses build. File dapat langsung dipublikasikan ke server statis atau CDN.
- CSS dibagi menjadi
global.css(variabel warna, tipografi, reset) dan CSS khusus halaman (index.css,login.css,dasbor.css). - JavaScript dipisah per halaman untuk meminimalkan ukuran file yang dimuat.
-
localStorage sebagai Database Lokal:
- Data disimpan dengan key
crud_mahasiswadalam format JSON. - Keterbatasan Kapasitas: localStorage memiliki batas maksimal sekitar 5-10MB per domain (bervariasi per browser). Dengan foto yang disimpan sebagai Data URL, aplikasi dapat menampung sekitar 100-200 data mahasiswa dengan foto resolusi sedang.
- Data disimpan dengan key
-
Inisialisasi Data: Saat pertama kali dijalankan, data diinisialisasi dari
window.INITIAL_MAHASISWA_DATA(lihatscripts/data/mahasiswa-initial.js). -
Struktur Data Mahasiswa:
{ "id": number, "nama": string, "nim": string, "programStudi": string, "angkatan": string, "alamat": string, "email": string, "ipk": number | "", "catatan?": string, "jenisKelamin": string, "fotoUrl?": string } -
Error Handling: Fungsi
loadData()membaca dari storage dan melakukan validasi struktur sebelum dipakai aplikasi. Jika terjadi error (misalnya user memanipulasi storage atau data corrupt), data akan di-reset ke data awal dengan notifikasi kepada user.
sanitizeJenisKelaminmengonversi berbagai istilah (male, pria, wanita, female) menjadi nilai konsisten (Laki-lakiatauPerempuan).normalizeFotoUrlmemastikan link foto tidak kosong dan mengganti URL lama dengan placeholder baru bila diperlukan.escapeHtmlmencegah injeksi HTML ketika menampilkan data dinamis pada tabel.- Semua data import melewati fungsi
buildMahasiswaImportRecord, sehingga tidak ada jalur pintas yang melewati validasi.
AppModulesmengekspos sekumpulan helper melaluiwindow.AppModules. Ini memudahkan debugging manual dari console browser tanpa mengubah struktur kode lama.- Fungsi utilitas seperti
applyFilters,renderPaginationPages,updateTotalDataDisplay, danperformBulkImportmemecah logika besar menjadi blok-blok kecil yang mudah diuji secara manual.
- jsPDF & jsPDF-AutoTable: digunakan untuk membuat PDF tabel mahasiswa dengan dukungan styling dan gambar.
- SheetJS (XLSX.js): menangani parsing file CSV/XLSX langsung di browser.
- Google Fonts (Inter): di-load melalui CSS untuk konsistensi tipografi.
- Semua library dimuat dari CDN, sehingga aplikasi berjalan tanpa instalasi tambahan.
- Password Hashing: Password demo tersimpan sebagai hash SHA-256 (lihat
login.js), bukan plain text untuk demonstrasi praktik keamanan yang baik. - Manajemen Sesi dengan sessionStorage:
- Mengapa sessionStorage?: Dipilih karena sifat sementara yang otomatis menghapus data saat tab browser ditutup, berbeda dengan localStorage yang persisten. Ini memberikan keamanan tambahan karena user harus login ulang setiap membuka aplikasi.
- Lifecycle Sesi: Sesi aktif hanya selama tab browser tetap terbuka. Jika user menutup tab atau browser, sesi otomatis hilang dan user harus login ulang.
- Validasi Sesi: Setiap halaman yang memerlukan autentikasi melakukan pengecekan sesi saat dimuat untuk memastikan user masih memiliki akses yang valid.
- Sanitasi Data: Nilai yang ditampilkan di DOM selalu di-escape untuk meminimalkan risiko XSS apabila user memasukkan karakter khusus.
- Konfirmasi Operasi Destruktif: Operasi seperti hapus data atau logout selalu meminta konfirmasi melalui
confirm()untuk mencegah kesalahan pengguna. ⚠️ Catatan Edukasi: Aplikasi ini dirancang untuk tujuan pembelajaran dan demonstrasi konsep pemrograman web. Tidak disarankan untuk mengelola data mahasiswa sesungguhnya karena seluruh data tersimpan di sisi klien (browser) tanpa enkripsi tambahan.
- Kapasitas localStorage:
- Batas maksimal sekitar 5-10MB per domain (bervariasi antara browser: Chrome ~10MB, Firefox ~10MB, Safari ~5MB).
- Foto disimpan sebagai Data URL yang berukuran lebih besar dari file asli (base64 encoding menambah ~33% ukuran).
- Estimasi kapasitas: 100-200 mahasiswa dengan foto resolusi sedang (500KB per record termasuk foto).
- Performa Browser:
- Operasi read/write localStorage bersifat synchronous dan dapat memblokir UI thread untuk data berukuran besar.
- Rendering tabel dengan 1000+ record dapat menyebabkan lag, diatasi dengan pagination dan lazy loading.
- Kompatibilitas Browser:
- Memerlukan browser modern yang mendukung ES6+, localStorage, sessionStorage, dan FileReader API.
- Fallback SHA-256 manual untuk browser yang tidak mendukung Web Crypto API.
pemweb-pakabdi/
├── README.md # Dokumentasi ringkas bawaan
├── data/
│ ├── foto/ # Placeholder foto default
│ ├── mahasiswa.csv # Contoh data untuk uji import CSV
│ ├── mahasiswa.xlsx # Contoh data untuk uji import Excel
│ ├── mahasiswa_8_data.json # Contoh data JSON 8 mahasiswa
│ ├── mahasiswa_20_data.json # Contoh data JSON 20 mahasiswa
│ └── mahasiswa_100_data.json # Contoh data JSON 100 mahasiswa
└── src/
├── assets/ # Semua icon, ilustrasi, dan gambar
│ └── foto-mahasiswa/ # Foto dummy untuk data awal
├── lib/
│ └── hashedPasswordGenerator.js # Script Node.js untuk membuat hash password
├── pages/
│ ├── index.html # Beranda
│ ├── login.html # Halaman login
│ └── dasbor.html # Dashboard CRUD utama
├── scripts/
│ ├── beranda.js # Logika beranda & redirect ke login/dasbor
│ ├── login.js # Logika autentikasi dan session
│ ├── dasbor.js # Inti CRUD, filter, import/export
│ └── data/
│ └── mahasiswa-initial.js # Data mahasiswa sebagai initial data
└── styles/
├── global.css # Variabel, reset, komponen global
├── beranda.css # Styling khusus beranda
├── login.css # Styling halaman login
└── dasbor.css # Styling halaman dasbor & tabel- Clone / Unduh repositori ini.
- Buka terminal pada direktori proyek.
- Jalankan server statis (pilih salah satu):
- VS Code Live Server.
npx serve .python -m http.server
- Akses
http://localhost:PORT/src/pages/index.html. - Login menggunakan kredensial demo.
- Eksplorasi seluruh fitur CRUD, import, filter, dan ekspor PDF.
- Logout sebelum menutup tab untuk membersihkan sesi.
Catatan: akses file langsung (
file://) tidak disarankan karena beberapa browser membatasi penggunaansessionStoragedanlocalStoragesaat file dibuka tanpa server.
src/pages/index.html: Halaman beranda. Menampilkan deskripsi singkat dan tombol aksi. Memuatberanda.js.src/pages/login.html: Form login dengan input email & password, tombol toggle password, serta link kembali. Memuatlogin.js.src/pages/dasbor.html:- Mengimpor library eksternal (jsPDF, SheetJS) dan data awal.
- Memuat form mahasiswa, toolbar filter, tabel data, dan kontrol aksi.
dasbor.jsdipanggil dengan atributdefer.
src/scripts/dasbor.js: File terbesar. Menangani:- Load/save data dari
localStorage. - Normalisasi data, validasi, render tabel, pagination.
- Fitur import/export, pengunggahan foto, dan session check.
- Load/save data dari
src/scripts/login.js: Validasi akun demo, hashing password, dan penyimpanan sesi.src/scripts/beranda.js: Mengecek status login agar tombol navigasi menyesuaikan.src/scripts/data/mahasiswa-initial.js: Data contoh sejumlah 20 mahasiswa dengan variasi prodi, angkatan (tahun 2000-2025), dan IPK.src/lib/hashedPasswordGenerator.js: Script Node.js untuk menghasilkan hash SHA-256 jika ingin mengganti password default.src/styles/global.css: Berisi reset, variabel CSS (warna, font), layout header/footer, utility classes.