Files
portal/app/resources/js/components/billing/AutopodborServicesPanel.vue
T
Дмитрий 793b20a39c feat(конкурентное поле): доводка фронта до прототипа — F1/F2/F3 + чистка M2
Сверка прототипа с реализацией показала расхождения — закрыты по TDD (dev, фронт):

- F1: экран «Предложения» (FieldProposalsScreen) переписан под вид «Поля» —
  карточки-плитки field-shared, тип+«предложение», крупная похожесть, Сайт +
  Справочник 2ГИС·Яндекс, править/удалять в карточке, массовый перенос; кнопка
  «Собрать конкурентов» открывает единое окно сбора 300 ₽ вместо старого autoform.
- F2: новый дружелюбный админ-экран AdminAutopodborPricingView (правка цен
  доп.услуг через PUT /api/admin/system-settings/{key} с обоснованием для аудита,
  сетка лидов для справки) + маршрут /admin/autopodbor-pricing + пункт меню.
- F3: колонка «когда списывается» в панели доп.услуг биллинга.
- M2: удалён мёртвый экран FieldManualCompetitorScreen (+ спека) — на него не
  было переходов; ручное добавление живёт окном на «Поле».

Тесты автоподбор+админ 43/43 зелёные, продакшен-вёрстка eslint-чистая, vite build .
НЕ на проде. M1 (18:00/21:00 МСК) — не баг, реальный инвариант продукта, не трогал.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 04:57:58 +03:00

74 lines
3.0 KiB
Vue

<script setup lang="ts">
/**
* «Дополнительные услуги» в Биллинге — тарифы «Конкурентного поля»:
* сбор конкурентов (шаг 1) и сбор источников (шаг 2). Списываются только при успехе.
* Цены — из autopodbor store (system_settings: autopodbor_price_search_rub/_study_rub).
* Панель показывается только если фича включена.
*/
import { computed, onMounted } from 'vue';
import { useAutopodborStore } from '../../stores/autopodborStore';
const store = useAutopodborStore();
const enabled = computed(() => store.enabled);
const searchPrice = computed(() => store.prices.search);
const studyPrice = computed(() => store.prices.study);
onMounted(() => {
void store.loadState();
});
</script>
<template>
<v-card v-if="enabled" variant="flat" border class="mt-4 ap-services">
<v-card-title class="text-subtitle-1 font-weight-bold">Дополнительные услуги</v-card-title>
<v-card-subtitle class="pb-2">«Конкурентное поле» деньги списываются только при успешном результате</v-card-subtitle>
<v-card-text>
<div class="ap-row">
<div class="ap-row__name">
<div class="font-weight-medium">Сбор конкурентов</div>
<div class="text-caption text-medium-emphasis">Подбор похожих конкурентов по вашим примерам и региону</div>
</div>
<div class="ap-row__when text-caption text-medium-emphasis">при успешном подборе</div>
<div class="ap-row__price num">{{ searchPrice }} </div>
</div>
<v-divider class="my-2" />
<div class="ap-row">
<div class="ap-row__name">
<div class="font-weight-medium">Сбор источников</div>
<div class="text-caption text-medium-emphasis">Все источники одного конкурента (сайты и телефоны) для проектов</div>
</div>
<div class="ap-row__when text-caption text-medium-emphasis">при успешном изучении</div>
<div class="ap-row__price num">{{ studyPrice }} </div>
</div>
</v-card-text>
</v-card>
</template>
<style scoped>
.ap-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
}
.ap-row__name {
min-width: 0;
flex: 1;
}
.ap-row__when {
flex-shrink: 0;
white-space: nowrap;
text-align: right;
min-width: 140px;
}
.ap-row__price {
font-family: 'JetBrains Mono', ui-monospace, monospace;
font-feature-settings: 'tnum';
font-weight: 600;
font-size: 16px;
color: #0f6e56;
white-space: nowrap;
}
</style>