refactor: integrate current user data across components

- Replaced instances of `authStore` with `currentUser` to streamline user authentication handling.
- Updated permission checks and user-related data retrieval to utilize the new `useQuery` for better performance and clarity.
- Cleaned up component structures and improved formatting for consistency and readability.
- Enhanced error handling and user feedback mechanisms in various components to improve user experience.
This commit is contained in:
2025-11-08 10:52:33 -03:00
parent 01138b3e1c
commit 9a5f2b294d
28 changed files with 2312 additions and 1235 deletions

View File

@@ -1,12 +1,12 @@
<script lang="ts">
import { useQuery, useConvexClient } from "convex-svelte";
import { api } from "@sgse-app/backend/convex/_generated/api";
import { authStore } from "$lib/stores/auth.svelte";
import type { Id } from "@sgse-app/backend/convex/_generated/dataModel";
const client = useConvexClient();
const currentUser = useQuery(api.auth.getCurrentUser, {});
const configAtual = useQuery(api.configuracaoEmail.obterConfigEmail, {});
let servidor = $state("");
let porta = $state(587);
let usuario = $state("");
@@ -17,7 +17,9 @@
let usarTLS = $state(true);
let processando = $state(false);
let testando = $state(false);
let mensagem = $state<{ tipo: "success" | "error"; texto: string } | null>(null);
let mensagem = $state<{ tipo: "success" | "error"; texto: string } | null>(
null,
);
function mostrarMensagem(tipo: "success" | "error", texto: string) {
mensagem = { tipo, texto };
@@ -63,7 +65,13 @@
async function salvarConfiguracao() {
// Validação de campos obrigatórios
if (!servidor?.trim() || !porta || !usuario?.trim() || !emailRemetente?.trim() || !nomeRemetente?.trim()) {
if (
!servidor?.trim() ||
!porta ||
!usuario?.trim() ||
!emailRemetente?.trim() ||
!nomeRemetente?.trim()
) {
mostrarMensagem("error", "Preencha todos os campos obrigatórios");
return;
}
@@ -89,24 +97,27 @@
return;
}
if (!authStore.usuario) {
if (!currentUser?.data) {
mostrarMensagem("error", "Usuário não autenticado");
return;
}
processando = true;
try {
const resultado = await client.mutation(api.configuracaoEmail.salvarConfigEmail, {
servidor: servidor.trim(),
porta: portaNum,
usuario: usuario.trim(),
senha: senha || "", // Senha vazia será tratada no backend
emailRemetente: emailRemetente.trim(),
nomeRemetente: nomeRemetente.trim(),
usarSSL,
usarTLS,
configuradoPorId: authStore.usuario._id as Id<"usuarios">
});
const resultado = await client.mutation(
api.configuracaoEmail.salvarConfigEmail,
{
servidor: servidor.trim(),
porta: portaNum,
usuario: usuario.trim(),
senha: senha || "", // Senha vazia será tratada no backend
emailRemetente: emailRemetente.trim(),
nomeRemetente: nomeRemetente.trim(),
usarSSL,
usarTLS,
configuradoPorId: currentUser.data._id as Id<"usuarios">,
},
);
if (resultado.sucesso) {
mostrarMensagem("success", "Configuração salva com sucesso!");
@@ -137,30 +148,39 @@
testando = true;
try {
const resultado = await client.action(api.configuracaoEmail.testarConexaoSMTP, {
servidor: servidor.trim(),
porta: portaNum,
usuario: usuario.trim(),
senha: senha,
usarSSL,
usarTLS,
});
const resultado = await client.action(
api.configuracaoEmail.testarConexaoSMTP,
{
servidor: servidor.trim(),
porta: portaNum,
usuario: usuario.trim(),
senha: senha,
usarSSL,
usarTLS,
},
);
if (resultado.sucesso) {
mostrarMensagem("success", "Conexão testada com sucesso! Servidor SMTP está respondendo.");
mostrarMensagem(
"success",
"Conexão testada com sucesso! Servidor SMTP está respondendo.",
);
} else {
mostrarMensagem("error", `Erro ao testar conexão: ${resultado.erro}`);
}
} catch (error: any) {
console.error("Erro ao testar conexão:", error);
mostrarMensagem("error", error.message || "Erro ao conectar com o servidor SMTP");
mostrarMensagem(
"error",
error.message || "Erro ao conectar com o servidor SMTP",
);
} finally {
testando = false;
}
}
const statusConfig = $derived(
configAtual?.data?.ativo ? "Configurado" : "Não configurado"
configAtual?.data?.ativo ? "Configurado" : "Não configurado",
);
const isLoading = $derived(configAtual === undefined);
@@ -172,13 +192,28 @@
<div class="flex items-center justify-between mb-6">
<div class="flex items-center gap-4">
<div class="p-3 bg-secondary/10 rounded-xl">
<svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8 text-secondary" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-8 w-8 text-secondary"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
/>
</svg>
</div>
<div>
<h1 class="text-3xl font-bold text-base-content">Configurações de Email (SMTP)</h1>
<p class="text-base-content/60 mt-1">Configurar servidor de email para envio de notificações</p>
<h1 class="text-3xl font-bold text-base-content">
Configurações de Email (SMTP)
</h1>
<p class="text-base-content/60 mt-1">
Configurar servidor de email para envio de notificações
</p>
</div>
</div>
</div>
@@ -226,18 +261,40 @@
<!-- Status -->
{#if !isLoading}
<div class="alert {configAtual?.data?.ativo ? 'alert-success' : 'alert-warning'} mb-6">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="stroke-current shrink-0 w-6 h-6">
<div
class="alert {configAtual?.data?.ativo
? 'alert-success'
: 'alert-warning'} mb-6"
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
class="stroke-current shrink-0 w-6 h-6"
>
{#if configAtual?.data?.ativo}
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
{:else}
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
/>
{/if}
</svg>
<span>
<strong>Status:</strong> {statusConfig}
<strong>Status:</strong>
{statusConfig}
{#if configAtual?.data?.testadoEm}
- Última conexão testada em {new Date(configAtual.data.testadoEm).toLocaleString('pt-BR')}
- Última conexão testada em {new Date(
configAtual.data.testadoEm,
).toLocaleString("pt-BR")}
{/if}
</span>
</div>
@@ -245,182 +302,207 @@
<!-- Formulário -->
{#if !isLoading}
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h2 class="card-title mb-4">Dados do Servidor SMTP</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<!-- Servidor -->
<div class="form-control md:col-span-1">
<label class="label" for="smtp-servidor">
<span class="label-text font-medium">Servidor SMTP *</span>
</label>
<input
id="smtp-servidor"
type="text"
bind:value={servidor}
placeholder="smtp.exemplo.com"
class="input input-bordered"
/>
<div class="label">
<span class="label-text-alt">Ex: smtp.gmail.com, smtp.office365.com</span>
</div>
</div>
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h2 class="card-title mb-4">Dados do Servidor SMTP</h2>
<!-- Porta -->
<div class="form-control">
<label class="label" for="smtp-porta">
<span class="label-text font-medium">Porta *</span>
</label>
<input
id="smtp-porta"
type="number"
bind:value={porta}
placeholder="587"
class="input input-bordered"
/>
<div class="label">
<span class="label-text-alt">Comum: 587 (TLS), 465 (SSL), 25</span>
</div>
</div>
<!-- Usuário -->
<div class="form-control">
<label class="label" for="smtp-usuario">
<span class="label-text font-medium">Usuário/Email *</span>
</label>
<input
id="smtp-usuario"
type="text"
bind:value={usuario}
placeholder="usuario@exemplo.com"
class="input input-bordered"
/>
</div>
<!-- Senha -->
<div class="form-control">
<label class="label" for="smtp-senha">
<span class="label-text font-medium">Senha *</span>
</label>
<input
id="smtp-senha"
type="password"
bind:value={senha}
placeholder="••••••••"
class="input input-bordered"
/>
<div class="label">
<span class="label-text-alt text-warning">
{#if configAtual?.data?.ativo}
Deixe em branco para manter a senha atual
{:else}
Digite a senha da conta de email
{/if}
</span>
</div>
</div>
<!-- Email Remetente -->
<div class="form-control">
<label class="label" for="smtp-email-remetente">
<span class="label-text font-medium">Email Remetente *</span>
</label>
<input
id="smtp-email-remetente"
type="email"
bind:value={emailRemetente}
placeholder="noreply@sgse.pe.gov.br"
class="input input-bordered"
/>
</div>
<!-- Nome Remetente -->
<div class="form-control">
<label class="label" for="smtp-nome-remetente">
<span class="label-text font-medium">Nome Remetente *</span>
</label>
<input
id="smtp-nome-remetente"
type="text"
bind:value={nomeRemetente}
placeholder="SGSE - Sistema de Gestão"
class="input input-bordered"
/>
</div>
</div>
<!-- Opções de Segurança -->
<div class="divider"></div>
<h3 class="font-bold mb-2">Configurações de Segurança</h3>
<div class="flex flex-wrap gap-6">
<div class="form-control">
<label class="label cursor-pointer gap-3">
<input
type="checkbox"
checked={usarSSL}
onchange={toggleSSL}
class="checkbox checkbox-primary"
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<!-- Servidor -->
<div class="form-control md:col-span-1">
<label class="label" for="smtp-servidor">
<span class="label-text font-medium">Servidor SMTP *</span>
</label>
<input
id="smtp-servidor"
type="text"
bind:value={servidor}
placeholder="smtp.exemplo.com"
class="input input-bordered"
/>
<span class="label-text">Usar SSL (porta 465)</span>
</label>
</div>
<div class="form-control">
<label class="label cursor-pointer gap-3">
<input
type="checkbox"
checked={usarTLS}
onchange={toggleTLS}
class="checkbox checkbox-primary"
/>
<span class="label-text">Usar TLS (porta 587)</span>
</label>
</div>
</div>
<div class="label">
<span class="label-text-alt"
>Ex: smtp.gmail.com, smtp.office365.com</span
>
</div>
</div>
<!-- Ações -->
<div class="card-actions justify-end mt-6 gap-3">
<button
class="btn btn-outline btn-info"
onclick={testarConexao}
disabled={testando || processando}
>
{#if testando}
<span class="loading loading-spinner loading-sm"></span>
{:else}
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
{/if}
Testar Conexão
</button>
<button
class="btn btn-primary"
onclick={salvarConfiguracao}
disabled={processando || testando}
>
{#if processando}
<span class="loading loading-spinner loading-sm"></span>
{:else}
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-3m-1 4l-3 3m0 0l-3-3m3 3V4" />
</svg>
{/if}
Salvar Configuração
</button>
<!-- Porta -->
<div class="form-control">
<label class="label" for="smtp-porta">
<span class="label-text font-medium">Porta *</span>
</label>
<input
id="smtp-porta"
type="number"
bind:value={porta}
placeholder="587"
class="input input-bordered"
/>
<div class="label">
<span class="label-text-alt">Comum: 587 (TLS), 465 (SSL), 25</span
>
</div>
</div>
<!-- Usuário -->
<div class="form-control">
<label class="label" for="smtp-usuario">
<span class="label-text font-medium">Usuário/Email *</span>
</label>
<input
id="smtp-usuario"
type="text"
bind:value={usuario}
placeholder="usuario@exemplo.com"
class="input input-bordered"
/>
</div>
<!-- Senha -->
<div class="form-control">
<label class="label" for="smtp-senha">
<span class="label-text font-medium">Senha *</span>
</label>
<input
id="smtp-senha"
type="password"
bind:value={senha}
placeholder="••••••••"
class="input input-bordered"
/>
<div class="label">
<span class="label-text-alt text-warning">
{#if configAtual?.data?.ativo}
Deixe em branco para manter a senha atual
{:else}
Digite a senha da conta de email
{/if}
</span>
</div>
</div>
<!-- Email Remetente -->
<div class="form-control">
<label class="label" for="smtp-email-remetente">
<span class="label-text font-medium">Email Remetente *</span>
</label>
<input
id="smtp-email-remetente"
type="email"
bind:value={emailRemetente}
placeholder="noreply@sgse.pe.gov.br"
class="input input-bordered"
/>
</div>
<!-- Nome Remetente -->
<div class="form-control">
<label class="label" for="smtp-nome-remetente">
<span class="label-text font-medium">Nome Remetente *</span>
</label>
<input
id="smtp-nome-remetente"
type="text"
bind:value={nomeRemetente}
placeholder="SGSE - Sistema de Gestão"
class="input input-bordered"
/>
</div>
</div>
<!-- Opções de Segurança -->
<div class="divider"></div>
<h3 class="font-bold mb-2">Configurações de Segurança</h3>
<div class="flex flex-wrap gap-6">
<div class="form-control">
<label class="label cursor-pointer gap-3">
<input
type="checkbox"
checked={usarSSL}
onchange={toggleSSL}
class="checkbox checkbox-primary"
/>
<span class="label-text">Usar SSL (porta 465)</span>
</label>
</div>
<div class="form-control">
<label class="label cursor-pointer gap-3">
<input
type="checkbox"
checked={usarTLS}
onchange={toggleTLS}
class="checkbox checkbox-primary"
/>
<span class="label-text">Usar TLS (porta 587)</span>
</label>
</div>
</div>
<!-- Ações -->
<div class="card-actions justify-end mt-6 gap-3">
<button
class="btn btn-outline btn-info"
onclick={testarConexao}
disabled={testando || processando}
>
{#if testando}
<span class="loading loading-spinner loading-sm"></span>
{:else}
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
{/if}
Testar Conexão
</button>
<button
class="btn btn-primary"
onclick={salvarConfiguracao}
disabled={processando || testando}
>
{#if processando}
<span class="loading loading-spinner loading-sm"></span>
{:else}
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M8 7H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-3m-1 4l-3 3m0 0l-3-3m3 3V4"
/>
</svg>
{/if}
Salvar Configuração
</button>
</div>
</div>
</div>
</div>
{/if}
<!-- Exemplos Comuns -->
<div class="card bg-base-100 shadow-xl mt-6">
<div class="card-body">
<h2 class="card-title mb-4">Exemplos de Configuração</h2>
<div class="overflow-x-auto">
<table class="table table-sm">
<thead>
@@ -464,13 +546,29 @@
<!-- Avisos -->
<div class="alert alert-info mt-6">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="stroke-current shrink-0 w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
class="stroke-current shrink-0 w-6 h-6"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
></path>
</svg>
<div>
<p><strong>Dica de Segurança:</strong> Para Gmail e outros provedores, você pode precisar gerar uma "senha de app" específica em vez de usar sua senha principal.</p>
<p class="text-sm mt-1">Gmail: Conta Google → Segurança → Verificação em duas etapas → Senhas de app</p>
<p>
<strong>Dica de Segurança:</strong> Para Gmail e outros provedores, você
pode precisar gerar uma "senha de app" específica em vez de usar sua senha
principal.
</p>
<p class="text-sm mt-1">
Gmail: Conta Google → Segurança → Verificação em duas etapas → Senhas de
app
</p>
</div>
</div>
</div>