/* ============================================================
RESTO SUITE — BUSINESS IDEA MODULE (UI)
Depends on suite-idea.jsx (logic) + suite-shared.jsx
============================================================ */
const { useState: useStateIU, useRef: useRefIU } = React;
/* ---------- guided interview ---------- */
function InterviewView({ idea, setIdea, onFinish }) {
const { t, lang } = useLang();
const qi = idea.interview.qIndex;
const done = qi >= INTERVIEW.length;
const q = INTERVIEW[Math.min(qi, INTERVIEW.length - 1)];
const [draft, setDraft] = useStateIU("");
const [lastHeard, setLastHeard] = useStateIU(null);
const check = computeIdea(idea, t, lang);
const goTo = (i) => {
setLastHeard(null);
setDraft(idea.interview.answers[INTERVIEW[i].id] || "");
setIdea({ interview: { ...idea.interview, qIndex: i } });
};
const submit = (skip) => {
let heard = [];
if (!skip && draft.trim()) {
const res = askInterview({ questionId: q.id, answer: draft, idea });
const p = { ...res.patch };
if (p.format) p.format = { ...idea.format, ...p.format };
if (p.founder) p.founder = { ...idea.founder, ...p.founder };
heard = res.heard;
const nextIndex = Math.max(qi + 1, idea.interview.maxIndex || 0);
setIdea({ ...p, interview: { ...idea.interview, qIndex: qi + 1 === INTERVIEW.length ? INTERVIEW.length : (idea.interview.maxIndex >= INTERVIEW.length ? INTERVIEW.length : qi + 1), maxIndex: nextIndex, answers: { ...idea.interview.answers, [q.id]: draft } } });
} else {
setIdea({ interview: { ...idea.interview, qIndex: idea.interview.maxIndex >= INTERVIEW.length ? INTERVIEW.length : qi + 1, maxIndex: Math.max(qi + 1, idea.interview.maxIndex || 0) } });
}
setLastHeard(heard.length ? heard : skip ? null : [[t("idea.notedLabel"), t("idea.noted")]]);
setDraft("");
};
if (done) {
return (
{t("idea.doneTitle")}
{t("idea.doneDesc", { filled: check.filled, total: check.total })}
{/* revisit any answer */}
{t("idea.yourAnswers")}
{INTERVIEW.map((it, i) => (
))}
);
}
return (
{/* progress */}
{qi + 1} / {INTERVIEW.length}
{check.filled}/{check.total} {t("idea.progressFields")}
{lastHeard && (
{lastHeard.map(([k, v], i) => (
✓ {heardLabel(lang, k)}: {v}
))}
)}
{t("q." + q.id + ".q")}
{t("q." + q.id + ".hint")}
{t("idea.interviewTip")}
);
}
/* ---------- form ---------- */
function FormView({ idea, setIdea }) {
const { t, lang } = useLang();
const ol = (v) => optLabel(lang, v);
const mix = idea.channelMix;
const mixSum = mix.dineIn + mix.delivery + mix.takeaway;
const setMix = (k, v) => setIdea({ channelMix: { ...mix, [k]: v } });
const setFormat = (p) => setIdea({ format: { ...idea.format, ...p } });
const setFounder = (p) => setIdea({ founder: { ...idea.founder, ...p } });
const sectionTitle = (txt) => (
{txt}
);
return (
setIdea({ conceptName: v })} placeholder={t("idea.conceptNamePh")} />
setIdea({ tagline: v })} placeholder={t("idea.taglinePh")} />
{sectionTitle(t("idea.secConcept"))}
setIdea({ category: v })} renderLabel={ol} />
setIdea({ cuisine: v })} placeholder={t("idea.cuisinePh")} />
setIdea({ cuisine: v })} renderLabel={ol} />
setFormat({ serviceStyle: v })} renderLabel={ol} />
{sectionTitle(t("idea.secCustomersPrice"))}
setIdea({ targetCustomer: v })} renderLabel={ol} />
setIdea({ priceBand: v })} renderLabel={ol} />
{sectionTitle(t("idea.secChannels"))}
{[["dineIn", t("idea.dineIn")], ["delivery", t("idea.delivery")], ["takeaway", t("idea.takeaway")]].map(([k, label], i) => (
setMix(k, v)} max={100} step={5} suffix="%" />
))}
{t("idea.mustTotal100")}
{mixSum}%
{sectionTitle(t("idea.secFormatLocation"))}
setFormat({ seats: v })} step={2} />
setFormat({ sqm: v })} step={5} suffix="m²" />
setIdea({ locationType: v })} renderLabel={ol} />
setIdea({ competition: v })} renderLabel={ol} />
setIdea({ rentExpectation: v })} />
{sectionTitle(t("idea.secWhyWin"))}
{t("idea.uspTitle")}
{t("idea.uspHint")}
{sectionTitle(t("idea.secAboutYou"))}
setFounder({ experience: v })} renderLabel={ol} />
setFounder({ capital: v })} />
setFounder({ involvement: v })} renderLabel={ol} />
);
}
/* ---------- brief / results ---------- */
function BriefRow({ label, value, tag }) {
return (
{label}
{value}{tag && {tag}}
);
}
function BriefView({ idea, setIdea, goFinancials }) {
const { t, lang } = useLang();
const ol = (v) => optLabel(lang, v);
const c = computeIdea(idea, t, lang);
const v = c.verdict;
const dash = (s) => (s && String(s).trim() ? s : "—");
const mix = idea.channelMix;
return (
{/* verdict */}
{t("idea.conceptVerdict")}
{v.label}
{v.tone === "green" ? t("idea.briefVerdictGreen") :
v.tone === "red" ? t("idea.briefVerdictRed") :
t("idea.briefVerdictAmber")}
{t("idea.conceptReadiness")}
{c.readiness}/100
{t("idea.fieldsCoherence", { filled: c.filled, total: c.total })}
{/* brief card */}
{dash(idea.conceptName) === "—" ? t("idea.conceptBriefFallback") : idea.conceptName}
{idea.tagline &&
“{idea.tagline}”
}
{c.mixSum === 100 ? "✓" : "≠100"}} />
{idea.usp && (
{t("idea.whyYouWin")}
{idea.usp}
)}
{c.fitout && (
{t("idea.roughFitout")}{fmtBaht(c.fitout.value)} ({c.fitout.basis})
)}
{/* reality check — concept + light market/location gut-check */}
{(c.flags.length > 0 || c.rentBench) && (
{t("idea.realityCheck")}
{t("idea.realityCheckDesc")}
{c.flags.length > 0
? c.flags.map((f, i) => )
: }
{c.rentBench && (
{t("idea.roughSalesFormat")}{fmtBaht(c.rentBench.salesEst)}/mo ({c.rentBench.basis}){t("idea.healthyRentUpTo")}{fmtBaht(c.rentBench.healthyRent)}
)}
{c.riskiest && (
{t("idea.testFirst")}
{c.riskiest.text}
)}
)}
{t("idea.prefillNote")}
);
}
/* ---------- module wrapper ---------- */
function IdeaModule({ idea, setIdea, goFinancials }) {
const { t } = useLang();
const onBrief = idea.step === 1;
return (
{!onBrief ? (
{idea.mode === "form" ? (
) : (
)}
{idea.mode === "interview"
? setIdea({ step: 1 })} />
:
}
) : (
)}
);
}
Object.assign(window, { IdeaModule });