3 changed files with 240 additions and 95 deletions
+1 -1
View File
@@ -5,6 +5,7 @@
--text-tertiary: #6e7681;
--text-link: #2f81f7;
--text-link-hover: #539bf5;
--text-slate: #57606a;
--border-primary: #30363d;
--border-hover: #8d96a0;
@@ -56,7 +57,6 @@ body {
h1, h2, h3, h4, h5, h6 {
font-weight: 600;
line-height: 1.25;
color: var(--text-primary);
}
p {
+192 -48
View File
@@ -2,68 +2,212 @@
import { useAuthStore } from "~/stores/auth-store.js";
const authStore = useAuthStore();
const isDark = ref(false);
const router = useRouter();
// State (No more isScrolled)
const isDark = ref(false);
const isUserMenuOpen = ref(false);
const isMobileMenuOpen = ref(false);
const userMenuRef = ref(null);
// Toggle Dark Mode
function toggleDark() {
isDark.value = !isDark.value;
if (isDark.value) {
document.documentElement.classList.add('dark');
localStorage.theme = 'dark';
} else {
document.documentElement.classList.remove('dark');
localStorage.theme = 'light';
}
isDark.value = !isDark.value;
if (isDark.value) {
document.documentElement.classList.add('dark');
localStorage.theme = 'dark';
} else {
document.documentElement.classList.remove('dark');
localStorage.theme = 'light';
}
}
function logout() {
authStore.logout()
router.push("/auth/login");
// Navigation Links
const navLinks = [
{ name: 'Dashboard', path: '/' },
{ name: 'Courses', path: '/courses' },
{ name: 'Students', path: '/students' },
{ name: 'Schedule', path: '/schedule' },
];
function handleLogout() {
isUserMenuOpen.value = false;
isMobileMenuOpen.value = false;
authStore.logout();
router.push("/auth/login");
}
function navigateTo(path) {
isUserMenuOpen.value = false;
isMobileMenuOpen.value = false;
router.push(path);
}
function closeDropdowns(event) {
if (userMenuRef.value && !userMenuRef.value.contains(event.target)) {
isUserMenuOpen.value = false;
}
}
onMounted(() => {
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
isDark.value = true;
document.documentElement.classList.add('dark');
}
// Initialize Theme
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
isDark.value = true;
document.documentElement.classList.add('dark');
}
// Click listener for closing dropdowns
window.addEventListener('click', closeDropdowns);
});
onUnmounted(() => {
window.removeEventListener('click', closeDropdowns);
});
</script>
<template>
<nav
class="sticky top-0 z-50 flex items-center justify-between px-6 py-4 bg-white/80 backdrop-blur-md shadow-sm border-b border-gray-100">
<nav
class="sticky top-0 z-50 w-full border-b border-slate-200 dark:border-slate-800 bg-white/95 dark:bg-slate-900/95 backdrop-blur-md transition-colors duration-300">
<div class="w-full px-6 md:px-8">
<div class="flex items-center justify-between h-16">
<div class="flex items-center gap-6">
<nuxt-link to="/" class="text-sm font-medium text-gray-600 hover:text-blue-600 transition-colors duration-200"
active-class="text-blue-600 font-bold">
Home
</nuxt-link>
</div>
<nuxt-link to="/" class="flex items-center gap-2 group flex-shrink-0">
<div
class="w-9 h-9 rounded-lg bg-blue-600 flex items-center justify-center text-white font-bold text-xl shadow-blue-500/20 shadow-lg group-hover:scale-110 transition-transform">
A
</div>
<span class="text-xl font-bold text-slate-900 dark:text-white tracking-tight hidden md:block">
Academic<span class="text-blue-600">Sys</span>
</span>
</nuxt-link>
<div class="flex items-center gap-4">
<button class="p-2 rounded-lg bg-gray-200 dark:bg-gray-700" @click="toggleDark">
<span v-if="isDark"></span>
<span v-else>🌙</span>
</button>
<div class="flex items-center gap-4 md:gap-8">
<template v-if="authStore?.token">
<label class="py-2 text-sm font-semibold">{{ authStore?.user.name }}</label>
<button
class="px-4 py-2 text-sm font-semibold text-red-800 bg-red-100 hover:bg-red-200 rounded-lg transition-all duration-200"
@click.prevent="logout">
Logout
</button>
</template>
<div class="hidden md:flex items-center gap-1">
<nuxt-link v-for="link in navLinks" :key="link.path" :to="link.path"
class="px-3 py-2 rounded-md text-sm font-medium text-slate-600 dark:text-slate-300 hover:text-blue-600 dark:hover:text-blue-400 hover:bg-slate-50 dark:hover:bg-slate-800 transition-all duration-200"
active-class="bg-blue-50 dark:bg-blue-900/20 text-blue-600 dark:text-blue-400 font-semibold">
{{ link.name }}
</nuxt-link>
</div>
<template v-else>
<nuxt-link to="/auth/login"
class="px-5 py-2 text-sm font-semibold text-white! bg-blue-600 hover:bg-blue-700 rounded-lg shadow-sm transition-all">
Login
</nuxt-link>
</template>
</div>
</nav>
<div class="hidden md:block h-6 w-px bg-slate-200 dark:bg-slate-700 mx-2"></div>
<main class="max-w-7xl mx-auto">
<slot />
</main>
<div class="flex items-center gap-3">
<button @click="toggleDark"
class="p-2.5 rounded-full text-slate-500 hover:bg-slate-100 dark:hover:bg-slate-800 transition-colors focus:outline-none focus:ring-2 focus:ring-blue-500">
<svg v-if="!isDark" class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" />
</svg>
<svg v-else class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" />
</svg>
</button>
<div v-if="authStore?.token" class="relative" ref="userMenuRef">
<button @click.stop="isUserMenuOpen = !isUserMenuOpen"
class="flex items-center gap-3 pl-2 pr-1 py-1.5 rounded-full border border-transparent hover:bg-slate-100 dark:hover:bg-slate-800 transition-all focus:outline-none focus:ring-2 focus:ring-blue-500"
:class="{ 'bg-slate-100 dark:bg-slate-800': isUserMenuOpen }">
<span
class="text-sm font-semibold text-slate-700 dark:text-slate-200 hidden sm:block ml-2">
{{ authStore.user.name.split(' ')[0] }}
</span>
<img :src="authStore.user.avatarUrl || `https://ui-avatars.com/api/?name=${authStore.user.name}&background=0D8ABC&color=fff`"
alt="Avatar"
class="w-9 h-9 rounded-full border border-slate-200 dark:border-slate-700 object-cover">
<svg class="w-4 h-4 text-slate-400" :class="{ 'rotate-180': isUserMenuOpen }"
fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M19 9l-7 7-7-7" />
</svg>
</button>
<transition enter-active-class="transition ease-out duration-100"
enter-from-class="transform opacity-0 scale-95"
enter-to-class="transform opacity-100 scale-100"
leave-active-class="transition ease-in duration-75"
leave-from-class="transform opacity-100 scale-100"
leave-to-class="transform opacity-0 scale-95">
<div v-if="isUserMenuOpen"
class="absolute right-0 mt-2 w-64 bg-white dark:bg-slate-900 rounded-xl shadow-xl border border-slate-100 dark:border-slate-800 py-2 focus:outline-none z-50">
<div class="px-4 py-3 border-b border-slate-100 dark:border-slate-800 mb-1">
<p class="text-xs text-slate-500 dark:text-slate-400 font-medium">Signed in as
</p>
<p class="text-sm font-bold text-slate-900 dark:text-white truncate">{{
authStore.user.email }}</p>
</div>
<button @click="navigateTo('/profile')"
class="w-full text-left px-4 py-2.5 text-sm text-slate-700 dark:text-slate-300 hover:bg-slate-50 dark:hover:bg-slate-800 flex items-center gap-3 transition-colors">
<span>👤</span> Your Profile
</button>
<button @click="navigateTo('/settings')"
class="w-full text-left px-4 py-2.5 text-sm text-slate-700 dark:text-slate-300 hover:bg-slate-50 dark:hover:bg-slate-800 flex items-center gap-3 transition-colors">
<span></span> Settings
</button>
<div class="border-t border-slate-100 dark:border-slate-800 mt-1 pt-1">
<button @click="handleLogout"
class="w-full text-left px-4 py-2.5 text-sm text-red-600 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-900/20 flex items-center gap-3 transition-colors">
<span>🚪</span> Sign out
</button>
</div>
</div>
</transition>
</div>
<template v-else>
<nuxt-link to="/auth/login"
class="hidden sm:inline-flex items-center justify-center px-6 py-2.5 text-sm font-semibold text-white bg-blue-600 hover:bg-blue-700 rounded-lg shadow-sm shadow-blue-500/30 transition-all">
Sign In
</nuxt-link>
</template>
<button @click="isMobileMenuOpen = !isMobileMenuOpen"
class="md:hidden p-2 rounded-lg text-slate-600 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-800 transition-colors">
<svg v-if="!isMobileMenuOpen" class="w-7 h-7" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M4 6h16M4 12h16M4 18h16" />
</svg>
<svg v-else class="w-7 h-7" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
</div>
<transition enter-active-class="transition duration-200 ease-out"
enter-from-class="transform -translate-y-4 opacity-0"
enter-to-class="transform translate-y-0 opacity-100"
leave-active-class="transition duration-150 ease-in"
leave-from-class="transform translate-y-0 opacity-100"
leave-to-class="transform -translate-y-4 opacity-0">
<div v-if="isMobileMenuOpen"
class="md:hidden border-t border-slate-200 dark:border-slate-800 bg-white dark:bg-slate-900 shadow-xl">
<div class="px-4 pt-2 pb-6 space-y-2">
<nuxt-link v-for="link in navLinks" :key="link.path" :to="link.path"
class="block px-3 py-3 rounded-lg text-base font-medium text-slate-700 dark:text-slate-200 hover:bg-slate-50 dark:hover:bg-slate-800 hover:text-blue-600"
active-class="bg-blue-50 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400"
@click="isMobileMenuOpen = false">
{{ link.name }}
</nuxt-link>
<template v-if="!authStore?.token">
<nuxt-link to="/auth/login"
class="block w-full text-center mt-6 px-5 py-3 text-base font-bold text-white bg-blue-600 rounded-lg shadow-lg shadow-blue-500/30">
Sign In
</nuxt-link>
</template>
</div>
</div>
</transition>
</div>
</div>
</nav>
<main class="w-full min-h-screen">
<slot />
</main>
</template>
+47 -46
View File
@@ -1,59 +1,60 @@
<template>
<title> Profile - {{ user.name }}</title>
<div class="min-h-screen bg-slate-50 font-sans text-slate-900 selection:bg-blue-100 pb-12">
<title> Profile - {{user.name}}</title>
<div class="min-h-screen bg-slate-50 dark:bg-slate-950 font-sans text-slate-900 dark:text-slate-200 selection:bg-blue-100 dark:selection:bg-blue-900 pb-12 transition-colors duration-300">
<div class="container mx-auto max-w-7xl px-4 py-8 md:py-12">
<div class="grid grid-cols-1 md:grid-cols-12 gap-8 lg:gap-12">
<div class="md:col-span-4 lg:col-span-3 flex flex-col gap-6">
<div class="bg-white rounded-2xl p-6 shadow-sm border border-slate-200">
<div class="bg-white dark:bg-slate-900 rounded-2xl p-6 shadow-sm border border-slate-200 dark:border-slate-800 transition-colors duration-300">
<div class="flex flex-col items-center text-center">
<div class="relative inline-block mb-4">
<div
class="h-32 w-32 rounded-full border-4 border-white bg-slate-100 overflow-hidden shadow-md ring-1 ring-slate-200">
class="h-32 w-32 rounded-full border-4 border-white dark:border-slate-800 bg-slate-100 dark:bg-slate-800 overflow-hidden shadow-md ring-1 ring-slate-200 dark:ring-slate-700">
<img :src="user.avatarUrl" :alt="user.name"
class="h-full w-full object-cover transition-transform hover:scale-105">
class="h-full w-full object-cover transition-transform hover:scale-105" />
</div>
<div class="absolute bottom-2 right-2 h-5 w-5 rounded-full border-[3px] border-white dark:border-slate-900 shadow-sm"
:class="user.isActive ? 'bg-emerald-500' : 'bg-gray-400'" title="Online Status">
</div>
<div class="absolute bottom-2 right-2 h-5 w-5 rounded-full border-[3px] border-white shadow-sm"
:class="user.isActive ? 'bg-emerald-500' : 'bg-gray-400'" title="Online Status" />
</div>
<h1 class="text-2xl font-bold text-slate-900 tracking-tight">{{ user.name }}</h1>
<p class="text-sm font-semibold text-slate-500 mb-6 uppercase tracking-wide">{{ user.role }}
<h1 class="text-2xl font-bold text-slate-900 dark:text-white tracking-tight">{{ user.name }}</h1>
<p class="text-sm font-semibold text-slate-500 dark:text-slate-400 mb-6 uppercase tracking-wide">{{ user.role }}
</p>
<div class="w-full space-y-3">
<button
class="w-full py-2.5 px-4 bg-slate-900 hover:bg-slate-800 text-white font-medium rounded-lg text-sm transition-all shadow-sm active:scale-95 cursor-pointer">
class="w-full py-2.5 px-4 bg-slate-900 dark:bg-blue-600 hover:bg-slate-800 dark:hover:bg-blue-500 text-white font-medium rounded-lg text-sm transition-all shadow-sm active:scale-95 cursor-pointer">
Edit Profile
</button>
<button
class="w-full py-2.5 px-4 bg-white border border-slate-300 hover:bg-slate-50 text-slate-700 font-medium rounded-lg text-sm transition-all active:scale-95 cursor-pointer">
class="w-full py-2.5 px-4 bg-white dark:bg-slate-800 border border-slate-300 dark:border-slate-700 hover:bg-slate-50 dark:hover:bg-slate-700 text-slate-700 dark:text-slate-200 font-medium rounded-lg text-sm transition-all active:scale-95 cursor-pointer">
View Settings
</button>
</div>
</div>
<div class="mt-8 pt-6 border-t border-slate-100 space-y-4">
<div class="flex items-center gap-3 text-sm text-slate-600">
<svg class="w-4 h-4 text-slate-400 shrink-0" fill="none" viewBox="0 0 24 24"
<div class="mt-8 pt-6 border-t border-slate-100 dark:border-slate-800 space-y-4">
<div class="flex items-center gap-3 text-sm text-slate-600 dark:text-slate-400">
<svg class="w-4 h-4 text-slate-400 dark:text-slate-500 shrink-0" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
</svg>
<span class="truncate">{{ user.email }}</span>
</div>
<div class="flex items-center gap-3 text-sm text-slate-600">
<svg class="w-4 h-4 text-slate-400 shrink-0" fill="none" viewBox="0 0 24 24"
<div class="flex items-center gap-3 text-sm text-slate-600 dark:text-slate-400">
<svg class="w-4 h-4 text-slate-400 dark:text-slate-500 shrink-0" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" />
</svg>
<span>Polytechnic of Leiria</span>
</div>
<div class="flex items-center gap-3 text-sm text-slate-600">
<svg class="w-4 h-4 text-slate-400 shrink-0" fill="none" viewBox="0 0 24 24"
<div class="flex items-center gap-3 text-sm text-slate-600 dark:text-slate-400">
<svg class="w-4 h-4 text-slate-400 dark:text-slate-500 shrink-0" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
@@ -65,15 +66,15 @@
<div class="grid grid-cols-2 gap-4">
<div
class="bg-white p-4 rounded-xl shadow-sm border border-slate-200 text-center hover:border-slate-300 transition-colors">
<div class="text-2xl font-bold text-slate-900">{{ totalCitations }}</div>
<div class="text-[10px] font-bold text-slate-400 uppercase tracking-widest mt-1">Citations
class="bg-white dark:bg-slate-900 p-4 rounded-xl shadow-sm border border-slate-200 dark:border-slate-800 text-center hover:border-slate-300 dark:hover:border-slate-700 transition-colors">
<div class="text-2xl font-bold text-slate-900 dark:text-white">{{ totalCitations }}</div>
<div class="text-[10px] font-bold text-slate-400 dark:text-slate-500 uppercase tracking-widest mt-1">Citations
</div>
</div>
<div
class="bg-white p-4 rounded-xl shadow-sm border border-slate-200 text-center hover:border-slate-300 transition-colors">
<div class="text-2xl font-bold text-slate-900">{{ user.publications.length }}</div>
<div class="text-[10px] font-bold text-slate-400 uppercase tracking-widest mt-1">Papers
class="bg-white dark:bg-slate-900 p-4 rounded-xl shadow-sm border border-slate-200 dark:border-slate-800 text-center hover:border-slate-300 dark:hover:border-slate-700 transition-colors">
<div class="text-2xl font-bold text-slate-900 dark:text-white">{{ user.publications.length }}</div>
<div class="text-[10px] font-bold text-slate-400 dark:text-slate-500 uppercase tracking-widest mt-1">Papers
</div>
</div>
</div>
@@ -81,75 +82,75 @@
<div class="md:col-span-8 lg:col-span-9 space-y-6">
<div class="bg-white p-1.5 rounded-xl border border-slate-200 shadow-sm flex gap-1 overflow-x-auto">
<div class="bg-white dark:bg-slate-900 p-1.5 rounded-xl border border-slate-200 dark:border-slate-800 shadow-sm flex gap-1 overflow-x-auto transition-colors">
<button
class="flex-1 min-w-[100px] py-2.5 px-4 rounded-lg text-lg font-semibold bg-slate-100 text-slate-900 shadow-sm ring-1 ring-black/5 cursor-pointer">
class="flex-1 min-w-[100px] py-2.5 px-4 rounded-lg text-lg font-semibold bg-slate-100 dark:bg-slate-800 text-slate-900 dark:text-white shadow-sm ring-1 ring-black/5 dark:ring-white/5 cursor-pointer transition-colors">
Overview
</button>
<button
class="flex-1 min-w-[100px] py-2.5 px-4 rounded-lg text-lg font-medium text-slate-500 hover:text-slate-900 hover:bg-slate-50 transition-colors cursor-pointer">
class="flex-1 min-w-[100px] py-2.5 px-4 rounded-lg text-lg font-medium text-slate-500 dark:text-slate-400 hover:text-slate-900 dark:hover:text-white hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors cursor-pointer">
Activity Log
</button>
<button
class="flex-1 min-w-[100px] py-2.5 px-4 rounded-lg text-lg font-medium text-slate-500 hover:text-slate-900 hover:bg-slate-50 transition-colors cursor-pointer">
class="flex-1 min-w-[100px] py-2.5 px-4 rounded-lg text-lg font-medium text-slate-500 dark:text-slate-400 hover:text-slate-900 dark:hover:text-white hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors cursor-pointer">
Settings
</button>
</div>
<div class="bg-white p-6 rounded-2xl shadow-sm border border-slate-200">
<h2 class="text-xs font-bold text-slate-400 uppercase tracking-wider mb-3">Biography</h2>
<p class="text-slate-700 leading-relaxed text-sm">
<div class="bg-white dark:bg-slate-900 p-6 rounded-2xl shadow-sm border border-slate-200 dark:border-slate-800 transition-colors">
<h2 class="text-xs font-bold text-slate-400 dark:text-slate-500 uppercase tracking-wider mb-3">Biography</h2>
<p class="text-slate-700 dark:text-slate-300 leading-relaxed text-sm">
{{ user.biography }}
</p>
</div>
<div class="flex items-center justify-between pt-2 px-1">
<h2 class="text-lg font-bold text-slate-900 flex items-center gap-2">
<h2 class="text-lg font-bold text-slate-900 dark:text-white flex items-center gap-2">
Recent Publications
<span class="bg-slate-200 text-slate-700 text-xs font-bold px-2 py-0.5 rounded-full">{{
<span class="bg-slate-200 dark:bg-slate-800 text-slate-700 dark:text-slate-300 text-xs font-bold px-2 py-0.5 rounded-full">{{
user.publications.length }}</span>
</h2>
</div>
<div class="flex flex-col gap-4">
<div v-if="user.publications.length === 0"
class="text-center py-16 border-2 border-dashed border-slate-200 rounded-xl bg-slate-50/50">
<p class="text-slate-500 font-medium">No publications found yet.</p>
class="text-center py-16 border-2 border-dashed border-slate-200 dark:border-slate-800 rounded-xl bg-slate-50/50 dark:bg-slate-900/50">
<p class="text-slate-500 dark:text-slate-400 font-medium">No publications found yet.</p>
</div>
<div v-for="pub in user.publications" :key="pub.id"
class="bg-white p-6 rounded-xl shadow-sm border border-slate-200 hover:shadow-md hover:border-blue-300 transition-all duration-200 group relative">
class="bg-white dark:bg-slate-900 p-6 rounded-xl shadow-sm border border-slate-200 dark:border-slate-800 hover:shadow-md hover:border-blue-300 dark:hover:border-blue-700 transition-all duration-200 group relative">
<div class="flex justify-between items-start gap-4 mb-2">
<h3
class="text-base font-bold text-slate-900 group-hover:text-blue-600 transition-colors leading-snug">
class="text-base font-bold text-slate-900 dark:text-slate-100 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors leading-snug">
<a href="#" class="before:absolute before:inset-0">{{ pub.title }}</a>
</h3>
<span
class="shrink-0 px-2.5 py-1 rounded-md bg-slate-100 text-slate-600 text-xs font-bold border border-slate-200">
class="shrink-0 px-2.5 py-1 rounded-md bg-slate-100 dark:bg-slate-800 text-slate-600 dark:text-slate-400 text-xs font-bold border border-slate-200 dark:border-slate-700">
{{ pub.publishedYear }}
</span>
</div>
<p class="text-slate-600 text-sm leading-relaxed line-clamp-2">
<p class="text-slate-600 dark:text-slate-400 text-sm leading-relaxed line-clamp-2">
{{ pub.abstract }}
</p>
<div
class="mt-4 pt-4 border-t border-slate-50 flex flex-wrap items-center gap-4 text-xs font-medium z-10 relative">
class="mt-4 pt-4 border-t border-slate-50 dark:border-slate-800 flex flex-wrap items-center gap-4 text-xs font-medium z-10 relative">
<span
class="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full bg-blue-50 text-blue-700 border border-blue-100">
<span class="w-1.5 h-1.5 rounded-full bg-blue-500" />
class="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full bg-blue-50 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 border border-blue-100 dark:border-blue-800/50">
<span class="w-1.5 h-1.5 rounded-full bg-blue-500"></span>
{{ pub.field }}
</span>
<span class="inline-flex items-center gap-1.5 text-slate-500">
<span class="inline-flex items-center gap-1.5 text-slate-500 dark:text-slate-400">
<svg class="w-3.5 h-3.5" fill="currentColor" viewBox="0 0 20 20">
<path
d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" />
</svg>
{{ pub.citations }} Citations
</span>
<span class="text-slate-300"></span>
<span class="text-slate-500">{{ pub.publishedDate }}</span>
<span class="text-slate-300 dark:text-slate-700"></span>
<span class="text-slate-500 dark:text-slate-400">{{ pub.publishedDate }}</span>
</div>
</div>
</div>
@@ -195,7 +196,7 @@ const user = ref<User>({
id: 1,
name: 'Dr. Maria Santos',
email: '[email protected]',
biography: 'Focused on distributed systems and IoT security. Currently leading the research group on \"Smart City Infrastructures\" at IPLeiria. My work primarily involves developing scalable architectures for real-time data processing and ensuring data integrity in edge computing environments.',
biography: 'Focused on distributed systems and IoT security. Currently leading the research group on "Smart City Infrastructures" at IPLeiria. My work primarily involves developing scalable architectures for real-time data processing and ensuring data integrity in edge computing environments.',
role: Role.RESEARCHER,
isActive: true,
avatarUrl: 'https://api.dicebear.com/7.x/notionists/svg?seed=Maria',