Duas aplicações Vue.js 3 especializadas: Admin Dashboard para operadores de cada tenant e SuperAdmin Panel para gestão global da plataforma. WebSocket real-time, gestão de handover, e interfaces responsivas.
┌─────────────────────────────────────────────────────────────────────────┐
│ Frontend Architecture │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────┐
│ Docker Container │
│ (frontend service) │
└─────────────────────────────────────┘
│
┌───────────────┴───────────────┐
│ │
┌───────▼───────┐ ┌──────▼───────┐
│ Admin App │ │ SuperAdmin │
│ Port 3000 │ │ Port 3001 │
└───────────────┘ └──────────────┘
│ │
┌───────────────┼───────────────┐ │
│ │ │ │
┌───▼───┐ ┌─────▼─────┐ ┌──────▼──────┐ ┌───▼────────────┐
│ Chat │ │ Handover │ │ Analytics │ │ Tenant Mgmt │
│ UI │ │ Manager │ │ Dashboard │ │ Global Config │
└───────┘ └───────────┘ └─────────────┘ └────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ RBAC (Role-Based Access Control) │
├─────────────────────────────────────────────────────────────────────────┤
│ admin → Acesso ao Admin App (3000) do seu tenant │
│ superadmin → Acesso ao SuperAdmin (3001) + todos os tenants │
└─────────────────────────────────────────────────────────────────────────┘Port 3000
Interface para operadores e administradores de cada tenant. Foco em atendimento ao cliente e gestão do dia-a-dia.
Port 3001
Interface para gestão global da plataforma. Configuração, provisionamento de tenants, e monitoramento.
A interface de chat usa WebSocket para atualizações em tempo real. Quando uma nova mensagem chega (WhatsApp, web, etc.), o operador vê instantaneamente sem refresh.
// Frontend connects to WebSocket
const ws = new WebSocket(
'wss://api.webotify.io/api/conversations/ws'
);
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
switch(data.type) {
case 'new_message':
// Add message to conversation
conversations.addMessage(data.payload);
break;
case 'conversation_updated':
// Update conversation status
conversations.update(data.payload);
break;
case 'handover_started':
// Show handover timer
handover.start(data.payload);
break;
}
};Quando um operador assume uma conversa (handover), a UI mostra um timer de 30 minutos. Se não houver interação, a conversa retorna automaticamente para a IA.
Estado normal. IA responde automaticamente. Operador pode visualizar mas não intervém.
Operador assumiu. Timer de 30 min visível. IA pausa, mensagens vão direto pro operador.
Sem ação em 30min → auto-return para IA. Operador é notificado antes (warning em 5min).
<template>
<div class="handover-timer" :class="timerClass">
<div class="timer-display">
{{ formattedTime }}
</div>
<div class="timer-label">
{{ isWarning ? 'Retorno em breve!' : 'Tempo restante' }}
</div>
<button @click="extendHandover" v-if="canExtend">
Estender +15min
</button>
</div>
</template>
<script setup>
const props = defineProps(['handoverStartedAt', 'durationMinutes']);
const remainingSeconds = computed(() => {
const elapsed = Date.now() - props.handoverStartedAt;
return Math.max(0, props.durationMinutes * 60 - elapsed / 1000);
});
const isWarning = computed(() => remainingSeconds.value < 300); // 5min
const timerClass = computed(() => isWarning.value ? 'warning' : 'normal');
</script>O Admin Dashboard mostra métricas específicas do tenant logado. Conversas ativas, tempo médio de resposta, handovers, e mais.
Vue.js 3 (Composition API)
Tailwind CSS
Pinia (Vue Store)
WebSocket
Vue Router 4
Axios / Fetch API
Vite
Docker (2 ports)
GET /api/conversations
POST /api/chat
GET /api/tenant-configs/{id}
PUT /api/prompts/override/{tenant}/{prompt} wss://api.webotify.io/api/conversations/ws
Events: new_message, handover_*, typing
Auth: JWT token in connection params Veja como outros componentes do Optimus foram construídos