Files
portal/app/resources/js/components/projects/ProjectLimitOverloadDialog.vue
T
Дмитрий 9ff19f3cc3 @
feat(bot): всеобъемлющая инструкция (36 статей) + 31 узкая экскурсия, которая открывает окна

Живой урок владельца 12.07.2026: «дубли чистятся в 2-х местах, а бот выдумал третье»,
«стыдно такого бота показывать», «видео показываем полное, а я спрашиваю про одно —
надо резать», «надо не только кнопку показывать, а и что за ней».

База знаний: 17 обзорных статей → 36 узких по темам. Портал обойдён целиком
(5 агентов): все экраны, окна, подсказки «(?)», тексты ошибок, внутренние правила.
Новое, чего бот не знал: дубли в ДВУХ местах (Поле и Предложения) + окно «источник
уже есть»; правило 18:00; почему приходит меньше лимита; оплата по счёту и акты;
списания; безопасность и 2FA; отчёты; массовые действия; регистрация.

Экскурсии: 15 → 31, каждая на свою тему (3–7 шагов). Раннер GuidedTour научен
шагу `open` — сам открывает окно/вкладку и подсвечивает то, что ВНУТРИ
(окно дублей, форму подбора, диалог пополнения, панель тарифов, карточку сделки).
99 новых якорей data-tour расставлено по всему порталу (4 агента).

Поиск: веса в tsvector (заголовок A / синонимы B / текст C) — иначе на «чистка
дублей» первой всплывала статья «Списания» из-за мимоходного упоминания «поля».

Тесты: Pest бот 39/39, Vitest 1222/1222. Новые сторожа: у каждой статьи есть
экскурсия; экскурсия не короче 3 и не длиннее 7 шагов; каждая цель экскурсии
реально существует в разметке; экскурсии про действия обязаны открывать окно.
Живая проверка в браузере: экскурсия про дубли сама открыла окно объединения
и перешла на второе место чистки.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@
2026-07-12 12:56:22 +03:00

89 lines
3.7 KiB
Vue

<script setup lang="ts">
/**
* Диалог «Проект не запущен» (Billing v2 Spec C §6.2, Task 12).
*
* Открывается, когда POST/PATCH /api/projects вернул 409 `balance_insufficient`.
* Сообщает: «Проект создан, но НЕ запущен — не хватает баланса».
* Предлагает три исхода:
* - «Пополнить баланс» (data-test="topup") → закрыть + перейти в /billing;
* - «Уменьшить объём» (data-test="reduce") → set-zero (родитель ставит daily_limit_target=0);
* - «Понятно» (data-test="close") → закрыть без действий.
*
* Backward compat: события save-blocked и set-zero сохранены.
*/
export interface OverloadPayload {
current_balance_rub: string;
current_capacity_leads: number;
would_be_required_leads: number;
deficit_leads: number;
/** Task 12: сумма пополнения в рублях, рассчитанная бэкендом */
topup_rub?: string;
}
import { useRouter } from 'vue-router';
defineProps<{
modelValue: boolean;
payload: OverloadPayload | null;
}>();
const emit = defineEmits<{
'update:modelValue': [value: boolean];
'save-blocked': [];
'set-zero': [];
}>();
// Косяк 06: «Пополнить» прямо из окна — закрываем и ведём в биллинг.
const router = useRouter();
function goTopup(): void {
emit('update:modelValue', false);
router?.push('/billing');
}
</script>
<template>
<v-dialog :model-value="modelValue" max-width="520" @update:model-value="$emit('update:modelValue', $event)">
<v-card v-if="payload" data-testid="overload-dialog" data-tour="overload-dialog">
<v-card-title>Проект не запущен</v-card-title>
<v-card-text>
<p>
Проект создан, но <strong>не запущен</strong> на балансе недостаточно средств для запуска.
</p>
<p class="text-medium-emphasis mt-2">
Чтобы запустить пополните примерно на
<strong>{{ payload.topup_rub ?? payload.deficit_leads }} </strong>
или уменьшите объём.
</p>
<p class="text-caption text-medium-emphasis mt-1">
Текущий баланс: {{ payload.current_balance_rub }}
({{ payload.current_capacity_leads }} лидов), нужно {{ payload.would_be_required_leads }} лидов.
</p>
</v-card-text>
<v-card-actions class="flex-wrap justify-end ga-2">
<v-btn variant="text" data-test="close" data-testid="overload-cancel" @click="$emit('update:modelValue', false)">
Понятно
</v-btn>
<v-btn
variant="text"
data-test="reduce"
data-testid="overload-set-zero"
data-tour="overload-reduce"
@click="$emit('set-zero')"
>
Уменьшить объём
</v-btn>
<v-btn
color="primary"
variant="flat"
data-test="topup"
data-testid="overload-topup"
data-tour="overload-topup"
@click="goTopup"
>
Пополнить баланс
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>