diff --git a/app/javascript/dashboard/api/captain/notificationTemplates.js b/app/javascript/dashboard/api/captain/notificationTemplates.js new file mode 100644 index 000000000..2a5fbac48 --- /dev/null +++ b/app/javascript/dashboard/api/captain/notificationTemplates.js @@ -0,0 +1,30 @@ +/* global axios */ +import ApiClient from '../ApiClient'; + +class CaptainNotificationTemplatesAPI extends ApiClient { + constructor() { + super('captain/units', { accountScoped: true }); + } + + getTemplates(unitId) { + return axios.get(`${this.url}/${unitId}/notification_templates`); + } + + createTemplate(unitId, data) { + return axios.post(`${this.url}/${unitId}/notification_templates`, { + notification_template: data, + }); + } + + updateTemplate(unitId, id, data) { + return axios.patch(`${this.url}/${unitId}/notification_templates/${id}`, { + notification_template: data, + }); + } + + deleteTemplate(unitId, id) { + return axios.delete(`${this.url}/${unitId}/notification_templates/${id}`); + } +} + +export default new CaptainNotificationTemplatesAPI(); diff --git a/app/javascript/dashboard/i18n/locale/en/captain.json b/app/javascript/dashboard/i18n/locale/en/captain.json index 43a71e37a..c70a4c2d8 100644 --- a/app/javascript/dashboard/i18n/locale/en/captain.json +++ b/app/javascript/dashboard/i18n/locale/en/captain.json @@ -352,6 +352,7 @@ "UNITS_GROUP": "Pix Units", "INBOXES_GROUP": "Inboxes", "TABS": { + "DASHBOARD": "Dashboard", "INSIGHTS": "AI Insights", "OPERATIONAL": "Operational" }, @@ -372,7 +373,22 @@ "AI_FAILURES": "AI Failures", "BULLET": "•", "COUNT_PREFIX": "(", - "COUNT_SUFFIX": ")" + "COUNT_SUFFIX": ")", + "TIMES": "x", + "SENTIMENT": "Sentiment", + "SENTIMENT_POSITIVE": "Positive", + "SENTIMENT_NEGATIVE": "Negative", + "SENTIMENT_NEUTRAL": "Neutral", + "PRAISES": "Customer Praises", + "COMPLAINTS": "Complaints", + "FAQ_GAPS": "FAQ Gaps", + "FAQ_GAPS_HINT": "Questions customers ask that the agent doesn't cover", + "MOST_REQUESTED_SUITES": "Most Requested Suites", + "PRICE_REACTIONS": "Price Reactions", + "PRICE_OBJECTIONS": "price objections", + "RECOMMENDATIONS": "Recommendations", + "SHOW_DETAILS": "View full analysis", + "HIDE_DETAILS": "Hide details" }, "EMPTY": { "TITLE": "No reports generated", @@ -393,6 +409,74 @@ "OPERATIONAL": { "COMING_SOON": "Coming soon", "COMING_SOON_DESC": "Real-time operational data (reservations, Pix charges, etc.) will be available here soon." + }, + "DASHBOARD": { + "TOTAL_CONVERSATIONS": "Analyzed conversations", + "AVG_SENTIMENT": "Avg. positive sentiment", + "FAQ_GAPS_TOTAL": "FAQ gaps identified", + "WEEKS_ANALYZED": "weeks analyzed", + "NO_DATA": "Not enough data. Generate more AI reports to see the dashboard.", + "SENTIMENT_TREND": "Sentiment trend by week", + "FAILURES_RANKING": "Agent failure ranking", + "FAILURES_RANKING_HINT": "Most frequent situations where the AI couldn't respond well", + "FAQ_PRIORITY": "Priority FAQs to create", + "FAQ_PRIORITY_HINT": "Questions customers ask most that aren't in the FAQ yet", + "CUSTOMER_BEHAVIOR": "Customer behavior", + "TOP_TOPICS_TITLE": "Most discussed topics", + "SUITES_TITLE": "Most requested suites", + "COMPLAINTS_TREND": "Complaints volume by week", + "HANDOFFS_TITLE": "Estimated handoffs to human", + "HANDOFFS_HINT": "Based on AI failure frequency. Direct handoff tracking coming soon.", + "TREND_UP": "rising", + "TREND_DOWN": "falling", + "TREND_STABLE": "stable", + "WEEKS": "weeks" + }, + "FAQ_QUICK_ADD": { + "BUTTON": "Create FAQ", + "TITLE": "Create FAQ from AI suggestion", + "QUESTION_LABEL": "Question (suggested by AI)", + "ANSWER_LABEL": "Answer", + "ANSWER_PLACEHOLDER": "Write the answer to this question...", + "ASSISTANT_LABEL": "AI Agent", + "ASSISTANT_PLACEHOLDER": "Select the agent", + "CANCEL": "Cancel", + "SAVE": "Save FAQ", + "SUCCESS": "FAQ created successfully!", + "ERROR": "Error creating FAQ. Please try again." + }, + "NOTIFICATIONS": { + "TITLE": "Automatic Notifications", + "DESCRIPTION": "Configure messages sent automatically before or after the guest's arrival.", + "LOADING": "Loading notifications...", + "ADD": "Add notification", + "ACTIVE": "Active", + "INACTIVE": "Inactive", + "DIRECTION": { + "BEFORE": "before", + "AFTER": "after", + "OF_ARRIVAL": "arrival" + }, + "FORM": { + "LABEL_PLACEHOLDER": "Template name (e.g. Arrival Instructions)", + "CONTENT_PLACEHOLDER": "Message to send... Use {{guest_name}}, {{check_in_time}}, {{suite_name}}", + "SEND": "Send", + "MINUTES": "min", + "CANCEL": "Cancel", + "SAVE": "Save" + }, + "CREATE": { + "SUCCESS": "Notification created successfully!", + "ERROR": "Error creating notification. Please try again." + }, + "UPDATE": { + "SUCCESS": "Notification updated!", + "ERROR": "Error updating notification." + }, + "DELETE": { + "SUCCESS": "Notification removed.", + "ERROR": "Error removing notification." + } } } } diff --git a/app/javascript/dashboard/i18n/locale/pt_BR/captain.json b/app/javascript/dashboard/i18n/locale/pt_BR/captain.json index f2d637a83..4d0f2c60b 100644 --- a/app/javascript/dashboard/i18n/locale/pt_BR/captain.json +++ b/app/javascript/dashboard/i18n/locale/pt_BR/captain.json @@ -352,6 +352,7 @@ "UNITS_GROUP": "Unidades Pix", "INBOXES_GROUP": "Caixas de Entrada", "TABS": { + "DASHBOARD": "Dashboard", "INSIGHTS": "Insights IA", "OPERATIONAL": "Operacional" }, @@ -372,7 +373,22 @@ "AI_FAILURES": "Falhas da IA", "BULLET": "•", "COUNT_PREFIX": "(", - "COUNT_SUFFIX": ")" + "COUNT_SUFFIX": ")", + "TIMES": "x", + "SENTIMENT": "Sentimento", + "SENTIMENT_POSITIVE": "Positivo", + "SENTIMENT_NEGATIVE": "Negativo", + "SENTIMENT_NEUTRAL": "Neutro", + "PRAISES": "Elogios dos clientes", + "COMPLAINTS": "Reclamações", + "FAQ_GAPS": "Lacunas no FAQ", + "FAQ_GAPS_HINT": "Perguntas que os clientes fazem mas o agente não cobre", + "MOST_REQUESTED_SUITES": "Suítes mais pedidas", + "PRICE_REACTIONS": "Reação a preços", + "PRICE_OBJECTIONS": "objeções de preço", + "RECOMMENDATIONS": "Recomendações", + "SHOW_DETAILS": "Ver análise completa", + "HIDE_DETAILS": "Ocultar detalhes" }, "EMPTY": { "TITLE": "Nenhum relatório gerado", @@ -393,6 +409,75 @@ "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." + }, + "DASHBOARD": { + "TOTAL_CONVERSATIONS": "Conversas analisadas", + "AVG_SENTIMENT": "Sentimento positivo médio", + "FAQ_GAPS_TOTAL": "Lacunas de FAQ identificadas", + "WEEKS_ANALYZED": "semanas analisadas", + "NO_DATA": "Dados insuficientes. Gere mais relatórios de IA para ver o dashboard.", + "SENTIMENT_TREND": "Tendência de sentimento por semana", + "FAILURES_RANKING": "Ranking de falhas do agente", + "FAILURES_RANKING_HINT": "Situações mais frequentes em que a IA não conseguiu responder bem", + "FAQ_PRIORITY": "FAQ prioritário para criar", + "FAQ_PRIORITY_HINT": "Perguntas que os clientes mais fazem e ainda não estão no FAQ", + "CUSTOMER_BEHAVIOR": "Comportamento dos clientes", + "TOP_TOPICS_TITLE": "Assuntos mais discutidos", + "SUITES_TITLE": "Suítes mais solicitadas", + "COMPLAINTS_TREND": "Volume de reclamações por semana", + "HANDOFFS_TITLE": "Estimativa de transferências para humano", + "HANDOFFS_HINT": "Baseado na frequência de falhas do agente. Rastreamento direto de transferências em breve.", + "TREND_UP": "em alta", + "TREND_DOWN": "em queda", + "TREND_STABLE": "estável", + "WEEKS": "semanas" + }, + "FAQ_QUICK_ADD": { + "BUTTON": "Criar FAQ", + "TITLE": "Criar FAQ a partir da sugestão da IA", + "QUESTION_LABEL": "Pergunta (sugerida pela IA)", + "ANSWER_LABEL": "Resposta", + "ANSWER_PLACEHOLDER": "Escreva a resposta para esta pergunta...", + "ASSISTANT_LABEL": "Agente de IA", + "ASSISTANT_PLACEHOLDER": "Selecione o agente", + "CANCEL": "Cancelar", + "SAVE": "Salvar FAQ", + "SUCCESS": "FAQ criado com sucesso!", + "ERROR": "Erro ao criar FAQ. Tente novamente." + }, + "NOTIFICATIONS": { + "TITLE": "Notificações Automáticas", + "DESCRIPTION": "Configure mensagens automáticas enviadas antes ou depois da chegada do hóspede.", + "LOADING": "Carregando notificações...", + "ADD": "Adicionar notificação", + "ACTIVE": "Ativo", + "INACTIVE": "Inativo", + "DIRECTION": { + "BEFORE": "antes", + "AFTER": "depois", + "OF_ARRIVAL": "da chegada" + }, + "TIMING_LABEL": "da chegada", + "FORM": { + "LABEL_PLACEHOLDER": "Nome do template (ex: Orientações de Chegada)", + "CONTENT_PLACEHOLDER": "Mensagem a enviar... Use {{guest_name}}, {{check_in_time}}, {{suite_name}}", + "SEND": "Enviar", + "MINUTES": "min", + "CANCEL": "Cancelar", + "SAVE": "Salvar" + }, + "CREATE": { + "SUCCESS": "Notificação criada com sucesso!", + "ERROR": "Erro ao criar notificação. Tente novamente." + }, + "UPDATE": { + "SUCCESS": "Notificação atualizada!", + "ERROR": "Erro ao atualizar notificação." + }, + "DELETE": { + "SUCCESS": "Notificação removida.", + "ERROR": "Erro ao remover notificação." + } } } } diff --git a/app/javascript/dashboard/routes/dashboard/settings/captain/captain.routes.js b/app/javascript/dashboard/routes/dashboard/settings/captain/captain.routes.js index c99b08b3c..5a89b37bd 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/captain/captain.routes.js +++ b/app/javascript/dashboard/routes/dashboard/settings/captain/captain.routes.js @@ -8,6 +8,7 @@ import UnitEdit from './units/Edit.vue'; import GalleryIndex from './gallery/Index.vue'; import GalleryEdit from './gallery/Edit.vue'; const ReportsIndex = () => import('./reports/Index.vue'); +const NotificationsIndex = () => import('./notifications/Index.vue'); export default { routes: [ @@ -77,6 +78,14 @@ export default { permissions: ['administrator'], }, }, + { + path: 'units/:unitId/notifications', + name: 'captain_settings_notifications', + component: NotificationsIndex, + meta: { + permissions: ['administrator'], + }, + }, ], }, ], diff --git a/app/javascript/dashboard/routes/dashboard/settings/captain/notifications/Index.vue b/app/javascript/dashboard/routes/dashboard/settings/captain/notifications/Index.vue new file mode 100644 index 000000000..7bf2184a9 --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/settings/captain/notifications/Index.vue @@ -0,0 +1,361 @@ + + +