import { useState } from "react";
const DEFAULTS = {
goal: 5000,
priceMain: 1000,
priceConsult: 100,
days: 30,
c1: 5,
c2: 50,
c3: 40,
c4: 50,
c5: 30,
};
const ceil1 = (n) => Math.ceil(n * 10) / 10;
const fmtN = (n) => {
const v = ceil1(n);
return v >= 1000 ? v.toLocaleString("ru-RU") : String(v);
};
function Field({ label, value, onChange, min, max, step = 1, suffix, hint }) {
return (
onChange(Number(e.target.value))}
style={{ width: "100%", accentColor: "#c8a96e", cursor: "pointer" }}
/>
{hint &&
{hint}
}
);
}
function FunnelStep({ num, label, value, sub, isGoal, isStart }) {
return (
шаг {num} — {label}
{value}
{sub &&
{sub}
}
);
}
function UpArrow({ pct, label }) {
return (
);
}
function DayItem({ value, label, sub, highlight, green }) {
return (
{value}
{label}
{sub &&
{sub}
}
);
}
export default function App() {
const [goal, setGoal] = useState(DEFAULTS.goal);
const [priceMain, setPriceMain] = useState(DEFAULTS.priceMain);
const [priceConsult, setPriceConsult] = useState(DEFAULTS.priceConsult);
const [days, setDays] = useState(DEFAULTS.days);
const [c1, setC1] = useState(DEFAULTS.c1);
const [c2, setC2] = useState(DEFAULTS.c2);
const [c3, setC3] = useState(DEFAULTS.c3);
const [c4, setC4] = useState(DEFAULTS.c4);
const [c5, setC5] = useState(DEFAULTS.c5);
const mainSales = priceMain > 0 ? goal / priceMain : 0;
const consults = c5 > 0 ? (mainSales / c5) * 100 : 0;
const wantMore = c4 > 0 ? (consults / c4) * 100 : 0;
const breakdowns = c3 > 0 ? (wantMore / c3) * 100 : 0;
const replies = c2 > 0 ? (breakdowns / c2) * 100 : 0;
const touches = c1 > 0 ? (replies / c1) * 100 : 0;
const touchesPerDay = days > 0 ? touches / days : 0;
const consultRevenue = consults * priceConsult;
const weeksTotal = days / 7;
const card = { background: "#1a1a1a", border: "1px solid #2a2a2a", borderRadius: 16, padding: 24 };
const cardTitle = { fontSize: 11, letterSpacing: "0.15em", textTransform: "uppercase", color: "#555", marginBottom: 18 };
return (
Обратное планирование
От цели — к касаниям
{/* Цель */}
Цель и продукт
Нужно продаж основного
{fmtN(mainSales)}
{fmtN(mainSales)} × {priceMain}$ = {fmtN(mainSales * priceMain)}$
{priceConsult > 0 && (
+ {fmtN(consults)} консульт. × {priceConsult}$ = {fmtN(consultRevenue)}$ доп.
)}
{/* Конверсии */}
Конверсии воронки
{/* Воронка снизу вверх */}
Воронка — от действий к цели ↑
{/* План */}
Что делать — в день и в неделю
В день
В неделю
Итог за {days} дней
{fmtN(mainSales * priceMain)}$ (основной) + {fmtN(consultRevenue)}$ (консультации) = {fmtN(mainSales * priceMain + consultRevenue)}$
${goal.toLocaleString("ru-RU")} цель
);
}