Restore to commit 74e578279624c6045ca440a3459ebfa1f8d54191

This commit is contained in:
southseact-3d
2026-02-07 20:32:41 +00:00
commit ed67b7741b
252 changed files with 99814 additions and 0 deletions

634
chat/public/index.html Normal file
View File

@@ -0,0 +1,634 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Chat with OpenCode</title>
<link rel="icon" type="image/png" href="/assets/Plugin.png">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link
href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600&family=Inter:wght@400;600&display=swap"
rel="stylesheet">
<link rel="stylesheet" href="/chat/styles.css">
<!-- PostHog Analytics -->
<script src="/posthog.js"></script>
</head>
<body>
<div class="app-shell">
<aside class="sidebar">
<div class="brand">
<img src="/assets/Plugin.png" alt="OC" style="width: 32px; height: 32px; border-radius: 8px;">
<div>
<div class="brand-title">Plugin Compass</div>
<div class="brand-sub">Terminal + Chat</div>
</div>
</div>
<button class="primary" id="new-chat">+ New chat</button>
<div class="sidebar-section">
<div class="section-heading">Sessions</div>
<div id="session-list" class="session-list"></div>
</div>
<div class="sidebar-section slim">
<div class="section-heading">Version control</div>
<div style="display:flex; flex-direction:column; gap:8px;">
<button id="github-button" class="primary">GitHub</button>
<button id="diagnostics-button" class="ghost" style="margin-left:8px;">Diagnostics</button>
<div id="git-output" class="git-output"></div>
</div>
</div>
</aside>
<main class="main">
<header class="topbar">
<div class="topbar-left">
<div class="crumb">plugincompass.com</div>
<div class="title" id="chat-title">Chat</div>
</div>
<div class="topbar-actions">
<div class="queue-indicator" id="queue-indicator">Idle</div>
</div>
</header>
<div class="panel" id="session-meta">
<div>
<div class="label">Session ID</div>
<div id="session-id" class="value">-</div>
</div>
<div>
<div class="label">Active model</div>
<div id="session-model" class="value">-</div>
</div>
<div>
<div class="label">Pending</div>
<div id="session-pending" class="value">0</div>
</div>
</div>
<section class="chat-area" id="chat-area"></section>
<div class="composer">
<div class="input-row">
<textarea id="message-input" rows="3" placeholder="Type your message to OpenCode..."></textarea>
<div class="composer-actions">
<button id="upload-media-btn" class="ghost" title="Attach images" style="display: none; align-items: center; justify-content: center; width: 40px; height: 40px; padding: 0; border-radius: 8px;">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"></path>
</svg>
</button>
<input id="upload-media-input" type="file" accept="image/*" multiple style="display:none" />
<button id="send-btn" class="primary">Send</button>
</div>
</div>
<div id="attachment-preview" class="attachment-preview" style="display:none"></div>
<div style="margin-top:10px; display:flex; gap:8px; align-items:center;">
<label class="model-select" style="background:transparent; border:1px solid var(--border);">
<span style="color:var(--muted); margin-right:6px;">CLI</span>
<select id="cli-select"
style="background: #fff; color: var(--text); border: none; padding:4px 8px; border-radius:6px;"></select>
</label>
<label class="model-select" style="background:transparent; border:1px solid var(--border);">
<img id="model-icon" src="" alt=""
style="width:18px; height:18px; border-radius:4px; margin-right:8px; display:none;" />
<span style="color:var(--muted); margin-right:6px;">Model</span>
<select id="model-select"
style="background: #fff; color: var(--text); border: none; padding:4px 8px; border-radius:6px;"></select>
</label>
<label id="custom-model-label" class="model-select"
style="display:none; margin-left:8px; background:transparent; border:1px solid var(--border);">
<span style="color:var(--muted); margin-right:6px;">Custom</span>
<input id="custom-model-input" type="text" placeholder="provider/model or model-name"
style="background:transparent; border:none; color:var(--text); padding:0 8px;" />
</label>
</div>
<div class="status-line" id="status-line"></div>
</div>
</main>
</div>
<div id="github-modal" class="modal"
style="display:none; position:fixed; inset:0; background:rgba(0,0,0,0.4); align-items:center; justify-content:center; z-index:10000;">
<div
style="background:var(--panel); padding:20px; border-radius:10px; width:420px; box-shadow:0 10px 40px rgba(0,0,0,0.2);">
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:8px;">
<strong style="color:var(--text);">GitHub</strong>
<button id="github-close"
style="border:none; background:transparent; color:var(--muted); cursor:pointer; display:flex; align-items:center; justify-content:center; width:24px; height:24px; padding:4px;">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
</div>
<div style="display:flex; flex-direction:column; gap:8px;">
<div style="display:flex; gap:8px; flex-wrap:wrap; align-items:center;">
<button data-git="pull" class="ghost">Pull</button>
<button data-git="fetch" class="ghost">Fetch</button>
<button data-git="status" class="ghost">Status</button>
<button data-git="log" class="ghost">Log</button>
</div>
<div style="display:flex; gap:8px;">
<button data-git="push" class="ghost">Commit & Push</button>
<button data-git="sync" class="ghost">Sync</button>
</div>
<input id="modal-commit-message" type="text" placeholder="Commit message" value="Update from chat UI"
style="padding:8px; border-radius:6px; border:1px solid var(--border);" />
</div>
<details style="margin-top:8px; padding:8px; border-radius:6px; background:var(--panel);">
<summary style="cursor:pointer; font-weight:600;">What commands will run</summary>
<div style="margin-top:8px; color:var(--muted);">
<ul>
<li><strong>Pull</strong> — git pull</li>
<li><strong>Fetch</strong> — git fetch --all</li>
<li><strong>Status</strong> — git status --short</li>
<li><strong>Log</strong> — git log --oneline -n 20</li>
<li><strong>Commit & Push</strong> — git add .; git commit -m "message"; git push origin main</li>
<li><strong>Sync</strong> — git pull; git add .; git commit -m "message"; git push origin main</li>
</ul>
<div style="font-size:12px; color:var(--muted);">Note: Commit will run with the provided message. The server
runs git in the workspace root (configurable via the CHAT_REPO_ROOT env var)</div>
</div>
</details>
</div>
</div>
<!-- Onboarding Modal -->
<div id="onboarding-modal" class="onboarding-modal"
style="display:none; position:fixed; inset:0; background:rgba(0,0,0,0.5); align-items:center; justify-content:center; z-index:10001;">
<div class="onboarding-container"
style="background:#fff; border-radius:20px; width:100%; max-width:520px; box-shadow:0 25px 80px rgba(0,0,0,0.2); position:relative; overflow:hidden;">
<button id="onboarding-exit"
style="position:absolute; top:16px; right:16px; border:none; background:transparent; color:#9ca3af; cursor:pointer; font-size:18px; width:32px; height:32px; border-radius:8px; display:flex; align-items:center; justify-content:center; z-index:10; transition:all 0.2s ease;">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
<div class="onboarding-progress" style="height:4px; background:#f3f4f6; width:100%;">
<div id="onboarding-progress-bar" class="onboarding-progress-bar"
style="height:100%; background:linear-gradient(90deg, #008060, #004c3f); width:20%; transition:width 0.3s ease;"></div>
</div>
<div id="onboarding-content" class="onboarding-content" style="padding:32px 32px 24px;">
<div id="onboarding-step-1" class="onboarding-step">
<div style="width:64px; height:64px; border-radius:16px; background:linear-gradient(135deg, #008060, #004c3f); display:flex; align-items:center; justify-content:center; margin:0 auto 20px;">
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<path d="M12 2L2 7l10 5 10-5-10-5z"></path>
<path d="M2 17l10 5 10-5"></path>
<path d="M2 12l10 5 10-5"></path>
</svg>
</div>
<h2 style="font-size:24px; font-weight:700; color:#0f172a; margin-bottom:12px; text-align:center;">Welcome to Plugin Compass</h2>
<p style="color:#6b7280; font-size:15px; line-height:1.6; text-align:center; margin-bottom:8px;">
Build custom WordPress plugins with AI. Replace expensive subscriptions with tailored solutions you can own and customize.
</p>
</div>
<div id="onboarding-step-2" class="onboarding-step" style="display:none;">
<div style="width:64px; height:64px; border-radius:16px; background:linear-gradient(135deg, #5A31F4, #8B5CF6); display:flex; align-items:center; justify-content:center; margin:0 auto 20px;">
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
</svg>
</div>
<h2 style="font-size:24px; font-weight:700; color:#0f172a; margin-bottom:12px; text-align:center;">Chat with AI</h2>
<p style="color:#6b7280; font-size:15px; line-height:1.6; text-align:center; margin-bottom:8px;">
Describe the plugin you want to build. Our AI understands WordPress development and creates complete, functional plugins.
</p>
</div>
<div id="onboarding-step-3" class="onboarding-step" style="display:none;">
<div style="width:64px; height:64px; border-radius:16px; background:linear-gradient(135deg, #F59E0B, #D97706); display:flex; align-items:center; justify-content:center; margin:0 auto 20px;">
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path>
</svg>
</div>
<h2 style="font-size:24px; font-weight:700; color:#0f172a; margin-bottom:12px; text-align:center;">Version Control</h2>
<p style="color:#6b7280; font-size:15px; line-height:1.6; text-align:center; margin-bottom:8px;">
Your plugins are automatically version-controlled. Track changes, collaborate, and deploy with confidence using GitHub integration.
</p>
</div>
<div id="onboarding-step-4" class="onboarding-step" style="display:none;">
<div style="width:64px; height:64px; border-radius:16px; background:linear-gradient(135deg, #10B981, #059669); display:flex; align-items:center; justify-content:center; margin:0 auto 20px;">
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path>
<polyline points="3.27 6.96 12 12.01 20.73 6.96"></polyline>
<line x1="12" y1="22.08" x2="12" y2="12"></line>
</svg>
</div>
<h2 style="font-size:24px; font-weight:700; color:#0f172a; margin-bottom:12px; text-align:center;">Download & Deploy</h2>
<p style="color:#6b7280; font-size:15px; line-height:1.6; text-align:center; margin-bottom:8px;">
Download your finished plugin as a ZIP file or connect directly to WordPress. Your code, your way.
</p>
</div>
<div id="onboarding-step-5" class="onboarding-step" style="display:none;">
<div style="width:64px; height:64px; border-radius:16px; background:linear-gradient(135deg, #EC4899, #DB2777); display:flex; align-items:center; justify-content:center; margin:0 auto 20px;">
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="10"></circle>
<path d="M8 14s1.5 2 4 2 4-2 4-2"></path>
<line x1="9" y1="9" x2="9.01" y2="9"></line>
<line x1="15" y1="9" x2="15.01" y2="9"></line>
</svg>
</div>
<h2 style="font-size:24px; font-weight:700; color:#0f172a; margin-bottom:12px; text-align:center;">Ready to Build!</h2>
<p style="color:#6b7280; font-size:15px; line-height:1.6; text-align:center; margin-bottom:8px;">
Start building your first plugin today. Need help? Check our docs or reach out to support.
</p>
</div>
</div>
<div class="onboarding-footer" style="padding:0 32px 28px; display:flex; align-items:center; justify-content:space-between;">
<div class="onboarding-dots" id="onboarding-dots" style="display:flex; gap:8px;">
<span class="onboarding-dot active" data-step="1"
style="width:8px; height:8px; border-radius:50%; background:#008060; transition:all 0.3s ease; cursor:pointer;"></span>
<span class="onboarding-dot" data-step="2"
style="width:8px; height:8px; border-radius:50%; background:#d1d5db; transition:all 0.3s ease; cursor:pointer;"></span>
<span class="onboarding-dot" data-step="3"
style="width:8px; height:8px; border-radius:50%; background:#d1d5db; transition:all 0.3s ease; cursor:pointer;"></span>
<span class="onboarding-dot" data-step="4"
style="width:8px; height:8px; border-radius:50%; background:#d1d5db; transition:all 0.3s ease; cursor:pointer;"></span>
<span class="onboarding-dot" data-step="5"
style="width:8px; height:8px; border-radius:50%; background:#d1d5db; transition:all 0.3s ease; cursor:pointer;"></span>
</div>
<div class="onboarding-buttons" style="display:flex; gap:12px;">
<button id="onboarding-back" class="onboarding-btn-secondary"
style="padding:10px 20px; font-size:14px; font-weight:600; border-radius:10px; border:1px solid #e5e7eb; background:#fff; color:#374151; cursor:pointer; transition:all 0.2s ease; display:none;">
Back
</button>
<button id="onboarding-next" class="onboarding-btn-primary"
style="padding:10px 24px; font-size:14px; font-weight:600; border-radius:10px; border:none; background:linear-gradient(135deg, #008060, #004c3f); color:#fff; cursor:pointer; transition:all 0.2s ease;">
Next
</button>
</div>
</div>
</div>
</div>
<!-- Upgrade Modal for Free Plan Upload Media -->
<div id="upgrade-modal" class="modal"
style="display:none; position:fixed; inset:0; background:rgba(0,0,0,0.4); align-items:center; justify-content:center; z-index:10000;">
<div
style="background:#fff; padding:28px; border-radius:16px; width:100%; max-width:480px; box-shadow:0 20px 60px rgba(0,0,0,0.15); border:1px solid var(--border); position:relative;">
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:20px;">
<div style="display:flex; align-items:center; gap:10px;">
<div
style="width:32px; height:32px; border-radius:10px; background:linear-gradient(135deg, var(--shopify-green), var(--shopify-green-dark)); display:flex; align-items:center; justify-content:center;">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z">
</path>
</svg>
</div>
<strong style="color:var(--ink); font-size:20px; font-weight:700;">Premium Feature</strong>
</div>
<button id="upgrade-close"
style="border:none; background:transparent; color:var(--muted); cursor:pointer; font-size:20px; display:flex; align-items:center; justify-content:center; width:32px; height:32px; border-radius:8px; transition:all 0.2s ease;">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
</div>
<div style="text-align:center; margin-bottom:24px;">
<div style="font-size:48px; margin-bottom:16px;">📷</div>
<h3 style="font-size:24px; font-weight:700; color:var(--ink); margin-bottom:8px;">Upload Media</h3>
<p style="color:var(--muted); margin-bottom:24px; line-height:1.6; font-size:15px;">Upload and attach images to
your conversations with AI. This feature is available on our Professional and Enterprise plans.</p>
</div>
<div
style="background:linear-gradient(135deg, rgba(0, 128, 96, 0.1), rgba(0, 76, 63, 0.06)); border:1px solid rgba(0, 128, 96, 0.2); border-radius:12px; padding:16px; margin-bottom:24px;">
<h4 style="font-weight:700; color:var(--shopify-green); margin-bottom:8px;">What's included:</h4>
<ul style="color:var(--muted); font-size:14px; line-height:1.5; margin:0; padding-left:16px;">
<li>Upload multiple images at once</li>
<li>Drag & drop interface</li>
<li>Automatic image optimization</li>
<li>Paste images directly into chat</li>
</ul>
</div>
<div style="display:flex; flex-direction:column; gap:12px;">
<button id="upgrade-btn" class="upgrade-btn"
style="display:flex; align-items:center; justify-content:center; gap:10px; padding:14px 20px; font-size:16px; font-weight:700; border-radius:12px; transition:all 0.2s ease; background:linear-gradient(135deg, var(--shopify-green), var(--shopify-green-dark)); color:white; border:none;">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z">
</path>
</svg>
Upgrade Now
</button>
<button id="upgrade-later" class="action-link" style="flex:1; justify-content:center;">Maybe Later</button>
</div>
</div>
</div>
<style>
/* Upgrade Modal Styles */
:root {
--shopify-green: #008060;
--shopify-green-dark: #004c3f;
--ink: #0f172a;
--muted: #6b7280;
}
#upgrade-close:hover {
background: rgba(0, 128, 96, 0.1);
color: var(--shopify-green);
}
#upgrade-btn {
background: linear-gradient(135deg, var(--shopify-green), var(--shopify-green-dark));
color: white;
border: none;
font-weight: 700;
}
#upgrade-btn:hover {
transform: translateY(-1px);
box-shadow: 0 10px 25px rgba(0, 128, 96, 0.25);
}
#upgrade-btn:active {
transform: translateY(0);
}
.action-link {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 10px 12px;
border-radius: 10px;
font-weight: 600;
border: 1px solid var(--border);
background: #fff;
color: var(--ink);
text-decoration: none;
transition: transform 0.15s ease, box-shadow 0.2s ease, border-color 0.2s ease;
cursor: pointer;
}
/* Onboarding Modal Styles */
#onboarding-exit:hover {
background: #f3f4f6;
color: #374151;
}
.onboarding-btn-primary:hover {
transform: translateY(-1px);
box-shadow: 0 8px 20px rgba(0, 128, 96, 0.3);
}
.onboarding-btn-primary:active {
transform: translateY(0);
}
.onboarding-btn-secondary:hover {
background: #f9fafb;
border-color: #d1d5db;
}
.onboarding-dot.active {
background: #008060;
transform: scale(1.2);
}
.onboarding-dot:hover {
background: #008060;
opacity: 0.7;
}
</style>
<script>
// Upgrade Modal functionality for index.html
window.showUpgradeModal = function () {
if (typeof state !== 'undefined' && state.accountPlan === 'enterprise') {
alert('You are already on the Enterprise plan with full access.');
return;
}
const modal = document.getElementById('upgrade-modal');
if (modal) {
modal.style.display = 'flex';
}
};
function hideUpgradeModal() {
const modal = document.getElementById('upgrade-modal');
if (modal) {
modal.style.display = 'none';
}
}
// Event listeners for upgrade modal
document.addEventListener('DOMContentLoaded', function () {
const upgradeClose = document.getElementById('upgrade-close');
const upgradeBtn = document.getElementById('upgrade-btn');
const upgradeLater = document.getElementById('upgrade-later');
const upgradeModal = document.getElementById('upgrade-modal');
if (upgradeClose) {
upgradeClose.addEventListener('click', hideUpgradeModal);
}
if (upgradeBtn) {
upgradeBtn.addEventListener('click', () => {
hideUpgradeModal();
window.location.href = '/select-plan';
});
}
if (upgradeLater) {
upgradeLater.addEventListener('click', hideUpgradeModal);
}
if (upgradeModal) {
upgradeModal.addEventListener('click', (e) => {
if (e.target === upgradeModal) {
hideUpgradeModal();
}
});
}
});
</script>
<script>
// Onboarding Modal functionality
(function() {
const ONBOARDING_COMPLETED_KEY = 'plugin_compass_onboarding_completed';
let currentStep = 1;
const totalSteps = 5;
function isOnboardingCompleted() {
try {
return localStorage.getItem(ONBOARDING_COMPLETED_KEY) === 'true';
} catch (e) {
return false;
}
}
function markOnboardingCompleted() {
try {
localStorage.setItem(ONBOARDING_COMPLETED_KEY, 'true');
} catch (e) {
console.warn('Failed to save onboarding completion status');
}
}
function showStep(step) {
for (let i = 1; i <= totalSteps; i++) {
const stepEl = document.getElementById('onboarding-step-' + i);
if (stepEl) {
stepEl.style.display = i === step ? 'block' : 'none';
}
}
const dots = document.querySelectorAll('.onboarding-dot');
dots.forEach((dot, index) => {
if (index + 1 === step) {
dot.classList.add('active');
dot.style.background = '#008060';
} else {
dot.classList.remove('active');
dot.style.background = '#d1d5db';
}
});
const progressPercent = (step / totalSteps) * 100;
const progressBar = document.getElementById('onboarding-progress-bar');
if (progressBar) {
progressBar.style.width = progressPercent + '%';
}
const backBtn = document.getElementById('onboarding-back');
const nextBtn = document.getElementById('onboarding-next');
if (backBtn) {
backBtn.style.display = step === 1 ? 'none' : 'block';
}
if (nextBtn) {
if (step === totalSteps) {
nextBtn.textContent = 'Get Started';
nextBtn.style.background = 'linear-gradient(135deg, #10B981, #059669)';
} else {
nextBtn.textContent = 'Next';
nextBtn.style.background = 'linear-gradient(135deg, #008060, #004c3f)';
}
}
}
function nextStep() {
if (currentStep < totalSteps) {
currentStep++;
showStep(currentStep);
} else {
completeOnboarding();
}
}
function prevStep() {
if (currentStep > 1) {
currentStep--;
showStep(currentStep);
}
}
function goToStep(step) {
if (step >= 1 && step <= totalSteps) {
currentStep = step;
showStep(currentStep);
}
}
function completeOnboarding() {
markOnboardingCompleted();
hideOnboarding();
if (typeof posthog !== 'undefined') {
posthog.capture('onboarding_completed');
}
}
function hideOnboarding() {
const modal = document.getElementById('onboarding-modal');
if (modal) {
modal.style.display = 'none';
}
}
function showOnboarding() {
const modal = document.getElementById('onboarding-modal');
if (modal) {
currentStep = 1;
showStep(currentStep);
modal.style.display = 'flex';
}
}
window.showOnboarding = showOnboarding;
window.hideOnboarding = hideOnboarding;
document.addEventListener('DOMContentLoaded', function() {
const exitBtn = document.getElementById('onboarding-exit');
const backBtn = document.getElementById('onboarding-back');
const nextBtn = document.getElementById('onboarding-next');
const modal = document.getElementById('onboarding-modal');
const dots = document.querySelectorAll('.onboarding-dot');
if (exitBtn) {
exitBtn.addEventListener('click', completeOnboarding);
}
if (backBtn) {
backBtn.addEventListener('click', prevStep);
}
if (nextBtn) {
nextBtn.addEventListener('click', nextStep);
}
dots.forEach(dot => {
dot.addEventListener('click', function() {
const step = parseInt(this.getAttribute('data-step'));
goToStep(step);
});
});
if (modal) {
modal.addEventListener('click', function(e) {
if (e.target === modal) {
completeOnboarding();
}
});
}
if (typeof document !== 'undefined') {
document.addEventListener('keydown', function(e) {
const onboardingModal = document.getElementById('onboarding-modal');
if (!onboardingModal || onboardingModal.style.display === 'none') return;
if (e.key === 'Escape') {
completeOnboarding();
} else if (e.key === 'ArrowRight') {
nextStep();
} else if (e.key === 'ArrowLeft') {
prevStep();
}
});
}
if (!isOnboardingCompleted()) {
setTimeout(showOnboarding, 500);
}
});
})();
</script>
<script src="/chat/app.js"></script>
</body>
</html>