import { useState, useEffect, useRef } from «react»;
const NICHES = [
{ id: «wb», name: «Маркетплейсы», emoji: «📦», desc: «WB / Ozon карточки товаров», baseCheck: 45000, difficulty: «средне», color: «#FF6B35» },
{ id: «realty», name: «Недвижимость», emoji: «🏠», desc: «Циан / Авито — описания объектов», baseCheck: 55000, difficulty: «высоко», color: «#4ECDC4» },
{ id: «info», name: «Инфобизнес», emoji: «📱», desc: «Telegram-эксперты, контент», baseCheck: 50000, difficulty: «легко», color: «#A8E6CF» },
{ id: «local», name: «Локальный бизнес», emoji: «☕», desc: «Рестораны, салоны, клиники», baseCheck: 35000, difficulty: «легко», color: «#FFD93D» },
{ id: «legal», name: «Юристы / B2B», emoji: «⚖️», desc: «Черновики договоров, документы», baseCheck: 65000, difficulty: «высоко», color: «#C77DFF» },
];
const DECISIONS = {
offer: [
{
id: «offer_result»,
text: «Как позиционируешь услугу клиенту?»,
options: [
{ text: «Продаю «тексты от GPT» и «промпты»», outcome: -1, money: 0, tip: «❌ Рынок платит за результат, не за инструмент. Клиенту всё равно, чем ты копаешь — важен котлован.» },
{ text: «Продаю рост конверсии на 20–30% за 5 дней», outcome: 1, money: 15000, tip: «✅ Правильно! Клиент покупает не ChatGPT, а решение своей боли.» },
{ text: «Предлагаю «современные AI-инструменты»», outcome: 0, money: 5000, tip: «⚠️ Чуть лучше, но всё ещё фокус на технологии. Говори о деньгах клиента.» },
],
},
{
id: «offer_level»,
text: «Клиент спрашивает цену. Что предлагаешь первым?»,
options: [
{ text: «Сразу пакет «Под ключ» за 100 000 ₽», outcome: -1, money: 0, tip: «❌ Без портфолио и доверия — слишком рискованно для клиента. Нет кейсов = нет продажи.» },
{ text: «Тест-драйв за 10 000 ₽ — 3 карточки», outcome: 1, money: 10000, tip: «✅ Снижаешь риск для клиента. Тест → кейс → большой чек.» },
{ text: «Скидку 50% ради первого заказа», outcome: 0, money: 3000, tip: «⚠️ Скидки обесценивают работу. Лучше предложить небольшой тест-драйв.» },
],
},
],
outreach: [
{
id: «cold_message»,
text: «Пишешь первое сообщение потенциальному клиенту. Как?»,
options: [
{ text: ««Привет! Делаю тексты с AI. Интересно?»», outcome: -1, money: 0, tip: «❌ Нет конкретики, нет боли, нет ценности. Конверсия — 0%.» },
{ text: «Персонализирую: называю конкретную проблему его бизнеса», outcome: 1, money: 20000, tip: «✅ Персонализация — ключ. Клиент видит, что ты изучил его ситуацию.» },
{ text: «Отправляю шаблон 100 людям сразу», outcome: -1, money: 0, tip: «❌ Масс-рассылка без персонализации даёт 0% ответов. Трать время на качество.» },
],
},
{
id: «rejection»,
text: «Из 50 сообщений — только 1 ответил. Ты:»,
options: [
{ text: «Бросаю — похоже, ниша не работает», outcome: -2, money: -5000, tip: «❌ 1–2% конверсия — это НОРМА для холодного рынка РФ. Это математика, не провал.» },
{ text: «Продолжаю — это нормальная конверсия, пишу ещё 50», outcome: 2, money: 15000, tip: «✅ Правильный mindset! 1 500 контактов = 1 000 000 ₽. Повторяй цикл.» },
{ text: «Делаю скидку 70% чтобы закрыть хоть кого-то», outcome: -1, money: 2000, tip: «⚠️ Скидки — не стратегия. Работай над персонализацией, а не ценой.» },
],
},
],
pipeline: [
{
id: «tools»,
text: «Midjourney заблокировал доступ. Что делаешь?»,
options: [
{ text: «Паникую — весь бизнес на MJ строился», outcome: -2, money: -10000, tip: «❌ Нельзя строить бизнес на одном инструменте. Рынок AI меняется каждый месяц.» },
{ text: «Переключаюсь на FLUX или Kandinsky — процесс тот же», outcome: 2, money: 20000, tip: «✅ Ценность — в методологии, не в промптах. Инструмент заменяем.» },
{ text: «Возвращаю деньги клиенту», outcome: -1, money: -5000, tip: «⚠️ Преждевременно. Ищи альтернативы перед тем как сдаться.» },
],
},
{
id: «quality»,
text: «AI сгенерировал текст с фактической ошибкой. Ты:»,
options: [
{ text: «Отправляю клиенту как есть — он сам проверит», outcome: -2, money: -15000, tip: «❌ Репутация дороже любого чека. AI галлюцинирует — финальный контроль всегда за тобой.» },
{ text: «Проверяю и правлю перед отправкой», outcome: 1, money: 10000, tip: «✅ Человеческий контроль — обязательный этап конвейера. Это твоя ценность.» },
{ text: «Признаюсь клиенту что это была ошибка AI», outcome: 0, money: 5000, tip: «⚠️ Честность ценится, но лучше не доводить до этого — проверяй всегда.» },
],
},
],
scale: [
{
id: «first_hire»,
text: «Первые 200 000 ₽ в кармане. Кого нанимаешь первым?»,
options: [
{ text: «Никого — всё сделаю сам», outcome: -1, money: 0, tip: «⚠️ Потолок одного человека — 3–4 клиента. Без команды нет масштаба.» },
{ text: «Операционного ассистента (15–30к) — снять рутину», outcome: 2, money: 40000, tip: «✅ Правильно! Освобождаешь время для продаж и стратегии.» },
{ text: «Дорогого разработчика за 150к», outcome: -1, money: -50000, tip: «❌ Слишком рано для сложной автоматизации. Сначала — простые процессы.» },
],
},
{
id: «retainer»,
text: «Клиент доволен результатом. Что предлагаешь дальше?»,
options: [
{ text: «Жду когда сам напишет за следующим заказом», outcome: -1, money: 0, tip: «⚠️ Упускаешь деньги. Активные продажи работают лучше ожидания.» },
{ text: «Предлагаю абонентскую плату 40к/мес за постоянное ведение», outcome: 2, money: 40000, tip: «✅ Retainer — ключ к стабильному доходу. 10 клиентов × 40к = 400к выручки/мес.» },
{ text: «Делаю скидку на следующий разовый заказ», outcome: 0, money: 10000, tip: «⚠️ Разовые заказы нестабильны. Стремись к повторяющемуся доходу.» },
],
},
],
};
const PHASES = [
{ id: «niche», label: «Выбор ниши», month: 0 },
{ id: «offer», label: «Упаковка оффера», month: 1 },
{ id: «outreach», label: «Первые продажи», month: 2 },
{ id: «pipeline», label: «Конвейер», month: 4 },
{ id: «scale», label: «Масштаб», month: 7 },
{ id: «finish», label: «Финиш», month: 12 },
];
function AnimatedCounter({ value, duration = 800 }) {
const [display, setDisplay] = useState(0);
const ref = useRef(null);
useEffect(() => {
const start = display;
const diff = value — start;
const steps = 30;
let step = 0;
clearInterval(ref.current);
ref.current = setInterval(() => {
step++;
setDisplay(Math.round(start + (diff * step) / steps));
if (step >= steps) clearInterval(ref.current);
}, duration / steps);
return () => clearInterval(ref.current);
}, [value]);
return {display.toLocaleString(«ru-RU»)};
}
export default function App() {
const [phase, setPhase] = useState(«intro»);
const [money, setMoney] = useState(0);
const [month, setMonth] = useState(0);
const [score, setScore] = useState(0);
const [niche, setNiche] = useState(null);
const [decisionPhase, setDecisionPhase] = useState(null);
const [decisionIdx, setDecisionIdx] = useState(0);
const [lastTip, setLastTip] = useState(null);
const [showTip, setShowTip] = useState(false);
const [history, setHistory] = useState([]);
const [animDir, setAnimDir] = useState(«in»);
const TARGET = 1000000;
const progress = Math.min((money / TARGET) * 100, 100);
const phaseOrder = [«offer», «outreach», «pipeline», «scale»];
function startGame() {
setPhase(«niche»);
setMoney(0);
setMonth(0);
setScore(0);
setHistory([]);
setDecisionIdx(0);
}
function chooseNiche(n) {
setNiche(n);
setAnimDir(«out»);
setTimeout(() => {
setPhase(«decision»);
setDecisionPhase(«offer»);
setDecisionIdx(0);
setAnimDir(«in»);
}, 300);
}
function handleDecision(option) {
const earned = option.money;
const newMoney = Math.max(0, money + earned);
const newScore = score + option.outcome;
setMoney(newMoney);
setScore(newScore);
setLastTip({ text: option.tip, money: earned, outcome: option.outcome });
setShowTip(true);
setHistory(h => […h, { decision: DECISIONS[decisionPhase][decisionIdx].text, choice: option.text, money: earned }]);
}
function nextDecision() {
setShowTip(false);
const decisions = DECISIONS[decisionPhase];
if (decisionIdx + 1 < decisions.length) { setDecisionIdx(i => i + 1);
} else {
const nextPhaseIdx = phaseOrder.indexOf(decisionPhase) + 1;
if (nextPhaseIdx < phaseOrder.length) { const np = phaseOrder[nextPhaseIdx]; setAnimDir(«out»); setTimeout(() => {
setDecisionPhase(np);
setDecisionIdx(0);
setMonth(m => m + Math.floor(Math.random() * 2) + 2);
setAnimDir(«in»);
}, 300);
} else {
setPhase(«finish»);
}
}
}
const phaseInfo = {
offer: { title: «Глава 3: Упаковка оффера», subtitle: «Продавай результат, а не инструмент», icon: «📦», bg: «#FF6B35» },
outreach: { title: «Глава 5: Первые продажи», subtitle: «Холодные контакты и конверсия 1–2%», icon: «📬», bg: «#4ECDC4» },
pipeline: { title: «Глава 4: AI-конвейер», subtitle: «Ты оператор, а не деталь машины», icon: «⚙️», bg: «#A8E6CF» },
scale: { title: «Глава 6–7: Масштаб», subtitle: «Команда, SOP, Retainer-модель», icon: «🚀», bg: «#C77DFF» },
};
const styles = {
app: {
minHeight: «100vh»,
background: «#0A0A0F»,
fontFamily: «‘Georgia’, serif»,
color: «#E8E0D5»,
display: «flex»,
flexDirection: «column»,
alignItems: «center»,
padding: «20px»,
backgroundImage: «radial-gradient(ellipse at 20% 20%, rgba(255,107,53,0.08) 0%, transparent 50%), radial-gradient(ellipse at 80% 80%, rgba(78,205,196,0.06) 0%, transparent 50%)»,
},
card: {
background: «rgba(255,255,255,0.04)»,
border: «1px solid rgba(255,255,255,0.1)»,
borderRadius: «16px»,
padding: «32px»,
maxWidth: «680px»,
width: «100%»,
backdropFilter: «blur(10px)»,
},
title: {
fontSize: «clamp(22px, 4vw, 32px)»,
fontWeight: «bold»,
letterSpacing: «-0.5px»,
lineHeight: 1.2,
marginBottom: «8px»,
},
subtitle: {
color: «#9A9080»,
fontSize: «14px»,
letterSpacing: «2px»,
textTransform: «uppercase»,
marginBottom: «32px»,
},
progressBar: {
background: «rgba(255,255,255,0.08)»,
borderRadius: «100px»,
height: «8px»,
overflow: «hidden»,
marginBottom: «8px»,
},
progressFill: {
height: «100%»,
background: «linear-gradient(90deg, #FF6B35, #FFD93D)»,
borderRadius: «100px»,
transition: «width 1s cubic-bezier(0.4, 0, 0.2, 1)»,
width: `${progress}%`,
},
moneyDisplay: {
display: «flex»,
justifyContent: «space-between»,
alignItems: «center»,
marginBottom: «24px»,
},
bigMoney: {
fontSize: «clamp(28px, 5vw, 48px)»,
fontWeight: «bold»,
fontFamily: «monospace»,
color: «#FFD93D»,
},
btn: {
padding: «14px 28px»,
borderRadius: «10px»,
border: «none»,
cursor: «pointer»,
fontWeight: «bold»,
fontSize: «15px»,
transition: «all 0.2s»,
fontFamily: «‘Georgia’, serif»,
},
primaryBtn: {
background: «linear-gradient(135deg, #FF6B35, #FF8C5A)»,
color: «#fff»,
boxShadow: «0 4px 20px rgba(255,107,53,0.3)»,
},
optionCard: {
background: «rgba(255,255,255,0.04)»,
border: «1px solid rgba(255,255,255,0.12)»,
borderRadius: «12px»,
padding: «18px 22px»,
marginBottom: «12px»,
cursor: «pointer»,
transition: «all 0.2s»,
textAlign: «left»,
width: «100%»,
color: «#E8E0D5»,
fontFamily: «‘Georgia’, serif»,
fontSize: «15px»,
},
tip: (outcome) => ({
padding: «20px»,
borderRadius: «12px»,
background: outcome > 0 ? «rgba(168,230,207,0.12)» : outcome < 0 ? «rgba(255,80,80,0.1)» : «rgba(255,200,50,0.1)», border: `1px solid ${outcome > 0 ? «rgba(168,230,207,0.3)» : outcome < 0 ? «rgba(255,80,80,0.3)» : «rgba(255,200,50,0.3)»}`,
marginBottom: «20px»,
}),
};
// INTRO
if (phase === «intro») {
return (
Симуляция бизнеса по книге Александра П.
Принимай решения. Зарабатывай. Избегай ловушек.
Цель — 1 000 000 ₽
);
}
// NICHE SELECTION
if (phase === «niche») {
return (
Ищи бизнес, где есть боль и бюджет. Выбери одну нишу для старта.
💡 «Деньги в старых нишах, где процессы неэффективны»
);
}
// DECISION PHASE
if (phase === «decision» && decisionPhase) {
const decisions = DECISIONS[decisionPhase];
const currentDecision = decisions[decisionIdx];
const info = phaseInfo[decisionPhase];
return (
{!showTip ? (
{currentDecision.options.map((opt, i) => (
style={styles.optionCard}
onMouseOver={e => { e.currentTarget.style.background = «rgba(255,255,255,0.09)»; e.currentTarget.style.borderColor = «rgba(255,255,255,0.25)»; }}
onMouseOut={e => { e.currentTarget.style.background = «rgba(255,255,255,0.04)»; e.currentTarget.style.borderColor = «rgba(255,255,255,0.12)»; }}
>
{[«А», «Б», «В»][i]}.
{opt.text}
))}
) : (
{lastTip.text}
{decisionIdx + 1 < decisions.length ? «Следующий выбор →» : «Следующий этап →»}
)}
);
}
// FINISH
if (phase === «finish») {
const reached = money >= TARGET;
const finalScore = score;
const rank = finalScore >= 8 ? «🏆 Предприниматель» : finalScore >= 4 ? «📈 Фрилансер» : «📚 Студент книги»;
const months = month + Math.floor(Math.random() * 2) + 2;
return (
{/* History */}
{history.map((h, i) => (
))}
{/* Key takeaway */}
1 000 000 ₽ = 25 клиентов × 40 000 ₽
Для этого нужно ~1 500 холодных контактов при конверсии 1–2%.
AI — это экскаватор. Ценность — в решении боли клиента.
onMouseOut={e => e.target.style.transform = «scale(1)»}
onClick={startGame}
>
Сыграть ещё раз →
);
}
return null;
}
Сайт «zdesda.ru» работает на WordPress