feat: add UserAvatar component to display employee profile pictures in absence and vacation requests; update backend to include profile picture URLs for employees
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 { Id, Doc } from '@sgse-app/backend/convex/_generated/dataModel';
|
import type { Id, Doc } from '@sgse-app/backend/convex/_generated/dataModel';
|
||||||
import ErrorModal from './ErrorModal.svelte';
|
import ErrorModal from './ErrorModal.svelte';
|
||||||
|
import UserAvatar from './chat/UserAvatar.svelte';
|
||||||
|
|
||||||
type SolicitacaoAusencia = Doc<'solicitacoesAusencias'> & {
|
type SolicitacaoAusencia = Doc<'solicitacoesAusencias'> & {
|
||||||
funcionario?: Doc<'funcionarios'> | null;
|
funcionario?: Doc<'funcionarios'> | null;
|
||||||
@@ -166,9 +167,16 @@
|
|||||||
<p class="mb-2 text-sm font-semibold uppercase tracking-wide text-base-content/60">
|
<p class="mb-2 text-sm font-semibold uppercase tracking-wide text-base-content/60">
|
||||||
Nome
|
Nome
|
||||||
</p>
|
</p>
|
||||||
<p class="text-lg font-bold text-base-content">
|
<div class="flex items-center gap-3">
|
||||||
{solicitacao.funcionario?.nome || 'N/A'}
|
<UserAvatar
|
||||||
</p>
|
fotoPerfilUrl={solicitacao.funcionario?.fotoPerfilUrl}
|
||||||
|
nome={solicitacao.funcionario?.nome || 'N/A'}
|
||||||
|
size="md"
|
||||||
|
/>
|
||||||
|
<p class="text-lg font-bold text-base-content">
|
||||||
|
{solicitacao.funcionario?.nome || 'N/A'}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{#if solicitacao.time}
|
{#if solicitacao.time}
|
||||||
<div class="rounded-xl bg-base-200/50 p-4 transition-all hover:bg-base-200">
|
<div class="rounded-xl bg-base-200/50 p-4 transition-all hover:bg-base-200">
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import { useConvexClient } from 'convex-svelte';
|
import { useConvexClient } from 'convex-svelte';
|
||||||
import { api } from '@sgse-app/backend/convex/_generated/api';
|
import { api } from '@sgse-app/backend/convex/_generated/api';
|
||||||
import type { Id, Doc } from '@sgse-app/backend/convex/_generated/dataModel';
|
import type { Id, Doc } from '@sgse-app/backend/convex/_generated/dataModel';
|
||||||
|
import UserAvatar from './chat/UserAvatar.svelte';
|
||||||
|
|
||||||
type PeriodoFerias = Doc<'ferias'> & {
|
type PeriodoFerias = Doc<'ferias'> & {
|
||||||
funcionario?: Doc<'funcionarios'> | null;
|
funcionario?: Doc<'funcionarios'> | null;
|
||||||
@@ -215,13 +216,20 @@
|
|||||||
<div class="card bg-base-100 shadow-xl">
|
<div class="card bg-base-100 shadow-xl">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="mb-4 flex items-start justify-between">
|
<div class="mb-4 flex items-start justify-between">
|
||||||
<div>
|
<div class="flex items-center gap-3">
|
||||||
<h2 class="card-title text-2xl">
|
<UserAvatar
|
||||||
{periodo.funcionario?.nome || 'Funcionário'}
|
fotoPerfilUrl={periodo.funcionario?.fotoPerfilUrl}
|
||||||
</h2>
|
nome={periodo.funcionario?.nome || 'Funcionário'}
|
||||||
<p class="text-base-content/70 mt-1 text-sm">
|
size="md"
|
||||||
Ano de Referência: {periodo.anoReferencia}
|
/>
|
||||||
</p>
|
<div>
|
||||||
|
<h2 class="card-title text-2xl">
|
||||||
|
{periodo.funcionario?.nome || 'Funcionário'}
|
||||||
|
</h2>
|
||||||
|
<p class="text-base-content/70 mt-1 text-sm">
|
||||||
|
Ano de Referência: {periodo.anoReferencia}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class={`badge ${getStatusBadge(periodo.status)} badge-lg`}>
|
<div class={`badge ${getStatusBadge(periodo.status)} badge-lg`}>
|
||||||
{getStatusTexto(periodo.status)}
|
{getStatusTexto(periodo.status)}
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ export const listarSolicitacoesSubordinados = query({
|
|||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
const solicitacoes: Array<Doc<"solicitacoesAusencias"> & {
|
const solicitacoes: Array<Doc<"solicitacoesAusencias"> & {
|
||||||
funcionario: Doc<"funcionarios"> | null;
|
funcionario: (Doc<"funcionarios"> & { fotoPerfilUrl: string | null }) | null;
|
||||||
time: Doc<"times"> | null;
|
time: Doc<"times"> | null;
|
||||||
}> = [];
|
}> = [];
|
||||||
|
|
||||||
@@ -122,9 +122,25 @@ export const listarSolicitacoesSubordinados = query({
|
|||||||
// Adicionar info do funcionário
|
// Adicionar info do funcionário
|
||||||
for (const s of solic) {
|
for (const s of solic) {
|
||||||
const funcionario = await ctx.db.get(s.funcionarioId);
|
const funcionario = await ctx.db.get(s.funcionarioId);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
solicitacoes.push({
|
solicitacoes.push({
|
||||||
...s,
|
...s,
|
||||||
funcionario,
|
funcionario: funcionario ? {
|
||||||
|
...funcionario,
|
||||||
|
fotoPerfilUrl,
|
||||||
|
} : null,
|
||||||
time,
|
time,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -143,6 +159,19 @@ export const obterDetalhes = query({
|
|||||||
if (!solicitacao) return null;
|
if (!solicitacao) return null;
|
||||||
|
|
||||||
const funcionario = await ctx.db.get(solicitacao.funcionarioId);
|
const funcionario = await ctx.db.get(solicitacao.funcionarioId);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let gestor = null;
|
let gestor = null;
|
||||||
if (solicitacao.gestorId) {
|
if (solicitacao.gestorId) {
|
||||||
gestor = await ctx.db.get(solicitacao.gestorId);
|
gestor = await ctx.db.get(solicitacao.gestorId);
|
||||||
@@ -164,7 +193,10 @@ export const obterDetalhes = query({
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
...solicitacao,
|
...solicitacao,
|
||||||
funcionario,
|
funcionario: funcionario ? {
|
||||||
|
...funcionario,
|
||||||
|
fotoPerfilUrl,
|
||||||
|
} : null,
|
||||||
gestor,
|
gestor,
|
||||||
time,
|
time,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -213,6 +213,18 @@ export const listarSolicitacoesSubordinados = query({
|
|||||||
todasFerias.map(async (ferias) => {
|
todasFerias.map(async (ferias) => {
|
||||||
const funcionario = await ctx.db.get(ferias.funcionarioId);
|
const funcionario = await ctx.db.get(ferias.funcionarioId);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Buscar time do funcionário
|
// Buscar time do funcionário
|
||||||
const membroTime = await ctx.db
|
const membroTime = await ctx.db
|
||||||
.query("timesMembros")
|
.query("timesMembros")
|
||||||
@@ -229,7 +241,10 @@ export const listarSolicitacoesSubordinados = query({
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
...ferias,
|
...ferias,
|
||||||
funcionario,
|
funcionario: funcionario ? {
|
||||||
|
...funcionario,
|
||||||
|
fotoPerfilUrl,
|
||||||
|
} : null,
|
||||||
time,
|
time,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
@@ -250,6 +265,19 @@ export const obterDetalhes = query({
|
|||||||
if (!ferias) return null;
|
if (!ferias) return null;
|
||||||
|
|
||||||
const funcionario = await ctx.db.get(ferias.funcionarioId);
|
const funcionario = await ctx.db.get(ferias.funcionarioId);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let gestor = null;
|
let gestor = null;
|
||||||
if (ferias.gestorId) {
|
if (ferias.gestorId) {
|
||||||
gestor = await ctx.db.get(ferias.gestorId);
|
gestor = await ctx.db.get(ferias.gestorId);
|
||||||
@@ -271,7 +299,10 @@ export const obterDetalhes = query({
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
...ferias,
|
...ferias,
|
||||||
funcionario,
|
funcionario: funcionario ? {
|
||||||
|
...funcionario,
|
||||||
|
fotoPerfilUrl,
|
||||||
|
} : null,
|
||||||
gestor,
|
gestor,
|
||||||
time,
|
time,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user