2026-09-02 21:29:00 +03:30
|
|
|
<script setup lang="ts">
|
|
|
|
|
import { computed, ref } from 'vue';
|
|
|
|
|
import { personInitials } from '@/lib/person-insights';
|
|
|
|
|
|
|
|
|
|
const props = withDefaults(
|
|
|
|
|
defineProps<{
|
|
|
|
|
name?: string | null;
|
|
|
|
|
src?: string | null;
|
|
|
|
|
size?: number;
|
|
|
|
|
}>(),
|
|
|
|
|
{
|
|
|
|
|
name: '',
|
|
|
|
|
src: '/brand/user-avatar.png',
|
|
|
|
|
size: 28,
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const initials = computed(() => personInitials(props.name));
|
|
|
|
|
const failed = ref(false);
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
<span class="user-avatar" :style="{ width: `${size}px`, height: `${size}px` }" :title="name || undefined">
|
|
|
|
|
<img
|
|
|
|
|
v-if="src && !failed"
|
|
|
|
|
:src="src"
|
|
|
|
|
:alt="name || 'آواتار'"
|
|
|
|
|
@error="failed = true"
|
|
|
|
|
/>
|
|
|
|
|
<em v-else>{{ initials }}</em>
|
|
|
|
|
</span>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
.user-avatar {
|
|
|
|
|
display: inline-grid;
|
|
|
|
|
place-items: center;
|
|
|
|
|
border-radius: 999px;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
background: linear-gradient(145deg, #5eead4, #0f766e);
|
|
|
|
|
box-shadow: 0 0 0 2px #fff, 0 0 0 3px #ccfbf1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
img {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 100%;
|
|
|
|
|
object-fit: cover;
|
|
|
|
|
display: block;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
em {
|
|
|
|
|
font-style: normal;
|
|
|
|
|
color: #fff;
|
2026-09-12 01:33:07 +03:30
|
|
|
font-weight: 600;
|
2026-09-02 21:29:00 +03:30
|
|
|
font-size: 0.62rem;
|
|
|
|
|
line-height: 1;
|
|
|
|
|
}
|
|
|
|
|
</style>
|