\documentclass[12pt,a4paper]{report}

\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[indonesian]{babel}
\usepackage[a4paper,margin=2.8cm]{geometry}
\usepackage{graphicx}
\usepackage{float}
\usepackage{array}
\usepackage{booktabs}
\usepackage{longtable}
\usepackage{hyperref}
\usepackage{xcolor}
\usepackage{listings}
\usepackage[most]{tcolorbox}
\usepackage{enumitem}
\usepackage{titlesec}
\usepackage{setspace}

\hypersetup{
  colorlinks=true,
  linkcolor=blue!60!black,
  urlcolor=blue!60!black,
  pdftitle={Laporan Proyek Minmon Homelab},
  pdfauthor={[Nama Mahasiswa]}
}

\onehalfspacing
\setlist[itemize]{noitemsep, topsep=4pt}
\setlist[enumerate]{noitemsep, topsep=4pt}

\renewcommand{\chaptername}{BAB}
\titleformat{\chapter}[display]
  {\bfseries\Large}
  {\chaptername\ \thechapter}
  {0.5em}
  {\Large}

\definecolor{codebg}{RGB}{248,248,248}
\definecolor{bordergray}{RGB}{210,210,210}
\definecolor{titleblue}{RGB}{25,66,122}

\lstdefinestyle{minmoncode}{
  backgroundcolor=\color{codebg},
  basicstyle=\ttfamily\small,
  breaklines=true,
  frame=single,
  rulecolor=\color{bordergray},
  showstringspaces=false,
  tabsize=2,
  keywordstyle=\color{blue!60!black}\bfseries,
  commentstyle=\color{green!40!black},
  stringstyle=\color{red!50!black}
}

\newcommand{\uipath}[1]{\texttt{#1}}
\newcommand{\uibutton}[1]{\textbf{#1}}

\newtcolorbox{infobox}[1][]{
  colback=blue!3,
  colframe=titleblue,
  boxrule=0.6pt,
  arc=0pt,
  left=8pt,
  right=8pt,
  top=8pt,
  bottom=8pt,
  #1
}

\newtcolorbox{warningbox}[1][]{
  colback=yellow!8,
  colframe=orange!70!black,
  boxrule=0.6pt,
  arc=0pt,
  left=8pt,
  right=8pt,
  top=8pt,
  bottom=8pt,
  #1
}

\newcommand{\placeholderfigure}[2]{
  \begin{figure}[H]
    \centering
    \fbox{\parbox[c][6cm][c]{0.82\textwidth}{\centering\textit{Placeholder gambar/diagram}\\[0.5em]#1}}
    \caption{#2}
  \end{figure}
}

\begin{document}

\begin{titlepage}
  \centering
  {\Large \textbf{LAPORAN PROYEK DAN MANUAL BOOK}}\\[1.2cm]
  {\Huge \textbf{MINMON}}\\[0.4cm]
  {\Large Dashboard Inventaris dan Monitoring Homelab Berbasis Web}\\[1.2cm]

  \begin{infobox}[width=0.9\textwidth]
  \textbf{Nama Mahasiswa} : [Isi Nama Anda]\\
  \textbf{NIM} : [Isi NIM Anda]\\
  \textbf{Program Studi} : [Isi Program Studi]\\
  \textbf{Mata Kuliah} : [Isi Mata Kuliah]\\
  \textbf{Dosen Pengampu} : [Isi Nama Dosen]\\
  \textbf{Institusi} : [Isi Nama Universitas / Sekolah]\\
  \textbf{Tahun Akademik} : [Isi Tahun Akademik]
  \end{infobox}

  \vfill

  {\large Dokumen ini disusun untuk mendeskripsikan proyek \textit{Minmon} yang digunakan untuk mendata dan memonitor inventaris homelab, khususnya lingkungan kecil yang umumnya terdiri dari 2 server utama dengan banyak service dan domain terkait.}\\[1cm]

  {\large \today}
\end{titlepage}

\tableofcontents
\clearpage

\chapter{Pendahuluan}

\section{Latar Belakang}
Homelab modern tidak lagi hanya berisi satu mesin dengan satu layanan. Dalam praktiknya, satu homelab kecil dapat terdiri dari beberapa server, banyak service seperti reverse proxy, dashboard, media server, database, automation tools, serta sejumlah domain atau subdomain yang harus diarahkan ke alamat IP yang benar. Ketika jumlah aset ini bertambah, pencatatan manual menjadi sulit dipelihara karena data server, service, domain, dan catatan operasional tersebar di berbagai tempat.

Minmon dikembangkan sebagai dashboard inventaris dan monitoring ringan berbasis web untuk membantu pemilik homelab mengelola aset tersebut dalam satu aplikasi terpusat. Aplikasi ini tidak ditujukan untuk deployment automation, melainkan untuk kebutuhan dokumentasi, inventaris, relasi data, dan validasi DNS sederhana. Dalam konteks penggunaan pribadi, proyek ini cocok untuk skenario homelab yang biasanya terdiri dari 2 server utama dengan banyak service dan domain yang perlu dicatat serta dipantau.

Implementasi saat ini menyediakan autentikasi admin, dashboard ringkasan, CRUD untuk server, service, domain, dan note, serta fitur pemeriksaan DNS A record. Selain itu, relasi antar entitas juga sudah diterapkan melalui select input agar pengguna tidak perlu memasukkan ID relasi secara manual. Dengan demikian, Minmon dapat berfungsi sebagai pusat data operasional homelab yang lebih rapi, konsisten, dan mudah diperluas.

\section{Tujuan}
Tujuan dari pengembangan proyek ini adalah sebagai berikut:

\begin{itemize}
  \item Membangun aplikasi web yang dapat digunakan untuk mengelola inventaris homelab secara terstruktur.
  \item Menyediakan fitur CRUD untuk data server, service, domain, dan note dalam satu dashboard terproteksi.
  \item Menyediakan pemeriksaan DNS sederhana untuk memverifikasi apakah domain mengarah ke IP server yang diharapkan.
  \item Mempermudah dokumentasi relasi data, misalnya service yang berjalan pada server tertentu dan note yang melekat pada server tertentu.
  \item Menjadi contoh implementasi full-stack berbasis React, tRPC, Drizzle ORM, PostgreSQL, dan better-auth.
\end{itemize}

\section{Manfaat}
Manfaat dari proyek ini antara lain:

\begin{itemize}
  \item Membantu pemilik homelab mendokumentasikan server, service, domain, dan note dalam satu tempat.
  \item Mengurangi kesalahan input relasi data karena pilihan parent-child dibuat melalui select input.
  \item Memudahkan pengecekan domain melalui fitur DNS check berbasis A record / IPv4.
  \item Memberikan gambaran ringkas kondisi homelab melalui dashboard summary.
  \item Menjadi bahan laporan akademik dan contoh produk perangkat lunak yang benar-benar dapat dipakai.
\end{itemize}

\chapter{Metode Pengembangan}

\section{Tahap Pengembangan}
Tahap pengembangan proyek Minmon dapat dijelaskan secara ringkas sebagai berikut:

\begin{enumerate}
  \item \textbf{Identifikasi kebutuhan}\\
  Menentukan kebutuhan utama untuk inventaris homelab, yaitu pengelolaan data server, service, domain, dan note, serta kebutuhan monitoring DNS sederhana.

  \item \textbf{Perancangan data dan relasi}\\
  Menentukan entitas inti: \texttt{server}, \texttt{service}, \texttt{domain}, dan \texttt{note}. Setiap service terkait ke satu server, setiap domain terkait ke satu service, dan setiap note terkait ke satu server.

  \item \textbf{Perancangan backend}\\
  Mengimplementasikan router tRPC untuk operasi list, detail, create, update, delete, serta ringkasan dashboard. Pemeriksaan DNS diimplementasikan sebagai mutation khusus pada domain.

  \item \textbf{Perancangan frontend}\\
  Membangun halaman login, dashboard summary, halaman list, halaman create, dan halaman detail/edit untuk setiap entitas. Form relasi dibuat menggunakan select agar lebih aman dan mudah dipakai.

  \item \textbf{Integrasi dan validasi}\\
  Menghubungkan frontend ke backend dengan TanStack Query dan tRPC client, lalu memastikan mutasi, invalidasi query, serta tampilan ringkasan berjalan dengan baik.

  \item \textbf{Pengujian dan penyempurnaan}\\
  Melakukan typecheck, pengecekan alur CRUD, pengecekan DNS, perbaikan kestabilan urutan list, dan penyempurnaan interaksi UI seperti delete dua langkah dan trigger DNS dari status badge.
\end{enumerate}

\section{Identitas/Keunikan Produk}
Minmon memiliki identitas produk sebagai dashboard inventaris dan monitoring ringan untuk homelab. Keunikan produk ini dibanding pencatatan manual biasa adalah sebagai berikut:

\begin{itemize}
  \item Fokus pada skenario homelab kecil-menengah, misalnya 2 server dengan banyak service dan domain.
  \item Menggabungkan inventaris dan dokumentasi operasional dalam satu aplikasi.
  \item Menyediakan relasi data yang jelas antara server, service, domain, dan note.
  \item Memiliki DNS A-record checking yang terintegrasi langsung pada alur domain.
  \item Menampilkan note yang terkait langsung pada halaman detail server.
  \item Menggunakan autentikasi admin sehingga dashboard tidak dapat diakses tanpa sesi.
\end{itemize}

\begin{infobox}[title=Keunikan Praktis Produk]
Untuk penggunaan pribadi, Minmon cocok sebagai pusat dokumentasi homelab yang tidak hanya menyimpan data inventaris, tetapi juga membantu memastikan domain masih mengarah ke IP yang benar dan memudahkan pelacakan note operasional pada setiap server.
\end{infobox}

\section{Diagram-diagram UML (use case, class, activity, state chart, sequence, collaboration)}
Bagian ini dapat diisi dengan diagram UML final. Struktur dan isi diagram sebaiknya disesuaikan dengan implementasi saat ini.

\subsection{Use Case Diagram}
Use case utama dalam sistem ini meliputi:

\begin{itemize}
  \item Admin sign in
  \item Admin mengakses dashboard summary
  \item Admin mengelola server
  \item Admin mengelola service
  \item Admin mengelola domain
  \item Admin menjalankan DNS check
  \item Admin mengelola note
  \item Admin melihat note pada detail server
  \item Admin sign out
\end{itemize}

\placeholderfigure{Tambahkan diagram use case hasil export UML Anda di sini.}{Use Case Diagram Minmon}

\subsection{Class Diagram}
Entitas utama pada sistem adalah:

\begin{itemize}
  \item \textbf{Server}: id, name, primaryIpAddress, secondaryIpAddress, operatingSystem, location, provider, description, status, createdAt, updatedAt
  \item \textbf{Service}: id, serverId, name, type, internalPort, externalPort, protocol, status, description, createdAt, updatedAt
  \item \textbf{Domain}: id, serviceId, name, expectedServerIp, lastResolvedIp, lastResolvedIps, resolutionStatus, lastCheckedAt, remarks, lastCheckMessage, createdAt, updatedAt
  \item \textbf{Note}: id, serverId, title, content, category, createdAt, updatedAt
\end{itemize}

Hubungan utama:

\begin{itemize}
  \item Server 1..* Service
  \item Server 1..* Note
  \item Service 1..* Domain
\end{itemize}

\placeholderfigure{Tambahkan diagram class hasil export UML Anda di sini.}{Class Diagram Minmon}

\subsection{Activity Diagram}
Activity diagram yang disarankan adalah alur \textit{Check DNS from Domain List}:

\begin{enumerate}
  \item Admin membuka halaman domain list.
  \item Admin menekan badge status DNS.
  \item UI memanggil mutation \texttt{domains.check}.
  \item Backend melakukan resolve IPv4 A record.
  \item Backend membandingkan hasil resolve dengan \texttt{expectedServerIp}.
  \item Backend menyimpan hasil ke database.
  \item UI me-refresh data dan menampilkan status baru.
\end{enumerate}

\placeholderfigure{Tambahkan activity diagram di sini.}{Activity Diagram DNS Check}

\subsection{State Chart Diagram}
State chart yang disarankan adalah state untuk status DNS domain:

\begin{itemize}
  \item UNRESOLVED
  \item MATCH
  \item MISMATCH
\end{itemize}

Transisi utama:

\begin{itemize}
  \item DNS berhasil dan IP cocok $\rightarrow$ MATCH
  \item DNS berhasil tetapi IP tidak cocok $\rightarrow$ MISMATCH
  \item DNS gagal resolve $\rightarrow$ UNRESOLVED
\end{itemize}

\placeholderfigure{Tambahkan state chart diagram di sini.}{State Chart Domain DNS}

\subsection{Sequence Diagram}
Sequence diagram yang cocok untuk proyek ini adalah alur \textit{Create Domain and Check DNS}:

\begin{itemize}
  \item Admin
  \item Web UI
  \item tRPC API
  \item Database
  \item DNS Resolver
\end{itemize}

\placeholderfigure{Tambahkan sequence diagram di sini.}{Sequence Diagram Create Domain and Check DNS}

\subsection{Collaboration Diagram}
Collaboration diagram dapat menunjukkan interaksi antara:

\begin{itemize}
  \item Admin
  \item Dashboard UI
  \item better-auth client
  \item tRPC router
  \item Database
  \item DNS lookup module
\end{itemize}

\placeholderfigure{Tambahkan collaboration diagram di sini.}{Collaboration Diagram Minmon}

\section{Potongan Code Fitur-Fitur Utama}
Bagian ini menampilkan beberapa potongan kode yang mewakili fitur inti dari implementasi saat ini.

\subsection{Redirect Root Berdasarkan Session}
Potongan berikut menunjukkan bahwa route \uipath{/} akan mengarahkan pengguna ke \uipath{/dashboard} atau \uipath{/login} berdasarkan session yang didapat dari auth client.

\begin{lstlisting}[style=minmoncode,language=TypeScript,caption={Root redirect berdasarkan session}]
export const Route = createFileRoute("/")({
  beforeLoad: async () => {
    const session = await authClient.getSession();

    throw redirect({
      to: session.data ? "/dashboard" : "/login",
    });
  },
  component: () => null,
});
\end{lstlisting}

\subsection{Ordering List yang Stabil}
List utama pada CRUD saat ini diurutkan berdasarkan \texttt{createdAt DESC} lalu \texttt{id DESC} agar urutan tetap deterministik ketika data di-refresh.

\begin{lstlisting}[style=minmoncode,language=TypeScript,caption={Stable ordering pada list router}]
return db
  .select()
  .from(domain)
  .orderBy(desc(domain.createdAt), desc(domain.id));
\end{lstlisting}

\subsection{Pemeriksaan DNS A Record}
Pemeriksaan DNS dilakukan dengan resolve IPv4 A record dan membandingkannya dengan IP yang diharapkan.

\begin{lstlisting}[style=minmoncode,language=TypeScript,caption={Logika DNS check}]
export function checkDomainDns(target: DomainCheckTarget) {
  return Effect.match(resolveIpv4ARecords(target.name), {
    onSuccess: (resolvedIps: string[]): DomainCheckResult => ({
      status: resolvedIps.includes(target.expectedServerIp)
        ? "MATCH"
        : "MISMATCH",
      resolvedIps,
      checkedAt: new Date(),
      message: null,
    }),
    onFailure: (error: Error): DomainCheckResult => ({
      status: "UNRESOLVED",
      resolvedIps: [],
      checkedAt: new Date(),
      message: error.message,
    }),
  });
}
\end{lstlisting}

\subsection{Select Input untuk Relasi Data}
Form relasi tidak lagi menggunakan input teks biasa untuk foreign key utama, tetapi menggunakan select agar lebih aman.

\begin{lstlisting}[style=minmoncode,language=TypeScript,caption={Contoh select relasi note -> server}]
<form.Field name="serverId">
  {(field) => (
    <SelectField
      label="Server"
      name={field.name}
      value={field.state.value}
      onBlur={field.handleBlur}
      onValueChange={field.handleChange}
      placeholder="Select a server"
      options={serverOptions}
    />
  )}
</form.Field>
\end{lstlisting}

\subsection{Delete Dua Langkah dengan Ikon}
Untuk mencegah salah hapus, aksi delete pada list menggunakan dua tahap klik: ikon trash lalu ikon check.

\begin{lstlisting}[style=minmoncode,language=TypeScript,caption={Confirm delete icon button}]
if (isConfirming) {
  onConfirm();
  setIsConfirming(false);
  return;
}

setIsConfirming(true);
\end{lstlisting}

\chapter{Manual Book}

\section{Gambaran Umum Penggunaan}
Bagian ini menjelaskan cara menggunakan aplikasi Minmon berdasarkan implementasi saat ini. Gaya penjelasan dibuat seperti manual book: langkah demi langkah, ringkas, dan fokus pada hasil yang diharapkan.

\begin{warningbox}[title=Data yang Masih Perlu Anda Lengkapi]
Untuk versi final laporan, Anda sebaiknya menambahkan screenshot nyata dari aplikasi Anda sendiri, termasuk nama server homelab, contoh service, dan domain yang benar-benar Anda gunakan.
\end{warningbox}

\section{Login ke Sistem}
\textbf{Path akses:} \uipath{/login}

\begin{enumerate}
  \item Jalankan aplikasi web dan server.
  \item Buka browser ke alamat \uipath{http://localhost:5173}.
  \item Jika belum login, sistem akan mengarahkan ke \uipath{/login}.
  \item Masukkan email admin dan password.
  \item Tekan tombol \uibutton{Sign In}.
\end{enumerate}

\textbf{Hasil yang diharapkan:} pengguna masuk ke halaman \uipath{/dashboard}.

\placeholderfigure{Tambahkan screenshot halaman login di sini.}{Halaman Login Minmon}

\section{Membuka Dashboard Summary}
\textbf{Path akses:} \uipath{/dashboard}

Halaman dashboard menampilkan ringkasan:

\begin{itemize}
  \item total server,
  \item total service,
  \item total domain,
  \item jumlah DNS match / mismatch / unresolved,
  \item service yang inactive/down,
  \item recent notes.
\end{itemize}

\textbf{Langkah penggunaan:}
\begin{enumerate}
  \item Login sebagai admin.
  \item Setelah redirect ke dashboard, periksa kartu ringkasan di bagian atas.
  \item Gunakan link area untuk membuka halaman Servers, Services, Domains, atau Notes.
\end{enumerate}

\placeholderfigure{Tambahkan screenshot dashboard summary di sini.}{Dashboard Summary}

\section{Mengelola Data Server}
\textbf{Path akses:} \uipath{/dashboard/servers}

\subsection{Menambah Server}
\begin{enumerate}
  \item Buka menu Servers.
  \item Klik tombol \uibutton{Add server}.
  \item Isi data server seperti nama, IP utama, lokasi, provider, dan status.
  \item Klik \uibutton{Save server}.
\end{enumerate}

\textbf{Hasil yang diharapkan:} data server tersimpan dan pengguna diarahkan ke halaman detail server.

\subsection{Melihat Detail Server}
\textbf{Path akses:} \uipath{/dashboard/servers/\$serverId}

Pada halaman ini pengguna dapat:

\begin{itemize}
  \item melihat ringkasan server,
  \item mengedit data server,
  \item melihat note yang terkait dengan server tersebut.
\end{itemize}

\placeholderfigure{Tambahkan screenshot detail server di sini.}{Halaman Detail Server}

\section{Mengelola Data Service}
\textbf{Path akses:} \uipath{/dashboard/services}

\subsection{Menambah Service}
\begin{enumerate}
  \item Buka menu Services.
  \item Klik \uibutton{Add service}.
  \item Pilih server parent pada field \textit{Server}.
  \item Isi nama service, type, port, protocol, status, dan deskripsi.
  \item Klik \uibutton{Save service}.
\end{enumerate}

\textbf{Hasil yang diharapkan:} service tersimpan dan terhubung ke server yang dipilih.

\section{Mengelola Data Domain}
\textbf{Path akses:} \uipath{/dashboard/domains}

\subsection{Menambah Domain}
\begin{enumerate}
  \item Buka menu Domains.
  \item Klik \uibutton{Add domain}.
  \item Pilih service parent pada field \textit{Service}.
  \item Isi nama domain dan expected IP bila diperlukan.
  \item Klik \uibutton{Save domain}.
\end{enumerate}

\textbf{Catatan:} jika expected IP dikosongkan, backend akan menggunakan IP server parent dari service terkait.

\subsection{Menjalankan DNS Check}
\begin{enumerate}
  \item Buka halaman domain list.
  \item Tekan badge status DNS pada row domain yang ingin dicek.
  \item Tunggu proses mutation selesai.
  \item Lihat hasil baru pada kolom status dan IP hasil resolve.
\end{enumerate}

\textbf{Hasil yang diharapkan:} status berubah menjadi \texttt{MATCH}, \texttt{MISMATCH}, atau \texttt{UNRESOLVED}.

\placeholderfigure{Tambahkan screenshot domain list dan DNS check di sini.}{Domain List dan DNS Check}

\section{Mengelola Data Note}
\textbf{Path akses:} \uipath{/dashboard/notes}

\subsection{Menambah Note}
\begin{enumerate}
  \item Buka menu Notes.
  \item Klik \uibutton{New note}.
  \item Pilih server pada field \textit{Server}.
  \item Isi title, category, dan content.
  \item Klik \uibutton{Save note}.
\end{enumerate}

\textbf{Hasil yang diharapkan:} note tersimpan dan terhubung ke server terpilih.

\subsection{Melihat Note pada Detail Server}
\begin{enumerate}
  \item Buka halaman detail server.
  \item Scroll ke bagian \textit{Server notes}.
  \item Lihat daftar note yang hanya terkait dengan server tersebut.
\end{enumerate}

\textbf{Hasil yang diharapkan:} note yang tampil hanyalah note dengan \texttt{serverId} yang sesuai.

\section{Aksi Hapus Data}
Pada list server, service, domain, dan note, aksi hapus saat ini menggunakan alur dua langkah:

\begin{enumerate}
  \item Klik ikon trash.
  \item Tombol berubah menjadi ikon check sebagai konfirmasi.
  \item Klik ikon check untuk benar-benar menghapus data.
\end{enumerate}

\textbf{Catatan penting:}
\begin{itemize}
  \item Hapus server akan menghapus service, domain, dan note terkait melalui cascade delete.
  \item Hapus service akan menghapus domain terkait melalui cascade delete.
\end{itemize}

\chapter{Kesimpulan dan Saran}

\section*{Kesimpulan}
\addcontentsline{toc}{section}{Kesimpulan}
Minmon berhasil diimplementasikan sebagai aplikasi web untuk inventaris dan monitoring ringan homelab. Sistem ini sudah mencakup autentikasi admin, dashboard summary, CRUD untuk server, service, domain, dan note, serta DNS A-record checking. Dalam konteks penggunaan homelab pribadi dengan sekitar 2 server dan banyak service/domain, aplikasi ini sudah cukup representatif untuk membantu pencatatan aset, dokumentasi operasional, dan validasi domain.

Keunggulan utama implementasi saat ini adalah struktur relasi yang jelas, form relasi berbasis select, ringkasan dashboard yang langsung informatif, serta adanya note yang bisa ditampilkan langsung pada halaman detail server. Selain itu, interaksi UI juga sudah dibuat lebih aman melalui delete dua langkah dan urutan list yang stabil.

\section*{Saran}
\addcontentsline{toc}{section}{Saran}
Saran pengembangan untuk tahap berikutnya antara lain:

\begin{itemize}
  \item Menambahkan fitur search, filter, dan pagination pada halaman list.
  \item Menambahkan histori hasil DNS check agar perubahan status domain dapat dilacak dari waktu ke waktu.
  \item Menambahkan multi-role authentication jika aplikasi ingin dipakai lebih dari satu pengguna.
  \item Menambahkan dukungan monitoring lain selain DNS A record, misalnya SSL expiry, ping, atau health endpoint HTTP.
  \item Menambahkan screenshot final dan diagram UML final agar dokumen ini siap dikumpulkan sebagai laporan akademik lengkap.
\end{itemize}

\begin{infobox}[title=Data yang Sebaiknya Anda Kirim Jika Ingin Saya Finalkan]
Saya masih bisa finalkan dokumen ini lebih jauh jika Anda mengirim:
\begin{itemize}
  \item nama, NIM, kampus, mata kuliah, dan dosen,
  \item nama asli 2 server homelab Anda,
  \item contoh service/domain nyata yang ingin dimasukkan,
  \item screenshot UI,
  \item atau file diagram UML final.
\end{itemize}
\end{infobox}

\end{document}
