// Voice Profile client. Fields come from the server so the form and the stored
// shape can never drift apart.
(function () {
'use strict';
var $ = function (id) { return document.getElementById(id); };
var state = { fields: [], profile: {} };
function gate(msg) {
$('vGate').style.display = 'block';
$('vGate').innerHTML = msg;
$('vCard').style.display = 'none';
$('vState').style.display = 'none';
}
function renderFields() {
var host = $('vFields');
host.innerHTML = '';
state.fields.forEach(function (f) {
var wrap = document.createElement('div');
wrap.className = 'v-f';
var lab = document.createElement('label');
lab.setAttribute('for', 'vf_' + f.key);
lab.textContent = f.label;
wrap.appendChild(lab);
var hint = document.createElement('div');
hint.className = 'hint';
hint.textContent = f.hint;
wrap.appendChild(hint);
var ta = document.createElement('textarea');
ta.id = 'vf_' + f.key;
ta.rows = f.max > 400 ? 6 : 2;
ta.maxLength = f.max;
ta.value = state.profile[f.key] || '';
wrap.appendChild(ta);
var count = document.createElement('div');
count.className = 'v-count';
var upd = function () { count.textContent = ta.value.length + ' / ' + f.max; };
ta.addEventListener('input', upd);
upd();
wrap.appendChild(count);
host.appendChild(wrap);
});
}
function showState(p) {
var el = $('vState');
el.style.display = 'block';
var filled = state.fields.filter(function (f) {
return String((p || {})[f.key] || '').trim().length > 2;
}).length;
if (p && p.complete) {
el.className = 'v-state';
el.innerHTML = '✅ Your voice profile is on. The Copy Engine and Email Engine are both writing with it — ' +
filled + ' of ' + state.fields.length + ' answers filled in.';
} else {
el.className = 'v-state off';
el.innerHTML = 'Not active yet. Fill in at least a couple of these — especially the writing sample, ' +
'which teaches it more than the rest combined — and everything the Suite writes will start sounding like you.';
}
}
function collect() {
var out = {};
state.fields.forEach(function (f) {
var el = $('vf_' + f.key);
out[f.key] = el ? el.value : '';
});
return out;
}
async function save() {
$('vErr').style.display = 'none';
$('vOk').style.display = 'none';
$('vSave').disabled = true;
var prev = $('vSave').textContent;
$('vSave').textContent = 'Saving…';
try {
var r = await fetch('/api/public/suite-voice', {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(collect())
});
var d = await r.json();
if (!r.ok) {
$('vErr').textContent = d.error || 'That did not save — try again.';
$('vErr').style.display = 'block';
} else {
state.profile = d.profile;
showState(d.profile);
$('vOk').innerHTML = d.profile.complete
? '✅ Saved. Head to the Copy Engine and write something — it should sound noticeably more like you.'
: '✅ Saved. Add a bit more (the writing sample especially) and it will switch on.';
$('vOk').style.display = 'block';
}
} catch (e) {
$('vErr').textContent = 'Connection hiccup — try again.';
$('vErr').style.display = 'block';
}
$('vSave').disabled = false;
$('vSave').textContent = prev;
}
async function clear() {
if (!window.confirm('Clear your voice profile? The Suite will go back to writing in the team voice.')) return;
try {
var r = await fetch('/api/public/suite-voice', {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ clear: true })
});
var d = await r.json();
if (r.ok) {
state.profile = d.profile;
renderFields();
showState(d.profile);
$('vOk').innerHTML = 'Cleared. Back to the team voice.';
$('vOk').style.display = 'block';
}
} catch (e) {}
}
async function boot() {
try {
var r = await fetch('/api/public/suite-voice');
if (r.status === 401) { gate('You’re not signed in yet. Open the Suite and connect the wallet that holds your position, then come back.'); return; }
if (r.status === 403) {
var g = await r.json();
gate((g.error || 'Not open for this position yet.') + ' See your Suite.');
return;
}
if (!r.ok) return;
var d = await r.json();
state.fields = d.fields || [];
state.profile = d.profile || {};
renderFields();
showState(state.profile);
} catch (e) {}
}
document.addEventListener('DOMContentLoaded', function () {
boot();
$('vSave').addEventListener('click', save);
$('vClear').addEventListener('click', clear);
});
})();