feat: implement template retrieval by ID and enhance error handling in template display for improved user experience
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
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 type { FunctionReference } from 'convex/server';
|
||||||
import type { Id, Doc } from '@sgse-app/backend/convex/_generated/dataModel';
|
import type { Id, Doc } from '@sgse-app/backend/convex/_generated/dataModel';
|
||||||
|
import { resolve } from '$app/paths';
|
||||||
|
|
||||||
const client = useConvexClient();
|
const client = useConvexClient();
|
||||||
const currentUser = useQuery(api.auth.getCurrentUser as FunctionReference<'query'>);
|
const currentUser = useQuery(api.auth.getCurrentUser as FunctionReference<'query'>);
|
||||||
@@ -191,7 +192,7 @@
|
|||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="mb-4 flex items-center justify-between">
|
<div class="mb-4 flex items-center justify-between">
|
||||||
<h2 class="card-title">Templates ({templatesFiltrados.length})</h2>
|
<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
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
class="h-5 w-5"
|
class="h-5 w-5"
|
||||||
@@ -263,7 +264,7 @@
|
|||||||
<td>
|
<td>
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<a
|
<a
|
||||||
href="/ti/notificacoes/templates/{template._id}"
|
href={resolve(`/ti/notificacoes/templates/${template._id}`)}
|
||||||
class="btn btn-sm btn-ghost"
|
class="btn btn-sm btn-ghost"
|
||||||
title="Editar"
|
title="Editar"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -3,29 +3,51 @@
|
|||||||
import { useConvexClient, useQuery } from 'convex-svelte';
|
import { useConvexClient, useQuery } 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 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 { goto } from '$app/navigation';
|
||||||
import { resolve } from '$app/paths';
|
import { resolve } from '$app/paths';
|
||||||
|
|
||||||
const client = useConvexClient();
|
const client = useConvexClient();
|
||||||
const currentUser = useQuery(api.auth.getCurrentUser as FunctionReference<'query'>);
|
const currentUser = useQuery(api.auth.getCurrentUser as FunctionReference<'query'>);
|
||||||
const templatesQuery = useQuery(api.templatesMensagens.listarTemplates, {});
|
|
||||||
|
const templateIdParam = $derived($page.params.id ?? '');
|
||||||
const params = $derived($page.params);
|
|
||||||
const templateIdParam = $derived(params.id ?? '');
|
// Query específica para buscar o template por ID
|
||||||
|
const templateQuery = useQuery(
|
||||||
const templates = $derived.by(() => {
|
api.templatesMensagens.obterTemplatePorId,
|
||||||
if (templatesQuery === undefined || templatesQuery === null) return [];
|
() => {
|
||||||
if ('data' in templatesQuery && templatesQuery.data !== undefined) {
|
if (!templateIdParam) return 'skip';
|
||||||
return Array.isArray(templatesQuery.data) ? templatesQuery.data : [];
|
// 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 carregandoTemplate = $derived(templateQuery === undefined || templateQuery === null);
|
||||||
const lista = templates as Doc<'templatesMensagens'>[];
|
const erroTemplate = $derived.by(() => {
|
||||||
return lista.find((t) => String(t._id) === templateIdParam) ?? null;
|
if (templateQuery && typeof templateQuery === 'object' && 'error' in templateQuery) {
|
||||||
|
return templateQuery.error as Error | string | null;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
});
|
});
|
||||||
|
|
||||||
let nome = $state('');
|
let nome = $state('');
|
||||||
@@ -143,9 +165,25 @@
|
|||||||
<a href={resolve('/ti/notificacoes/templates')} class="btn btn-outline"> Voltar </a>
|
<a href={resolve('/ti/notificacoes/templates')} class="btn btn-outline"> Voltar </a>
|
||||||
</div>
|
</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">
|
<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>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
{#if mensagem}
|
{#if mensagem}
|
||||||
@@ -279,6 +317,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -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)
|
* Criar template customizado (apenas TI_MASTER)
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user