feat: implement template retrieval by ID and enhance error handling in template display for improved user experience

This commit is contained in:
2025-12-01 19:54:33 -03:00
parent 8fabb4149c
commit 6e836e9eb5
3 changed files with 72 additions and 19 deletions

View File

@@ -3,6 +3,7 @@
import { api } from '@sgse-app/backend/convex/_generated/api';
import type { FunctionReference } from 'convex/server';
import type { Id, Doc } from '@sgse-app/backend/convex/_generated/dataModel';
import { resolve } from '$app/paths';
const client = useConvexClient();
const currentUser = useQuery(api.auth.getCurrentUser as FunctionReference<'query'>);
@@ -191,7 +192,7 @@
<div class="card-body">
<div class="mb-4 flex items-center justify-between">
<h2 class="card-title">Templates ({templatesFiltrados.length})</h2>
<a href="/ti/notificacoes/templates/novo" class="btn btn-primary gap-2">
<a href={resolve('/ti/notificacoes/templates/novo')} class="btn btn-primary gap-2">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
@@ -263,7 +264,7 @@
<td>
<div class="flex gap-2">
<a
href="/ti/notificacoes/templates/{template._id}"
href={resolve(`/ti/notificacoes/templates/${template._id}`)}
class="btn btn-sm btn-ghost"
title="Editar"
>

View File

@@ -3,29 +3,51 @@
import { useConvexClient, useQuery } from 'convex-svelte';
import { api } from '@sgse-app/backend/convex/_generated/api';
import type { FunctionReference } from 'convex/server';
import type { Doc } from '@sgse-app/backend/convex/_generated/dataModel';
import type { Doc, Id } from '@sgse-app/backend/convex/_generated/dataModel';
import { goto } from '$app/navigation';
import { resolve } from '$app/paths';
const client = useConvexClient();
const currentUser = useQuery(api.auth.getCurrentUser as FunctionReference<'query'>);
const templatesQuery = useQuery(api.templatesMensagens.listarTemplates, {});
const params = $derived($page.params);
const templateIdParam = $derived(params.id ?? '');
const templates = $derived.by(() => {
if (templatesQuery === undefined || templatesQuery === null) return [];
if ('data' in templatesQuery && templatesQuery.data !== undefined) {
return Array.isArray(templatesQuery.data) ? templatesQuery.data : [];
const templateIdParam = $derived($page.params.id ?? '');
// Query específica para buscar o template por ID
const templateQuery = useQuery(
api.templatesMensagens.obterTemplatePorId,
() => {
if (!templateIdParam) return 'skip';
// Validar se o ID tem o formato correto do Convex
if (typeof templateIdParam === 'string' && templateIdParam.length > 0) {
return { templateId: templateIdParam as Id<'templatesMensagens'> };
}
return 'skip';
}
if (Array.isArray(templatesQuery)) return templatesQuery;
return [];
);
// Extrair template da query
const template = $derived.by(() => {
if (templateQuery === undefined || templateQuery === null) return null;
// useQuery retorna os dados diretamente
if (templateQuery && typeof templateQuery === 'object') {
// Se tem propriedade data, usar ela
if ('data' in templateQuery && templateQuery.data !== undefined && templateQuery.data !== null) {
return templateQuery.data as Doc<'templatesMensagens'> | null;
}
// Caso contrário, assumir que é o próprio template
if (!('data' in templateQuery)) {
return templateQuery as Doc<'templatesMensagens'> | null;
}
}
return null;
});
const template = $derived.by(() => {
const lista = templates as Doc<'templatesMensagens'>[];
return lista.find((t) => String(t._id) === templateIdParam) ?? null;
const carregandoTemplate = $derived(templateQuery === undefined || templateQuery === null);
const erroTemplate = $derived.by(() => {
if (templateQuery && typeof templateQuery === 'object' && 'error' in templateQuery) {
return templateQuery.error as Error | string | null;
}
return null;
});
let nome = $state('');
@@ -143,9 +165,25 @@
<a href={resolve('/ti/notificacoes/templates')} class="btn btn-outline"> Voltar </a>
</div>
{#if !template}
{#if carregandoTemplate}
<div class="flex flex-col items-center justify-center gap-4 py-10">
<span class="loading loading-spinner loading-lg"></span>
<p class="text-base-content/60 text-sm">Carregando template...</p>
</div>
{:else if erroTemplate}
<div class="alert alert-error">
<span>Template não encontrado.</span>
<span>Erro ao carregar template: {typeof erroTemplate === 'string' ? erroTemplate : erroTemplate?.message || 'Erro desconhecido'}</span>
<a href={resolve('/ti/notificacoes/templates')} class="btn btn-sm btn-outline">
Voltar para Templates
</a>
</div>
{:else if !template}
<div class="alert alert-error">
<span>Template não encontrado. Verifique se o ID está correto.</span>
<div class="text-xs mt-2 opacity-70">ID: {templateIdParam}</div>
<a href={resolve('/ti/notificacoes/templates')} class="btn btn-sm btn-outline mt-2">
Voltar para Templates
</a>
</div>
{:else}
{#if mensagem}
@@ -279,6 +317,7 @@
{/if}
</button>
</div>
</div>
</div>
{/if}
</div>

View File

@@ -32,6 +32,19 @@ export const obterTemplatePorCodigo = query({
},
});
/**
* Obter template por ID
*/
export const obterTemplatePorId = query({
args: {
templateId: v.id("templatesMensagens"),
},
handler: async (ctx, args) => {
const template = await ctx.db.get(args.templateId);
return template;
},
});
/**
* Criar template customizado (apenas TI_MASTER)
*/