Buatkan Form Pelatihan / Workshop dengan data disimpan pada google sheet. Back end menggunakan google apps script dan front end menggunakan index.html yang dipanggil dengan function doGet(e) {
return HtmlService.createHtmlOutputFromFile('index’)}. Untuk front end buatkan
Landing Page (Hero Section)
- Full screen
- Gradient biru modern
- Call-to-action “Mulai Isi Data”
- Cocok untuk aplikasi GAS berbasis form publik
Form Dipisahkan Secara Visual
- Landing page ➜ Form input
- Navigasi tanpa reload (SPA-style sederhana)
UI Modern & Clean
- Typography rapi
- Card layout
- Shadow + rounded corner
- Warna biru konsisten (tema edukasi / sistem informasi)
Struktur Frontend Lebih Profesional
- HTML semantic (section)
- CSS terstruktur
- JavaScript jelas dan minimal
<!doctype html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Form Pelatihan Workshop</title>
<script src="/_sdk/element_sdk.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
color: #333;
box-sizing: border-box;
overflow-x: hidden;
}
html, body, #app {
height: 100%;
width: 100%;
}
#app {
overflow-auto;
}
/* Landing Page Styles */
.landing-section {
min-height: 100%;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
display: flex;
align-items: center;
justify-content: center;
padding: 2rem;
width: 100%;
}
.hero-content {
text-align: center;
color: white;
max-width: 700px;
}
.hero-title {
font-size: 3rem;
font-weight: bold;
margin-bottom: 1.5rem;
text-shadow: 2px 2px 4px rgba(0,0,0,0.2);
}
.hero-subtitle {
font-size: 1.25rem;
margin-bottom: 2.5rem;
opacity: 0.95;
}
.cta-button {
background: white;
color: #667eea;
padding: 1rem 3rem;
font-size: 1.125rem;
font-weight: 600;
border: none;
border-radius: 50px;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
}
.cta-button:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(0,0,0,0.3);
}
/* Form Section Styles */
.form-section {
display: none;
min-height: 100%;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 3rem 1.5rem;
width: 100%;
}
.form-section.active {
display: flex;
flex-direction: column;
align-items: center;
}
.form-container {
background: white;
border-radius: 20px;
box-shadow: 0 10px 40px rgba(0,0,0,0.2);
padding: 2.5rem;
width: 100%;
max-width: 600px;
margin-bottom: 2rem;
}
.form-header {
text-align: center;
margin-bottom: 2rem;
}
.form-title {
font-size: 2rem;
color: #667eea;
margin-bottom: 0.5rem;
}
.back-button {
background: none;
border: none;
color: #667eea;
cursor: pointer;
font-size: 0.9rem;
margin-bottom: 1rem;
display: inline-flex;
align-items: center;
gap: 0.5rem;
transition: color 0.3s ease;
}
.back-button:hover {
color: #764ba2;
}
.form-group {
margin-bottom: 1.5rem;
}
.form-label {
display: block;
margin-bottom: 0.5rem;
font-weight: 600;
color: #333;
}
.form-input,
.form-select,
.form-textarea {
width: 100%;
padding: 0.875rem;
border: 2px solid #e0e0e0;
border-radius: 10px;
font-size: 1rem;
transition: all 0.3s ease;
font-family: inherit;
}
.form-input:focus,
.form-select:focus,
.form-textarea:focus {
outline: none;
border-color: #667eea;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
}
.form-textarea {
resize: vertical;
min-height: 100px;
}
.submit-button {
width: 100%;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 1rem;
font-size: 1.125rem;
font-weight: 600;
border: none;
border-radius: 10px;
cursor: pointer;
transition: all 0.3s ease;
margin-top: 1rem;
}
.submit-button:hover:not(:disabled) {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
}
.submit-button:disabled {
opacity: 0.6;
cursor: not-allowed;
}
.success-message,
.error-message {
text-align: center;
padding: 1rem;
border-radius: 10px;
margin-top: 1rem;
font-weight: 500;
}
.success-message {
background: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.error-message {
background: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.hidden {
display: none;
}
@media (max-width: 768px) {
.hero-title {
font-size: 2rem;
}
.hero-subtitle {
font-size: 1rem;
}
.form-container {
padding: 1.5rem;
}
.form-title {
font-size: 1.5rem;
}
}
</style>
<style>@view-transition { navigation: auto; }</style>
<script src="/_sdk/data_sdk.js" type="text/javascript"></script>
<script src="https://cdn.tailwindcss.com" type="text/javascript"></script>
</head>
<body>
<div id="app"><!-- Landing Page -->
<section class="landing-section" id="landingSection">
<div class="hero-content">
<h1 class="hero-title" id="heroTitle">Form Pendaftaran Pelatihan</h1>
<p class="hero-subtitle" id="heroSubtitle">Daftarkan diri Anda untuk mengikuti pelatihan dan workshop profesional</p><button class="cta-button" id="ctaButton" onclick="showForm()">Mulai Isi Data</button>
</div>
</section><!-- Form Section -->
<section class="form-section" id="formSection">
<div class="form-container"><button class="back-button" onclick="showLanding()"> ← Kembali </button>
<div class="form-header">
<h2 class="form-title" id="formTitle">Data Peserta</h2>
</div>
<form id="registrationForm" onsubmit="handleSubmit(event)">
<div class="form-group"><label class="form-label" for="nama">Nama Lengkap</label> <input type="text" id="nama" name="nama" class="form-input" required>
</div>
<div class="form-group"><label class="form-label" for="email">Email</label> <input type="email" id="email" name="email" class="form-input" required>
</div>
<div class="form-group"><label class="form-label" for="telepon">Nomor Telepon</label> <input type="tel" id="telepon" name="telepon" class="form-input" required>
</div>
<div class="form-group"><label class="form-label" for="instansi">Instansi/Perusahaan</label> <input type="text" id="instansi" name="instansi" class="form-input" required>
</div>
<div class="form-group"><label class="form-label" for="pelatihan">Pilih Pelatihan</label> <select id="pelatihan" name="pelatihan" class="form-select" required> <option value="">-- Pilih Pelatihan --</option> <option value="Web Development">Web Development</option> <option value="Data Science">Data Science</option> <option value="Digital Marketing">Digital Marketing</option> <option value="UI/UX Design">UI/UX Design</option> <option value="Project Management">Project Management</option> </select>
</div>
<div class="form-group"><label class="form-label" for="catatan">Catatan (Opsional)</label> <textarea id="catatan" name="catatan" class="form-textarea"></textarea>
</div><button type="submit" class="submit-button" id="submitButton">Kirim Pendaftaran</button>
</form>
<div id="successMessage" class="success-message hidden"></div>
<div id="errorMessage" class="error-message hidden"></div>
</div>
</section>
</div>
<script>
const defaultConfig = {
hero_title: "Form Pendaftaran Pelatihan",
hero_subtitle: "Daftarkan diri Anda untuk mengikuti pelatihan dan workshop profesional",
cta_button: "Mulai Isi Data",
form_title: "Data Peserta",
submit_button: "Kirim Pendaftaran",
background_color: "#667eea",
surface_color: "#ffffff",
text_color: "#333333",
primary_action_color: "#667eea",
secondary_action_color: "#764ba2",
font_family: "Segoe UI",
font_size: 16
};
function showForm() {
document.getElementById('landingSection').style.display = 'none';
document.getElementById('formSection').classList.add('active');
}
function showLanding() {
document.getElementById('formSection').classList.remove('active');
document.getElementById('landingSection').style.display = 'flex';
}
function showMessage(elementId, message) {
const element = document.getElementById(elementId);
element.textContent = message;
element.classList.remove('hidden');
setTimeout(() => {
element.classList.add('hidden');
}, 5000);
}
function handleSubmit(event) {
event.preventDefault();
const submitButton = document.getElementById('submitButton');
const form = document.getElementById('registrationForm');
submitButton.disabled = true;
submitButton.textContent = 'Mengirim...';
const formData = {
nama: document.getElementById('nama').value,
email: document.getElementById('email').value,
telepon: document.getElementById('telepon').value,
instansi: document.getElementById('instansi').value,
pelatihan: document.getElementById('pelatihan').value,
catatan: document.getElementById('catatan').value,
timestamp: new Date().toISOString()
};
// Untuk Google Apps Script deployment
if (typeof google !== 'undefined' && google.script && google.script.run) {
google.script.run
.withSuccessHandler(function(response) {
showMessage('successMessage', 'Pendaftaran berhasil dikirim! Terima kasih.');
form.reset();
submitButton.disabled = false;
submitButton.textContent = window.elementSdk?.config?.submit_button || defaultConfig.submit_button;
})
.withFailureHandler(function(error) {
showMessage('errorMessage', 'Terjadi kesalahan. Silakan coba lagi.');
submitButton.disabled = false;
submitButton.textContent = window.elementSdk?.config?.submit_button || defaultConfig.submit_button;
})
.submitForm(formData);
} else {
// Demo mode - simulasi sukses
setTimeout(() => {
showMessage('successMessage', 'Mode Demo: Data berhasil "dikirim"! (Dalam production, data akan tersimpan di Google Sheets)');
form.reset();
submitButton.disabled = false;
submitButton.textContent = window.elementSdk?.config?.submit_button || defaultConfig.submit_button;
}, 1000);
}
}
async function onConfigChange(config) {
const heroTitle = document.getElementById('heroTitle');
const heroSubtitle = document.getElementById('heroSubtitle');
const ctaButton = document.getElementById('ctaButton');
const formTitle = document.getElementById('formTitle');
const submitButton = document.getElementById('submitButton');
if (heroTitle) heroTitle.textContent = config.hero_title || defaultConfig.hero_title;
if (heroSubtitle) heroSubtitle.textContent = config.hero_subtitle || defaultConfig.hero_subtitle;
if (ctaButton) ctaButton.textContent = config.cta_button || defaultConfig.cta_button;
if (formTitle) formTitle.textContent = config.form_title || defaultConfig.form_title;
if (submitButton && !submitButton.disabled) {
submitButton.textContent = config.submit_button || defaultConfig.submit_button;
}
const baseSize = config.font_size || defaultConfig.font_size;
const customFont = config.font_family || defaultConfig.font_family;
const baseFontStack = 'Segoe UI, Tahoma, Geneva, Verdana, sans-serif';
document.body.style.fontFamily = `${customFont}, ${baseFontStack}`;
document.body.style.fontSize = `${baseSize}px`;
if (heroTitle) heroTitle.style.fontSize = `${baseSize * 3}px`;
if (heroSubtitle) heroSubtitle.style.fontSize = `${baseSize * 1.25}px`;
if (ctaButton) ctaButton.style.fontSize = `${baseSize * 1.125}px`;
if (formTitle) formTitle.style.fontSize = `${baseSize * 2}px`;
if (submitButton) submitButton.style.fontSize = `${baseSize * 1.125}px`;
const landingSection = document.getElementById('landingSection');
const formSection = document.getElementById('formSection');
const bgColor = config.background_color || defaultConfig.background_color;
const secondaryColor = config.secondary_action_color || defaultConfig.secondary_action_color;
if (landingSection) {
landingSection.style.background = `linear-gradient(135deg, ${bgColor} 0%, ${secondaryColor} 100%)`;
}
if (formSection) {
formSection.style.background = `linear-gradient(135deg, ${bgColor} 0%, ${secondaryColor} 100%)`;
}
const formContainer = document.querySelector('.form-container');
if (formContainer) {
formContainer.style.background = config.surface_color || defaultConfig.surface_color;
}
const primaryColor = config.primary_action_color || defaultConfig.primary_action_color;
const textColor = config.text_color || defaultConfig.text_color;
if (ctaButton) {
ctaButton.style.color = primaryColor;
}
const backButton = document.querySelector('.back-button');
if (backButton) {
backButton.style.color = primaryColor;
}
if (formTitle) {
formTitle.style.color = primaryColor;
}
if (submitButton) {
submitButton.style.background = `linear-gradient(135deg, ${primaryColor} 0%, ${secondaryColor} 100%)`;
}
const labels = document.querySelectorAll('.form-label');
labels.forEach(label => {
label.style.color = textColor;
});
}
if (window.elementSdk) {
window.elementSdk.init({
defaultConfig,
onConfigChange,
mapToCapabilities: (config) => ({
recolorables: [
{
get: () => config.background_color || defaultConfig.background_color,
set: (value) => {
config.background_color = value;
window.elementSdk.setConfig({ background_color: value });
}
},
{
get: () => config.surface_color || defaultConfig.surface_color,
set: (value) => {
config.surface_color = value;
window.elementSdk.setConfig({ surface_color: value });
}
},
{
get: () => config.text_color || defaultConfig.text_color,
set: (value) => {
config.text_color = value;
window.elementSdk.setConfig({ text_color: value });
}
},
{
get: () => config.primary_action_color || defaultConfig.primary_action_color,
set: (value) => {
config.primary_action_color = value;
window.elementSdk.setConfig({ primary_action_color: value });
}
},
{
get: () => config.secondary_action_color || defaultConfig.secondary_action_color,
set: (value) => {
config.secondary_action_color = value;
window.elementSdk.setConfig({ secondary_action_color: value });
}
}
],
borderables: [],
fontEditable: {
get: () => config.font_family || defaultConfig.font_family,
set: (value) => {
config.font_family = value;
window.elementSdk.setConfig({ font_family: value });
}
},
fontSizeable: {
get: () => config.font_size || defaultConfig.font_size,
set: (value) => {
config.font_size = value;
window.elementSdk.setConfig({ font_size: value });
}
}
}),
mapToEditPanelValues: (config) => new Map([
["hero_title", config.hero_title || defaultConfig.hero_title],
["hero_subtitle", config.hero_subtitle || defaultConfig.hero_subtitle],
["cta_button", config.cta_button || defaultConfig.cta_button],
["form_title", config.form_title || defaultConfig.form_title],
["submit_button", config.submit_button || defaultConfig.submit_button]
])
});
}
</script>
<script>(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'9af267ad54b6d210',t:'MTc2NTkzMjQwMy4wMDAwMDA='};var a=document.createElement('script');a.nonce='';a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script></body>
</html>

Tidak ada komentar:
Posting Komentar