diff --git a/app/javascript/dashboard/api/captain/contactMemories.js b/app/javascript/dashboard/api/captain/contactMemories.js new file mode 100644 index 000000000..0657e49d7 --- /dev/null +++ b/app/javascript/dashboard/api/captain/contactMemories.js @@ -0,0 +1,34 @@ +/* global axios */ +import ApiClient from '../ApiClient'; + +class ContactMemoriesAPI extends ApiClient { + constructor() { + super('memories', { accountScoped: true }); + } + + get url() { + return `${this.baseUrl()}/contacts/${this.contactId}/memories`; + } + + list(contactId) { + this.contactId = contactId; + return axios.get(this.url); + } + + update(contactId, id, payload) { + this.contactId = contactId; + return axios.patch(`${this.url}/${id}`, payload); + } + + destroy(contactId, id) { + this.contactId = contactId; + return axios.delete(`${this.url}/${id}`); + } + + forgetAll(contactId) { + this.contactId = contactId; + return axios.delete(this.url); + } +} + +export default new ContactMemoriesAPI(); diff --git a/app/javascript/dashboard/i18n/locale/en/captain.json b/app/javascript/dashboard/i18n/locale/en/captain.json index 239c30515..6d4ab1547 100644 --- a/app/javascript/dashboard/i18n/locale/en/captain.json +++ b/app/javascript/dashboard/i18n/locale/en/captain.json @@ -423,6 +423,14 @@ "SUCCESS_MESSAGE": "FAQ deleted successfully", "ERROR_MESSAGE": "An error occurred while deleting FAQ, please try again." } + }, + "MEMORY": { + "LOADING": "Loading…", + "EMPTY": "No memories for this contact yet.", + "CONFIRM_DELETE": "Forget this memory?", + "CONFIRM_FORGET_ALL": "Forget ALL memories for this contact? This cannot be undone after 30 days.", + "FORGET": "Forget", + "FORGET_ALL": "Forget all" } }, "CAPTAIN_REPORTS": { @@ -437,8 +445,39 @@ "DASHBOARD": "Dashboard", "INSIGHTS": "AI Insights", "OPERATIONAL": "Operational", + "EXECUTIVE": "Executive", "LANDING_PAGES": "Landing Pages" }, + "EXECUTIVE": { + "LOADING": "Loading executive digest...", + "NO_DATA": "No insights for the period. Run the weekly analysis to see data here.", + "TITLE": "Executive Digest", + "SUBTITLE": "Same report sent to Mattermost, with drill-down and filters.", + "DELIVER_BUTTON": "Send to Mattermost now", + "DELIVER_SUCCESS": "Digest queued. It will arrive in Mattermost shortly.", + "DELIVER_ERROR": "Failed to dispatch the digest. Check Rails log.", + "CONVERSATIONS": "Conversations", + "MESSAGES": "Messages", + "UNITS_ANALYZED": "Units analyzed", + "INSIGHTS_COUNT": "Insights generated", + "UNIT_TABLE": "Comparative by unit", + "COL_UNIT": "Unit", + "COL_CONVS": "Conversations", + "COL_DELTA": "vs previous week", + "COL_AI_RATE": "AI success rate", + "COL_FAILURES": "Failures", + "AI_FAILURES": "Where Angelina failed (click to see conversations)", + "OPPORTUNITIES": "Opportunities — what customers asked for", + "OPPORTUNITIES_HINT": "Click an opportunity to see real conversations where it was mentioned.", + "COMPLAINTS": "Recurring complaints", + "PRAISES": "Recurring praises", + "RECOMMENDATIONS": "AI Recommendations", + "DRILLDOWN_TITLE": "Related conversations", + "NO_CONVERSATIONS_FOUND": "No conversations found with those keywords in the period.", + "NO_CONVERSATIONS_HINT": "The insight description is an AI abstraction. If no keyword matches the literal conversation text, nothing is returned. Try clicking a more specific item.", + "SEARCH_TOKENS": "Keywords searched", + "OPEN_CONVERSATION": "Open in Chatwoot" + }, "LP": { "LOADING": "Loading data...", "NO_DATA": "No clicks recorded yet. Integrate the pixel on your landing page to see data here.", @@ -515,8 +554,23 @@ "FAILED": "Failed" }, "OPERATIONAL": { - "COMING_SOON": "Coming soon", - "COMING_SOON_DESC": "Real-time operational data (reservations, Pix charges, etc.) will be available here soon." + "LOADING": "Loading operational data...", + "NO_DATA": "No operational data for the selected period.", + "CONVERSATIONS_SECTION": "Conversations", + "RESERVATIONS_SECTION": "Reservations", + "TOTAL": "Total", + "RESOLVED": "Resolved", + "OPEN": "Open", + "AVG_RESOLUTION": "Avg resolution time", + "RES_TOTAL": "Total reservations", + "RES_PAID": "Paid", + "RES_EXPIRED": "Expired", + "RES_REVENUE": "Paid revenue", + "BY_INBOX": "Volume by inbox", + "RESOLUTION_RATE_TOOLTIP": "Resolution rate", + "DAILY_DIST": "Daily distribution", + "HOURLY_DIST": "Hourly distribution", + "PEAK": "Peak" }, "DASHBOARD": { "TOTAL_CONVERSATIONS": "Analyzed conversations", diff --git a/app/javascript/dashboard/i18n/locale/pt_BR/captain.json b/app/javascript/dashboard/i18n/locale/pt_BR/captain.json index d162ba132..e3cbc589e 100644 --- a/app/javascript/dashboard/i18n/locale/pt_BR/captain.json +++ b/app/javascript/dashboard/i18n/locale/pt_BR/captain.json @@ -425,6 +425,14 @@ "SUCCESS_MESSAGE": "FAQ excluída com sucesso", "ERROR_MESSAGE": "Ocorreu um erro ao excluir a FAQ, por favor tente novamente." } + }, + "MEMORY": { + "LOADING": "Carregando…", + "EMPTY": "Sem memórias para este contato ainda.", + "CONFIRM_DELETE": "Esquecer esta memória?", + "CONFIRM_FORGET_ALL": "Esquecer TODAS as memórias deste contato? Após 30 dias não é possível desfazer.", + "FORGET": "Esquecer", + "FORGET_ALL": "Esquecer tudo" } }, "CAPTAIN_REPORTS": { @@ -439,8 +447,39 @@ "DASHBOARD": "Dashboard", "INSIGHTS": "Insights IA", "OPERATIONAL": "Operacional", + "EXECUTIVE": "Executivo", "LANDING_PAGES": "Landing Pages" }, + "EXECUTIVE": { + "LOADING": "Carregando digest executivo...", + "NO_DATA": "Sem insights gerados para o período. Rode a análise semanal pra ver os dados aqui.", + "TITLE": "Digest Executivo", + "SUBTITLE": "Mesmo relatório enviado ao Mattermost, com drill-down e filtros.", + "DELIVER_BUTTON": "Enviar ao Mattermost agora", + "DELIVER_SUCCESS": "Digest enfileirado. Vai chegar no Mattermost em instantes.", + "DELIVER_ERROR": "Falha ao disparar o digest. Veja o log do Rails.", + "CONVERSATIONS": "Conversas", + "MESSAGES": "Mensagens", + "UNITS_ANALYZED": "Unidades analisadas", + "INSIGHTS_COUNT": "Insights gerados", + "UNIT_TABLE": "Comparativo por unidade", + "COL_UNIT": "Unidade", + "COL_CONVS": "Conversas", + "COL_DELTA": "vs semana anterior", + "COL_AI_RATE": "Taxa de acerto IA", + "COL_FAILURES": "Falhas", + "AI_FAILURES": "Onde a Angelina errou (clique pra ver conversas)", + "OPPORTUNITIES": "Oportunidades — o que clientes pediram", + "OPPORTUNITIES_HINT": "Clique em uma oportunidade pra ver as conversas reais onde foi mencionada.", + "COMPLAINTS": "Reclamações recorrentes", + "PRAISES": "Elogios recorrentes", + "RECOMMENDATIONS": "Recomendações da IA", + "DRILLDOWN_TITLE": "Conversas relacionadas", + "NO_CONVERSATIONS_FOUND": "Nenhuma conversa encontrada com essas palavras no período.", + "NO_CONVERSATIONS_HINT": "A descrição do insight é uma abstração da IA. Se nenhuma palavra-chave bateu com o texto literal das conversas, nada é retornado. Tente clicar em outro item mais específico.", + "SEARCH_TOKENS": "Palavras buscadas", + "OPEN_CONVERSATION": "Abrir no Chatwoot" + }, "LP": { "LOADING": "Carregando dados...", "NO_DATA": "Nenhum clique registrado ainda. Integre o pixel na landing page para ver os dados aqui.", @@ -517,8 +556,23 @@ "FAILED": "Falhou" }, "OPERATIONAL": { - "COMING_SOON": "Em breve", - "COMING_SOON_DESC": "Os dados operacionais em tempo real (reservas, cobranças Pix, etc.) estarão disponíveis aqui em breve." + "LOADING": "Carregando dados operacionais...", + "NO_DATA": "Sem dados operacionais para o período selecionado.", + "CONVERSATIONS_SECTION": "Conversas", + "RESERVATIONS_SECTION": "Reservas", + "TOTAL": "Total", + "RESOLVED": "Resolvidas", + "OPEN": "Em aberto", + "AVG_RESOLUTION": "Tempo médio de resolução", + "RES_TOTAL": "Total de reservas", + "RES_PAID": "Pagas", + "RES_EXPIRED": "Expiradas", + "RES_REVENUE": "Receita paga", + "BY_INBOX": "Volume por canal", + "RESOLUTION_RATE_TOOLTIP": "Taxa de resolução", + "DAILY_DIST": "Distribuição por dia", + "HOURLY_DIST": "Distribuição por hora", + "PEAK": "Pico" }, "DASHBOARD": { "TOTAL_CONVERSATIONS": "Conversas analisadas", diff --git a/app/javascript/dashboard/routes/dashboard/contact/components/ContactMemories.vue b/app/javascript/dashboard/routes/dashboard/contact/components/ContactMemories.vue new file mode 100644 index 000000000..d93fa0499 --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/contact/components/ContactMemories.vue @@ -0,0 +1,65 @@ + + + + + {{ t('CAPTAIN.MEMORY.LOADING') }} + {{ error }} + + {{ t('CAPTAIN.MEMORY.EMPTY') }} + + + + {{ m.memory_type }} + {{ m.content }} + {{ Math.round(m.confidence * 100) }}% + + {{ t('CAPTAIN.MEMORY.FORGET') }} + + + + + {{ t('CAPTAIN.MEMORY.FORGET_ALL') }} + + +