| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- import { sentimentDashboardMockSource } from '../data/sentiment-dashboard.mock.js';
- const summaryCardsConfig = [
- { key: 'atRiskClients', label: 'Clientes em risco' },
- { key: 'opportunities', label: 'Oportunidades' },
- { key: 'recentInteractions', label: 'Interacoes recentes' },
- { key: 'netTrend', label: 'Tendencia liquida' }
- ];
- const priorityLabel = {
- high: 'Alta prioridade',
- medium: 'Media prioridade',
- low: 'Baixa prioridade'
- };
- export function getSentimentDashboardViewModel() {
- return {
- summaryCards: mapSummaryCards(sentimentDashboardMockSource.summary),
- alerts: mapAlerts(sentimentDashboardMockSource.alerts),
- timeline: sentimentDashboardMockSource.timeline,
- aspects: mapAspects(sentimentDashboardMockSource.aspects)
- };
- }
- export function getSummaryInsight(cardId, viewModel) {
- const card = viewModel.summaryCards.find((item) => item.id === cardId);
- if (!card) return createFallbackInsight();
- const insightByCard = {
- atRiskClients: {
- title: 'Clientes em risco em destaque',
- context: `${card.value} clientes apresentam sinais de queda de engajamento ou resposta tardia.`,
- actions: [
- 'Priorizar contato em ate 24h para os casos com maior ticket.',
- 'Acionar playbook de retencao com oferta de recuperacao.',
- 'Distribuir os casos criticos para vendedores com melhor conversao.'
- ]
- },
- opportunities: {
- title: 'Oportunidades comerciais ativas',
- context: `${card.value} clientes estao com indicios de compra em aberto.`,
- actions: [
- 'Executar abordagem consultiva nos clientes com intencao alta.',
- 'Enviar proposta com prazo curto para acelerar fechamento.',
- 'Marcar follow-up com dono da conta ainda hoje.'
- ]
- },
- recentInteractions: {
- title: 'Volume recente de interacoes',
- context: `${card.value} interacoes recentes exigem triagem por impacto no resultado.`,
- actions: [
- 'Separar interacoes por risco, oportunidade e neutras.',
- 'Garantir SLA para mensagens sem retorno.',
- 'Acompanhar taxa de resolucao no primeiro contato.'
- ]
- },
- netTrend: {
- title: 'Tendencia liquida de resultado',
- context: `Tendencia atual de ${card.value}, indicando saldo positivo entre ganhos e perdas.`,
- actions: [
- 'Escalar abordagem que gerou maior crescimento nas ultimas semanas.',
- 'Manter monitoramento de contas em risco para evitar reversao.',
- 'Transformar casos de sucesso em rotina para todo o time.'
- ]
- }
- };
- return insightByCard[cardId] ?? createFallbackInsight();
- }
- export function getAlertInsight(alertId, viewModel) {
- const alert = viewModel.alerts.find((item) => item.id === alertId);
- if (!alert) return createFallbackInsight();
- const categoryGuidance = {
- churn_risk: [
- 'Fazer contato humano com proposta de recuperacao em ate 24h.',
- 'Identificar causa raiz da perda de interesse no ultimo ciclo.',
- 'Negociar condicoes para reativar a conta com menor atrito.'
- ],
- frustration: [
- 'Responder com empatia e reconhecer o problema sem delay.',
- 'Resolver o ponto de frustracao com responsavel e prazo claro.',
- 'Fazer retorno ativo confirmando que o problema foi resolvido.'
- ],
- buying_intent: [
- 'Acionar vendedor responsavel para proposta objetiva imediata.',
- 'Remover bloqueios de compra (prazo, condicao, produto).',
- 'Registrar proximo passo com data de fechamento prevista.'
- ]
- };
- return {
- title: alert.title,
- context: alert.description,
- actions: categoryGuidance[alert.category] ?? createFallbackInsight().actions
- };
- }
- export function getTimelineInsight(period, viewModel) {
- const timelinePoint = viewModel.timeline.find((item) => item.period === period);
- if (!timelinePoint) return createFallbackInsight();
- const balance = timelinePoint.gains - timelinePoint.losses;
- const trendText =
- balance >= 0
- ? `saldo positivo de ${balance} pontos entre ganhos e perdas`
- : `saldo negativo de ${Math.abs(balance)} pontos entre ganhos e perdas`;
- return {
- title: `Leitura da ${timelinePoint.period}`,
- context: `Na ${timelinePoint.period}, houve ${timelinePoint.gains} ganhos e ${timelinePoint.losses} perdas, com ${trendText}.`,
- actions: [
- 'Replicar o comportamento das contas com ganho na semana.',
- 'Atuar nos principais motivos de perda identificados no periodo.',
- 'Definir meta da proxima semana com base no saldo atual.'
- ]
- };
- }
- function mapSummaryCards(summary) {
- return summaryCardsConfig.map((config) => ({
- id: config.key,
- label: config.label,
- value: summary[config.key]?.value ?? summary[config.key],
- image: summary[config.key]?.image ?? null
- }));
- }
- function mapAlerts(alerts) {
- return alerts.map((alert) => ({
- ...alert,
- priorityLabel: priorityLabel[alert.priority] ?? priorityLabel.low
- }));
- }
- function mapAspects(aspects) {
- return aspects.map((aspect) => ({
- ...aspect,
- volume: aspect.positive.length + aspect.neutral.length + aspect.negative.length
- }));
- }
- function createFallbackInsight() {
- return {
- title: 'Detalhes da analise',
- context: 'Selecione um item para visualizar diagnostico e recomendacoes.',
- actions: ['Priorizar casos de alto impacto.', 'Executar proximo passo comercial.', 'Monitorar resultado diariamente.']
- };
- }
|