79 lines
1.7 KiB
Vue
79 lines
1.7 KiB
Vue
<template>
|
|
<div class="flex items-center space-x-2">
|
|
<img
|
|
v-if="avatarUrl"
|
|
:src="avatarUrl"
|
|
:alt="alt"
|
|
:class="avatarClasses"
|
|
>
|
|
<div v-else :class="fallbackClasses">
|
|
<User class="w-4 h-4 text-primary-600" />
|
|
</div>
|
|
<div v-if="showUserInfo">
|
|
<p class="font-medium text-gray-900">{{ userName }}</p>
|
|
<p class="text-sm text-gray-600">@{{ username }}</p>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { computed } from 'vue'
|
|
import { User } from 'lucide-vue-next'
|
|
import { getMediaUrl } from '@/utils/axios'
|
|
|
|
const props = defineProps({
|
|
user: {
|
|
type: Object,
|
|
required: true
|
|
},
|
|
size: {
|
|
type: String,
|
|
default: 'md', // 'sm', 'md', 'lg'
|
|
validator: (value) => ['sm', 'md', 'lg'].includes(value)
|
|
},
|
|
showUserInfo: {
|
|
type: Boolean,
|
|
default: false
|
|
}
|
|
})
|
|
|
|
const avatarUrl = computed(() => {
|
|
if (props.user?.avatar_url) {
|
|
return getMediaUrl(props.user.avatar_url)
|
|
}
|
|
return null
|
|
})
|
|
|
|
const alt = computed(() => {
|
|
return props.user?.full_name || 'Avatar utilisateur'
|
|
})
|
|
|
|
const userName = computed(() => {
|
|
return props.user?.full_name || 'Utilisateur'
|
|
})
|
|
|
|
const username = computed(() => {
|
|
return props.user?.username || 'user'
|
|
})
|
|
|
|
const avatarClasses = computed(() => {
|
|
const baseClasses = 'rounded-full object-cover'
|
|
const sizeClasses = {
|
|
sm: 'w-6 h-6',
|
|
md: 'w-8 h-8',
|
|
lg: 'w-10 h-10'
|
|
}
|
|
return `${sizeClasses[props.size]} ${baseClasses}`
|
|
})
|
|
|
|
const fallbackClasses = computed(() => {
|
|
const baseClasses = 'rounded-full bg-primary-100 flex items-center justify-center'
|
|
const sizeClasses = {
|
|
sm: 'w-6 h-6',
|
|
md: 'w-8 h-8',
|
|
lg: 'w-10 h-10'
|
|
}
|
|
return `${sizeClasses[props.size]} ${baseClasses}`
|
|
})
|
|
</script>
|