Files
sgse-app/apps/web/src/lib/components/chat/UserAvatar.svelte

100 lines
2.1 KiB
Svelte

<script lang="ts">
import { User } from 'lucide-svelte';
import { getCachedAvatar } from '$lib/utils/avatarCache';
import { onMount } from 'svelte';
interface Props {
fotoPerfilUrl?: string | null;
nome: string;
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
userId?: string; // ID do usuário para cache
}
let { fotoPerfilUrl, nome, size = 'md', userId }: Props = $props();
let cachedAvatarUrl = $state<string | null>(null);
let loading = $state(true);
onMount(async () => {
if (fotoPerfilUrl) {
loading = true;
try {
cachedAvatarUrl = await getCachedAvatar(fotoPerfilUrl, userId);
} catch (error) {
console.warn('Erro ao carregar avatar:', error);
cachedAvatarUrl = null;
} finally {
loading = false;
}
} else {
loading = false;
}
});
// Atualizar quando fotoPerfilUrl mudar
$effect(() => {
if (fotoPerfilUrl) {
loading = true;
getCachedAvatar(fotoPerfilUrl, userId)
.then((url) => {
cachedAvatarUrl = url;
loading = false;
})
.catch((error) => {
console.warn('Erro ao carregar avatar:', error);
cachedAvatarUrl = null;
loading = false;
});
} else {
cachedAvatarUrl = null;
loading = false;
}
});
const sizeClasses = {
xs: 'w-8 h-8',
sm: 'w-10 h-10',
md: 'w-12 h-12',
lg: 'w-16 h-16',
xl: 'w-32 h-32'
};
const iconSizes = {
xs: 16,
sm: 20,
md: 24,
lg: 32,
xl: 64
};
</script>
<div class="avatar placeholder">
<div
class={`${sizeClasses[size]} bg-base-200 text-base-content/50 flex items-center justify-center overflow-hidden rounded-full`}
>
{#if loading}
<span class="loading loading-spinner loading-xs"></span>
{:else if cachedAvatarUrl}
<img
src={cachedAvatarUrl}
alt={`Foto de perfil de ${nome}`}
class="h-full w-full object-cover"
loading="lazy"
onerror={() => {
cachedAvatarUrl = null;
}}
/>
{:else if fotoPerfilUrl}
<!-- Fallback: usar URL original se cache falhar -->
<img
src={fotoPerfilUrl}
alt={`Foto de perfil de ${nome}`}
class="h-full w-full object-cover"
loading="lazy"
/>
{:else}
<User size={iconSizes[size]} />
{/if}
</div>
</div>