12
.editorconfig
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# EditorConfig is awesome: https://EditorConfig.org
|
||||||
|
|
||||||
|
# top-most EditorConfig file
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
indent_style = tab
|
||||||
|
indent_size = 2
|
||||||
|
end_of_line = lf
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
insert_final_newline = true
|
||||||
@@ -1,186 +0,0 @@
|
|||||||
# Relatório de Testes - Sistema de Central de Chamados
|
|
||||||
|
|
||||||
**Data:** 16 de novembro de 2025
|
|
||||||
**Testador:** Sistema Automatizado
|
|
||||||
**Página Testada:** `/ti/central-chamados`
|
|
||||||
|
|
||||||
## Resumo Executivo
|
|
||||||
|
|
||||||
Foram realizados testes completos na página de Central de Chamados do sistema SGSE. A maioria das funcionalidades está funcionando corretamente, mas foram identificados alguns problemas que precisam ser corrigidos.
|
|
||||||
|
|
||||||
## Testes Realizados
|
|
||||||
|
|
||||||
### ✅ Testes Bem-Sucedidos
|
|
||||||
|
|
||||||
1. **Login no Sistema**
|
|
||||||
- Status: ✅ PASSOU
|
|
||||||
- Usuário logado: Deyvison (dfw@poli.br)
|
|
||||||
|
|
||||||
2. **Visualização de SLAs Configurados**
|
|
||||||
- Status: ✅ PASSOU
|
|
||||||
- Tabela de SLAs exibe 7 SLAs ativos corretamente
|
|
||||||
- Resumo mostra: 4 Baixa, 2 Média, 1 Alta/Crítica
|
|
||||||
- Detalhes completos (tempos, prioridades) são exibidos corretamente
|
|
||||||
|
|
||||||
3. **Cards de Prioridade**
|
|
||||||
- Status: ✅ PASSOU
|
|
||||||
- Cards mostram corretamente "Configurado" ou "Não configurado"
|
|
||||||
- Botão "Configurar" funciona corretamente
|
|
||||||
- Detalhes dos SLAs configurados são exibidos nos cards
|
|
||||||
|
|
||||||
4. **Criação de SLA**
|
|
||||||
- Status: ✅ PASSOU
|
|
||||||
- SLA criado com sucesso para prioridade "Alta"
|
|
||||||
- Formulário preenche corretamente quando clica em "Configurar"
|
|
||||||
- Tabela atualiza automaticamente após criação
|
|
||||||
- Card de prioridade atualiza para "Configurado"
|
|
||||||
|
|
||||||
5. **Edição de SLA**
|
|
||||||
- Status: ✅ PASSOU
|
|
||||||
- Botão "Editar" abre formulário com dados corretos
|
|
||||||
- Atualização funciona corretamente
|
|
||||||
|
|
||||||
6. **Lista de Chamados**
|
|
||||||
- Status: ✅ PASSOU
|
|
||||||
- 4 chamados sendo exibidos corretamente
|
|
||||||
- Filtros funcionando (status, responsável, setor)
|
|
||||||
- Detalhes do chamado são exibidos ao selecionar
|
|
||||||
|
|
||||||
7. **Atribuição de Responsável**
|
|
||||||
- Status: ✅ PASSOU
|
|
||||||
- Dropdown mostra 2 usuários TI: Deyvison e Suporte_TI
|
|
||||||
- Formulário está funcional
|
|
||||||
|
|
||||||
8. **Prorrogação de Prazo**
|
|
||||||
- Status: ✅ PASSOU
|
|
||||||
- Dropdown de tickets carrega corretamente (4 tickets)
|
|
||||||
- Formulário permite selecionar tipo de prazo e horas
|
|
||||||
- Botão habilita quando todos os campos estão preenchidos
|
|
||||||
|
|
||||||
### ⚠️ Problemas Identificados
|
|
||||||
|
|
||||||
#### 1. Templates de Email - Listagem Após Criação
|
|
||||||
|
|
||||||
- **Status:** ⚠️ PROBLEMA
|
|
||||||
- **Descrição:** Templates são criados com sucesso (mensagem "Templates padrão criados com sucesso" aparece), mas não são listados na interface após criação
|
|
||||||
- **Ação Realizada:** Botão "Criar templates padrão" foi clicado e retornou sucesso
|
|
||||||
- **Comportamento Esperado:** Templates deveriam aparecer em uma lista após criação
|
|
||||||
- **Comportamento Atual:** Seção continua mostrando "Nenhum template encontrado"
|
|
||||||
- **Severidade:** MÉDIA
|
|
||||||
- **Impacto:** Usuários não conseguem visualizar/editar templates de email após criação
|
|
||||||
- **Possível Causa:** Query de templates pode não estar sendo atualizada após criação, ou filtro pode estar excluindo templates de chamados
|
|
||||||
|
|
||||||
#### 2. Warning no Console - Token de Autenticação
|
|
||||||
|
|
||||||
- **Status:** ⚠️ AVISO (Não crítico)
|
|
||||||
- **Descrição:** `⚠️ [useConvexWithAuth] Token não disponível` aparece no console durante carregamento inicial
|
|
||||||
- **Severidade:** BAIXA
|
|
||||||
- **Impacto:** Não afeta funcionalidade (autenticação funciona corretamente após carregamento)
|
|
||||||
- **Observação:** Parece ser um problema de timing durante inicialização da página
|
|
||||||
|
|
||||||
#### 3. Warning no Console - Formato de Query
|
|
||||||
|
|
||||||
- **Status:** ⚠️ AVISO (Não crítico)
|
|
||||||
- **Descrição:** `🔍 [usuariosTI] Formato inesperado: object {data: undefined, isLoading: undefined, error: undefined, isStale: undefined}` aparece no console
|
|
||||||
- **Severidade:** BAIXA
|
|
||||||
- **Impacto:** Não afeta funcionalidade (usuários são carregados corretamente - 2 usuários TI encontrados)
|
|
||||||
- **Observação:** Indica possível inconsistência no formato de retorno da query durante carregamento inicial
|
|
||||||
|
|
||||||
## Detalhes dos Testes
|
|
||||||
|
|
||||||
### Teste de Criação de SLA
|
|
||||||
|
|
||||||
- **Prioridade Testada:** Alta
|
|
||||||
- **Valores Inseridos:**
|
|
||||||
- Nome: "SLA - Alta - Teste"
|
|
||||||
- Tempo de Resposta: 2h
|
|
||||||
- Tempo de Conclusão: 8h
|
|
||||||
- Auto-encerramento: 24h
|
|
||||||
- Alerta: 2h antes
|
|
||||||
- **Resultado:** ✅ SLA criado e exibido na tabela e no card
|
|
||||||
|
|
||||||
### Teste de Edição de SLA
|
|
||||||
|
|
||||||
- **SLA Editado:** Prioridade Baixa
|
|
||||||
- **Alterações:**
|
|
||||||
- Nome: "SLA Baixa - Editado em Teste"
|
|
||||||
- Tempo de Resposta: 6h
|
|
||||||
- **Resultado:** ✅ Atualização bem-sucedida
|
|
||||||
|
|
||||||
### Teste de Prorrogação
|
|
||||||
|
|
||||||
- **Ticket Selecionado:** SGSE-202511-3750
|
|
||||||
- **Prazo:** Conclusão
|
|
||||||
- **Horas Adicionais:** 24h
|
|
||||||
- **Motivo:** "Teste de prorrogação de prazo - necessário mais tempo para análise"
|
|
||||||
- **Resultado:** ✅ Formulário preenchido corretamente, botão habilitado
|
|
||||||
|
|
||||||
## Lista de Erros Encontrados
|
|
||||||
|
|
||||||
### Erros Críticos
|
|
||||||
|
|
||||||
- **Nenhum erro crítico encontrado**
|
|
||||||
|
|
||||||
### Erros de Funcionalidade
|
|
||||||
|
|
||||||
1. **Templates de Email não aparecem após criação**
|
|
||||||
- Localização: Seção "Templates de Email - Chamados"
|
|
||||||
- Ação necessária: Verificar query de templates e atualização reativa após criação
|
|
||||||
|
|
||||||
### Avisos (Warnings)
|
|
||||||
|
|
||||||
1. **Token de autenticação não disponível durante carregamento inicial**
|
|
||||||
- Localização: Console do navegador
|
|
||||||
- Ação necessária: Melhorar timing de inicialização de autenticação
|
|
||||||
|
|
||||||
2. **Formato inesperado de query durante carregamento**
|
|
||||||
- Localização: Console do navegador (usuariosTI)
|
|
||||||
- Ação necessária: Verificar formato de retorno de useQuery do convex-svelte
|
|
||||||
|
|
||||||
## Recomendações
|
|
||||||
|
|
||||||
### Prioridade ALTA
|
|
||||||
|
|
||||||
1. **Corrigir listagem de templates de email após criação**
|
|
||||||
- Verificar se a query `templatesChamados` está sendo atualizada após criação
|
|
||||||
- Verificar se o filtro de templates está correto (deve incluir templates de chamados)
|
|
||||||
- Adicionar refresh automático após criação de templates
|
|
||||||
|
|
||||||
### Prioridade MÉDIA
|
|
||||||
|
|
||||||
2. **Investigar e corrigir warnings no console**
|
|
||||||
- Melhorar timing de autenticação para evitar warning inicial
|
|
||||||
- Padronizar formato de retorno de queries do convex-svelte
|
|
||||||
|
|
||||||
### Prioridade BAIXA
|
|
||||||
|
|
||||||
3. **Melhorar logs de debug**
|
|
||||||
- Reduzir verbosidade de logs informativos
|
|
||||||
- Manter apenas logs de erro e warnings importantes
|
|
||||||
|
|
||||||
## Conclusão
|
|
||||||
|
|
||||||
O sistema está **funcionalmente operacional**, com a maioria das funcionalidades testadas funcionando corretamente:
|
|
||||||
|
|
||||||
✅ **Funcionalidades Testadas e Funcionando:**
|
|
||||||
|
|
||||||
- Login e autenticação
|
|
||||||
- Visualização de SLAs (tabela e cards)
|
|
||||||
- Criação de SLAs
|
|
||||||
- Edição de SLAs
|
|
||||||
- Lista de chamados
|
|
||||||
- Atribuição de responsável
|
|
||||||
- Prorrogação de prazo (formulário funcional)
|
|
||||||
- Criação de templates (backend funciona, frontend não atualiza)
|
|
||||||
|
|
||||||
⚠️ **Problemas Identificados:**
|
|
||||||
|
|
||||||
- Templates não aparecem na lista após criação (problema de atualização reativa)
|
|
||||||
- Warnings no console (não afetam funcionalidade)
|
|
||||||
|
|
||||||
**Status Geral:** ✅ **OPERACIONAL COM PEQUENOS AJUSTES NECESSÁRIOS**
|
|
||||||
|
|
||||||
**Próximos Passos:**
|
|
||||||
|
|
||||||
1. Corrigir atualização reativa de templates após criação
|
|
||||||
2. Investigar e resolver warnings do console (opcional, não crítico)
|
|
||||||
@@ -1,12 +1,11 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { useQuery, useConvexClient } from 'convex-svelte';
|
import { useQuery, useConvexClient } from 'convex-svelte';
|
||||||
import { api } from '@sgse-app/backend/convex/_generated/api';
|
import { api } from '@sgse-app/backend/convex/_generated/api';
|
||||||
|
import type { FunctionReference } from 'convex/server';
|
||||||
import { format } from 'date-fns';
|
import { format } from 'date-fns';
|
||||||
import { ptBR } from 'date-fns/locale';
|
import { ptBR } from 'date-fns/locale';
|
||||||
import type { Id, Doc } from '@sgse-app/backend/convex/_generated/dataModel';
|
import type { Id, Doc } from '@sgse-app/backend/convex/_generated/dataModel';
|
||||||
|
|
||||||
// Tipos para agendamentos
|
|
||||||
type TipoAgendamento = 'email' | 'chat';
|
|
||||||
type StatusAgendamento = 'agendado' | 'enviado' | 'cancelado';
|
type StatusAgendamento = 'agendado' | 'enviado' | 'cancelado';
|
||||||
|
|
||||||
interface AgendamentoEmail {
|
interface AgendamentoEmail {
|
||||||
@@ -43,7 +42,7 @@
|
|||||||
| { tipo: 'chat'; dados: AgendamentoChat };
|
| { tipo: 'chat'; dados: AgendamentoChat };
|
||||||
|
|
||||||
const client = useConvexClient();
|
const client = useConvexClient();
|
||||||
const currentUser = useQuery(api.auth.getCurrentUser, {});
|
const currentUser = useQuery(api.auth.getCurrentUser as FunctionReference<'query'>);
|
||||||
|
|
||||||
// Queries
|
// Queries
|
||||||
const templatesQuery = useQuery(api.templatesMensagens.listarTemplates, {});
|
const templatesQuery = useQuery(api.templatesMensagens.listarTemplates, {});
|
||||||
@@ -57,10 +56,9 @@
|
|||||||
Array.from(emailIdsRastreados).map((id) => id as Id<'notificacoesEmail'>)
|
Array.from(emailIdsRastreados).map((id) => id as Id<'notificacoesEmail'>)
|
||||||
);
|
);
|
||||||
// Usar função para evitar execução quando array está vazio
|
// Usar função para evitar execução quando array está vazio
|
||||||
const emailsStatusQuery = $derived.by(() => {
|
const emailsStatusQuery = useQuery(api.email.buscarEmailsPorIds, () =>
|
||||||
if (emailIdsArray.length === 0) return null;
|
emailIdsArray.length === 0 ? 'skip' : { emailIds: emailIdsArray }
|
||||||
return useQuery(api.email.buscarEmailsPorIds, { emailIds: emailIdsArray });
|
);
|
||||||
});
|
|
||||||
|
|
||||||
// Queries para agendamentos
|
// Queries para agendamentos
|
||||||
const agendamentosEmailQuery = useQuery(api.email.listarAgendamentosEmail, {});
|
const agendamentosEmailQuery = useQuery(api.email.listarAgendamentosEmail, {});
|
||||||
@@ -101,8 +99,8 @@
|
|||||||
const carregandoTemplates = $derived(templatesQuery === undefined || templatesQuery === null);
|
const carregandoTemplates = $derived(templatesQuery === undefined || templatesQuery === null);
|
||||||
const carregandoUsuarios = $derived(usuariosQuery === undefined || usuariosQuery === null);
|
const carregandoUsuarios = $derived(usuariosQuery === undefined || usuariosQuery === null);
|
||||||
|
|
||||||
// Verificar erros de forma mais robusta
|
// Verificar erros de forma mais robusta (código mantido mas variáveis não utilizadas removidas para lint)
|
||||||
const erroTemplates = $derived.by(() => {
|
/* const erroTemplates = $derived.by(() => {
|
||||||
if (templatesQuery === undefined || templatesQuery === null) return false;
|
if (templatesQuery === undefined || templatesQuery === null) return false;
|
||||||
// Verificar se é um objeto com propriedade error
|
// Verificar se é um objeto com propriedade error
|
||||||
if (typeof templatesQuery === 'object' && 'error' in templatesQuery) {
|
if (typeof templatesQuery === 'object' && 'error' in templatesQuery) {
|
||||||
@@ -117,7 +115,7 @@
|
|||||||
return usuariosQuery.error !== undefined && usuariosQuery.error !== null;
|
return usuariosQuery.error !== undefined && usuariosQuery.error !== null;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
}); */
|
||||||
|
|
||||||
// Log para debug (remover depois se necessário)
|
// Log para debug (remover depois se necessário)
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
@@ -566,7 +564,7 @@
|
|||||||
titulo: tituloTemplate.trim(),
|
titulo: tituloTemplate.trim(),
|
||||||
corpo: corpoTemplate.trim(),
|
corpo: corpoTemplate.trim(),
|
||||||
variaveis: variaveis.length > 0 ? variaveis : undefined,
|
variaveis: variaveis.length > 0 ? variaveis : undefined,
|
||||||
criadoPorId: currentUser.data._id as Id<'usuarios'>
|
criadoPorId: currentUser.data!._id as Id<'usuarios'>
|
||||||
});
|
});
|
||||||
|
|
||||||
if (resultado.sucesso) {
|
if (resultado.sucesso) {
|
||||||
@@ -592,6 +590,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function enviarNotificacao() {
|
async function enviarNotificacao() {
|
||||||
|
if (!currentUser?.data) {
|
||||||
|
mostrarMensagem('error', 'Você precisa estar autenticado para enviar notificações.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!enviarParaTodos && !destinatarioId) {
|
if (!enviarParaTodos && !destinatarioId) {
|
||||||
mostrarMensagem('error', "Selecione um destinatário ou marque 'Enviar para todos'");
|
mostrarMensagem('error', "Selecione um destinatário ou marque 'Enviar para todos'");
|
||||||
return;
|
return;
|
||||||
@@ -622,7 +625,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
agendadaPara = dataHora.getTime();
|
agendadaPara = dataHora.getTime();
|
||||||
} catch (error) {
|
} catch {
|
||||||
mostrarMensagem('error', 'Data ou hora inválida');
|
mostrarMensagem('error', 'Data ou hora inválida');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -743,9 +746,9 @@
|
|||||||
templateCodigo: template.codigo,
|
templateCodigo: template.codigo,
|
||||||
variaveis: {
|
variaveis: {
|
||||||
nome: destinatario.nome,
|
nome: destinatario.nome,
|
||||||
matricula: destinatario.matricula
|
matricula: destinatario.matricula || ''
|
||||||
},
|
},
|
||||||
enviadoPor: currentUser.data._id as Id<'usuarios'>,
|
enviadoPor: currentUser.data!._id as Id<'usuarios'>,
|
||||||
agendadaPara: agendadaPara
|
agendadaPara: agendadaPara
|
||||||
});
|
});
|
||||||
if (emailId) {
|
if (emailId) {
|
||||||
@@ -783,7 +786,7 @@
|
|||||||
destinatarioId: destinatario._id as Id<'usuarios'>,
|
destinatarioId: destinatario._id as Id<'usuarios'>,
|
||||||
assunto: 'Notificação do Sistema',
|
assunto: 'Notificação do Sistema',
|
||||||
corpo: mensagemPersonalizada,
|
corpo: mensagemPersonalizada,
|
||||||
enviadoPor: currentUser.data._id as Id<'usuarios'>,
|
enviadoPor: currentUser.data!._id as Id<'usuarios'>,
|
||||||
agendadaPara: agendadaPara
|
agendadaPara: agendadaPara
|
||||||
});
|
});
|
||||||
if (emailId) {
|
if (emailId) {
|
||||||
@@ -946,7 +949,7 @@
|
|||||||
nome: destinatario.nome,
|
nome: destinatario.nome,
|
||||||
matricula: destinatario.matricula || ''
|
matricula: destinatario.matricula || ''
|
||||||
},
|
},
|
||||||
enviadoPor: currentUser.data._id as Id<'usuarios'>,
|
enviadoPor: currentUser.data!._id as Id<'usuarios'>,
|
||||||
agendadaPara: agendadaPara
|
agendadaPara: agendadaPara
|
||||||
});
|
});
|
||||||
if (emailId) {
|
if (emailId) {
|
||||||
@@ -992,11 +995,10 @@
|
|||||||
destinatarioId: destinatario._id as Id<'usuarios'>,
|
destinatarioId: destinatario._id as Id<'usuarios'>,
|
||||||
assunto: 'Notificação do Sistema',
|
assunto: 'Notificação do Sistema',
|
||||||
corpo: mensagemPersonalizada,
|
corpo: mensagemPersonalizada,
|
||||||
enviadoPor: currentUser.data?._id as Id<'usuarios'>,
|
enviadoPor: currentUser.data!._id as Id<'usuarios'>,
|
||||||
agendadaPara: agendadaPara
|
agendadaPara: agendadaPara
|
||||||
});
|
});
|
||||||
if (emailId) {
|
if (emailId) {
|
||||||
resultadoEmail = { sucesso: true, emailId };
|
|
||||||
if (agendadaPara) {
|
if (agendadaPara) {
|
||||||
const dataFormatada = format(
|
const dataFormatada = format(
|
||||||
new Date(agendadaPara),
|
new Date(agendadaPara),
|
||||||
@@ -1203,7 +1205,7 @@
|
|||||||
{#if carregandoUsuarios}
|
{#if carregandoUsuarios}
|
||||||
<option disabled>Carregando usuários...</option>
|
<option disabled>Carregando usuários...</option>
|
||||||
{:else if usuarios.length > 0}
|
{:else if usuarios.length > 0}
|
||||||
{#each usuarios as usuario}
|
{#each usuarios as usuario (usuario._id)}
|
||||||
<option value={usuario._id}>
|
<option value={usuario._id}>
|
||||||
{usuario.nome} ({usuario.matricula})
|
{usuario.nome} ({usuario.matricula})
|
||||||
</option>
|
</option>
|
||||||
@@ -1213,11 +1215,11 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</select>
|
</select>
|
||||||
{#if enviarParaTodos}
|
{#if enviarParaTodos}
|
||||||
<label class="label">
|
<div class="label">
|
||||||
<span class="label-text-alt text-warning">
|
<span class="label-text-alt text-warning">
|
||||||
⚠️ A notificação será enviada para todos os {usuarios.length} usuários do sistema
|
⚠️ A notificação será enviada para todos os {usuarios.length} usuários do sistema
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -1280,7 +1282,7 @@
|
|||||||
{#if carregandoTemplates}
|
{#if carregandoTemplates}
|
||||||
<option disabled>Carregando templates...</option>
|
<option disabled>Carregando templates...</option>
|
||||||
{:else if templates.length > 0}
|
{:else if templates.length > 0}
|
||||||
{#each templates as template}
|
{#each templates as template (template._id)}
|
||||||
<option value={template._id}>
|
<option value={template._id}>
|
||||||
{template.nome}
|
{template.nome}
|
||||||
</option>
|
</option>
|
||||||
@@ -1440,9 +1442,9 @@
|
|||||||
<!-- Terminal de Status -->
|
<!-- Terminal de Status -->
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
<div class="mb-2 flex items-center justify-between">
|
<div class="mb-2 flex items-center justify-between">
|
||||||
<label class="label">
|
<div class="label pl-0">
|
||||||
<span class="label-text font-medium">Terminal de Status</span>
|
<span class="label-text font-medium">Terminal de Status</span>
|
||||||
</label>
|
</div>
|
||||||
{#if logsEnvio.length > 0}
|
{#if logsEnvio.length > 0}
|
||||||
<button type="button" class="btn btn-sm btn-ghost" onclick={limparLogs}>
|
<button type="button" class="btn btn-sm btn-ghost" onclick={limparLogs}>
|
||||||
<svg
|
<svg
|
||||||
@@ -1471,7 +1473,7 @@
|
|||||||
{#if logsEnvio.length === 0}
|
{#if logsEnvio.length === 0}
|
||||||
<div class="text-neutral-content/60 italic">Aguardando envio de notificação...</div>
|
<div class="text-neutral-content/60 italic">Aguardando envio de notificação...</div>
|
||||||
{:else}
|
{:else}
|
||||||
{#each logsEnvio as log}
|
{#each logsEnvio as log, i (i)}
|
||||||
<div class="mb-1">
|
<div class="mb-1">
|
||||||
<span class="text-neutral-content/60">[{formatarTimestamp(log.timestamp)}]</span>
|
<span class="text-neutral-content/60">[{formatarTimestamp(log.timestamp)}]</span>
|
||||||
<span
|
<span
|
||||||
@@ -1529,7 +1531,7 @@
|
|||||||
{:else if templates.length > 0}
|
{:else if templates.length > 0}
|
||||||
<!-- Mostrar templates se existirem -->
|
<!-- Mostrar templates se existirem -->
|
||||||
<div class="max-h-[600px] space-y-3 overflow-y-auto">
|
<div class="max-h-[600px] space-y-3 overflow-y-auto">
|
||||||
{#each templates as template}
|
{#each templates as template (template._id)}
|
||||||
<div class="card bg-base-200 compact">
|
<div class="card bg-base-200 compact">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="flex items-start justify-between">
|
<div class="flex items-start justify-between">
|
||||||
@@ -1731,17 +1733,11 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{#each agendamentosFiltrados as agendamento}
|
{#each agendamentosFiltrados as agendamento (agendamento.dados._id)}
|
||||||
{@const status = obterStatusAgendamento(agendamento)}
|
{@const status = obterStatusAgendamento(agendamento)}
|
||||||
{@const nomeDestinatario = obterNomeDestinatario(agendamento)}
|
{@const nomeDestinatario = obterNomeDestinatario(agendamento)}
|
||||||
{@const dataFormatada = formatarDataAgendamento(agendamento)}
|
{@const dataFormatada = formatarDataAgendamento(agendamento)}
|
||||||
{@const podeCancelar = status === 'agendado'}
|
{@const podeCancelar = status === 'agendado'}
|
||||||
{@const templateNome =
|
|
||||||
agendamento.tipo === 'email' && agendamento.dados.templateInfo
|
|
||||||
? agendamento.dados.templateInfo.nome
|
|
||||||
: agendamento.tipo === 'email' && agendamento.dados.templateId
|
|
||||||
? 'Template removido'
|
|
||||||
: '-'}
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
@@ -1898,18 +1894,19 @@
|
|||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<!-- Código -->
|
<!-- Código -->
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<label class="label">
|
<label class="label" for="codigo-template">
|
||||||
<span class="label-text font-medium">Código *</span>
|
<span class="label-text font-medium">Código *</span>
|
||||||
<span class="label-text-alt">Ex: AVISO_IMPORTANTE</span>
|
<span class="label-text-alt">Ex: AVISO_IMPORTANTE</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
|
id="codigo-template"
|
||||||
type="text"
|
type="text"
|
||||||
bind:value={codigoTemplate}
|
bind:value={codigoTemplate}
|
||||||
placeholder="CODIGO_TEMPLATE"
|
placeholder="CODIGO_TEMPLATE"
|
||||||
class="input input-bordered"
|
class="input input-bordered"
|
||||||
maxlength="50"
|
maxlength="50"
|
||||||
/>
|
/>
|
||||||
<label class="label">
|
<label class="label" for="codigo-template">
|
||||||
<span class="label-text-alt"
|
<span class="label-text-alt"
|
||||||
>Código único para identificar o template (será convertido para MAIÚSCULAS)</span
|
>Código único para identificar o template (será convertido para MAIÚSCULAS)</span
|
||||||
>
|
>
|
||||||
@@ -1918,34 +1915,36 @@
|
|||||||
|
|
||||||
<!-- Nome -->
|
<!-- Nome -->
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<label class="label">
|
<label class="label" for="nome-template">
|
||||||
<span class="label-text font-medium">Nome *</span>
|
<span class="label-text font-medium">Nome *</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
|
id="nome-template"
|
||||||
type="text"
|
type="text"
|
||||||
bind:value={nomeTemplate}
|
bind:value={nomeTemplate}
|
||||||
placeholder="Nome do Template"
|
placeholder="Nome do Template"
|
||||||
class="input input-bordered"
|
class="input input-bordered"
|
||||||
maxlength="100"
|
maxlength="100"
|
||||||
/>
|
/>
|
||||||
<label class="label">
|
<label class="label" for="nome-template">
|
||||||
<span class="label-text-alt">Nome exibido na lista de templates</span>
|
<span class="label-text-alt">Nome exibido na lista de templates</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Título -->
|
<!-- Título -->
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<label class="label">
|
<label class="label" for="titulo-template">
|
||||||
<span class="label-text font-medium">Título *</span>
|
<span class="label-text font-medium">Título *</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
|
id="titulo-template"
|
||||||
type="text"
|
type="text"
|
||||||
bind:value={tituloTemplate}
|
bind:value={tituloTemplate}
|
||||||
placeholder="Título da Mensagem"
|
placeholder="Título da Mensagem"
|
||||||
class="input input-bordered"
|
class="input input-bordered"
|
||||||
maxlength="200"
|
maxlength="200"
|
||||||
/>
|
/>
|
||||||
<label class="label">
|
<label class="label" for="titulo-template">
|
||||||
<span class="label-text-alt"
|
<span class="label-text-alt"
|
||||||
>Título usado no assunto do email ou cabeçalho da mensagem</span
|
>Título usado no assunto do email ou cabeçalho da mensagem</span
|
||||||
>
|
>
|
||||||
@@ -1954,35 +1953,37 @@
|
|||||||
|
|
||||||
<!-- Corpo -->
|
<!-- Corpo -->
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<label class="label">
|
<label class="label" for="corpo-template">
|
||||||
<span class="label-text font-medium">Corpo da Mensagem *</span>
|
<span class="label-text font-medium">Corpo da Mensagem *</span>
|
||||||
</label>
|
</label>
|
||||||
<textarea
|
<textarea
|
||||||
|
id="corpo-template"
|
||||||
bind:value={corpoTemplate}
|
bind:value={corpoTemplate}
|
||||||
placeholder="Digite o conteúdo da mensagem..."
|
placeholder="Digite o conteúdo da mensagem..."
|
||||||
class="textarea textarea-bordered h-32"
|
class="textarea textarea-bordered h-32"
|
||||||
maxlength="2000"
|
maxlength="2000"
|
||||||
></textarea>
|
></textarea>
|
||||||
<label class="label">
|
<label class="label" for="corpo-template">
|
||||||
<span class="label-text-alt"
|
<span class="label-text-alt"
|
||||||
>Use {'{{'}variavel{'}}'} para variáveis dinâmicas (ex: {'{{'}nome{'}}'},
|
>Use {{variavel}} para variáveis dinâmicas (ex: {{nome}},
|
||||||
{'{{'}data{'}}'})</span
|
{{data}})</span
|
||||||
>
|
>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Variáveis -->
|
<!-- Variáveis -->
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<label class="label">
|
<label class="label" for="variaveis-template">
|
||||||
<span class="label-text font-medium">Variáveis (opcional)</span>
|
<span class="label-text font-medium">Variáveis (opcional)</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
|
id="variaveis-template"
|
||||||
type="text"
|
type="text"
|
||||||
bind:value={variaveisTemplate}
|
bind:value={variaveisTemplate}
|
||||||
placeholder="nome, data, valor (separadas por vírgula)"
|
placeholder="nome, data, valor (separadas por vírgula)"
|
||||||
class="input input-bordered"
|
class="input input-bordered"
|
||||||
/>
|
/>
|
||||||
<label class="label">
|
<label class="label" for="variaveis-template">
|
||||||
<span class="label-text-alt"
|
<span class="label-text-alt"
|
||||||
>Liste as variáveis que podem ser substituídas no template (separadas por vírgula ou
|
>Liste as variáveis que podem ser substituídas no template (separadas por vírgula ou
|
||||||
espaço)</span
|
espaço)</span
|
||||||
@@ -2019,6 +2020,6 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-backdrop" onclick={fecharModalNovoTemplate}></div>
|
<button class="modal-backdrop" onclick={fecharModalNovoTemplate}>fechar</button>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 117 KiB |
|
Before Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 300 KiB |
|
Before Width: | Height: | Size: 117 KiB |
|
Before Width: | Height: | Size: 300 KiB |
|
Before Width: | Height: | Size: 276 KiB |
|
Before Width: | Height: | Size: 287 KiB |
@@ -162,6 +162,29 @@ export const enfileirarEmail = mutation({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancelar agendamento de email
|
||||||
|
*/
|
||||||
|
export const cancelarAgendamentoEmail = mutation({
|
||||||
|
args: {
|
||||||
|
emailId: v.id("notificacoesEmail"),
|
||||||
|
},
|
||||||
|
handler: async (ctx, args) => {
|
||||||
|
const email = await ctx.db.get(args.emailId);
|
||||||
|
if (!email) {
|
||||||
|
return { sucesso: false, erro: "Email não encontrado" };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (email.status !== "pendente") {
|
||||||
|
return { sucesso: false, erro: "Apenas emails pendentes podem ser cancelados" };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove o email da fila
|
||||||
|
await ctx.db.delete(args.emailId);
|
||||||
|
return { sucesso: true };
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enviar email usando template
|
* Enviar email usando template
|
||||||
*/
|
*/
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 301 KiB |