feat: добавил ограничение записи на лекции
Backend CI / build-and-test (push) Failing after 32s
Frontend CI / build-and-check (push) Failing after 5m5s
🚀 Create and publish a Docker image / Detect changes in backend and frontend (push) Successful in 6s
🚀 Create and publish a Docker image / Build & publish backend image (push) Failing after 1m28s
🚀 Create and publish a Docker image / Build & publish frontend image (push) Failing after 19s
🚀 Create and publish a Docker image / Update stack on Portainer (push) Has been skipped
Backend CI / build-and-test (push) Failing after 32s
Frontend CI / build-and-check (push) Failing after 5m5s
🚀 Create and publish a Docker image / Detect changes in backend and frontend (push) Successful in 6s
🚀 Create and publish a Docker image / Build & publish backend image (push) Failing after 1m28s
🚀 Create and publish a Docker image / Build & publish frontend image (push) Failing after 19s
🚀 Create and publish a Docker image / Update stack on Portainer (push) Has been skipped
This commit is contained in:
@@ -3,6 +3,7 @@ import { computed, ref } from 'vue'
|
||||
import { lecturesApi, usersApi } from '@/api'
|
||||
import { mapApiLecture, mapApiReview } from '@/api/mappers'
|
||||
import type { Lecture, Review } from '@/types'
|
||||
import { useUserStore } from './user'
|
||||
|
||||
export const useLecturesStore = defineStore('lectures', () => {
|
||||
const lectures = ref<Lecture[]>([])
|
||||
@@ -74,16 +75,23 @@ export const useLecturesStore = defineStore('lectures', () => {
|
||||
async function register(lectureId: string) {
|
||||
const lecture = lectures.value.find(item => item.id === lectureId)
|
||||
if (!lecture || lecture.freeSeats === 0 || lecture.registrationClosed || registered.value.includes(lectureId)) return
|
||||
const userStore = useUserStore()
|
||||
if (!userStore.hasEnrollmentSlotAvailable) {
|
||||
throw new Error('Лимит записей достигнут. Отмените одну из записей или повысьте уровень.')
|
||||
}
|
||||
|
||||
await lecturesApi.enroll(lectureId)
|
||||
registered.value.push(lectureId)
|
||||
lecture.freeSeats = Math.max(lecture.freeSeats - 1, 0)
|
||||
lecture.enrolledSeats += 1
|
||||
lecture.registered = true
|
||||
userStore.adjustActiveEnrollments(1)
|
||||
await userStore.fetchStats().catch(() => undefined)
|
||||
}
|
||||
|
||||
async function unregister(lectureId: string) {
|
||||
await lecturesApi.unenroll(lectureId)
|
||||
const userStore = useUserStore()
|
||||
registered.value = registered.value.filter(id => id !== lectureId)
|
||||
const lecture = lectures.value.find(item => item.id === lectureId)
|
||||
if (lecture) {
|
||||
@@ -91,6 +99,8 @@ export const useLecturesStore = defineStore('lectures', () => {
|
||||
lecture.enrolledSeats = Math.max(lecture.enrolledSeats - 1, 0)
|
||||
lecture.registered = false
|
||||
}
|
||||
userStore.adjustActiveEnrollments(-1)
|
||||
await userStore.fetchStats().catch(() => undefined)
|
||||
}
|
||||
|
||||
function isRegistered(lectureId: string) {
|
||||
|
||||
+55
-14
@@ -1,7 +1,8 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
import { computed, ref } from 'vue'
|
||||
import { achievementsApi, notificationsApi, usersApi } from '@/api'
|
||||
import { mapApiAchievement, mapApiCoinTransaction, mapApiNotification } from '@/api/mappers'
|
||||
import type { UserStatsDto } from '@/api/types'
|
||||
import type { Achievement, CoinTransaction, Notification } from '@/types'
|
||||
import { useAuthStore } from './auth'
|
||||
|
||||
@@ -11,6 +12,53 @@ export const useUserStore = defineStore('user', () => {
|
||||
const coinHistory = ref<CoinTransaction[]>([])
|
||||
const loading = ref(false)
|
||||
const error = ref<string | null>(null)
|
||||
const activeEnrollments = computed(() => useAuthStore().user?.activeEnrollments ?? 0)
|
||||
const enrollmentSlotLimit = computed(() => useAuthStore().user?.enrollmentSlotLimit ?? 0)
|
||||
const hasEnrollmentSlotAvailable = computed(() =>
|
||||
enrollmentSlotLimit.value === 0 || activeEnrollments.value < enrollmentSlotLimit.value
|
||||
)
|
||||
|
||||
function applyStats(stats: UserStatsDto) {
|
||||
const auth = useAuthStore()
|
||||
if (!auth.user) return
|
||||
|
||||
auth.setUser({
|
||||
...auth.user,
|
||||
coins: stats.coins,
|
||||
level: stats.level,
|
||||
xp: stats.xp,
|
||||
currentLevelXp: stats.currentLevelXp,
|
||||
nextLevelXp: stats.nextLevelXp,
|
||||
lecturesAttended: stats.attendedLectures,
|
||||
hoursLearned: Math.round(stats.attendedLectures * 1.5 * 10) / 10,
|
||||
achievements: Array.from({ length: stats.achievementsCount }, (_, index) => String(index + 1)),
|
||||
activeEnrollments: stats.activeEnrollments,
|
||||
enrollmentSlotLimit: stats.enrollmentSlotLimit,
|
||||
enrollmentSlotRules: stats.enrollmentSlotRules,
|
||||
})
|
||||
}
|
||||
|
||||
async function fetchStats() {
|
||||
error.value = null
|
||||
try {
|
||||
const stats = await usersApi.myStats()
|
||||
applyStats(stats)
|
||||
return stats
|
||||
} catch (err) {
|
||||
error.value = err instanceof Error ? err.message : 'Не удалось загрузить статистику профиля.'
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
function adjustActiveEnrollments(delta: number) {
|
||||
const auth = useAuthStore()
|
||||
if (!auth.user || typeof auth.user.activeEnrollments !== 'number') return
|
||||
|
||||
auth.setUser({
|
||||
...auth.user,
|
||||
activeEnrollments: Math.max(auth.user.activeEnrollments + delta, 0),
|
||||
})
|
||||
}
|
||||
|
||||
async function fetchStudentData() {
|
||||
const auth = useAuthStore()
|
||||
@@ -29,19 +77,7 @@ export const useUserStore = defineStore('user', () => {
|
||||
notificationsApi.list(),
|
||||
])
|
||||
|
||||
if (auth.user) {
|
||||
auth.setUser({
|
||||
...auth.user,
|
||||
coins: stats.coins,
|
||||
level: stats.level,
|
||||
xp: stats.xp,
|
||||
currentLevelXp: stats.currentLevelXp,
|
||||
nextLevelXp: stats.nextLevelXp,
|
||||
lecturesAttended: stats.attendedLectures,
|
||||
hoursLearned: Math.round(stats.attendedLectures * 1.5 * 10) / 10,
|
||||
achievements: Array.from({ length: stats.achievementsCount }, (_, index) => String(index + 1)),
|
||||
})
|
||||
}
|
||||
applyStats(stats)
|
||||
const unlocked = new Map(achievementPayload.map(item => {
|
||||
const achievement = mapApiAchievement(item)
|
||||
return [achievement.id, achievement]
|
||||
@@ -85,6 +121,11 @@ export const useUserStore = defineStore('user', () => {
|
||||
coinHistory,
|
||||
loading,
|
||||
error,
|
||||
activeEnrollments,
|
||||
enrollmentSlotLimit,
|
||||
hasEnrollmentSlotAvailable,
|
||||
fetchStats,
|
||||
adjustActiveEnrollments,
|
||||
fetchStudentData,
|
||||
fetchNotifications,
|
||||
markAllRead,
|
||||
|
||||
Reference in New Issue
Block a user