feat: integrate UserAvatar component in absence management to display user profile pictures alongside names for improved user experience
This commit is contained in:
71
apps/web/src/routes/(dashboard)/+error.svelte
Normal file
71
apps/web/src/routes/(dashboard)/+error.svelte
Normal file
@@ -0,0 +1,71 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { goto } from '$app/navigation';
|
||||
import { Home, ArrowLeft, AlertCircle, FileQuestion } from 'lucide-svelte';
|
||||
|
||||
const is404 = $derived($page.status === 404);
|
||||
const is500 = $derived($page.status === 500 || ($page.status ?? 0) >= 500);
|
||||
const status = $derived($page.status ?? 500);
|
||||
const errorMessage = $derived($page.error?.message);
|
||||
</script>
|
||||
|
||||
<div class="flex min-h-[60vh] items-center justify-center p-4">
|
||||
<div class="card w-full max-w-2xl bg-base-100 shadow-xl">
|
||||
<div class="card-body text-center">
|
||||
{#if is404}
|
||||
<div class="mb-6 flex justify-center">
|
||||
<div class="bg-warning/10 rounded-full p-6">
|
||||
<FileQuestion class="text-warning h-24 w-24" />
|
||||
</div>
|
||||
</div>
|
||||
<h1 class="text-base-content mb-4 text-6xl font-bold">404</h1>
|
||||
<h2 class="text-base-content mb-2 text-3xl font-semibold">Página não encontrada</h2>
|
||||
<p class="text-base-content/70 mb-8 text-lg">
|
||||
A página que você está procurando não existe ou foi movida.
|
||||
</p>
|
||||
{:else if is500}
|
||||
<div class="mb-6 flex justify-center">
|
||||
<div class="bg-error/10 rounded-full p-6">
|
||||
<AlertCircle class="text-error h-24 w-24" />
|
||||
</div>
|
||||
</div>
|
||||
<h1 class="text-base-content mb-4 text-6xl font-bold">500</h1>
|
||||
<h2 class="text-base-content mb-2 text-3xl font-semibold">Erro interno do servidor</h2>
|
||||
<p class="text-base-content/70 mb-8 text-lg">
|
||||
Ocorreu um erro inesperado. Nossa equipe foi notificada e está trabalhando para resolver o problema.
|
||||
</p>
|
||||
{:else}
|
||||
<div class="mb-6 flex justify-center">
|
||||
<div class="bg-error/10 rounded-full p-6">
|
||||
<AlertCircle class="text-error h-24 w-24" />
|
||||
</div>
|
||||
</div>
|
||||
<h1 class="text-base-content mb-4 text-6xl font-bold">{status}</h1>
|
||||
<h2 class="text-base-content mb-2 text-3xl font-semibold">Erro</h2>
|
||||
<p class="text-base-content/70 mb-8 text-lg">
|
||||
{errorMessage || 'Ocorreu um erro inesperado.'}
|
||||
</p>
|
||||
{/if}
|
||||
|
||||
<div class="card-actions justify-center gap-4">
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
onclick={() => goto('/')}
|
||||
type="button"
|
||||
>
|
||||
<Home class="h-5 w-5" />
|
||||
Voltar ao Início
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-ghost"
|
||||
onclick={() => window.history.back()}
|
||||
type="button"
|
||||
>
|
||||
<ArrowLeft class="h-5 w-5" />
|
||||
Voltar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
import ExcelJS from 'exceljs';
|
||||
import logoGovPE from '$lib/assets/logo_governo_PE.png';
|
||||
import { toast } from 'svelte-sonner';
|
||||
import UserAvatar from '$lib/components/chat/UserAvatar.svelte';
|
||||
|
||||
const client = useConvexClient();
|
||||
const currentUser = useQuery(api.auth.getCurrentUser, {});
|
||||
@@ -672,8 +673,17 @@
|
||||
<tbody>
|
||||
{#each ausenciasFiltradas as ausencia}
|
||||
<tr>
|
||||
<td class="font-semibold">
|
||||
{ausencia.funcionario?.nome || 'N/A'}
|
||||
<td>
|
||||
<div class="flex items-center gap-3">
|
||||
<UserAvatar
|
||||
fotoPerfilUrl={ausencia.funcionario?.fotoPerfilUrl}
|
||||
nome={ausencia.funcionario?.nome || 'N/A'}
|
||||
size="sm"
|
||||
/>
|
||||
<span class="font-semibold">
|
||||
{ausencia.funcionario?.nome || 'N/A'}
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
{#if ausencia.time}
|
||||
|
||||
71
apps/web/src/routes/+error.svelte
Normal file
71
apps/web/src/routes/+error.svelte
Normal file
@@ -0,0 +1,71 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { goto } from '$app/navigation';
|
||||
import { Home, ArrowLeft, AlertCircle, FileQuestion } from 'lucide-svelte';
|
||||
|
||||
const is404 = $derived($page.status === 404);
|
||||
const is500 = $derived($page.status === 500 || ($page.status ?? 0) >= 500);
|
||||
const status = $derived($page.status ?? 500);
|
||||
const errorMessage = $derived($page.error?.message);
|
||||
</script>
|
||||
|
||||
<div class="flex min-h-screen items-center justify-center bg-base-200 p-4">
|
||||
<div class="card w-full max-w-2xl bg-base-100 shadow-xl">
|
||||
<div class="card-body text-center">
|
||||
{#if is404}
|
||||
<div class="mb-6 flex justify-center">
|
||||
<div class="bg-warning/10 rounded-full p-6">
|
||||
<FileQuestion class="text-warning h-24 w-24" />
|
||||
</div>
|
||||
</div>
|
||||
<h1 class="text-base-content mb-4 text-6xl font-bold">404</h1>
|
||||
<h2 class="text-base-content mb-2 text-3xl font-semibold">Página não encontrada</h2>
|
||||
<p class="text-base-content/70 mb-8 text-lg">
|
||||
A página que você está procurando não existe ou foi movida.
|
||||
</p>
|
||||
{:else if is500}
|
||||
<div class="mb-6 flex justify-center">
|
||||
<div class="bg-error/10 rounded-full p-6">
|
||||
<AlertCircle class="text-error h-24 w-24" />
|
||||
</div>
|
||||
</div>
|
||||
<h1 class="text-base-content mb-4 text-6xl font-bold">500</h1>
|
||||
<h2 class="text-base-content mb-2 text-3xl font-semibold">Erro interno do servidor</h2>
|
||||
<p class="text-base-content/70 mb-8 text-lg">
|
||||
Ocorreu um erro inesperado. Nossa equipe foi notificada e está trabalhando para resolver o problema.
|
||||
</p>
|
||||
{:else}
|
||||
<div class="mb-6 flex justify-center">
|
||||
<div class="bg-error/10 rounded-full p-6">
|
||||
<AlertCircle class="text-error h-24 w-24" />
|
||||
</div>
|
||||
</div>
|
||||
<h1 class="text-base-content mb-4 text-6xl font-bold">{status}</h1>
|
||||
<h2 class="text-base-content mb-2 text-3xl font-semibold">Erro</h2>
|
||||
<p class="text-base-content/70 mb-8 text-lg">
|
||||
{errorMessage || 'Ocorreu um erro inesperado.'}
|
||||
</p>
|
||||
{/if}
|
||||
|
||||
<div class="card-actions justify-center gap-4">
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
onclick={() => goto('/')}
|
||||
type="button"
|
||||
>
|
||||
<Home class="h-5 w-5" />
|
||||
Voltar ao Início
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-ghost"
|
||||
onclick={() => window.history.back()}
|
||||
type="button"
|
||||
>
|
||||
<ArrowLeft class="h-5 w-5" />
|
||||
Voltar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -29,9 +29,26 @@ export const listarTodas = query({
|
||||
time = await ctx.db.get(membroTime.timeId);
|
||||
}
|
||||
|
||||
// Buscar usuário do funcionário para obter fotoPerfilUrl
|
||||
let fotoPerfilUrl: string | null = null;
|
||||
if (funcionario) {
|
||||
const usuario = await ctx.db
|
||||
.query('usuarios')
|
||||
.withIndex('by_funcionarioId', (q) => q.eq('funcionarioId', funcionario._id))
|
||||
.first();
|
||||
if (usuario?.fotoPerfil) {
|
||||
fotoPerfilUrl = await ctx.storage.getUrl(usuario.fotoPerfil);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...s,
|
||||
funcionario,
|
||||
funcionario: funcionario
|
||||
? {
|
||||
...funcionario,
|
||||
fotoPerfilUrl
|
||||
}
|
||||
: null,
|
||||
time
|
||||
};
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user