simbiot-harness/sites/shkor-com/v2/start/status/index.html

108 lines
8.9 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#050506">
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'><rect width='64' height='64' rx='14' fill='%23050506'/><circle cx='32' cy='32' r='20' fill='none' stroke='%23c6ff4d' stroke-width='3' stroke-dasharray='4 6'/><circle cx='32' cy='32' r='7' fill='%23c6ff4d'/></svg>">
<title>Your workspace — Shkor Labs</title>
<meta name="robots" content="noindex">
<meta name="referrer" content="no-referrer">
<link rel="stylesheet" href="../../styles.css">
<link rel="stylesheet" href="../../apply/apply.css">
<style>.creds{margin-top:16px;padding:16px 18px;border-radius:12px;background:rgba(255,255,255,.035);box-shadow:inset 0 0 0 1px var(--line-2);font:14px/1.9 var(--mono);color:var(--fg-2)}.creds b{display:inline;font:inherit;color:var(--fg)}</style>
</head>
<body>
<header class="nav">
<div class="wrap nav-in">
<a class="brand" href="../../" aria-label="Shkor Labs — home">
<svg viewBox="0 0 32 32" aria-hidden="true"><circle cx="16" cy="16" r="12" fill="none" stroke="currentColor" stroke-width="2" stroke-dasharray="3 4"/><circle cx="16" cy="16" r="4.5" fill="currentColor"/></svg>
<span>Shkor<b>Labs</b></span>
</a>
</div>
</header>
<main id="main" class="apply">
<div class="grid-bg" aria-hidden="true"></div>
<div class="wrap status-in">
<p class="kicker">Autopilot · $99/month</p>
<h1 id="title">Loading…</h1>
<p class="lead" id="sub"></p>
<ol class="timeline" id="tl" aria-live="polite"></ol>
<div class="bookmark">
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M6 3h12v18l-6-4-6 4V3Z" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linejoin="round"/></svg>
<p><b>Bookmark this page.</b> It's your private link: come back any time to finish a step or find your workspace login. Don't share it.</p>
</div>
</div>
</main>
<script>
(function () {
var q = new URLSearchParams(location.search), t = q.get('t') || '';
try { if (!t) t = localStorage.getItem('shkor_ap') || ''; } catch (x) {}
var tl = document.getElementById('tl'), title = document.getElementById('title'), sub = document.getElementById('sub'), busy = false;
var ARROW = '<svg viewBox="0 0 20 20" aria-hidden="true"><path d="M4 10h11M11 5l5 5-5 5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>';
var KYC = { 'Not Started': 'Not started', 'In Progress': 'In progress', 'In Review': 'Under review', 'Approved': 'Verified', 'Declined': 'Not approved', 'Abandoned': 'Abandoned', 'Expired': 'Link expired' };
function esc(s) { return String(s || '').replace(/[&<>"]/g, function (c) { return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' }[c]; }); }
function item(state, head, body, action) { return '<li class="tl ' + state + '"><span class="tl-dot" aria-hidden="true"></span><div><b>' + head + '</b><p>' + body + '</p>' + (action || '') + '</div></li>'; }
function pill(state, text) { return ' <span class="pill ' + state + '">' + esc(text) + '</span>'; }
function render(d) {
var first = (d.name || '').split(' ')[0], s = d.stage, h = '';
var kycState = s === 'kyc' ? 'wip' : s === 'declined' ? 'bad' : 'ok';
h += item(kycState, 'Identity verification' + pill(kycState, KYC[d.kyc] || d.kyc),
s === 'declined' ? 'We couldn’t verify your identity, so we can’t open a workspace. If you think this is a mistake, write to hello@shkor.com.' : 'ID document and a selfie, handled by Didit. About 2 minutes.',
d.kyc_url ? '<a class="btn" href="' + esc(d.kyc_url) + '"><span>' + (d.kyc === 'Not Started' ? 'Verify now' : 'Continue verification') + '</span>' + ARROW + '</a>' : '');
var payState = s === 'pay' ? 'wip' : (s === 'deploying' || s === 'ready') ? 'ok' : 'todo';
var cancelled = q.get('cancelled') && s === 'pay';
h += item(payState, 'Payment · $99/month' + (payState === 'ok' ? pill('ok', 'Paid') : ''),
s === 'pay' ? (q.get('paid') ? 'Confirming your payment…' : cancelled ? 'Payment was cancelled — you can try again.' : 'Secure card payment by Stripe. Monthly, cancel any time.') : payState === 'ok' ? 'Subscription active. Receipts go to ' + esc(d.email) + '.' : 'Opens after verification.',
s === 'pay' && !q.get('paid') ? '<button class="btn" id="pay" type="button"><span>Pay $99 and deploy</span>' + ARROW + '</button><p class="form-err" id="payerr"></p>' : '');
var depState = s === 'deploying' ? 'wip' : s === 'ready' ? 'ok' : 'todo';
var dep = 'Your own server, web panel with Claude Code and OpenCode, and a Simbiot agent.';
var act = '';
if (s === 'deploying') dep = 'Creating your server and installing the tools. This usually takes 15–40 minutes — this page updates by itself, and you can close it.';
if (s === 'ready' && d.panel) {
dep = 'Your workspace is live. Sign in to the panel, then pick Claude Code (sign in with your own Claude account) or OpenCode (works right away). Both are already connected to the lab MCP — git, payments, your project, your subdomains.';
act = '<div class="creds">Panel: <b><a href="' + esc(d.panel.url) + '" target="_blank" rel="noopener">' + esc(d.panel.url) + '</a></b><br>Login: <b>' + esc(d.panel.user) + '</b><br>Password: <b>' + esc(d.panel.password) + '</b></div>'
+ '<a class="btn" href="' + esc(d.panel.url) + '" target="_blank" rel="noopener"><span>Open my workspace</span>' + ARROW + '</a>'
+ ' <a class="btn btn-ghost" href="/api/account/session?t=' + encodeURIComponent(t) + '"><span>Open my account</span>' + ARROW + '</a>';
}
h += item(depState, 'Your workspace' + (s === 'ready' ? pill('ok', 'Live') : s === 'deploying' ? pill('wip', 'Deploying') : ''), dep, act);
if (s === 'ready' && d.earnings) {
var e = d.earnings, money = function (v) { return '$' + Number(v || 0).toFixed(2); }, rows = '';
(e.projects || []).forEach(function (p) {
rows += '<br>' + esc(p.name) + ': <b>' + money(p.net) + '</b> <span style="opacity:.6">(' + money(p.gross) + ' sales − ' + money(p.studio_share) + ' studio ' + esc(p.studio_pct || '') + ')</span>';
});
h += item(e.gross > 0 ? 'ok' : 'todo', 'Your earnings' + pill(e.gross > 0 ? 'ok' : 'wip', money(e.available) + ' available'),
e.projects && e.projects.length ? 'Sales through the cooperative’s payments. The studio’s share is withheld automatically at each payment.'
: 'Create your project and products through the lab MCP (project_create, product_create) — every sale shows up here, with the studio’s share already withheld.',
'<div class="creds">Sales: <b>' + money(e.gross) + '</b> · Studio share: <b>' + money(e.studio_share) + '</b><br>Yours: <b>' + money(e.net) + '</b> · Paid out: <b>' + money(e.paid_out) + '</b>' + rows + '</div>'
+ '<p style="margin-top:10px">Withdrawals are coming soon — the balance is already tracked.</p>');
}
tl.innerHTML = h;
title.textContent = s === 'ready' ? 'Welcome aboard, ' + first + '.' : s === 'deploying' ? 'Deploying your workspace…' : s === 'declined' ? 'Verification not approved' : s === 'pay' ? 'Verified. One step left.' : 'Hi ' + first + ', let’s verify you.';
sub.textContent = s === 'kyc' ? 'Payment opens as soon as your identity is verified. If you’ve just finished, the result usually arrives within a minute.' : '';
var pay = document.getElementById('pay');
if (pay) pay.addEventListener('click', function () {
pay.disabled = true; pay.querySelector('span').textContent = 'Opening Stripe…';
fetch('/api/autopilot/checkout', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ t: t }) })
.then(function (r) { return r.json().then(function (j) { return { ok: r.ok, j: j }; }); })
.then(function (res) { if (!res.ok || !res.j.url) throw new Error(res.j.error || 'Couldn’t open the payment page.'); location.href = res.j.url; })
.catch(function (x) { document.getElementById('payerr').textContent = x.message; pay.disabled = false; pay.querySelector('span').textContent = 'Pay $99 and deploy'; });
});
}
function load() {
if (busy) return; busy = true;
fetch('/api/autopilot/status?t=' + encodeURIComponent(t), { cache: 'no-store' })
.then(function (r) { return r.json().then(function (j) { return { ok: r.ok, j: j }; }); })
.then(function (res) {
if (!res.ok) { title.textContent = 'Order not found'; sub.innerHTML = esc(res.j.error || 'Check your link.') + ' <a href="../">Start again</a>.'; return; }
render(res.j);
})
.catch(function () { title.textContent = 'Can’t load right now'; sub.textContent = 'Please refresh in a moment.'; })
.then(function () { busy = false; });
}
load();
setInterval(function () { if (!document.hidden && !document.getElementById('pay')) load(); }, 15000);
})();
</script>
</body>
</html>