Toast system_alert ganha botão de ação com deeplink

Novo <Toast group="system-alerts"> no AppLayout com template custom
(vive no bloco global — persiste em qualquer layout/rota). Renderiza:
- Ícone de alerta + título em bold
- Detail em texto menor com opacity
- Botão com deeplink quando payload.deeplink existe, severity danger

Label do botão inferido do deeplink:
- /configuracoes/creditos-whatsapp → "Ir pra loja"
- /configuracoes/whatsapp-pessoal  → "Ver conexão"
- /configuracoes/whatsapp-oficial  → "Ver canal oficial"
- outros → "Abrir" (ou payload.actionLabel se vier explícito)

Clique navega via router.push se é path interno, senão
window.location.href. Toast continua sticky (24h) + closable.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Leonardo
2026-04-23 10:00:18 -03:00
parent 5c50db6704
commit 6db06abfc2
2 changed files with 53 additions and 2 deletions
+38 -1
View File
@@ -17,7 +17,18 @@
<script setup>
import { useLayout } from '@/layout/composables/layout';
import { computed, onMounted, onBeforeUnmount, provide, watch } from 'vue';
import { useRoute } from 'vue-router';
import { useRoute, useRouter } from 'vue-router';
const router = useRouter();
function goToDeeplink(link) {
if (!link) return;
if (typeof link === 'string' && link.startsWith('/')) {
router.push(link);
} else {
window.location.href = link;
}
}
import AppFooter from './AppFooter.vue';
import AppSidebar from './AppSidebar.vue';
@@ -175,6 +186,32 @@ onBeforeUnmount(() => {
<GlobalNoticeBanner />
<ConversationDrawer />
<GlobalInboundNotifier />
<!-- Toast especial pra alertas de sistema (heartbeat, saldo baixo, etc)
vermelho sticky com botão de ação opcional via payload.deeplink -->
<Toast group="system-alerts" position="top-right" :pt="{ root: { style: 'width: 28rem; max-width: 92vw' } }">
<template #message="slotProps">
<div class="flex flex-col gap-2 w-full">
<div class="flex items-start gap-2">
<i class="pi pi-exclamation-circle text-lg mt-0.5" style="color: var(--p-red-500)" />
<div class="flex-1 min-w-0">
<div class="font-bold text-sm">{{ slotProps.message.summary }}</div>
<div class="text-xs mt-0.5 leading-relaxed opacity-85">{{ slotProps.message.detail }}</div>
</div>
</div>
<Button
v-if="slotProps.message.data?.deeplink"
:label="slotProps.message.data?.actionLabel || 'Abrir'"
icon="pi pi-arrow-right"
iconPos="right"
size="small"
severity="danger"
class="rounded-full self-end"
@click="goToDeeplink(slotProps.message.data.deeplink)"
/>
</div>
</template>
</Toast>
</template>
<style>