Redesign playground: template tabs, live preview, split pane, mobile responsive
All checks were successful
Build & Deploy to Staging / Build & Deploy to Staging (push) Successful in 13m8s

- Add 3 pre-built templates (Invoice, Report, Custom HTML)
- Split-pane editor with live HTML preview (updates as you type)
- Generation timer shows actual response time
- Before/after comparison (free watermarked vs Pro clean)
- Pro CTA integrated into result panel
- Fully responsive: stacks on mobile
- Professional polish matching site design language
This commit is contained in:
DocFast CEO 2026-02-20 09:32:25 +00:00
parent a178a1b06d
commit dabf3c1004
6 changed files with 762 additions and 138 deletions

View file

@ -173,6 +173,35 @@ async function checkout() {
}
// === Demo Playground ===
var pgTemplates = {
invoice: '<html>\n<head>\n<style>\n body { font-family: Inter, -apple-system, sans-serif; padding: 40px; color: #1a1a2e; }\n .header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 40px; }\n .company { font-size: 24px; font-weight: 800; color: #34d399; }\n .invoice-title { font-size: 14px; color: #666; text-transform: uppercase; letter-spacing: 1px; }\n .invoice-num { font-size: 20px; font-weight: 700; }\n .meta { display: grid; grid-template-columns: 1fr 1fr; gap: 30px; margin-bottom: 40px; }\n .meta-label { font-size: 12px; color: #999; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 4px; }\n .meta-value { font-size: 14px; }\n table { width: 100%; border-collapse: collapse; margin-bottom: 30px; }\n th { background: #f8f9fa; padding: 12px 16px; text-align: left; font-size: 12px; text-transform: uppercase; letter-spacing: 0.5px; color: #666; border-bottom: 2px solid #e9ecef; }\n td { padding: 14px 16px; border-bottom: 1px solid #f0f0f0; font-size: 14px; }\n .text-right { text-align: right; }\n .total-row td { font-weight: 700; font-size: 16px; border-top: 2px solid #1a1a2e; border-bottom: none; }\n .footer { margin-top: 40px; padding-top: 20px; border-top: 1px solid #e9ecef; font-size: 12px; color: #999; text-align: center; }\n</style>\n</head>\n<body>\n <div class="header">\n <div>\n <div class="company">Acme Corp</div>\n <div style="color:#666;font-size:13px;">123 Business Ave, Suite 100<br>San Francisco, CA 94102</div>\n </div>\n <div style="text-align:right;">\n <div class="invoice-title">Invoice</div>\n <div class="invoice-num">#INV-2024-0042</div>\n <div style="color:#666;font-size:13px;margin-top:4px;">Feb 20, 2026</div>\n </div>\n </div>\n <div class="meta">\n <div><div class="meta-label">Bill To</div><div class="meta-value"><strong>Jane Smith</strong><br>456 Client Road<br>New York, NY 10001</div></div>\n <div><div class="meta-label">Payment Due</div><div class="meta-value">March 20, 2026</div><div class="meta-label" style="margin-top:12px;">Payment Method</div><div class="meta-value">Bank Transfer</div></div>\n </div>\n <table>\n <thead><tr><th>Description</th><th class="text-right">Qty</th><th class="text-right">Rate</th><th class="text-right">Amount</th></tr></thead>\n <tbody>\n <tr><td>Web Development — Landing Page</td><td class="text-right">40 hrs</td><td class="text-right">$150</td><td class="text-right">$6,000</td></tr>\n <tr><td>UI/UX Design — Mockups</td><td class="text-right">16 hrs</td><td class="text-right">$125</td><td class="text-right">$2,000</td></tr>\n <tr><td>API Integration &amp; Testing</td><td class="text-right">24 hrs</td><td class="text-right">$150</td><td class="text-right">$3,600</td></tr>\n <tr class="total-row"><td colspan="3">Total</td><td class="text-right">$11,600</td></tr>\n </tbody>\n </table>\n <div class="footer">Thank you for your business! • Payment terms: Net 30 • Acme Corp</div>\n</body>\n</html>',
report: '<html>\n<head>\n<style>\n body { font-family: Inter, -apple-system, sans-serif; padding: 40px; color: #1a1a2e; line-height: 1.6; }\n h1 { font-size: 28px; font-weight: 800; margin-bottom: 8px; }\n .subtitle { color: #666; font-size: 14px; margin-bottom: 32px; }\n .stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-bottom: 32px; }\n .stat { background: #f8f9fa; border-radius: 12px; padding: 20px; text-align: center; }\n .stat-num { font-size: 32px; font-weight: 800; color: #34d399; }\n .stat-label { font-size: 12px; color: #666; text-transform: uppercase; letter-spacing: 0.5px; margin-top: 4px; }\n h2 { font-size: 18px; font-weight: 700; margin: 28px 0 12px; padding-bottom: 8px; border-bottom: 2px solid #f0f0f0; }\n p { color: #444; font-size: 14px; }\n .highlight { background: linear-gradient(135deg, #34d399 0%, #60a5fa 100%); color: white; border-radius: 12px; padding: 24px; margin: 24px 0; }\n .highlight h3 { font-size: 16px; margin-bottom: 8px; }\n .highlight p { color: rgba(255,255,255,0.9); }\n</style>\n</head>\n<body>\n <h1>Q4 2025 Performance Report</h1>\n <div class="subtitle">Prepared by Analytics Team — February 2026</div>\n <div class="stats">\n <div class="stat"><div class="stat-num">142%</div><div class="stat-label">Revenue Growth</div></div>\n <div class="stat"><div class="stat-num">2.4M</div><div class="stat-label">API Calls</div></div>\n <div class="stat"><div class="stat-num">99.9%</div><div class="stat-label">Uptime</div></div>\n </div>\n <h2>Executive Summary</h2>\n <p>Q4 saw exceptional growth across all key metrics. Customer acquisition increased by 85% while churn decreased to an all-time low of 1.2%. Our expansion into the EU market contributed significantly to revenue gains.</p>\n <div class="highlight">\n <h3>🎯 Key Achievement</h3>\n <p>Crossed 10,000 active users milestone in December, two months ahead of target. Enterprise segment grew 200% QoQ.</p>\n </div>\n <h2>Product Updates</h2>\n <p>Launched 3 major features: batch processing, webhook notifications, and custom templates. Template engine adoption reached 40% of Pro users within the first month.</p>\n <h2>Outlook</h2>\n <p>Q1 2026 focus areas include Markdown-to-PDF improvements, enhanced template library, and SOC 2 certification to unlock enterprise sales pipeline.</p>\n</body>\n</html>',
custom: '<html>\n<head>\n<style>\n body {\n font-family: sans-serif;\n padding: 40px;\n }\n h1 { color: #34d399; }\n</style>\n</head>\n<body>\n <h1>Hello World!</h1>\n <p>Edit this HTML and watch the preview update in real time.</p>\n <p>Then click <strong>Generate PDF</strong> to download it.</p>\n</body>\n</html>'
};
var previewDebounce = null;
function updatePreview() {
var iframe = document.getElementById('demoPreview');
var html = document.getElementById('demoHtml').value;
if (!iframe) return;
var doc = iframe.contentDocument || iframe.contentWindow.document;
doc.open();
doc.write(html);
doc.close();
}
function setTemplate(name) {
var ta = document.getElementById('demoHtml');
ta.value = pgTemplates[name] || pgTemplates.custom;
updatePreview();
// Update active tab
document.querySelectorAll('.pg-tab').forEach(function(t) {
var isActive = t.getAttribute('data-template') === name;
t.classList.toggle('active', isActive);
t.setAttribute('aria-selected', isActive ? 'true' : 'false');
});
}
async function generateDemo() {
var btn = document.getElementById('demoGenerateBtn');
var status = document.getElementById('demoStatus');
@ -183,14 +212,16 @@ async function generateDemo() {
if (!html) {
errorEl.textContent = 'Please enter some HTML.';
errorEl.style.display = 'block';
result.style.display = 'none';
result.classList.remove('visible');
return;
}
errorEl.style.display = 'none';
result.style.display = 'none';
result.classList.remove('visible');
btn.disabled = true;
status.textContent = 'Generating PDF…';
btn.classList.add('pg-generating');
status.textContent = 'Generating…';
var startTime = performance.now();
try {
var res = await fetch('/v1/demo/html', {
@ -204,21 +235,25 @@ async function generateDemo() {
errorEl.textContent = data.error || 'Something went wrong.';
errorEl.style.display = 'block';
btn.disabled = false;
btn.classList.remove('pg-generating');
status.textContent = '';
return;
}
var elapsed = ((performance.now() - startTime) / 1000).toFixed(1);
var blob = await res.blob();
var url = URL.createObjectURL(blob);
var dl = document.getElementById('demoDownload');
dl.href = url;
result.style.display = 'block';
document.getElementById('demoDownload').href = url;
document.getElementById('demoTime').textContent = elapsed;
result.classList.add('visible');
status.textContent = '';
btn.disabled = false;
btn.classList.remove('pg-generating');
} catch (err) {
errorEl.textContent = 'Network error. Please try again.';
errorEl.style.display = 'block';
btn.disabled = false;
btn.classList.remove('pg-generating');
status.textContent = '';
}
}
@ -233,6 +268,21 @@ document.addEventListener('DOMContentLoaded', function() {
// Demo playground
document.getElementById('demoGenerateBtn').addEventListener('click', generateDemo);
// Playground tabs
document.querySelectorAll('.pg-tab').forEach(function(tab) {
tab.addEventListener('click', function() { setTemplate(this.getAttribute('data-template')); });
});
// Init with invoice template
setTemplate('invoice');
// Live preview on input
document.getElementById('demoHtml').addEventListener('input', function() {
clearTimeout(previewDebounce);
previewDebounce = setTimeout(updatePreview, 150);
});
// Playground checkout button
var pgCheckout = document.getElementById('btn-checkout-playground');
if (pgCheckout) pgCheckout.addEventListener('click', checkout);
// Checkout buttons
document.getElementById('btn-checkout').addEventListener('click', checkout);
var heroCheckout = document.getElementById('btn-checkout-hero');