forked from geolba/tethys.backend
Arno Kaimbacher
cefd9081ae
- adapted menu.ts, NavBar.vue, NavBarItem.vue for highlighting active nav item - NavBarItemLabel.vue for app menu highlighting - adapted routes.ts - adapted app.edge for new favicon - adapted LayoutAuthenticated.vue (:showAsideMenu="false") for showing AsideMenu optional - new material icons: BriefcaseCheck.vue, SwapHorizontal.vue, AccountGroup.vue, Lock.vue - started with FirstRunWizard
116 lines
3.4 KiB
Vue
116 lines
3.4 KiB
Vue
<script setup>
|
|
import { computed } from 'vue';
|
|
|
|
const props = defineProps({
|
|
username: {
|
|
type: String,
|
|
required: true,
|
|
},
|
|
avatar: {
|
|
type: String,
|
|
default: null,
|
|
},
|
|
api: {
|
|
type: String,
|
|
default: 'avataaars',
|
|
},
|
|
});
|
|
|
|
const avatar = computed(
|
|
// () => props.avatar ?? `https://avatars.dicebear.com/api/${props.api}/${props.username?.replace(/[^a-z0-9]+/i, '-')}.svg`
|
|
|
|
// () => props.avatar ?? `https://avatars.dicebear.com/api/initials/${props.username}.svg`,
|
|
|
|
() => {
|
|
const initials = props.username
|
|
.split(' ')
|
|
.map((part) => part.charAt(0).toUpperCase())
|
|
.join('');
|
|
|
|
return props.avatar ?? generateAvatarUrl(props.username);
|
|
},
|
|
);
|
|
|
|
const username = computed(() => props.username);
|
|
|
|
const darkenColor = (color) => {
|
|
// Convert hex to RGB
|
|
const r = parseInt(color.slice(0, 2), 16);
|
|
const g = parseInt(color.slice(2, 4), 16);
|
|
const b = parseInt(color.slice(4, 6), 16);
|
|
|
|
// Calculate darker color by reducing 20% of each RGB component
|
|
const darkerR = Math.round(r * 0.6);
|
|
const darkerG = Math.round(g * 0.6);
|
|
const darkerB = Math.round(b * 0.6);
|
|
|
|
// Convert back to hex
|
|
const darkerColor = ((darkerR << 16) + (darkerG << 8) + darkerB).toString(16);
|
|
|
|
return darkerColor.padStart(6, '0'); // Ensure it's 6 digits
|
|
};
|
|
|
|
const getRandomColor = () => {
|
|
return Math.floor(Math.random() * 16777215).toString(16);
|
|
};
|
|
|
|
const adjustOpacity = (hexColor, opacity) => {
|
|
// Remove # if present
|
|
hexColor = hexColor.replace('#', '');
|
|
// Convert hex to RGB
|
|
// const r = parseInt(hexColor.slice(0, 2), 16);
|
|
// const g = parseInt(hexColor.slice(2, 4), 16);
|
|
// const b = parseInt(hexColor.slice(4, 6), 16);
|
|
|
|
// const r = parseInt(hexColor.slice(1, 3), 16);
|
|
// const g = parseInt(hexColor.slice(3, 5), 16);
|
|
// const b = parseInt(hexColor.slice(5, 7), 16);
|
|
const [r, g, b] = hexColor.match(/\w\w/g).map(x => parseInt(x, 16));
|
|
|
|
return `rgba(${r},${g},${b},${opacity})`;
|
|
};
|
|
|
|
const lightenColor = (hexColor, percent) => {
|
|
let r = parseInt(hexColor.substring(0, 2), 16);
|
|
let g = parseInt(hexColor.substring(2, 4), 16);
|
|
let b = parseInt(hexColor.substring(4, 6), 16);
|
|
|
|
r = Math.floor(r * (100 + percent) / 100);
|
|
g = Math.floor(g * (100 + percent) / 100);
|
|
b = Math.floor(b * (100 + percent) / 100);
|
|
|
|
r = (r < 255) ? r : 255;
|
|
g = (g < 255) ? g : 255;
|
|
b = (b < 255) ? b : 255;
|
|
|
|
const lighterHex = ((r << 16) | (g << 8) | b).toString(16);
|
|
|
|
return lighterHex.padStart(6, '0');
|
|
};
|
|
|
|
// backgroundColor = '7F9CF5',
|
|
const generateAvatarUrl = (name) => {
|
|
const initials = name
|
|
.split(' ')
|
|
.map((part) => part.charAt(0).toUpperCase())
|
|
.join('');
|
|
|
|
const originalColor = getRandomColor();
|
|
|
|
const backgroundColor = lightenColor(originalColor, 60); // Lighten by 20%
|
|
|
|
const textColor = darkenColor(originalColor);
|
|
|
|
// const avatarUrl = `https://ui-avatars.com/api/?name=${initials}&size=50&background=${backgroundColor}&color=${textColor}`;
|
|
const avatarUrl = `/api/avatar?name=${name}&size=50&background=${backgroundColor}&textColor=${textColor}`;
|
|
return avatarUrl;
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<div>
|
|
<img :src="avatar" :alt="username"
|
|
class="rounded-full block h-auto w-full max-w-full bg-gray-100 dark:bg-slate-800" />
|
|
</div>
|
|
</template>
|