import React, { useEffect, useMemo, useState } from “react”;
/**
* Small Business Problem Solver – Single‑file React App
* —————————————————-
* • Diagnose top small‑business problems
* • See expert resolutions & step‑by‑step checklists
* • Run a weekly cash‑flow review
* • Build an action plan and export to CSV
* • Handy templates (emails/scripts)
* • Simple calculators: Cash runway & Break‑even
*
* Styling: TailwindCSS utility classes (no external CSS needed)
*/
const PROBLEMS = [ {children}
{
key: “cashflow”,
title: “Cash Flow”,
symptoms: [
“Late customer payments”,
“Seasonal dips in revenue”,
“Tight month‑end balances”,
],
resolutions: [
{
title: “Speed up customer payments”,
steps: [
“Invoice on delivery/completion (no delays).”,
“Enable multiple payment methods (card, bank, wallet).”,
“Offer 2–3% discount for payment within 7 days.”,
“Automate polite reminders at 3, 7, 14 days overdue.”,
],
},
{
title: “Tighten expense control”,
steps: [
“Audit all subscriptions/recurring costs; cancel low‑value items.”,
“Re‑quote utilities, insurance, merchant fees each quarter.”,
“Renegotiate supplier terms (net‑30 → net‑45 where feasible).”,
],
},
{
title: “Build a 3–6 month cash buffer”,
steps: [
“Sweep 5–10% of weekly sales into a ring‑fenced account.”,
“Stagger large purchases; avoid lump‑sum shocks.”,
“Add a revolving line of credit before you need it.”,
],
},
{
title: “Inventory discipline”,
steps: [
“Prioritise fast‑moving/high‑margin SKUs.”,
“Adopt just‑in‑time reorders; reduce dead stock.”,
“Run a monthly stock‑age report and discount slow movers.”,
],
},
{
title: “Forecast & monitor”,
steps: [
“Maintain a 12‑week cash forecast (weekly inflow/outflow).”,
“Review AR/AP ageing weekly; set collection targets.”,
“Hold a 15‑minute cash huddle every Monday.”,
],
},
],
},
{
key: “capital”,
title: “Access to Capital”,
symptoms: [“Loan rejections”, “Insufficient working capital”],
resolutions: [
{
title: “Diversify funding sources”,
steps: [
“Investigate government grants and microfinance.”,
“Prepare a lender‑ready pack (P&L, balance sheet, forecast).”,
“Consider invoice financing, crowdfunding, or angels.”,
],
},
{
title: “Strengthen credit profile”,
steps: [
“Open business credit accounts and pay on time.”,
“Keep utilisation <30% on revolving credit.",
"Dispute any credit report errors in writing.",
],
},
],
},
{
key: "workload",
title: "Overwhelming Workload",
symptoms: ["Founder doing everything", "Burnout", "Bottlenecks"],
resolutions: [
{
title: "Automate repetitive work",
steps: [
"Automate invoicing, reminders, receipts, and bank feeds.",
"Use booking links, canned replies, and help‑desk FAQs.",
"Deploy an AI sales assistant/chatbot for common questions.",
],
},
{
title: "Delegate & outsource",
steps: [
"Document SOPs for fulfilment, support, and marketing.",
"Outsource bookkeeping/ads/creative to specialists.",
"Use project boards (Kanban) for capacity and handovers.",
],
},
],
},
{
key: "customers",
title: "Customer Acquisition & Retention",
symptoms: ["Low lead volume", "High churn", "Weak visibility"],
resolutions: [
{
title: "Consistent low‑cost marketing",
steps: [
"Publish weekly value posts (pain→solution→CTA).",
"Collect & showcase reviews; add case studies.",
"Build an email list; send a bi‑weekly nurture.",
],
},
{
title: "Search & local presence",
steps: [
"Optimise Google Business Profile; get 10+ fresh reviews.",
"Basic SEO: page titles, meta, internal links, fast pages.",
"Create pillar pages + FAQs for core services.",
],
},
{
title: "Loyalty & referrals",
steps: [
"Introduce a simple refer‑a‑friend reward.",
"Upsell/cross‑sell bundles and retainers.",
"Re‑engage past customers quarterly with an offer.",
],
},
],
},
{
key: "talent",
title: "Hiring & Retention",
symptoms: ["Hard to attract talent", "Turnover"],
resolutions: [
{
title: "Compete beyond salary",
steps: [
"Offer flexible hours/remote options where possible.",
"Create a growth plan (training, certifications).",
"Celebrate wins; recognise publicly each week.",
],
},
{
title: "Right‑sized resourcing",
steps: [
"Blend freelancers with core FTEs for spikes.",
"Write crisp role scorecards with outcomes not tasks.",
"Run 30‑60‑90 day onboarding with clear checkpoints.",
],
},
],
},
{
key: "digital",
title: "Technology & Digital Gaps",
symptoms: ["Manual processes", "No CRM", "No analytics"],
resolutions: [
{
title: "Adopt a simple revenue stack",
steps: [
"CRM for pipeline + follow‑ups (e.g., HubSpot Free).",
"Email marketing + automations for nurture.",
"Live chat / AI assistant for lead capture 24/7.",
],
},
{
title: "Data visibility",
steps: [
"Connect accounting to bank feeds for daily reconciliation.",
"Track CAC/LTV, conversion rate, and payback monthly.",
"Build a single KPIs dashboard reviewed weekly.",
],
},
],
},
{
key: "compliance",
title: "Regulatory & Compliance",
symptoms: ["Confusing rules", "Paperwork burden"],
resolutions: [
{
title: "Make compliance lightweight",
steps: [
"Subscribe to an updates feed for your sector.",
"Adopt templated policies and digital signatures.",
"Schedule quarterly mini‑audits with an advisor.",
],
},
],
},
];
const WEEKLY_CHECKS = [
{ id: 1, text: "All invoices sent this week" },
{ id: 2, text: "Overdues chased (3/7/14 days)" },
{ id: 3, text: "AR ageing reviewed; high‑risk flagged" },
{ id: 4, text: "AP due this week scheduled/negotiated" },
{ id: 5, text: "Bank balance & runway updated" },
{ id: 6, text: "5–10% swept to cash buffer" },
{ id: 7, text: "Unexpected expenses reviewed" },
{ id: 8, text: "Top SKUs stocked; slow stock discounted" },
{ id: 9, text: "12‑week forecast updated" },
{ id: 10, text: "Sales vs forecast checked; upsell plan" },
{ id: 11, text: "Debt/credit usage reviewed" },
{ id: 12, text: "Actions assigned; targets for next week" },
];
function classNames(...xs) {
return xs.filter(Boolean).join(" ");
}
function Section({ title, children, className = "" }) {
return (
{title}
);
}
function useLocalState(key, initial) {
const [state, setState] = useState(() => {
try {
const raw = localStorage.getItem(key);
return raw ? JSON.parse(raw) : initial;
} catch {
return initial;
}
});
useEffect(() => {
try {
localStorage.setItem(key, JSON.stringify(state));
} catch {}
}, [key, state]);
return [state, setState];
}
function downloadCSV(filename, rows) {
const esc = (v) => `”${String(v ?? “”).replace(/”/g, ‘””‘)}”`;
const csv = rows.map((r) => r.map(esc).join(“,”)).join(“\n”);
const blob = new Blob([csv], { type: “text/csv;charset=utf-8;” });
const link = document.createElement(“a”);
link.href = URL.createObjectURL(blob);
link.download = filename;
link.click();
}
function copy(text) {
navigator.clipboard.writeText(text);
}
export default function SMBProblemSolverApp() {
const [activeTab, setActiveTab] = useLocalState(“tab”, “diagnose”);
const [selected, setSelected] = useLocalState(“selectedProblems”, [“cashflow”]);
const [checkStates, setCheckStates] = useLocalState(
“weeklyChecks”,
WEEKLY_CHECKS.map((c) => ({ …c, done: false }))
);
const [actionPlan, setActionPlan] = useLocalState(“actionPlan”, []);
const problemsByKey = useMemo(() => Object.fromEntries(PROBLEMS.map((p) => [p.key, p])), []);
const quickWins = useMemo(() => {
const wins = [];
selected.forEach((k) => {
const p = problemsByKey[k];
if (!p) return;
p.resolutions.slice(0, 2).forEach((r) => {
wins.push({
problem: p.title,
resolution: r.title,
tasks: r.steps,
impact: k === “cashflow” ? “High” : “Medium”,
effort: r.steps.length <= 3 ? "Low" : "Medium",
});
});
});
return wins;
}, [selected, problemsByKey]);
const progress = useMemo(() => {
const total = checkStates.length;
const done = checkStates.filter((c) => c.done).length;
return { total, done, pct: total ? Math.round((done / total) * 100) : 0 };
}, [checkStates]);
function toggleProblem(key) {
setSelected((prev) =>
prev.includes(key) ? prev.filter((k) => k !== key) : […prev, key]
);
}
function toggleCheck(id) {
setCheckStates((prev) => prev.map((c) => (c.id === id ? { …c, done: !c.done } : c)));
}
function resetWeek() {
setCheckStates(WEEKLY_CHECKS.map((c) => ({ …c, done: false })));
}
function addToActionPlan(win) {
const rows = win.tasks.map((t) => ({
problem: win.problem,
resolution: win.resolution,
task: t,
owner: “”,
due: “”,
status: “Not started”,
}));
setActionPlan((prev) => […prev, …rows]);
setActiveTab(“plan”);
}
function updatePlan(i, patch) {
setActionPlan((prev) => prev.map((r, idx) => (idx === i ? { …r, …patch } : r)));
}
function exportPlan() {
const header = [“Problem”, “Resolution”, “Task”, “Owner”, “Due”, “Status”];
const rows = [header, …actionPlan.map((r) => [r.problem, r.resolution, r.task, r.owner, r.due, r.status])];
downloadCSV(“SMB_Action_Plan.csv”, rows);
}
return (
{activeTab === “diagnose” && (
<>
))}
))}
>
)}
{activeTab === “resolutions” && (
<>
{selected.map((k) => {
const p = problemsByKey[k];
if (!p) return null;
return (
))}
))}
);
})}
>
)}
{activeTab === “weekly” && (
<>
>
)}
{activeTab === “plan” && (
<>
{actionPlan.length === 0 ? (
No tasks yet. Add quick wins from the Diagnose/Resolutions tabs.
) : (
| Problem | Resolution | Task | Owner | Due | Status |
|---|---|---|---|---|---|
| {row.problem} | {row.resolution} | {row.task} | updatePlan(i, { owner: e.target.value })} className=”w-32 px-2 py-1 rounded border” placeholder=”Name” /> | updatePlan(i, { due: e.target.value })} className=”px-2 py-1 rounded border” /> |
)}
>
)}
{activeTab === “templates” && (
<>
>
)}
{activeTab === “calc” && (
<>
>
)}
);
}
function TemplateCard({ title, body }) {
return (
);
}
function RunwayCalc() {
const [cash, setCash] = useState(20000);
const [monthly, setMonthly] = useState(12000);
const runway = useMemo(() => (monthly > 0 ? (cash / monthly).toFixed(1) : “∞”), [cash, monthly]);
return (
);
}
function BreakEvenCalc() {
const [fixed, setFixed] = useState(8000);
const [price, setPrice] = useState(100);
const [variable, setVariable] = useState(40);
const margin = useMemo(() => Math.max(price – variable, 0), [price, variable]);
const units = useMemo(() => (margin > 0 ? Math.ceil(fixed / margin) : 0), [fixed, margin]);
const revenue = useMemo(() => units * price, [units, price]);
return (
);
}