Lewati ke konten

Antarmuka Web: HTML & CSS (Index.html)

Di Google Apps Script, kita dapat menyatukan seluruh struktur antarmuka (HTML) dan desain visual (CSS) ke dalam satu file tunggal: Index.html.

Dengan menaruh kode CSS di dalam tag <style> di bagian <head>, proyek kita menjadi sangat ringkas—hanya terdiri dari 2 file:

Editor Google Apps Script:
├── Code.gs # Backend: Logika CRUD & router web (doGet & doPost)
└── Index.html # Frontend: Struktur HTML + Styling CSS dalam 1 file

1. Prompt untuk Membuat Index.html (Framework T-C-R-E-I)

Section titled “1. Prompt untuk Membuat Index.html (Framework T-C-R-E-I)”
[PERSONA]
Bertindaklah sebagai asisten UI/UX dan Frontend Web Developer Google Apps Script.
[TASK]
- Buatkan satu file Index.html lengkap yang memuat struktur HTML dan styling CSS modern untuk aplikasi absensi presensi sederhana.
- Pastikan form absensi dan tabel riwayat kehadiran tampil rapi, elegan, dan responsif.
[CONTEXT]
- Header aplikasi: Judul "PresensiApp".
- Formulir input (CREATE): Input Nama Lengkap (wajib), Dropdown Status (Hadir, Izin, Sakit), Catatan singkat (opsional), Tombol "Kirim Presensi" (method="POST").
- Tabel riwayat (READ & DELETE): Kolom Waktu, Nama, Status (badge), Catatan, dan Tombol hapus di setiap baris data.
- Desain visual: Tema gelap arang (Deep Charcoal #121212 - #181818), border halus #333333, teks putih bersih, dan tata letak responsif (2 kolom di laptop, 1 kolom di HP).
[OUTPUT FORMAT]
Satu file Index.html lengkap yang menggabungkan seluruh kode HTML dengan tag <style>...</style> di dalam <head>.

2. Kode Hasil Index.html (HTML & CSS Terpadu)

Section titled “2. Kode Hasil Index.html (HTML & CSS Terpadu)”

Berikut adalah kode lengkap Index.html yang siap kamu salin ke editor Apps Script:

<!DOCTYPE html>
<html lang="id">
<head>
<base target="_top">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Aplikasi Presensi Karyawan</title>
<!-- =======================================================================
STYLING MODERN CSS (Deep Charcoal Theme)
======================================================================= -->
<style>
:root {
--bg-main: #121212;
--bg-surface: #181818;
--bg-card: #242424;
--border-color: #333333;
--text-primary: #fafafa;
--text-secondary: #a3a3a3;
--accent: #e5e5e5;
--accent-hover: #ffffff;
--success: #22c55e;
--warning: #eab308;
--danger: #ef4444;
--radius-md: 0.5rem;
--radius-lg: 0.75rem;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
background-color: var(--bg-main);
color: var(--text-primary);
line-height: 1.5;
min-height: 100vh;
display: flex;
flex-direction: column;
}
.container {
width: 100%;
max-width: 1100px;
margin: 0 auto;
padding: 0 1.25rem;
}
/* Header */
.app-header {
background-color: var(--bg-surface);
border-bottom: 1px solid var(--border-color);
padding: 1.25rem 0;
}
.brand h1 {
font-size: 1.35rem;
font-weight: 700;
color: var(--text-primary);
}
.brand h1 span {
color: var(--text-secondary);
}
.brand p {
font-size: 0.85rem;
color: var(--text-secondary);
}
/* Layout 2 Kolom Responsif */
.main-layout {
flex: 1;
display: grid;
grid-template-columns: 1fr;
gap: 1.5rem;
padding-top: 2rem;
padding-bottom: 2rem;
}
@media (min-width: 768px) {
.main-layout {
grid-template-columns: 360px 1fr;
align-items: start;
}
}
.card {
background-color: var(--bg-surface);
border: 1px solid var(--border-color);
border-radius: var(--radius-lg);
padding: 1.5rem;
}
.card h2 {
font-size: 1.15rem;
font-weight: 600;
margin-bottom: 0.25rem;
}
.section-desc {
font-size: 0.85rem;
color: var(--text-secondary);
margin-bottom: 1.25rem;
}
/* Formulir */
.form-group {
margin-bottom: 1.15rem;
}
.form-group label {
display: block;
font-size: 0.85rem;
font-weight: 500;
color: var(--text-primary);
margin-bottom: 0.35rem;
}
.form-group input,
.form-group select {
width: 100%;
padding: 0.65rem 0.85rem;
background-color: var(--bg-card);
border: 1px solid var(--border-color);
border-radius: var(--radius-md);
color: var(--text-primary);
font-size: 0.9rem;
outline: none;
transition: border-color 0.2s;
}
.form-group input:focus,
.form-group select:focus {
border-color: var(--accent);
}
.btn-primary {
width: 100%;
padding: 0.75rem;
background-color: var(--accent);
color: var(--bg-main);
border: none;
border-radius: var(--radius-md);
font-size: 0.9rem;
font-weight: 600;
cursor: pointer;
transition: background-color 0.2s;
}
.btn-primary:hover {
background-color: var(--accent-hover);
}
/* Tabel Riwayat */
.table-responsive {
overflow-x: auto;
}
.data-table {
width: 100%;
border-collapse: collapse;
font-size: 0.85rem;
}
.data-table th,
.data-table td {
padding: 0.75rem 0.85rem;
text-align: left;
border-bottom: 1px solid var(--border-color);
}
.data-table th {
color: var(--text-secondary);
font-weight: 600;
}
/* Status Badges */
.badge {
display: inline-block;
padding: 0.2rem 0.55rem;
border-radius: 9999px;
font-size: 0.75rem;
font-weight: 600;
}
.badge-hadir {
background-color: rgba(34, 197, 94, 0.15);
color: var(--success);
border: 1px solid rgba(34, 197, 94, 0.3);
}
.badge-izin {
background-color: rgba(234, 179, 8, 0.15);
color: var(--warning);
border: 1px solid rgba(234, 179, 8, 0.3);
}
.badge-sakit {
background-color: rgba(239, 68, 68, 0.15);
color: var(--danger);
border: 1px solid rgba(239, 68, 68, 0.3);
}
.btn-delete {
background: transparent;
border: none;
cursor: pointer;
color: var(--danger);
opacity: 0.7;
transition: opacity 0.2s;
}
.btn-delete:hover {
opacity: 1;
}
/* Footer */
.app-footer {
text-align: center;
padding: 2rem 0;
color: var(--text-secondary);
font-size: 0.85rem;
border-top: 1px solid var(--border-color);
}
</style>
</head>
<body>
<!-- Header Aplikasi -->
<header class="app-header">
<div class="container header-wrapper">
<div class="brand">
<h1>Presensi<span>App</span></h1>
<p>Sistem pencatatan kehadiran harian sederhana</p>
</div>
</div>
</header>
<!-- Konten Utama -->
<main class="container main-layout">
<!-- Bagian 1: Form Absen Masuk (CREATE) -->
<section class="card form-card">
<h2>Catat Kehadiran</h2>
<p class="section-desc">Silakan isi data kehadiranmu untuk hari ini.</p>
<!-- Form submit langsung ke doPost() di Code.gs -->
<form method="POST">
<input type="hidden" name="action" value="create">
<div class="form-group">
<label for="nama">Nama Lengkap</label>
<input type="text" id="nama" name="nama" placeholder="Contoh: Sarah Azhari" required>
</div>
<div class="form-group">
<label for="status">Status Kehadiran</label>
<select id="status" name="status" required>
<option value="Hadir" selected>Hadir</option>
<option value="Izin">Izin</option>
<option value="Sakit">Sakit</option>
</select>
</div>
<div class="form-group">
<label for="catatan">Catatan / Keterangan (Opsional)</label>
<input type="text" id="catatan" name="catatan" placeholder="Contoh: Bekerja dari kantor / dinas luar">
</div>
<button type="submit" class="btn-primary">Kirim Presensi</button>
</form>
</section>
<!-- Bagian 2: Tabel Riwayat Kehadiran (READ & DELETE) -->
<section class="card table-card">
<h2>Daftar Kehadiran Hari Ini</h2>
<p class="section-desc">Daftar presensi yang tercatat di Google Sheets.</p>
<div class="table-responsive">
<table class="data-table">
<thead>
<tr>
<th>Waktu</th>
<th>Nama</th>
<th>Status</th>
<th>Catatan</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
<? if (attendanceData && attendanceData.length > 0) { ?>
<? for (var i = 0; i < attendanceData.length; i++) { ?>
<tr>
<td><?= attendanceData[i].timestamp ?></td>
<td><strong><?= attendanceData[i].nama ?></strong></td>
<td>
<span class="badge badge-<?= attendanceData[i].status.toLowerCase() ?>">
<?= attendanceData[i].status ?>
</span>
</td>
<td><?= attendanceData[i].catatan ?></td>
<td>
<!-- Tombol Hapus (DELETE) -->
<form method="POST" style="display:inline;" onsubmit="return confirm('Hapus catatan ini?');">
<input type="hidden" name="action" value="delete">
<input type="hidden" name="id" value="<?= attendanceData[i].id ?>">
<button type="submit" class="btn-delete" title="Hapus">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path></svg>
</button>
</form>
</td>
</tr>
<? } ?>
<? } else { ?>
<tr>
<td colspan="5" style="text-align:center; color: var(--text-secondary); padding: 2rem;">
Belum ada data presensi hari ini.
</td>
</tr>
<? } ?>
</tbody>
</table>
</div>
</section>
</main>
<footer class="app-footer">
<div class="container">
<p>&copy; 2026 PresensiApp — Didukung oleh Google Sheets & Apps Script.</p>
</div>
</footer>
</body>
</html>

  • Memahami alasan menggabungkan HTML dan CSS langsung ke dalam file Index.html.
  • Membuat file Index.html di editor Google Apps Script dan menyalin kode di atas.
  • Siap melanjutkan ke backend Code.gs untuk menghubungkan database Google Sheets.