ButtonFloating

src/components/button/ButtonFloating.vue + ButtonIncidentFloating.vue
Action high 4 usos

Dois componentes flutuantes que vivem fora do fluxo normal da página. ButtonFloating gerencia dois elementos fixos: um botão circular de ajuda (right:0, top:45vh) com link para vídeo tutorial ou dropdown de múltiplos vídeos, e uma barra de chat interna em forma de pílula (bottom:0, right:1rem, z-index:4000) com badge de mensagens não lidas. Toda a lógica é interna — sem props. A visibilidade é controlada por feature flag (hasDpsp) e condições de sessão. ButtonIncidentFloating exibe o status operacional do sistema (via InStatus API) como pílula colorida. Ao clicar, abre dropdown com nome do incidente, impacto, componentes afetados e timestamp. Aceita 1 prop (isOutPedbot) para ajustar o posicionamento em contextos de dashboard.

Help — link direto (1 vídeo)

Quando a rota atual possui exatamente 1 vídeo tutorial associado, o botão circular de ajuda funciona como link direto — clique abre o vídeo imediatamente. Posicionamento: position:fixed; right:0; top:45vh. O botão usa vs-button circular com ícone help-circle do Feather.

Área da aplicação (fixed right:0 top:45vh)
fixed · right:0 · top:45vh
Real src/layouts/main/Main.vue:142
<!-- Main.vue — uso do ButtonFloating -->
<ButtonFloating v-if="!disablePedbotReferences"/>

<!-- ButtonFloating.vue — botão de ajuda (link direto, 1 vídeo) -->
<vs-button
  v-if="videos.length === 1"
  :href="videos[0].link"
  target="_blank"
  color="primary"
  type="filled"
  icon="help_circle"
  radius
  style="position:fixed; right:0; top:45vh; z-index:4000;"
/>

Help — dropdown (múltiplos vídeos)

Quando há mais de 1 vídeo tutorial para a rota atual, o botão de ajuda abre um vs-dropdown listando todos os vídeos disponíveis. Cada item é um link externo (target="_blank").

Dropdown aberto — múltiplos vídeos
Como criar um atendimento
Configurando filas de espera
Transferência de conversas
Real src/components/button/ButtonFloating.vue
<!-- Dropdown com múltiplos vídeos -->
<vs-dropdown
  v-if="videos.length > 1"
  style="position:fixed; right:0; top:45vh; z-index:4000;"
>
  <vs-button
    color="primary"
    type="filled"
    icon="help_circle"
    radius
  />
  <vs-dropdown-menu>
    <vs-dropdown-item
      v-for="video in videos"
      :key="video.id"
    >
      <a :href="video.link" target="_blank">
        <feather-icon icon="VideoIcon" svgClasses="w-4 h-4 mr-2"/>
        {{ video.title }}
      </a>
    </vs-dropdown-item>
  </vs-dropdown-menu>
</vs-dropdown>

Barra de Chat Interno

Pílula fixa no rodapé do lado direito. Exibe "Chat Interno", avatar do usuário com badge de mensagens não lidas, e um chevron indicando que o painel pode ser expandido. Dimensões: width:16rem; height:3.3rem. Border-radius: 2rem 2rem 0 0 (apenas cantos superiores arredondados). Ao clicar, emite o evento de bus OpenInternalChat.

fixed · bottom:0 · right:1rem · z-index:4000
Chat Interno
3
Real src/components/button/ButtonFloating.vue
<!-- Chat bar pill — ButtonFloating.vue -->
<div
  v-if="validate && !twoFactorActivated && !interChatIsActive && !isChatAttendancePage"
  class="chat-bar-pill"
  style="
    position: fixed;
    bottom: 0;
    right: 1rem;
    width: 16rem;
    height: 3.3rem;
    background: var(--vs-primary);
    border-radius: 2rem 2rem 0 0;
    z-index: 4000;
    display: flex;
    align-items: center;
    padding: 0 14px;
    cursor: pointer;
  "
  @click="$bus.$emit('OpenInternalChat')"
>
  <span style="flex:1; color:#fff; font-weight:600;">Chat Interno</span>
  <vs-avatar
    size="28px"
    :src="AppActiveUser.photoURL"
    style="position:relative;"
  >
    <!-- badge de não lidas -->
    <span
      v-if="unseenMessages > 0"
      class="badge-unseen"
    >{{ unseenMessages }}</span>
  </vs-avatar>
  <feather-icon icon="ChevronUpIcon" svgClasses="w-4 h-4 ml-2 text-white"/>
</div>

ButtonIncidentFloating — Sem Incidentes

Quando o status é operational, a pílula exibe fundo verde (#28C76F) e o texto "Sem Incidentes" com ícone de wifi. Clicar nesta versão não abre dropdown — não há incidente para mostrar. A cor da pílula varia conforme o status retornado pela InStatus API (veja tabela de cores abaixo).

Status atual

Todos os status

operational
partial­outage
under­maintenance
degraded­performance
major­outage
Real src/App.vue:3
<!-- App.vue -->
<ButtonIncidentFloating
  v-if="showIncidentButton"
  class="select-none"
  :isOutPedbot="isOutPedbot"
/>

<!-- ButtonIncidentFloating.vue — pílula operacional -->
<div
  class="incident-pill"
  :style="{ background: statusColor }"
  @click="openDropdown"
>
  <feather-icon icon="WifiIcon" svgClasses="w-4 h-4"/>
  <span>{{ statusLabel }}</span>
</div>

<!-- computed -->
<script>
const STATUS_COLORS = {
  operational:          '#28C76F',
  partialoutage:        '#EC8C19',
  undermaintenance:     '#555555',
  degradedperformance:  '#F4CB16',
  majoroutage:          '#FE4304',
}

computed: {
  statusColor() {
    return STATUS_COLORS[this.incidentInfos?.status] || '#28C76F'
  },
  statusLabel() {
    return this.incidentInfos?.status === 'operational'
      ? 'Sem Incidentes'
      : 'Incidente'
  }
}
</script>

ButtonIncidentFloating — Incidente Ativo + Dropdown

Quando há um incidente ativo (ex: partialoutage), a pílula muda para laranja e o texto passa a "Incidente". Ao clicar, abre um dropdown de 30em de largura com: nome do incidente, chip de impacto (vs-chip), lista de componentes afetados com indicador colorido, e timestamp da última atualização. Em telas de atendimento (chat-attendance) o posicionamento é relative; em rotas de dashboard é fixed alinhado à direita; demais contextos usam absolute; right:60px; top:25px.

Lentidão no envio de mensagens WhatsApp
Partial Outage
Componentes afetados
WhatsApp API — Degraded Performance
MarIA — Operational
Pedbot Admin — Operational
Real src/views/chat-attendance/Index.vue:171
<!-- Index.vue (chat-attendance) -->
<ButtonIncidentFloating
  class="button-incident-floating"
  :isOutPedbot="false"
/>

<!-- ButtonIncidentFloating.vue — dropdown de incidente -->
<vs-dropdown vs-trigger-click>
  <div
    class="incident-pill select-none"
    :style="{ background: statusColor }"
  >
    <feather-icon icon="WifiIcon" svgClasses="w-4 h-4"/>
    <span>{{ statusLabel }}</span>
  </div>

  <vs-dropdown-menu style="width: 30em;">
    <div class="incident-header">
      <p class="incident-name">{{ incidentInfos.name }}</p>
      <vs-chip :color="statusColor">{{ incidentInfos.impact }}</vs-chip>
    </div>

    <vs-list>
      <vs-list-item
        v-for="comp in incidentInfos.components"
        :key="comp.id"
        :title="comp.name"
        :subtitle="comp.status"
      />
    </vs-list>

    <p class="incident-timestamp">
      Última atualização: {{ formattedDate }}
    </p>
  </vs-dropdown-menu>
</vs-dropdown>

API

ButtonFloating — Sem props (lógica interna)

Estado internoTipoDescrição
videos Array Lista de vídeos tutoriais buscados pela rota atual via tutorialVideosApi. length === 1 → link direto; length > 1 → dropdown.
validate Boolean Usuário autenticado + rota válida. Controla visibilidade da barra de chat.
interChatIsActive Boolean Quando true, o painel de chat já está aberto — oculta a pílula.
twoFactorActivated Boolean Quando true (2FA pendente), oculta a barra de chat. Lido de AppActiveUser.twofactor_activity.
isChatAttendancePage Boolean Detectado pela rota atual — oculta a pílula de chat nas telas de atendimento.
unseenMessages Number Total de mensagens não lidas no chat interno. Exibido como badge vermelho. Lido de store/internalUsers.

ButtonFloating — Eventos (Event Bus)

EventoDireçãoDescrição
OpenInternalChat Emite / Escuta Emitido ao clicar na barra de chat. Também escutado para abrir o painel programaticamente de qualquer lugar da aplicação.

ButtonFloating — Condições de visibilidade

!disablePedbotReferences (feature flag hasDpsp) deve ser false para renderizar o componente em Main.vue
validate === true — usuário autenticado
twoFactorActivated === true → pílula de chat oculta
interChatIsActive === true → pílula de chat oculta (painel já aberto)
isChatAttendancePage === true → pílula de chat oculta na tela de atendimento

ButtonFloating — Responsividade

BreakpointDimensãoFonte
Padrão (desktop) width:16rem; height:3.3rem
iOS (≤ 430×932) 130px × 36px; font-size:12px Media query @media (max-width:430px)
Android (≤ 393×873) Similar ao iOS — redução proporcional Media query @media (max-width:393px)

ButtonIncidentFloating — Props

NomeTipoDefaultObrig.Descrição
isOutPedbot Boolean false Não Quando true, desativa o posicionamento needToFix (usado em dashboards). Quando false, o componente infere o posicionamento correto pela rota.

ButtonIncidentFloating — Status e cores

Status (InStatus)CorTexto da pílula
operational #28C76F Sem Incidentes
partialoutage #EC8C19 Incidente
undermaintenance #555555 Incidente
degradedperformance #F4CB16 Incidente
majoroutage #FE4304 Incidente

ButtonIncidentFloating — Posicionamento por contexto

ContextoPositionAlinhamento
Tela de atendimento (chat-attendance) relative Menor, integrado ao layout
Rotas de dashboard (isOutPedbot=false) fixed justify-content: flex-end
Padrão / outros contextos absolute right:60px; top:25px
URL contém "admin-beta" Detectado como ambiente beta — pode alterar comportamento de posicionamento

Dependências

TipoDependência
Vuesax vs-button, vs-dropdown, vs-dropdown-menu, vs-dropdown-item, vs-avatar, vs-chip, vs-list, vs-list-item
Custom InternalChatContactsrc/layouts/components/internal-chat-message/InternalChatContact.vue
Custom feather-icon — ícones HelpCircle, ChevronUp, Wifi, Video
Store layout.features.hasDpsp — feature flag DPSP
Store user.internalUsersunseenMsg por usuário
Store AppActiveUsertwofactor_activity, photoURL
Store internalChatMessages/resetInternalChatMessage — mensagens do chat interno
Store inStatus.incidentInfos — dados de incidente da InStatus API
HTTP tutorialVideosApi — vídeos tutoriais por rota (Pedbot API)
HTTP InStatus API — status operacional e incidentes ativos (via store)
Event Bus $bus.$emit / $bus.$on('OpenInternalChat')

Onde é usado

ArquivoComponenteNota
src/layouts/main/Main.vue:142 ButtonFloating Uso principal — layout raiz do admin. Condicionado por !disablePedbotReferences.
src/App.vue:3 ButtonIncidentFloating Montado na raiz da aplicação. :isOutPedbot varia por rota.
src/views/chat-attendance/Index.vue:171 ButtonIncidentFloating Versão menor com posicionamento relativo. :isOutPedbot="false".
src/views/chat-attendance/NewIndex.vue ButtonIncidentFloating Nova versão da tela de atendimento. Mesmo padrão do Index.vue.