/* ============================================================
SHLOK — Welcome / Completion / Debug screens
============================================================ */
/* ---------- WELCOME (card) ---------- */
function Welcome({ onStart }) {
return (
Discover Your Business Operating Style
A few quick cards — no forms, no jargon. Just tap through and help us understand
how your business really runs.
swipe or tap · about 3 minutes
);
}
/* ---------- COMPLETION ---------- */
function Complete({ data, onRestart }) {
const SH = window.SHLOK;
const tags = SH.generateTags(data);
const style = SH.styleLabel(data, tags);
const need = SH.biggestNeed(data);
const [analysisResult, setAnalysisResult] = React.useState(null);
function asSentence(value) {
const cleaned = String(value || "").trim();
if (!cleaned) return "";
return /[.!?]$/.test(cleaned) ? cleaned : cleaned + ".";
}
function cleanSignals(value) {
return Array.isArray(value)
? value.map((item) => String(item || "").trim()).filter(Boolean)
: [];
}
const resultStyle = asSentence(
analysisResult && analysisResult.business_style_label
? analysisResult.business_style_label
: style
);
const resultNeed = asSentence(
analysisResult && analysisResult.biggest_need
? analysisResult.biggest_need
: need
);
const resultTags = cleanSignals(
analysisResult && analysisResult.hearing_signals && analysisResult.hearing_signals.length
? analysisResult.hearing_signals
: tags
);
React.useEffect(() => {
let cancelled = false;
function respondentId() {
try {
const key = "shlok_research_respondent_id";
const existing = window.localStorage && window.localStorage.getItem(key);
if (existing) return existing;
const generated = "anon_" + Math.random().toString(36).slice(2) + Date.now().toString(36);
if (window.localStorage) window.localStorage.setItem(key, generated);
return generated;
} catch (_err) {
return undefined;
}
}
const answers = {
role_identity: data.role_identity,
business_type: data.business_type,
business_type_other: data.business_type_other || undefined,
team_size: data.team_size,
current_tools: data.current_tools || [],
top_daily_worries: data.top_daily_worries || [],
messy_areas: data.messy_areas || [],
owner_burden: data.owner_burden || [],
business_feeling_scores: {
clarity: g(data, "clarity"), control: g(data, "control"),
stress: g(data, "stress"), tracking: g(data, "tracking"),
dependence: g(data, "dependence"),
},
most_common_scenario: data.most_common_scenario,
loss_due_to_poor_tracking: data.loss_due_to_poor_tracking || [],
loss_context_optional: data.loss_context_optional || undefined,
desired_outcomes: data.desired_outcomes || [],
trust_factors: data.trust_factors || [],
preferred_landing_message: data.preferred_landing_message,
primary_emotional_need: data.primary_emotional_need,
final_note_type: data.final_note_type || undefined,
final_note_text: data.final_note_text || undefined,
final_voice_note_placeholder: data.final_voice_note_placeholder || undefined,
};
const payload = {
form_key: "shlok_business_operating_style",
config_version: (SH.config && SH.config.version) || "unknown",
anonymous_respondent_id: respondentId(),
answers,
contact_permission: data.contact_permission,
contact_details: {
name: data.name || undefined,
business_name: data.business_name || undefined,
location: data.location || undefined,
contact: data.contact || undefined,
},
generated_tags: tags,
};
/* eslint-disable no-console */
console.log("%c SHLOK research response ", "background:#f3f0ea;color:#070707;font-weight:700;border-radius:4px;padding:2px 6px", payload);
console.log(payload);
if (SH.responseEndpoint) {
fetch(SH.responseEndpoint, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload),
keepalive: true,
}).then((response) => {
if (!response.ok) throw new Error("research response save failed");
return response.json();
}).then((body) => {
const result = body && body.data && body.data.analysis_result;
if (!cancelled && result) setAnalysisResult(result);
}).catch((err) => {
console.warn("SHLOK research response save failed", err);
});
}
return () => {
cancelled = true;
};
}, []);
function g(d, k) {
const s = d.business_feeling_scores || {};
return typeof s[k] === "number" ? s[k] : 5;
}
function share() {
const txt = "I just did Shlok's 3-minute business operating-style scan — worth a look.";
if (navigator.share) navigator.share({ title: "Shlok", text: txt }).catch(() => {});
else {
navigator.clipboard && navigator.clipboard.writeText(txt);
}
}
return (
Thank you. Your answers help shape Shlok.
We’re building Shlok around real business stress, not assumptions.
Your business style looks like
{resultStyle}
Your biggest need
{resultNeed}
{resultTags.length ? (
What we’re hearing
{resultTags.map((t, i) => (
{t}
))}
) : null}
);
}
/* ---------- DEBUG PANEL ---------- */
function DebugPanel({ data, onClose }) {
const SH = window.SHLOK;
const tags = SH.generateTags(data);
const comp = SH.completion(data);
const angle = SH.landingAngle(data, tags);
const answers = Object.entries(data).filter(([k]) => !k.startsWith("_"));
const json = JSON.stringify(
Object.fromEntries(answers.filter(([, v]) => v != null && (!Array.isArray(v) || v.length))),
null, 2
);
return (
Research debug
Completion
{comp.pct}%
{comp.done} of {comp.total} steps answered
Generated tags ({tags.length})
{tags.length ? tags.map((t) => {t})
: None yet}
Likely landing-page angle
{angle}
Selected answers
{json || "{}"}
);
}
Object.assign(window, { Welcome, Complete, DebugPanel });