Files
tp/main_dc/yalarba/yalarba-nuxt/app/pages/profile/index.vue
T
2026-06-12 00:29:34 +05:00

223 lines
5.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="profile">
<section class="page-hero">
<div class="container">
<h1>Профиль</h1>
</div>
</section>
<section class="section">
<div class="container">
<div v-if="!isAuthenticated" class="profile__guest">
<p class="body-text--gray">Войдите, чтобы увидеть профиль</p>
<NuxtLink to="/auth/login" class="btn btn--primary btn--md">
Войти
</NuxtLink>
</div>
<template v-else-if="user">
<div class="profile__header">
<div class="profile__avatar">
<img v-if="user.avatar" :src="user.avatar" alt="" class="avatar avatar--lg" />
<span v-else class="avatar avatar--lg profile__avatar-placeholder">
{{ userInitials }}
</span>
</div>
<div class="profile__info">
<h2>{{ user.name }}</h2>
<p class="body-text--gray">{{ user.email }}</p>
<span class="tag" style="margin-top: 8px">
{{ user.role === 'admin' ? 'Администратор' : user.role === 'moderator' ? 'Модератор' : 'Пользователь' }}
</span>
</div>
</div>
<div class="profile__nav">
<NuxtLink to="/profile" class="profile__tab profile__tab--active">
Обзор
</NuxtLink>
<NuxtLink to="/objects/my" class="profile__tab">
Мои объекты
</NuxtLink>
<NuxtLink to="/profile/settings" class="profile__tab">
Настройки
</NuxtLink>
<button class="profile__tab profile__tab--logout" @click="handleLogout">
Выйти
</button>
</div>
<div class="profile__content">
<div class="profile__stats">
<div class="profile__stat-card">
<h3>{{ objectsCount }}</h3>
<p class="small-text">Объектов</p>
</div>
<div class="profile__stat-card">
<h3>{{ reviewsCount }}</h3>
<p class="small-text">Отзывов</p>
</div>
<div class="profile__stat-card">
<h3>{{ favoritesCount }}</h3>
<p class="small-text">В избранном</p>
</div>
</div>
</div>
</template>
</div>
</section>
</div>
</template>
<script setup lang="ts">
definePageMeta({
title: 'Профиль',
middleware: 'auth',
})
const { isAuthenticated, user, logout } = useAuth()
const objectsCount = ref(0)
const reviewsCount = ref(0)
const favoritesCount = ref(0)
const userInitials = computed(() => {
if (!user.value?.name) return '?'
return user.value.name.charAt(0).toUpperCase()
})
function handleLogout() {
logout()
}
onMounted(async () => {
try {
const api = useApi()
const profile = await api.get<{
objects_count?: number
reviews_count?: number
favorites_count?: number
}>('/profile')
objectsCount.value = profile.objects_count || 0
reviewsCount.value = profile.reviews_count || 0
favoritesCount.value = profile.favorites_count || 0
} catch {
// ignore
}
})
</script>
<style scoped>
.page-hero {
background: var(--color-primary);
padding: 60px 0;
text-align: center;
color: var(--color-text-white);
}
.page-hero h1 {
color: var(--color-text-white);
}
.profile__guest {
text-align: center;
padding: 60px 0;
display: flex;
flex-direction: column;
align-items: center;
gap: 16px;
}
.profile__header {
display: flex;
align-items: center;
gap: 24px;
margin-bottom: 32px;
}
.profile__avatar-placeholder {
display: flex;
align-items: center;
justify-content: center;
font-family: var(--font-body);
font-size: 24px;
font-weight: var(--font-weight-bold);
color: var(--color-primary);
background: var(--color-light-green);
}
.profile__info h2 {
margin-bottom: 4px;
}
.profile__nav {
display: flex;
gap: 4px;
border-bottom: 1px solid var(--color-stroke);
margin-bottom: 32px;
overflow-x: auto;
}
.profile__tab {
padding: 12px 20px;
font-family: var(--font-body);
font-size: var(--font-size-small);
font-weight: var(--font-weight-medium);
color: var(--color-text-gray);
border-bottom: 2px solid transparent;
transition: all var(--transition-fast);
white-space: nowrap;
background: none;
}
.profile__tab:hover {
color: var(--color-text-black);
}
.profile__tab--active {
color: var(--color-primary);
border-bottom-color: var(--color-primary);
}
.profile__tab--logout {
margin-left: auto;
color: var(--color-red);
}
.profile__tab--logout:hover {
color: var(--color-red);
opacity: 0.8;
}
.profile__stats {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
max-width: 600px;
}
.profile__stat-card {
background: var(--color-white);
border: 1px solid var(--color-stroke);
border-radius: var(--radius-md);
padding: 24px;
text-align: center;
}
.profile__stat-card h3 {
color: var(--color-primary);
margin-bottom: 4px;
}
@media (max-width: 744px) {
.profile__header {
flex-direction: column;
text-align: center;
}
.profile__stats {
grid-template-columns: 1fr;
}
}
</style>