PageSourceSearch

https://tyga.ai/js/database/tygarunPanel.js

js tyga.ai collected 2026-10-05 15:11:21 UTC 9,898 bytes, 227 lines download raw bytes

1/**
2 * tyga.run Panel — ready-made SaaS APIs (bookings, logins, payments, CRM...)
3 * Viber-proof: ONE click to enable. No credentials, no code, no config shown.
4 * Power users can expand "Advanced" to paste their own key.
5 * States: onboarding (not enabled), connected, unavailable
6 */
7
8import { api } from '../common/api.js';
9
10// Friendly names for the modules Vibers actually ask for
11const FRIENDLY_MODULES = [
12  { key: 'scheduling', label: 'Bookings', icon: 'fa-calendar-check' },
13  { key: 'auth', label: 'Logins & Accounts', icon: 'fa-user-shield' },
14  { key: 'crm', label: 'Contacts', icon: 'fa-address-book' },
15  { key: 'ecommerce', label: 'Online Store', icon: 'fa-shopping-cart' },
16  { key: 'billing', label: 'Payments', icon: 'fa-credit-card' },
17  { key: 'email', label: 'Email', icon: 'fa-envelope' },
18  { key: 'support', label: 'Support Tickets', icon: 'fa-headset' },
19  { key: 'surveys', label: 'Surveys & Forms', icon: 'fa-poll' },
20  { key: 'event-ticketing', label: 'Event Tickets', icon: 'fa-ticket-alt' },
21  { key: 'elearning', label: 'Courses', icon: 'fa-graduation-cap' },
22  { key: 'notifications', label: 'Notifications', icon: 'fa-bell' },
23  { key: 'file-management', label: 'File Uploads', icon: 'fa-cloud-upload-alt' },
24];
25
26class TygarunPanel {
27  constructor() {
28    this.projectId = null;
29    this.status = null;   // { configured, enabled, sandbox, modules }
30    this.$container = null;
31  }
32
33  async initialize(projectId, status, $container) {
34    this.projectId = projectId;
35    this.status = status;
36    this.$container = $container || $('#database-tab');
37
38    if (status.enabled) {
39      this.showConnected();
40    } else {
41      this.showOnboarding();
42    }
43  }
44
45  // ═══════════════════════════════════════════════════════════════════════════
46  // State A: Onboarding — ONE button. Like assembling Lego.
47  // ═══════════════════════════════════════════════════════════════════════════
48
49  showOnboarding() {
50    this.$container.html(`
51      <div class="anydb-onboarding">
52        <div class="anydb-onboarding-card">
53          <div class="anydb-icon"><i class="fas fa-bolt"></i></div>
54          <h3>Ready-made APIs</h3>
55          <p class="text-muted">
56            Add real bookings, logins, payments, contacts and more to your site —
57            powered by <strong>tyga.run</strong>. Nothing to set up, nothing to code.
58          </p>
59
60          <div class="anydb-hint-chips mb-3">
61            ${FRIENDLY_MODULES.slice(0, 6).map(m =>
62              `<span class="anydb-hint-chip"><i class="fas ${m.icon}"></i> ${m.label}</span>`).join('')}
63          </div>
64
65          <button class="btn btn-primary btn-lg w-100" id="tygarun-enable-btn">
66            <i class="fas fa-bolt"></i> Enable Ready-made APIs
67          </button>
68          <div class="form-text text-muted mt-2">
69            Starts in safe test mode — no real charges or emails until you go live.
70          </div>
71
72          <div class="mt-3">
73            <a class="text-muted small" data-bs-toggle="collapse" href="#tygarun-advanced" role="button" style="cursor:pointer;">
74              <i class="fas fa-cog"></i> Advanced (optional)
75            </a>
76            <div class="collapse mt-2" id="tygarun-advanced">
77              <input type="password" class="form-control form-control-sm bg-dark text-light border-secondary"
78                     id="tygarun-input-apikey" placeholder="Your own tyga.run API key (optional)">
79              <div class="form-text text-muted">Leave empty to use the built-in connection.</div>
80            </div>
81          </div>
82        </div>
83      </div>
84    `);
85
86    $('#tygarun-enable-btn').on('click', () => this.enable());
87  }
88
89  async enable() {
90    const userKey = ($('#tygarun-input-apikey').val() || '').trim();
91    const $btn = $('#tygarun-enable-btn');
92    $btn.prop('disabled', true).html('<i class="fas fa-spinner fa-spin"></i> Enabling...');
93
94    try {
95      const body = { sandbox: true };
96      if (userKey) body.apiKey = userKey;
97      const result = await api.post(`/api/tygarun/${this.projectId}/connect`, body);
98      if (result?.status === 'ok') {
99        this.status.enabled = true;
100        this.status.sandbox = result.tygarun?.sandbox ?? true;
101        this._toast('Ready-made APIs enabled!', 'success');
102        this.showConnected();
103      } else {
104        throw new Error(result?.message || 'Could not enable');
105      }
106    } catch (err) {
107      $btn.prop('disabled', false).html('<i class="fas fa-bolt"></i> Enable Ready-made APIs');
108      this._toast(`Could not enable: ${err.message}`, 'error');
109    }
110  }
111
112  // ═══════════════════════════════════════════════════════════════════════════
113  // State B: Connected — friendly module grid + AI hints. No code shown.
114  // ═══════════════════════════════════════════════════════════════════════════
115
116  showConnected() {
117    const sandbox = this.status.sandbox !== false;
118    this.$container.html(`
119      <div class="anydb-onboarding">
120        <div class="anydb-onboarding-card" style="max-width: 640px;">
121          <div class="d-flex align-items-center justify-content-between mb-3">
122            <h4 class="mb-0"><i class="fas fa-bolt text-warning"></i> Ready-made APIs</h4>
123            <span class="anydb-status-badge connected"><i class="fas fa-circle"></i> Enabled</span>
124          </div>
125
126          <div class="anydb-info-row mb-3">
127            <span class="anydb-info-label">Mode</span>
128            <span class="anydb-info-value">${sandbox
129              ? '<span class="badge bg-info">Test mode</span> <span class="text-muted small">safe to experiment</span>'
130              : '<span class="badge bg-success">Live</span>'}</span>
131          </div>
132
133          <div class="mb-3">
134            ${sandbox ? `
135              <button class="btn btn-success w-100" id="tygarun-golive-btn">
136                <i class="fas fa-rocket"></i> Go live
137              </button>
138              <div class="form-text text-muted mt-1">${this._goLiveHint()}</div>
139            ` : `
140              <button class="btn btn-outline-secondary btn-sm" id="tygarun-testmode-btn">
141                <i class="fas fa-flask"></i> Back to test mode
142              </button>
143            `}
144          </div>
145
146          <p class="text-muted small mb-2">Your site can now use:</p>
147          <div class="anydb-hint-chips mb-4">
148            ${FRIENDLY_MODULES.map(m =>
149              `<span class="anydb-hint-chip"><i class="fas ${m.icon}"></i> ${m.label}</span>`).join('')}
150          </div>
151
152          <div class="anydb-ai-hints">
153            <p class="text-muted small mb-1">Just ask the AI:</p>
154            <div class="anydb-hint-chips">
155              <span class="anydb-hint-chip">"Add a booking form"</span>
156              <span class="anydb-hint-chip">"Let visitors create an account"</span>
157              <span class="anydb-hint-chip">"Add a contact form that saves leads"</span>
158            </div>
159          </div>
160
161          <div class="mt-4 text-end">
162            <button class="btn btn-sm btn-outline-danger" id="tygarun-disable-btn">
163              <i class="fas fa-unlink"></i> Turn off
164            </button>
165          </div>
166        </div>
167      </div>
168    `);
169
170    $('#tygarun-disable-btn').on('click', () => this.disable());
171    $('#tygarun-golive-btn').on('click', () => this.setLive(true));
172    $('#tygarun-testmode-btn').on('click', () => this.setLive(false));
173  }
174
175  // Plain-language description of what going live turns on, from enabled modules
176  _goLiveHint() {
177    const modules = this.status.modules || [];
178    const labels = FRIENDLY_MODULES.filter(m => modules.includes(m.key)).map(m => m.label.toLowerCase());
179    const what = labels.length ? labels.join(', ') : 'your site\u2019s features';
180    const payments = modules.includes('billing') ? ' Payments will charge real cards.' : '';
181    return `Turns on real ${what} for visitors.${payments}`;
182  }
183
184  async setLive(live) {
185    const msg = live
186      ? `Go live? ${this._goLiveHint()}`
187      : 'Switch back to test mode? Visitors will see demo data again.';
188    if (!confirm(msg)) return;
189    const $btn = $(live ? '#tygarun-golive-btn' : '#tygarun-testmode-btn');
190    $btn.prop('disabled', true).html('<i class="fas fa-spinner fa-spin"></i>');
191    try {
192      const result = await api.post(`/api/tygarun/${this.projectId}/live`, { live });
193      if (result?.status !== 'ok') throw new Error(result?.message || 'Could not switch mode');
194      this.status.sandbox = result.sandbox;
195      this._toast(result.message, 'success');
196      this.showConnected();
197    } catch (err) {
198      this._toast(`Error: ${err.message}`, 'error');
199      this.showConnected();
200    }
201  }
202
203  async disable() {
204    if (!confirm('Turn off ready-made APIs? Booking forms, logins etc. will stop working.')) return;
205    try {
206      await api.post(`/api/tygarun/${this.projectId}/disconnect`);
207      this.status.enabled = false;
208      this._toast('Ready-made APIs turned off', 'success');
209      this.showOnboarding();
210    } catch (err) {
211      this._toast(`Error: ${err.message}`, 'error');
212    }
213  }
214
215  _toast(message, type = 'info') {
216    if (window.showToast) window.showToast(message, type);
217    else console.log(`[tygarun] ${type}: ${message}`);
218  }
219
220  destroy() {
221    this.projectId = null;
222    this.status = null;
223  }
224}
225
226const tygarunPanel = new TygarunPanel();
227export default tygarunPanel;

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.