diff --git a/app/resources/js/components/advertising/CampaignWizard.vue b/app/resources/js/components/advertising/CampaignWizard.vue index 9b938cc3..4d5ec700 100644 --- a/app/resources/js/components/advertising/CampaignWizard.vue +++ b/app/resources/js/components/advertising/CampaignWizard.vue @@ -21,6 +21,7 @@ import { reactive, ref, computed, watch, onMounted } from 'vue'; import { createCampaign, + patchCampaign, fetchAudienceSize, type CampaignCreate, type AudienceSize, @@ -118,11 +119,50 @@ function removeAd(index: number): void { form.ads.splice(index, 1); } +const budgetError = ref(null); +const budgetSaving = ref(false); + function goBack(): void { step.value = Math.max(1, step.value - 1); } -function goNext(): void { +/** + * Уходя с шага 3 «Бюджет» — сохраняем черновик (Р37: фронт денег не считает, + * передаёт строки как ввёл пользователь). Пустой недельный бюджет блокирует + * переход; ошибка PATCH — тоже блокирует, введённое не теряется (форма не чистится). + */ +async function saveBudgetStep(): Promise { + if (!form.weekly_budget_rub || form.weekly_budget_rub.trim() === '') { + budgetError.value = 'Укажите бюджет в неделю.'; + return false; + } + if (draftId.value === null) { + budgetError.value = 'Черновик кампании ещё не создан.'; + return false; + } + budgetError.value = null; + budgetSaving.value = true; + try { + await patchCampaign(draftId.value, { + weekly_budget_rub: form.weekly_budget_rub, + daily_budget_rub: form.daily_budget_rub || null, + audience_days: form.audience_days, + use_uploaded_list: form.use_uploaded_list, + }); + return true; + } catch (e) { + budgetError.value = extractErrorMessage(e, 'Не удалось сохранить бюджет.'); + return false; + } finally { + budgetSaving.value = false; + } +} + +async function goNext(): Promise { + if (step.value === 3) { + const saved = await saveBudgetStep(); + if (!saved) return; + } step.value = Math.min(stepTitles.length, step.value + 1); } @@ -138,7 +178,7 @@ onMounted(() => { void createDraft(); }); -defineExpose({ form, draftId, audienceSize, canLaunch, refreshAudienceSize }); +defineExpose({ form, draftId, audienceSize, canLaunch, refreshAudienceSize, budgetError });