feat: Add 'atas' (minutes/records) management feature, and implement various improvements across UI, backend logic, and authentication.
This commit is contained in:
@@ -1,11 +1,21 @@
|
||||
<script lang="ts">
|
||||
import { useConvexClient, useQuery } from 'convex-svelte';
|
||||
import { api } from '@sgse-app/backend/convex/_generated/api';
|
||||
import { authStore } from '$lib/stores/auth.svelte';
|
||||
import { useConvexClient, useQuery } from 'convex-svelte';
|
||||
import {
|
||||
AlertCircle,
|
||||
CheckCircle2,
|
||||
Eye,
|
||||
EyeOff,
|
||||
Info,
|
||||
Key,
|
||||
Lock,
|
||||
Shield,
|
||||
XCircle
|
||||
} from 'lucide-svelte';
|
||||
import { onMount } from 'svelte';
|
||||
import { goto } from '$app/navigation';
|
||||
import { resolve } from '$app/paths';
|
||||
import { onMount } from 'svelte';
|
||||
import { Key, Eye, EyeOff, CheckCircle2, XCircle, Shield, Lock, AlertCircle, Info } from 'lucide-svelte';
|
||||
import { authStore } from '$lib/stores/auth.svelte';
|
||||
|
||||
const convex = useConvexClient();
|
||||
const currentUser = useQuery(api.auth.getCurrentUser, {});
|
||||
@@ -15,9 +25,9 @@
|
||||
let confirmarSenha = $state('');
|
||||
let carregando = $state(false);
|
||||
let notice = $state<{ type: 'success' | 'error'; message: string } | null>(null);
|
||||
let mostrarSenhaAtual = $state(false);
|
||||
let mostrarNovaSenha = $state(false);
|
||||
let mostrarConfirmarSenha = $state(false);
|
||||
const mostrarSenhaAtual = $state(false);
|
||||
const mostrarNovaSenha = $state(false);
|
||||
const mostrarConfirmarSenha = $state(false);
|
||||
|
||||
onMount(() => {
|
||||
if (!currentUser?.data) {
|
||||
@@ -140,13 +150,15 @@
|
||||
<main class="container mx-auto max-w-4xl px-4 py-8">
|
||||
<!-- Header Moderno -->
|
||||
<div class="mb-8">
|
||||
<div class="bg-linear-to-r from-primary/20 via-primary/10 to-primary/20 rounded-2xl p-6 mb-6 shadow-lg border border-primary/20">
|
||||
<div
|
||||
class="from-primary/20 via-primary/10 to-primary/20 border-primary/20 mb-6 rounded-2xl border bg-linear-to-r p-6 shadow-lg"
|
||||
>
|
||||
<div class="flex items-center gap-4">
|
||||
<div class="p-3 bg-primary/20 rounded-2xl">
|
||||
<Key class="h-8 w-8 text-primary" strokeWidth={2.5} />
|
||||
<div class="bg-primary/20 rounded-2xl p-3">
|
||||
<Key class="text-primary h-8 w-8" strokeWidth={2.5} />
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<h1 class="text-primary text-4xl font-bold mb-2">Alterar Senha</h1>
|
||||
<h1 class="text-primary mb-2 text-4xl font-bold">Alterar Senha</h1>
|
||||
<p class="text-base-content/70 text-lg">
|
||||
Atualize sua senha de acesso ao sistema de forma segura
|
||||
</p>
|
||||
@@ -159,7 +171,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Breadcrumbs -->
|
||||
<div class="breadcrumbs text-sm mb-6">
|
||||
<div class="breadcrumbs mb-6 text-sm">
|
||||
<ul>
|
||||
<li><a href={resolve('/')} class="link link-hover">Dashboard</a></li>
|
||||
<li>Alterar Senha</li>
|
||||
@@ -172,7 +184,7 @@
|
||||
<div
|
||||
class="alert {notice.type === 'success'
|
||||
? 'alert-success'
|
||||
: 'alert-error'} mb-6 shadow-xl animate-in fade-in slide-in-from-top duration-300"
|
||||
: 'alert-error'} animate-in fade-in slide-in-from-top mb-6 shadow-xl duration-300"
|
||||
>
|
||||
{#if notice.type === 'success'}
|
||||
<CheckCircle2 class="h-6 w-6 shrink-0 stroke-current" strokeWidth={2} />
|
||||
@@ -183,25 +195,25 @@
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||||
<div class="grid grid-cols-1 gap-6 lg:grid-cols-3">
|
||||
<!-- Formulário Principal -->
|
||||
<div class="lg:col-span-2">
|
||||
<div
|
||||
class="card bg-base-100 border-base-300/50 border-2 shadow-xl hover:shadow-2xl transition-all duration-300"
|
||||
class="card bg-base-100 border-base-300/50 border-2 shadow-xl transition-all duration-300 hover:shadow-2xl"
|
||||
>
|
||||
<div class="card-body p-8">
|
||||
<div class="flex items-center gap-3 mb-6">
|
||||
<div class="p-2 bg-primary/10 rounded-xl">
|
||||
<Lock class="h-6 w-6 text-primary" strokeWidth={2} />
|
||||
<div class="mb-6 flex items-center gap-3">
|
||||
<div class="bg-primary/10 rounded-xl p-2">
|
||||
<Lock class="text-primary h-6 w-6" strokeWidth={2} />
|
||||
</div>
|
||||
<h2 class="text-2xl font-bold text-base-content">Formulário de Alteração</h2>
|
||||
<h2 class="text-base-content text-2xl font-bold">Formulário de Alteração</h2>
|
||||
</div>
|
||||
|
||||
<form onsubmit={handleSubmit} class="space-y-6">
|
||||
<!-- Senha Atual -->
|
||||
<div class="form-control">
|
||||
<label class="label" for="senha-atual">
|
||||
<span class="label-text font-semibold text-base">Senha Atual</span>
|
||||
<span class="label-text text-base font-semibold">Senha Atual</span>
|
||||
<span class="label-text-alt text-error font-bold">*</span>
|
||||
</label>
|
||||
<div class="relative">
|
||||
@@ -209,22 +221,22 @@
|
||||
id="senha-atual"
|
||||
type={mostrarSenhaAtual ? 'text' : 'password'}
|
||||
placeholder="Digite sua senha atual"
|
||||
class="input input-bordered input-primary w-full pr-12 h-12 text-base"
|
||||
class="input input-bordered input-primary h-12 w-full pr-12 text-base"
|
||||
bind:value={senhaAtual}
|
||||
required
|
||||
disabled={carregando}
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-ghost btn-circle absolute top-1/2 right-2 -translate-y-1/2 hover:bg-primary/10"
|
||||
class="btn btn-sm btn-ghost btn-circle hover:bg-primary/10 absolute top-1/2 right-2 -translate-y-1/2"
|
||||
onclick={() => (mostrarSenhaAtual = !mostrarSenhaAtual)}
|
||||
disabled={carregando}
|
||||
aria-label={mostrarSenhaAtual ? 'Ocultar senha' : 'Mostrar senha'}
|
||||
>
|
||||
{#if mostrarSenhaAtual}
|
||||
<EyeOff class="h-5 w-5 text-base-content/60" strokeWidth={2} />
|
||||
<EyeOff class="text-base-content/60 h-5 w-5" strokeWidth={2} />
|
||||
{:else}
|
||||
<Eye class="h-5 w-5 text-base-content/60" strokeWidth={2} />
|
||||
<Eye class="text-base-content/60 h-5 w-5" strokeWidth={2} />
|
||||
{/if}
|
||||
</button>
|
||||
</div>
|
||||
@@ -233,7 +245,7 @@
|
||||
<!-- Nova Senha -->
|
||||
<div class="form-control">
|
||||
<label class="label" for="nova-senha">
|
||||
<span class="label-text font-semibold text-base">Nova Senha</span>
|
||||
<span class="label-text text-base font-semibold">Nova Senha</span>
|
||||
<span class="label-text-alt text-error font-bold">*</span>
|
||||
</label>
|
||||
<div class="relative">
|
||||
@@ -241,22 +253,22 @@
|
||||
id="nova-senha"
|
||||
type={mostrarNovaSenha ? 'text' : 'password'}
|
||||
placeholder="Digite sua nova senha"
|
||||
class="input input-bordered input-primary w-full pr-12 h-12 text-base"
|
||||
class="input input-bordered input-primary h-12 w-full pr-12 text-base"
|
||||
bind:value={novaSenha}
|
||||
required
|
||||
disabled={carregando}
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-ghost btn-circle absolute top-1/2 right-2 -translate-y-1/2 hover:bg-primary/10"
|
||||
class="btn btn-sm btn-ghost btn-circle hover:bg-primary/10 absolute top-1/2 right-2 -translate-y-1/2"
|
||||
onclick={() => (mostrarNovaSenha = !mostrarNovaSenha)}
|
||||
disabled={carregando}
|
||||
aria-label={mostrarNovaSenha ? 'Ocultar senha' : 'Mostrar senha'}
|
||||
>
|
||||
{#if mostrarNovaSenha}
|
||||
<EyeOff class="h-5 w-5 text-base-content/60" strokeWidth={2} />
|
||||
<EyeOff class="text-base-content/60 h-5 w-5" strokeWidth={2} />
|
||||
{:else}
|
||||
<Eye class="h-5 w-5 text-base-content/60" strokeWidth={2} />
|
||||
<Eye class="text-base-content/60 h-5 w-5" strokeWidth={2} />
|
||||
{/if}
|
||||
</button>
|
||||
</div>
|
||||
@@ -270,7 +282,7 @@
|
||||
<!-- Confirmar Senha -->
|
||||
<div class="form-control">
|
||||
<label class="label" for="confirmar-senha">
|
||||
<span class="label-text font-semibold text-base">Confirmar Nova Senha</span>
|
||||
<span class="label-text text-base font-semibold">Confirmar Nova Senha</span>
|
||||
<span class="label-text-alt text-error font-bold">*</span>
|
||||
</label>
|
||||
<div class="relative">
|
||||
@@ -278,29 +290,31 @@
|
||||
id="confirmar-senha"
|
||||
type={mostrarConfirmarSenha ? 'text' : 'password'}
|
||||
placeholder="Digite novamente sua nova senha"
|
||||
class="input input-bordered input-primary w-full pr-12 h-12 text-base"
|
||||
class="input input-bordered input-primary h-12 w-full pr-12 text-base"
|
||||
bind:value={confirmarSenha}
|
||||
required
|
||||
disabled={carregando}
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-ghost btn-circle absolute top-1/2 right-2 -translate-y-1/2 hover:bg-primary/10"
|
||||
class="btn btn-sm btn-ghost btn-circle hover:bg-primary/10 absolute top-1/2 right-2 -translate-y-1/2"
|
||||
onclick={() => (mostrarConfirmarSenha = !mostrarConfirmarSenha)}
|
||||
disabled={carregando}
|
||||
aria-label={mostrarConfirmarSenha ? 'Ocultar senha' : 'Mostrar senha'}
|
||||
>
|
||||
{#if mostrarConfirmarSenha}
|
||||
<EyeOff class="h-5 w-5 text-base-content/60" strokeWidth={2} />
|
||||
<EyeOff class="text-base-content/60 h-5 w-5" strokeWidth={2} />
|
||||
{:else}
|
||||
<Eye class="h-5 w-5 text-base-content/60" strokeWidth={2} />
|
||||
<Eye class="text-base-content/60 h-5 w-5" strokeWidth={2} />
|
||||
{/if}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Botões -->
|
||||
<div class="flex flex-col sm:flex-row justify-end gap-4 mt-8 pt-6 border-t border-base-300">
|
||||
<div
|
||||
class="border-base-300 mt-8 flex flex-col justify-end gap-4 border-t pt-6 sm:flex-row"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-outline btn-lg flex-1 sm:flex-initial"
|
||||
@@ -312,7 +326,7 @@
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary btn-lg flex-1 sm:flex-initial shadow-lg hover:shadow-xl transition-all duration-200"
|
||||
class="btn btn-primary btn-lg flex-1 shadow-lg transition-all duration-200 hover:shadow-xl sm:flex-initial"
|
||||
disabled={carregando}
|
||||
>
|
||||
{#if carregando}
|
||||
@@ -332,35 +346,33 @@
|
||||
<!-- Sidebar com Informações -->
|
||||
<div class="space-y-6">
|
||||
<!-- Requisitos de Senha -->
|
||||
<div
|
||||
class="card bg-linear-to-br from-info/10 to-info/5 border-2 border-info/20 shadow-lg"
|
||||
>
|
||||
<div class="card from-info/10 to-info/5 border-info/20 border-2 bg-linear-to-br shadow-lg">
|
||||
<div class="card-body p-6">
|
||||
<div class="flex items-center gap-3 mb-4">
|
||||
<div class="p-2 bg-info/20 rounded-xl">
|
||||
<Info class="h-6 w-6 text-info" strokeWidth={2} />
|
||||
<div class="mb-4 flex items-center gap-3">
|
||||
<div class="bg-info/20 rounded-xl p-2">
|
||||
<Info class="text-info h-6 w-6" strokeWidth={2} />
|
||||
</div>
|
||||
<h3 class="text-lg font-bold text-base-content">Requisitos de Senha</h3>
|
||||
<h3 class="text-base-content text-lg font-bold">Requisitos de Senha</h3>
|
||||
</div>
|
||||
<ul class="space-y-3 text-sm">
|
||||
<li class="flex items-start gap-2">
|
||||
<CheckCircle2 class="h-5 w-5 text-success shrink-0 mt-0.5" strokeWidth={2} />
|
||||
<CheckCircle2 class="text-success mt-0.5 h-5 w-5 shrink-0" strokeWidth={2} />
|
||||
<span class="text-base-content/80">Mínimo de 8 caracteres</span>
|
||||
</li>
|
||||
<li class="flex items-start gap-2">
|
||||
<CheckCircle2 class="h-5 w-5 text-success shrink-0 mt-0.5" strokeWidth={2} />
|
||||
<CheckCircle2 class="text-success mt-0.5 h-5 w-5 shrink-0" strokeWidth={2} />
|
||||
<span class="text-base-content/80">Pelo menos uma letra maiúscula (A-Z)</span>
|
||||
</li>
|
||||
<li class="flex items-start gap-2">
|
||||
<CheckCircle2 class="h-5 w-5 text-success shrink-0 mt-0.5" strokeWidth={2} />
|
||||
<CheckCircle2 class="text-success mt-0.5 h-5 w-5 shrink-0" strokeWidth={2} />
|
||||
<span class="text-base-content/80">Pelo menos uma letra minúscula (a-z)</span>
|
||||
</li>
|
||||
<li class="flex items-start gap-2">
|
||||
<CheckCircle2 class="h-5 w-5 text-success shrink-0 mt-0.5" strokeWidth={2} />
|
||||
<CheckCircle2 class="text-success mt-0.5 h-5 w-5 shrink-0" strokeWidth={2} />
|
||||
<span class="text-base-content/80">Pelo menos um número (0-9)</span>
|
||||
</li>
|
||||
<li class="flex items-start gap-2">
|
||||
<CheckCircle2 class="h-5 w-5 text-success shrink-0 mt-0.5" strokeWidth={2} />
|
||||
<CheckCircle2 class="text-success mt-0.5 h-5 w-5 shrink-0" strokeWidth={2} />
|
||||
<span class="text-base-content/80">Pelo menos um caractere especial (!@#$%...)</span>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -369,34 +381,34 @@
|
||||
|
||||
<!-- Dicas de Segurança -->
|
||||
<div
|
||||
class="card bg-linear-to-br from-warning/10 to-warning/5 border-2 border-warning/20 shadow-lg"
|
||||
class="card from-warning/10 to-warning/5 border-warning/20 border-2 bg-linear-to-br shadow-lg"
|
||||
>
|
||||
<div class="card-body p-6">
|
||||
<div class="flex items-center gap-3 mb-4">
|
||||
<div class="p-2 bg-warning/20 rounded-xl">
|
||||
<Shield class="h-6 w-6 text-warning" strokeWidth={2} />
|
||||
<div class="mb-4 flex items-center gap-3">
|
||||
<div class="bg-warning/20 rounded-xl p-2">
|
||||
<Shield class="text-warning h-6 w-6" strokeWidth={2} />
|
||||
</div>
|
||||
<h3 class="text-lg font-bold text-base-content">Dicas de Segurança</h3>
|
||||
<h3 class="text-base-content text-lg font-bold">Dicas de Segurança</h3>
|
||||
</div>
|
||||
<ul class="space-y-3 text-sm">
|
||||
<li class="flex items-start gap-2">
|
||||
<AlertCircle class="h-5 w-5 text-warning shrink-0 mt-0.5" strokeWidth={2} />
|
||||
<AlertCircle class="text-warning mt-0.5 h-5 w-5 shrink-0" strokeWidth={2} />
|
||||
<span class="text-base-content/80">Nunca compartilhe sua senha</span>
|
||||
</li>
|
||||
<li class="flex items-start gap-2">
|
||||
<AlertCircle class="h-5 w-5 text-warning shrink-0 mt-0.5" strokeWidth={2} />
|
||||
<AlertCircle class="text-warning mt-0.5 h-5 w-5 shrink-0" strokeWidth={2} />
|
||||
<span class="text-base-content/80">Use uma senha única para cada sistema</span>
|
||||
</li>
|
||||
<li class="flex items-start gap-2">
|
||||
<AlertCircle class="h-5 w-5 text-warning shrink-0 mt-0.5" strokeWidth={2} />
|
||||
<AlertCircle class="text-warning mt-0.5 h-5 w-5 shrink-0" strokeWidth={2} />
|
||||
<span class="text-base-content/80">Altere sua senha regularmente</span>
|
||||
</li>
|
||||
<li class="flex items-start gap-2">
|
||||
<AlertCircle class="h-5 w-5 text-warning shrink-0 mt-0.5" strokeWidth={2} />
|
||||
<AlertCircle class="text-warning mt-0.5 h-5 w-5 shrink-0" strokeWidth={2} />
|
||||
<span class="text-base-content/80">Evite informações pessoais óbvias</span>
|
||||
</li>
|
||||
<li class="flex items-start gap-2">
|
||||
<AlertCircle class="h-5 w-5 text-warning shrink-0 mt-0.5" strokeWidth={2} />
|
||||
<AlertCircle class="text-warning mt-0.5 h-5 w-5 shrink-0" strokeWidth={2} />
|
||||
<span class="text-base-content/80">Considere usar um gerenciador de senhas</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
Reference in New Issue
Block a user