144 lines
3.7 KiB
Vue
144 lines
3.7 KiB
Vue
<script setup lang="ts">
|
|
import { ref } from 'vue';
|
|
|
|
withDefaults(
|
|
defineProps<{
|
|
img?: string | null;
|
|
icon?: string;
|
|
title?: string;
|
|
caption?: string;
|
|
color?: string;
|
|
bgColor?: string;
|
|
toggleTitle?: string;
|
|
fallbackImg?: string;
|
|
fallbackCover?: string;
|
|
|
|
hideFade?: boolean;
|
|
hideActive?: boolean;
|
|
active?: boolean;
|
|
readonly?: boolean;
|
|
useToggle?: boolean;
|
|
labelAction?: string;
|
|
|
|
menu?: { icon: string; color: string; bgColor: string }[];
|
|
tabsList?: { name: string | number; label: string }[];
|
|
}>(),
|
|
{},
|
|
);
|
|
const showOverlay = ref(false);
|
|
|
|
defineEmits<{
|
|
(e: 'view'): void;
|
|
(e: 'edit'): void;
|
|
}>();
|
|
</script>
|
|
|
|
<template>
|
|
<div>
|
|
<div class="surface-1" style="border: 4px solid var(--surface-1)">
|
|
<q-avatar
|
|
square
|
|
size="10rem"
|
|
font-size="8rem"
|
|
class="relative-position"
|
|
style="z-index: 1; cursor: pointer"
|
|
@mouseover="showOverlay = true"
|
|
@mouseleave="showOverlay = false"
|
|
@click.stop="
|
|
() => {
|
|
if (readonly === false) $emit('view');
|
|
}
|
|
"
|
|
>
|
|
<div
|
|
v-if="img"
|
|
class="full-width full-height"
|
|
:style="{
|
|
background: `${bgColor || 'var(--brand-1)'}`,
|
|
color: `${color || 'white'}`,
|
|
}"
|
|
>
|
|
<q-img id="profile-view" :src="img" :ratio="1">
|
|
<template #error>
|
|
<q-img
|
|
v-if="fallbackImg"
|
|
:src="fallbackImg"
|
|
:ratio="1"
|
|
style="background-color: transparent"
|
|
>
|
|
<template #error>
|
|
<div
|
|
class="full-width full-height flex items-center justify-center"
|
|
:style="{
|
|
background: `${bgColor || 'var(--brand-1)'}`,
|
|
color: `${color || 'white'}`,
|
|
}"
|
|
>
|
|
<q-icon :name="icon || 'mdi-account'" />
|
|
</div>
|
|
</template>
|
|
</q-img>
|
|
<div
|
|
v-else
|
|
class="full-width full-height flex items-center justify-center"
|
|
:style="{
|
|
background: `${bgColor || 'var(--brand-1)'}`,
|
|
color: `${color || 'white'}`,
|
|
}"
|
|
>
|
|
<q-icon :name="icon || 'mdi-account'" />
|
|
</div>
|
|
</template>
|
|
</q-img>
|
|
</div>
|
|
|
|
<div
|
|
v-else
|
|
class="full-width full-height flex items-center justify-center"
|
|
:style="{
|
|
background: `${bgColor || 'var(--brand-1)'}`,
|
|
color: `${color || 'white'}`,
|
|
}"
|
|
>
|
|
<q-icon :name="icon || 'mdi-account'" />
|
|
</div>
|
|
|
|
<Transition name="slide-fade">
|
|
<div
|
|
v-if="showOverlay && !readonly"
|
|
class="absolute text-caption full-width full-height"
|
|
style="overflow: hidden"
|
|
:class="{ dark: $q.dark.isActive }"
|
|
>
|
|
<div
|
|
class="upload-overlay absolute-bottom flex items-center justify-center"
|
|
@click.stop="
|
|
() => {
|
|
if (readonly === false) $emit('edit');
|
|
}
|
|
"
|
|
>
|
|
{{
|
|
labelAction === undefined
|
|
? $t('general.editImage')
|
|
: labelAction
|
|
}}
|
|
</div>
|
|
</div>
|
|
</Transition>
|
|
</q-avatar>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.upload-overlay {
|
|
top: 60%;
|
|
background-color: hsla(var(--gray-10-hsl) / 0.5);
|
|
color: white;
|
|
|
|
&.dark {
|
|
background-color: rgba(255, 255, 255, 0.2);
|
|
}
|
|
}
|
|
</style>
|