Dev #11
@@ -14,13 +14,17 @@ const userStore = useUserStore()
|
||||
const router = useRouter()
|
||||
const isProfileMenuOpen = ref(false)
|
||||
const isCoinDialogOpen = ref(false)
|
||||
const isLevelDialogOpen = ref(false)
|
||||
const isSlotsDialogOpen = ref(false)
|
||||
const profileMenuRef = ref<HTMLElement | null>(null)
|
||||
|
||||
const unreadCount = computed(() => userStore.unreadCount())
|
||||
const showStudentChips = computed(() => auth.user?.activeRole === 'student')
|
||||
const enrollmentSlotText = computed(() => {
|
||||
if (auth.user?.activeRole !== 'student') return ''
|
||||
if (typeof auth.user.enrollmentSlotLimit !== 'number') return ''
|
||||
return `${auth.user.activeEnrollments ?? 0}/${auth.user.enrollmentSlotLimit}`
|
||||
const user = auth.user
|
||||
if (!user || user.activeRole !== 'student') return ''
|
||||
if (typeof user.enrollmentSlotLimit !== 'number') return ''
|
||||
return `${user.activeEnrollments ?? 0}/${user.enrollmentSlotLimit}`
|
||||
})
|
||||
const roleLabels: Record<UserRole, string> = {
|
||||
student: 'Студент',
|
||||
@@ -53,8 +57,18 @@ function closeCoinDialog() {
|
||||
isCoinDialogOpen.value = false
|
||||
}
|
||||
|
||||
function closeLevelDialog() {
|
||||
isLevelDialogOpen.value = false
|
||||
}
|
||||
|
||||
function closeSlotsDialog() {
|
||||
isSlotsDialogOpen.value = false
|
||||
}
|
||||
|
||||
function toggleProfileMenu() {
|
||||
closeCoinDialog()
|
||||
closeLevelDialog()
|
||||
closeSlotsDialog()
|
||||
isProfileMenuOpen.value = !isProfileMenuOpen.value
|
||||
}
|
||||
|
||||
@@ -63,6 +77,25 @@ function openCoinDialog() {
|
||||
isCoinDialogOpen.value = true
|
||||
}
|
||||
|
||||
function openLevelDialog() {
|
||||
closeProfileMenu()
|
||||
closeCoinDialog()
|
||||
closeSlotsDialog()
|
||||
isLevelDialogOpen.value = true
|
||||
}
|
||||
|
||||
function openSlotsDialog() {
|
||||
closeProfileMenu()
|
||||
closeCoinDialog()
|
||||
closeLevelDialog()
|
||||
isSlotsDialogOpen.value = true
|
||||
}
|
||||
|
||||
function openMyLecturesFromSlotsDialog() {
|
||||
closeSlotsDialog()
|
||||
router.push('/my-lectures')
|
||||
}
|
||||
|
||||
function openProfile() {
|
||||
closeProfileMenu()
|
||||
router.push('/profile')
|
||||
@@ -109,22 +142,35 @@ onBeforeUnmount(() => {
|
||||
|
||||
<div class="topbar-right">
|
||||
<CoinChip
|
||||
v-if="auth.user"
|
||||
v-if="auth.user && showStudentChips"
|
||||
:amount="auth.user.coins"
|
||||
aria-haspopup="dialog"
|
||||
@click="openCoinDialog"
|
||||
/>
|
||||
|
||||
<div v-if="auth.user" class="level-chip">
|
||||
<button
|
||||
v-if="auth.user && showStudentChips"
|
||||
class="level-chip"
|
||||
type="button"
|
||||
aria-haspopup="dialog"
|
||||
@click="openLevelDialog"
|
||||
>
|
||||
<AppIcon class="level-icon" icon="star" :size="15" />
|
||||
<span class="level-label">Ур.</span>
|
||||
<span class="level-value">{{ auth.user.level }}</span>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<div v-if="enrollmentSlotText" class="slot-chip" title="Занятые слоты записи / доступные слоты">
|
||||
<button
|
||||
v-if="enrollmentSlotText"
|
||||
class="slot-chip"
|
||||
type="button"
|
||||
aria-haspopup="dialog"
|
||||
title="Занятые слоты записи / доступные слоты"
|
||||
@click="openSlotsDialog"
|
||||
>
|
||||
<AppIcon class="slot-icon" icon="calendar" :size="15" />
|
||||
<span class="slot-value">{{ enrollmentSlotText }}</span>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<button class="notif-btn" type="button" aria-label="Уведомления" @click="$router.push('/notifications')">
|
||||
<AppIcon icon="bell" :size="18" />
|
||||
@@ -183,6 +229,27 @@ onBeforeUnmount(() => {
|
||||
<button class="btn-primary" type="button" @click="closeCoinDialog">ОК</button>
|
||||
</template>
|
||||
</ModalDialog>
|
||||
|
||||
<ModalDialog v-model="isLevelDialogOpen" title="Уровень студента" icon="star" size="sm">
|
||||
<p>
|
||||
Уровень показывает ваш прогресс в UniVerse. Он растет вместе с активностью: посещением открытых лекций,
|
||||
полезными отзывами и достижениями.
|
||||
</p>
|
||||
<template #footer>
|
||||
<button class="btn-primary" type="button" @click="closeLevelDialog">Понятно</button>
|
||||
</template>
|
||||
</ModalDialog>
|
||||
|
||||
<ModalDialog v-model="isSlotsDialogOpen" title="Слоты записи" icon="calendar" size="sm">
|
||||
<p>
|
||||
Слоты показывают, сколько открытых лекций уже занято в вашем текущем лимите. Когда лимит заполнен,
|
||||
освободите слот отменой записи или повышайте уровень, чтобы получить больше возможностей.
|
||||
</p>
|
||||
<template #footer>
|
||||
<button class="btn-secondary" type="button" @click="openMyLecturesFromSlotsDialog">Мои записи</button>
|
||||
<button class="btn-primary" type="button" @click="closeSlotsDialog">Понятно</button>
|
||||
</template>
|
||||
</ModalDialog>
|
||||
</header>
|
||||
</template>
|
||||
|
||||
@@ -238,8 +305,10 @@ onBeforeUnmount(() => {
|
||||
border-radius: 20px;
|
||||
background: var(--color-primary-a10);
|
||||
color: var(--color-primary-dark);
|
||||
cursor: default;
|
||||
cursor: pointer;
|
||||
font: inherit;
|
||||
white-space: nowrap;
|
||||
transition: background-color 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease;
|
||||
}
|
||||
.level-icon {
|
||||
color: var(--color-primary);
|
||||
@@ -264,8 +333,21 @@ onBeforeUnmount(() => {
|
||||
border-radius: 20px;
|
||||
background: var(--color-primary-a10);
|
||||
color: var(--color-success-text);
|
||||
cursor: default;
|
||||
cursor: pointer;
|
||||
font: inherit;
|
||||
white-space: nowrap;
|
||||
transition: background-color 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease;
|
||||
}
|
||||
.level-chip:hover,
|
||||
.slot-chip:hover {
|
||||
background: var(--color-primary-a18);
|
||||
border-color: var(--color-primary-a40);
|
||||
}
|
||||
.level-chip:focus-visible,
|
||||
.slot-chip:focus-visible {
|
||||
outline: 2px solid var(--color-primary-a45);
|
||||
outline-offset: 2px;
|
||||
box-shadow: 0 0 0 3px var(--color-primary-a12);
|
||||
}
|
||||
.slot-icon {
|
||||
color: var(--color-primary);
|
||||
|
||||
Reference in New Issue
Block a user