Minggu, 15 Februari 2026

Prompt Sheet to Web

 




Code.gs

// ===============================
// CONFIG
// ===============================
const SPREADSHEET_ID = "ISI_SPREADSHEET_ID";
const SHEET_NAME = "ISI_NAMA_SHEET";

// ===============================
// ENTRY POINT (SPA)
// ===============================
function doGet(e) {
  const page = e.parameter.page || "home";
  return HtmlService
    .createHtmlOutput(htmlGenerate(page))
    .setTitle("SPA Spreadsheet App")
    .setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}

// ===============================
// HTML GENERATOR
// ===============================
function htmlGenerate(page) {
  return `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SPA Spreadsheet</title>

<style>
body {
  margin:0;
  font-family: Arial, sans-serif;
  background:#f4f6f9;
}

header {
  background:#2c3e50;
  color:white;
  padding:15px;
  display:flex;
  justify-content:space-between;
}

nav a {
  color:white;
  margin-left:15px;
  text-decoration:none;
}

.container {
  padding:20px;
  max-width:1200px;
  margin:auto;
}

.card {
  background:white;
  padding:20px;
  border-radius:10px;
  box-shadow:0 4px 10px rgba(0,0,0,0.1);
}

.grid {
  display:grid;
  grid-template-columns: repeat(auto-fit,minmax(250px,1fr));
  gap:20px;
}

table {
  width:100%;
  border-collapse:collapse;
}

th,td {
  padding:10px;
  border-bottom:1px solid #ddd;
}

th {
  background:#2c3e50;
  color:white;
}

.loading {
  text-align:center;
  padding:20px;
}

.error {
  color:red;
  text-align:center;
}
</style>
</head>

<body>

<header>
  <div>Spreadsheet SPA</div>
  <nav>
    <a href="#" onclick="navigate('home')">Home</a>
    <a href="#" onclick="navigate('table')">Table</a>
    <a href="#" onclick="navigate('cards')">Cards</a>
  </nav>
</header>

<div class="container">
  <div id="app"></div>
</div>

<script>

// ===============================
// SPA ROUTER
// ===============================
function navigate(page){
  history.pushState({}, "", "?page=" + page);
  renderPage(page);
}

window.onpopstate = function(){
  const params = new URLSearchParams(window.location.search);
  const page = params.get("page") || "home";
  renderPage(page);
};

// ===============================
// INITIAL LOAD
// ===============================
document.addEventListener("DOMContentLoaded", function(){
  const params = new URLSearchParams(window.location.search);
  const page = params.get("page") || "${page}";
  renderPage(page);
});

// ===============================
// RENDER PAGE
// ===============================
function renderPage(page){
  const app = document.getElementById("app");

  if(page === "home"){
    app.innerHTML = \`
      <div class="card">
        <h2>Welcome</h2>
        <p>Aplikasi SPA berbasis Google Spreadsheet.</p>
      </div>
    \`;
  }

  if(page === "table"){
    app.innerHTML = '<div class="loading">Loading...</div>';
    loadData("table");
  }

  if(page === "cards"){
    app.innerHTML = '<div class="loading">Loading...</div>';
    loadData("cards");
  }
}

// ===============================
// FETCH DATA
// ===============================
function loadData(viewType){
  google.script.run
    .withSuccessHandler(function(response){
      if(response.status !== "success"){
        showError(response.message);
        return;
      }

      if(viewType === "table"){
        renderTable(response.data);
      } else {
        renderCards(response.data);
      }
    })
    .withFailureHandler(function(error){
      showError(error.message);
    })
    .getData();
}

function showError(message){
  document.getElementById("app").innerHTML =
    '<div class="error">Error: '+ message +'</div>';
}

// ===============================
// TABLE VIEW
// ===============================
function renderTable(data){
  if(data.length === 0){
    document.getElementById("app").innerHTML = "No Data";
    return;
  }

  const headers = Object.keys(data[0]);

  let html = '<div class="card"><table><thead><tr>';
  headers.forEach(h => html += '<th>'+h+'</th>');
  html += '</tr></thead><tbody>';

  data.forEach(row => {
    html += '<tr>';
    headers.forEach(h => html += '<td>'+row[h]+'</td>');
    html += '</tr>';
  });

  html += '</tbody></table></div>';
  document.getElementById("app").innerHTML = html;
}

// ===============================
// CARD VIEW
// ===============================
function renderCards(data){
  let html = '<div class="grid">';
  data.forEach(row => {
    html += '<div class="card">';
    for(let key in row){
      html += '<p><strong>'+key+':</strong> '+row[key]+'</p>';
    }
    html += '</div>';
  });
  html += '</div>';
  document.getElementById("app").innerHTML = html;
}

</script>

</body>
</html>
`;
}

// ===============================
// API METHOD
// ===============================
function getData(){
  try{
    const sheet = SpreadsheetApp
      .openById(SPREADSHEET_ID)
      .getSheetByName(SHEET_NAME);

    const values = sheet.getDataRange().getValues();
    const headers = values.shift();

    const data = values.map(row => {
      let obj = {};
      headers.forEach((h,i)=> obj[h] = row[i]);
      return obj;
    });

    return { status:"success", data:data };

  } catch(err){
    return { status:"error", message: err.toString() };
  }
}

Tidak ada komentar:

Posting Komentar

Software Development

  https://notebooklm.google.com/notebook/aa90cb8a-990f-46a7-aa65-fdf54cf21e0c?artifactId=eac3296b-2923-4ed2-84c5-172a3f551baf https://chatgp...