/* ============================================================ BLUEPRINTSENSES — HOME (Plan overview) Answers "where does my concept stand?" before anything is entered: verdict status, module cards, concept slot, what needs attention, and one clear "Start here". ============================================================ */ /* Mint's example concept — loaded only when the user asks for it */ const EXAMPLE_IDEA = { mode: "form", conceptName: "Nami Ramen", tagline: "Slow-broth ramen for Thonglor nights", usp: "The only 18-hour tonkotsu on the soi, open until 10pm with a ฿199 set for the lunch crowd.", category: "Casual dining", categoryConfirmed: true, cuisine: "Ramen", targetCustomer: ["Office workers", "Expats"], priceBand: "Mid", avgSpend: 280, channelMix: { dineIn: 70, delivery: 20, takeaway: 10 }, format: { seats: 32, sqm: 70, serviceStyle: "Table service" }, locationType: "Street / shophouse", hours: { open: 11, close: 22 }, founder: { experience: "Worked in F&B", capital: 1800000, risk: "", involvement: "Owner-operator" }, step: 1, formStep: 0, }; const EXAMPLE_FIN = { step: 3, revMode: "detailed", detailed: { seats: 32, turns: 1.8, avgCheck: 280, openDays: 26 }, investment: { renovation: 650000, equipment: 450000, furniture: 180000, deposit: 135000, licenses: 30000, management: 60000, inventory: 40000, reserve: 250000 }, space: { shopSqm: 70, kitchenSqm: 18 }, foodPct: 0.32, staff: 110000, rent: 45000, utilities: 22000, marketing: 12000, management: 10000, other: 12000, taxes: 8000, }; function homeStatus(idea, fin, check, live) { const started = check.started || (fin.step || 0) > 0; if (!started) return { key: "none" }; if (check.readiness < 60 || (fin.step || 0) < 3 || live.sales <= 0) return { key: "draft" }; return { key: "final", verdict: live.verdict }; } function ModuleCard({ n, title, sub, status, tone, locked, onClick, time }) { const { t } = useLang(); return ( ); } function HomeModule({ plan, ws, activeId, setActive, setNS, updatePlan, switchConcept, newConcept }) { const { t, lang } = useLang(); const { pro, askUnlock } = usePro(); const idea = plan.idea, fin = plan.financials; const check = computeIdea(idea, t, lang); const live = computeFin(fin, t); const own = computeOwnership(plan.ownership, fin, t); const st = homeStatus(idea, fin, check, live); const [showAll, setShowAll] = React.useState(false); const start = (mode) => { setNS("idea", { mode, step: 0 }); setActive("concept"); }; const loadExample = () => updatePlan((p) => ({ ...p, idea: deepMerge(IDEA_DEFAULTS, EXAMPLE_IDEA), financials: deepMerge(FIN_DEFAULTS, EXAMPLE_FIN) })); /* coaching flags once data exists: Financial's only after the user has opened it */ const finOpened = (fin.step || 0) > 0; const attention = [...(check.started ? check.flags : []), ...(finOpened ? [...coherenceWithNumbers(idea, fin, live, t), ...live.flags] : [])].filter((f) => f.tone !== "green"); const shown = showAll ? attention : attention.slice(0, 3); const statusLabel = st.key === "none" ? t("home.notStarted") : st.key === "draft" ? t("home.draft") : st.verdict.label; const statusTone = st.key === "final" ? st.verdict.tone : st.key === "draft" ? "amber" : "muted"; return ( {/* verdict + slot */}
{t("home.verdict")}
{statusLabel}
{t("home.verdictSub." + st.key, { n: check.readiness })}
{t("home.slot")}
{pro ? "✓ " + t("home.unlocked") : t("home.free")}
{!pro &&
}
{st.key !== "none" && (
)}
{/* start here */} {st.key === "none" && (
{t("home.startHere")}
{t("home.startTitle")}
{t("home.startSub")}
{[["interview", "home.answerQuestions", "home.answerQuestionsSub"], ["form", "home.fillForm", "home.fillFormSub"]].map(([m, l, s], i) => ( ))}
⏱ {t("home.about15")}
)} {/* modules */}
setActive("concept")} status={check.started ? t("home.readyN", { n: check.readiness }) : t("home.start")} tone={check.readiness >= 75 ? "green" : check.started ? "amber" : "muted"} /> setActive("financial")} status={(fin.step || 0) >= 3 && live.sales > 0 ? live.verdict.label : (fin.step || 0) > 0 ? t("home.inProgress") : t("home.start")} tone={(fin.step || 0) >= 3 && live.sales > 0 ? live.verdict.tone : "muted"} /> setActive("ownership")} status={!pro ? t("home.whatItAnswers") : own.complete ? t("home.done") : own.rows.length ? t("home.inProgress") : t("home.start")} tone={own.complete ? "green" : "muted"} /> setActive("outputs")} status={!pro ? t("home.seePreview") : t("home.open")} tone="muted" />
{/* what needs attention */} {attention.length > 0 && (

{t("home.attention")}

{shown.map((f, i) => )}
{attention.length > 3 && }
)} {/* my concepts */}

{t("home.myConcepts")}

{ws.concepts.map((c) => ( ))}
{/* after pre-opening */}
{t("home.next")} {t("home.menuCosting")} — {t("home.menuCostingSub")}
); } Object.assign(window, { HomeModule, EXAMPLE_IDEA, EXAMPLE_FIN });