143 lines
6.1 KiB
HTML
143 lines
6.1 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Review the script — PayToLaugh</title>
|
|
<meta name="description" content="Read the script, ask for changes, approve it when it sounds right.">
|
|
<link rel="stylesheet" href="/assets/app.css">
|
|
<style>
|
|
.seg{border:1px solid var(--line);border-radius:12px;padding:18px 20px;margin-bottom:14px;background:#0f1117}
|
|
.seg .top{display:flex;justify-content:space-between;gap:14px;align-items:baseline;margin-bottom:10px;flex-wrap:wrap}
|
|
.seg .n{font:600 11px/1 var(--mono);letter-spacing:.12em;text-transform:uppercase;color:var(--accent)}
|
|
.seg .cam{font:11px/1 var(--mono);letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
|
|
.seg .line{font-size:18px;line-height:1.5;margin:0}
|
|
.seg .foot{font:11.5px/1 var(--mono);color:var(--muted);margin-top:10px}
|
|
.warn{background:#2a2112;border:1px solid #5b4520;color:#f0d9a7;border-radius:10px;padding:13px 16px;margin-bottom:16px;font-size:14px}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="wrap">
|
|
|
|
<header class="page">
|
|
<h1 id="title">The script</h1>
|
|
<p id="sub">Read it through. If it does not sound like your pet, say so and we will rewrite it.</p>
|
|
</header>
|
|
|
|
<section>
|
|
<div class="msg" id="msg"></div>
|
|
<div id="out"><p style="color:var(--muted)">Loading…</p></div>
|
|
</section>
|
|
|
|
<footer>PayToLaugh · your pet has opinions.</footer>
|
|
</div>
|
|
|
|
<script src="/assets/app.js"></script>
|
|
<script>
|
|
navBar("videos");
|
|
var email = requireSession();
|
|
var pid = new URLSearchParams(location.search).get("id");
|
|
var poll = null;
|
|
|
|
if (!pid) {
|
|
document.getElementById("out").innerHTML =
|
|
'<div class="empty">No script chosen. <a href="/videos.html">Back to my videos</a>.</div>';
|
|
}
|
|
|
|
function segHtml(s) {
|
|
return '<div class="seg">'
|
|
+ '<div class="top"><span class="n">Shot ' + (s.index || "") + '</span>'
|
|
+ '<span class="cam">' + esc(s.camera || "") + '</span></div>'
|
|
+ '<p class="line">' + esc(s.line || "") + '</p>'
|
|
+ '<div class="foot">' + (s.word_count || 0) + ' words · about ' + (s.est_seconds || 0) + 's'
|
|
+ (s.note ? ' · ' + esc(s.note) : '') + '</div>'
|
|
+ '</div>';
|
|
}
|
|
|
|
function render(r) {
|
|
var p = r.project, s = r.script, out = document.getElementById("out");
|
|
var used = parseInt(p.revisions || 0, 10);
|
|
var left = (r.max_revisions || 3) - used;
|
|
|
|
if (p.status === "scripting") {
|
|
out.innerHTML = '<div class="card"><p style="margin:0;color:var(--muted)">'
|
|
+ 'Writing the script now. This usually takes under a minute — the page will update itself.</p></div>';
|
|
if (!poll) poll = setInterval(load, 5000);
|
|
return;
|
|
}
|
|
if (poll) { clearInterval(poll); poll = null; }
|
|
|
|
if (p.status === "script_failed") {
|
|
out.innerHTML = '<div class="card"><p style="margin:0 0 16px">The writer could not finish this one.</p>'
|
|
+ '<a class="btn" style="display:inline-block;text-decoration:none" href="/create.html">Start again</a></div>';
|
|
return;
|
|
}
|
|
if (!s || !s.segments) {
|
|
out.innerHTML = '<div class="empty">No script on this project yet.</div>';
|
|
return;
|
|
}
|
|
|
|
document.getElementById("title").textContent = s.title || "The script";
|
|
document.getElementById("sub").textContent = s.premise || "";
|
|
|
|
var approved = p.status === "approved";
|
|
var warn = (s._warnings && s._warnings.length)
|
|
? '<div class="warn"><strong>Worth a look:</strong> ' + s._warnings.map(esc).join(" · ") + '</div>'
|
|
: "";
|
|
|
|
var head = '<div class="quote" style="margin-bottom:22px">'
|
|
+ '<div><div class="big">$' + Number(p.price_usd || 0).toFixed(2) + '</div>'
|
|
+ '<div class="sub">' + ((p.segments || 4) * 8) + ' seconds · ' + (p.segments || 4) + ' shots</div></div>'
|
|
+ '<div class="sub">' + (approved ? "Approved" : left + " rewrite" + (left === 1 ? "" : "s") + " left") + '</div>'
|
|
+ '</div>';
|
|
|
|
var actions = approved
|
|
? '<div class="card"><p style="margin:0"><strong>Approved.</strong> Filming is switched on once payment is live. '
|
|
+ 'Nothing has been charged.</p></div>'
|
|
: '<div class="card">'
|
|
+ '<h2 class="sec">Not quite right?</h2>'
|
|
+ '<div class="field">'
|
|
+ '<label for="fb">What would you change</label>'
|
|
+ '<span class="hint">Be specific. “Too polite, he would be smugger about it” beats “make it funnier”.</span>'
|
|
+ '<textarea id="fb" ' + (left <= 0 ? "disabled" : "") + ' placeholder="The third shot is too wordy, and he would never admit the robot is good at anything."></textarea>'
|
|
+ '</div>'
|
|
+ '<button class="btn ghost" id="revise" ' + (left <= 0 ? "disabled" : "") + '>'
|
|
+ (left > 0 ? "Rewrite it" : "No rewrites left") + '</button>'
|
|
+ '<button class="btn" id="approve" style="margin-left:10px">Approve this script</button>'
|
|
+ '</div>';
|
|
|
|
out.innerHTML = head + warn + s.segments.map(segHtml).join("") + actions;
|
|
|
|
var rv = document.getElementById("revise");
|
|
if (rv) rv.onclick = async function () {
|
|
hideMsg("msg");
|
|
var fb = document.getElementById("fb").value.trim();
|
|
if (fb.length < 5) { showMsg("msg", "Tell us what you would like changed."); return; }
|
|
rv.disabled = true; rv.textContent = "Sending…";
|
|
var res = await api("revise_script", { email: email, project_id: pid, feedback: fb });
|
|
if (!res.ok) { rv.disabled = false; rv.textContent = "Rewrite it"; showMsg("msg", res.error || "That did not go through."); return; }
|
|
showMsg("msg", "Rewriting now…", "ok");
|
|
load();
|
|
};
|
|
|
|
var ap = document.getElementById("approve");
|
|
if (ap) ap.onclick = async function () {
|
|
hideMsg("msg");
|
|
ap.disabled = true; ap.textContent = "Approving…";
|
|
var res = await api("approve_script", { email: email, project_id: pid });
|
|
if (!res.ok) { ap.disabled = false; ap.textContent = "Approve this script"; showMsg("msg", res.error || "That did not go through."); return; }
|
|
showMsg("msg", res.status_text || "Approved.", "ok");
|
|
load();
|
|
};
|
|
}
|
|
|
|
async function load() {
|
|
if (!pid || !email) return;
|
|
var r = await api("get_project", { email: email, project_id: pid });
|
|
if (!r.ok) { showMsg("msg", r.error || "Could not load that script."); return; }
|
|
render(r);
|
|
}
|
|
load();
|
|
</script>
|
|
</body>
|
|
</html>
|