diff --git a/src/views/pages/MarketingAnalysis.vue b/src/views/pages/MarketingAnalysis.vue index 7b40ce6..f5653df 100644 --- a/src/views/pages/MarketingAnalysis.vue +++ b/src/views/pages/MarketingAnalysis.vue @@ -341,13 +341,13 @@
-
Категория
-
Доля
+
Возраст
+
Доход
{{ row.label }}
-
{{ row.value }}%
+
{{ row.value }} ₸
@@ -1517,33 +1517,77 @@ const ageBarData = computed(() => ({ ] })); -const incomeBarData = computed(() => { - const above = aboveAvgIncomeValue.value; - const other = Math.max(0, 100 - above); - return { - labels: ['Остальные', 'Выше среднего'], - datasets: [ - { - data: [other, above], - borderRadius: 10, - backgroundColor: (context) => { - const { chart } = context; - const { ctx, chartArea } = chart; - if (!chartArea) return ['rgba(148,163,184,0.55)', 'rgba(82,196,26,0.55)']; - return [makeVerticalGradient(ctx, chartArea, 'rgba(148,163,184,0.75)', 'rgba(148,163,184,0.25)'), makeVerticalGradient(ctx, chartArea, 'rgba(82,196,26,0.80)', 'rgba(82,196,26,0.25)')]; - } - } - ] +// Income by age rows +const incomeRows = computed(() => { + const incomeByAge = report.value?.sections?.target_audience?.income_by_age ?? {}; + + // Маппинг ключей бэкенда на ключи фронтенда + const backendKeyMap = { + '18-24': { '18-24': 1.0 }, + '18-25': { '18-24': 1.0 }, + '25-34': { '25-34': 1.0 }, + '25-45': { '25-34': 0.5, '35-44': 0.5 }, + '35-44': { '35-44': 1.0 }, + '20-40': { '25-34': 0.5, '35-44': 0.5 }, + '45-54': { '45-54': 1.0 }, + '40-60': { '45-54': 1.0 }, + '55+': { '55+': 1.0 }, + '60+': { '55+': 1.0 }, + '60_plus': { '55+': 1.0 } }; + + // Стандартный порядок для отображения + const order = [ + { key: '18-24', label: '18–24' }, + { key: '25-34', label: '25–34' }, + { key: '35-44', label: '35–44' }, + { key: '45-54', label: '45–54' }, + { key: '55+', label: '55+' } + ]; + + // Агрегируем значения из бэкенда + const aggregated = {}; + Object.keys(incomeByAge).forEach((backendKey) => { + const mapping = backendKeyMap[backendKey]; + if (mapping) { + const value = Number(incomeByAge[backendKey]) || 0; + Object.keys(mapping).forEach((frontendKey) => { + if (!aggregated[frontendKey]) aggregated[frontendKey] = 0; + aggregated[frontendKey] += value * mapping[frontendKey]; + }); + } + }); + + // Формируем строки в нужном порядке + return order + .map(({ key, label }) => { + const value = aggregated[key] || 0; + return { key, label, value: Math.round(value) }; + }) + .filter((row) => row.value > 0); }); +const incomeBarData = computed(() => ({ + labels: incomeRows.value.map((r) => r.label), + datasets: [ + { + data: incomeRows.value.map((r) => r.value), + borderRadius: 10, + backgroundColor: (context) => { + const { chart } = context; + const { ctx, chartArea } = chart; + if (!chartArea) return 'rgba(82,196,26,0.55)'; + return makeVerticalGradient(ctx, chartArea, 'rgba(82,196,26,0.80)', 'rgba(82,196,26,0.25)'); + } + } + ] +})); + const incomeTableRows = computed(() => { - const above = aboveAvgIncomeValue.value; - const other = Math.max(0, 100 - above); - return [ - { label: 'Остальные', value: other }, - { label: 'Выше среднего', value: above } - ]; + return incomeRows.value.map((row) => ({ + label: row.label, + value: row.value.toLocaleString('ru-RU') + })); }); // Segments list