Rabu, 17 Desember 2025

APPS SCRIPT - CRUD3

 





Code.gs

/*************************
 * KONFIGURASI
 *************************/
const SPREADSHEET_ID = '1Xga5ntrruM1PC3bCCH_kJjp6XcMielI2ISVZqrkHsKE';
const SHEET_NAME = 'Peserta';

/*************************
 * ENTRY POINT WEB APP
 *************************/
function doGet() {
  return HtmlService.createHtmlOutputFromFile('index')
    .setTitle('Manajemen Peserta Pelatihan')
    .setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}

/*************************
 * HELPER
 *************************/
function getSheet() {
  const ss = SpreadsheetApp.openById(SPREADSHEET_ID);
  const sheet = ss.getSheetByName(SHEET_NAME);
  if (!sheet) throw new Error('Sheet "Peserta" tidak ditemukan');
  return sheet;
}

/*************************
 * READ
 *************************/
function getPeserta() {
  const sheet = getSheet();
  const lastRow = sheet.getLastRow();

  if (lastRow < 2) return [];

  const data = sheet.getRange(2, 1, lastRow - 1, 4).getValues();
  return data.map(r => ({
    id: r[0],
    nama: r[1],
    email: r[2],
    kelas: r[3]
  }));
}

/*************************
 * CREATE
 *************************/
function addPeserta(p) {
  const sheet = getSheet();
  sheet.appendRow([
    Date.now(),
    p.nama,
    p.email,
    p.kelas
  ]);
  return true;
}

/*************************
 * UPDATE
 *************************/
function updatePeserta(p) {
  const sheet = getSheet();
  const ids = sheet.getRange(2, 1, sheet.getLastRow() - 1, 1).getValues();

  for (let i = 0; i < ids.length; i++) {
    if (ids[i][0] == p.id) {
      sheet.getRange(i + 2, 2, 1, 3).setValues([[
        p.nama,
        p.email,
        p.kelas
      ]]);
      return true;
    }
  }
  return false;
}

/*************************
 * DELETE
 *************************/
function deletePeserta(id) {
  const sheet = getSheet();
  const ids = sheet.getRange(2, 1, sheet.getLastRow() - 1, 1).getValues();

  for (let i = 0; i < ids.length; i++) {
    if (ids[i][0] == id) {
      sheet.deleteRow(i + 2);
      return true;
    }
  }
  return false;
}


Index.html

<!DOCTYPE html>
<html>
<head>
  <base target="_top">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <!-- Bootstrap 5 -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">

  <style>
    body {
      background-color: #f8f9fa;
    }
    .hero {
      background: linear-gradient(120deg, #0d6efd, #6610f2);
      color: white;
      padding: 80px 20px;
      border-radius: 0 0 40px 40px;
    }
    .card {
      border-radius: 16px;
    }
    .btn {
      border-radius: 30px;
    }
  </style>
</head>

<body>

<!-- HERO -->
<section class="hero text-center">
  <div class="container">
    <h1 class="display-5 fw-bold">Manajemen Peserta Pelatihan</h1>
    <p class="lead mt-3">
      Web App SPA berbasis Google Apps Script & Google Sheet
    </p>
  </div>
</section>

<!-- CONTENT -->
<div class="container mt-5">

  <div class="row">
    <!-- FORM -->
    <div class="col-md-4 mb-4">
      <div class="card shadow-sm">
        <div class="card-body">
          <h5 class="card-title mb-3">Form Peserta</h5>

          <input type="hidden" id="id">

          <div class="mb-2">
            <label class="form-label">Nama</label>
            <input id="nama" class="form-control">
          </div>

          <div class="mb-2">
            <label class="form-label">Email</label>
            <input id="email" class="form-control">
          </div>

          <div class="mb-3">
            <label class="form-label">Kelas</label>
            <input id="kelas" class="form-control">
          </div>

          <div class="d-grid gap-2">
            <button class="btn btn-primary" onclick="simpan()">Simpan</button>
            <button class="btn btn-outline-secondary" onclick="resetForm()">Batal</button>
          </div>
        </div>
      </div>
    </div>

    <!-- TABLE -->
    <div class="col-md-8">
      <div class="card shadow-sm">
        <div class="card-body">
          <h5 class="card-title mb-3">Daftar Peserta</h5>

          <div class="table-responsive">
            <table class="table table-hover align-middle">
              <thead class="table-light">
                <tr>
                  <th>Nama</th>
                  <th>Email</th>
                  <th>Kelas</th>
                  <th width="140">Aksi</th>
                </tr>
              </thead>
              <tbody id="dataPeserta"></tbody>
            </table>
          </div>

        </div>
      </div>
    </div>
  </div>
</div>

<!-- SCRIPT -->
<script>
  let peserta = [];
  let modeEdit = false;

  document.addEventListener('DOMContentLoaded', loadPeserta);

  function loadPeserta() {
    google.script.run
      .withSuccessHandler(data => {
        peserta = data || [];
        render();
      })
      .withFailureHandler(err => {
        alert('Gagal memuat data: ' + err.message);
      })
      .getPeserta();
  }

  function render() {
    const tbody = document.getElementById('dataPeserta');
    tbody.innerHTML = '';

    if (peserta.length === 0) {
      tbody.innerHTML = `
        <tr>
          <td colspan="4" class="text-center text-muted">
            Belum ada data
          </td>
        </tr>`;
      return;
    }

    peserta.forEach(p => {
      tbody.innerHTML += `
        <tr>
          <td>${p.nama}</td>
          <td>${p.email}</td>
          <td>${p.kelas}</td>
          <td>
            <button class="btn btn-sm btn-warning me-1"
              onclick="editPeserta(${p.id})">Edit</button>
            <button class="btn btn-sm btn-danger"
              onclick="hapusPeserta(${p.id})">Hapus</button>
          </td>
        </tr>`;
    });
  }

  function simpan() {
    const data = {
      id: document.getElementById('id').value,
      nama: document.getElementById('nama').value,
      email: document.getElementById('email').value,
      kelas: document.getElementById('kelas').value
    };

    const callback = () => {
      resetForm();
      loadPeserta();
    };

    if (modeEdit) {
      google.script.run.withSuccessHandler(callback).updatePeserta(data);
    } else {
      google.script.run.withSuccessHandler(callback).addPeserta(data);
    }
  }

  function editPeserta(id) {
    const p = peserta.find(x => x.id == id);
    if (!p) return;

    document.getElementById('id').value = p.id;
    document.getElementById('nama').value = p.nama;
    document.getElementById('email').value = p.email;
    document.getElementById('kelas').value = p.kelas;
    modeEdit = true;
  }

  function hapusPeserta(id) {
    if (!confirm('Hapus data ini?')) return;
    google.script.run.withSuccessHandler(loadPeserta).deletePeserta(id);
  }

  function resetForm() {
    document.getElementById('id').value = '';
    document.getElementById('nama').value = '';
    document.getElementById('email').value = '';
    document.getElementById('kelas').value = '';
    modeEdit = false;
  }
</script>

</body>
</html>


Buatkan Versi Bootstrap / Tailwind dan tambahkan Hero

Siap 👍
Berikut saya buatkan VERSI BOOTSTRAP (SPA) + HERO SECTION
➡️ Backend (Code.gs) TIDAK BERUBAH
➡️ Fokus pada UI modern + UX profesional (cocok untuk demo kuliah & project mahasiswa)


🎯 Studi Kasus (Final UI)

Aplikasi Manajemen Peserta Pelatihan Digital Skills
✔ SPA
✔ CRUD Lengkap
✔ Bootstrap 5
✔ Hero Section
✔ Responsive

Tidak ada komentar:

Posting Komentar

Laporan KUS - Sertifikat

  https://www.youtube.com/watch?v=1xegpb4fLk4 =arrayformula(if(row(A:A)=1;"Image";substitute(F:F;"open?";"uc?export...