feat: первое подключение фронтенда
🚀 Create and publish a Docker image / Detect changes in backend and frontend (push) Successful in 8s
🚀 Create and publish a Docker image / Build & publish backend image (push) Successful in 54s
🚀 Create and publish a Docker image / Build & publish frontend image (push) Successful in 27s
🚀 Create and publish a Docker image / Update stack on Portainer (push) Successful in 6s
🚀 Create and publish a Docker image / Detect changes in backend and frontend (push) Successful in 8s
🚀 Create and publish a Docker image / Build & publish backend image (push) Successful in 54s
🚀 Create and publish a Docker image / Build & publish frontend image (push) Successful in 27s
🚀 Create and publish a Docker image / Update stack on Portainer (push) Successful in 6s
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
import type { Achievement, CoinTransaction, Lecture, Review, User, UserRole } from '@/types'
|
||||
import type {
|
||||
AchievementDto,
|
||||
CoinTransactionDto,
|
||||
LectureDto,
|
||||
ReviewDto,
|
||||
UserAuthDto,
|
||||
UserDto,
|
||||
UserStatsDto,
|
||||
UserAchievementDto,
|
||||
} from './types'
|
||||
|
||||
export function mapApiRole(role: string | undefined): UserRole {
|
||||
if (role === 'Teacher') return 'teacher'
|
||||
if (role === 'Admin') return 'admin'
|
||||
return 'student'
|
||||
}
|
||||
|
||||
export function mapApiUser(user: UserAuthDto | UserDto, stats?: UserStatsDto): User {
|
||||
return {
|
||||
id: String(user.id),
|
||||
name: user.displayName || user.email || 'Пользователь UniVerse',
|
||||
email: user.email || '',
|
||||
role: mapApiRole(user.role),
|
||||
avatar: 'avatarUrl' in user ? user.avatarUrl ?? undefined : undefined,
|
||||
institute: 'ЮФУ',
|
||||
department: '',
|
||||
year: 0,
|
||||
direction: '',
|
||||
coins: stats?.coins ?? ('coins' in user ? user.coins : 0),
|
||||
level: stats?.level ?? ('level' in user ? user.level : 1),
|
||||
xp: stats?.xp ?? ('xp' in user ? user.xp : 0),
|
||||
lecturesAttended: stats?.attendedLectures ?? 0,
|
||||
hoursLearned: stats ? Math.round(stats.attendedLectures * 1.5 * 10) / 10 : 0,
|
||||
achievements: stats ? Array.from({ length: stats.achievementsCount }, (_, index) => String(index + 1)) : [],
|
||||
}
|
||||
}
|
||||
|
||||
export function mapApiLecture(lecture: LectureDto): Lecture {
|
||||
const startsAt = new Date(lecture.startsAt)
|
||||
const endsAt = new Date(lecture.endsAt)
|
||||
const durationMs = endsAt.getTime() - startsAt.getTime()
|
||||
const duration = Number.isFinite(durationMs) && durationMs > 0 ? Math.round(durationMs / 60000) : 90
|
||||
const totalSeats = lecture.maxEnrollments || 0
|
||||
const enrolled = lecture.enrollmentsCount || 0
|
||||
const freeSeats = Math.max(totalSeats - enrolled, 0)
|
||||
const locationName = lecture.locationName || (lecture.format === 'Online' ? 'Онлайн' : 'Аудитория уточняется')
|
||||
|
||||
return {
|
||||
id: String(lecture.id),
|
||||
title: lecture.title || lecture.courseName || 'Лекция без названия',
|
||||
description: lecture.description || 'Описание появится позже.',
|
||||
teacher: lecture.teacherName || 'Преподаватель уточняется',
|
||||
teacherTitle: '',
|
||||
department: '',
|
||||
institute: lecture.courseName || 'ЮФУ',
|
||||
date: startsAt.toISOString().slice(0, 10),
|
||||
time: startsAt.toLocaleTimeString('ru-RU', { hour: '2-digit', minute: '2-digit' }),
|
||||
duration,
|
||||
building: lecture.format === 'Online' ? 'Онлайн' : locationName,
|
||||
room: lecture.format === 'Online' ? undefined : locationName,
|
||||
format: lecture.format === 'Online' ? 'online' : 'offline',
|
||||
totalSeats,
|
||||
freeSeats,
|
||||
registrationClosed: !lecture.isOpen,
|
||||
tags: lecture.courseName ? [`#${lecture.courseName}`] : [],
|
||||
rating: 0,
|
||||
reviewCount: 0,
|
||||
status: startsAt.getTime() > Date.now() ? 'upcoming' : 'completed',
|
||||
registered: lecture.isEnrolled,
|
||||
}
|
||||
}
|
||||
|
||||
export function mapApiReview(review: ReviewDto): Review {
|
||||
const sentiment = review.sentiment === 'Negative' ? 'negative' : review.sentiment === 'Neutral' ? 'neutral' : 'positive'
|
||||
const status =
|
||||
review.llmStatus === 'Rejected' ? 'rejected' : review.llmStatus === 'Analyzed' ? 'done' : 'pending'
|
||||
|
||||
return {
|
||||
id: String(review.id),
|
||||
lectureId: String(review.lectureId),
|
||||
userId: String(review.userId),
|
||||
userName: review.userName || 'Анонимный отзыв',
|
||||
text: review.text || '',
|
||||
sentiment,
|
||||
createdAt: review.createdAt,
|
||||
status,
|
||||
quality: review.qualityScore ?? undefined,
|
||||
}
|
||||
}
|
||||
|
||||
export function mapApiAchievement(input: AchievementDto | UserAchievementDto): Achievement {
|
||||
const dto = 'achievement' in input ? input.achievement : input
|
||||
const awardedAt = 'achievement' in input ? input.awardedAt : undefined
|
||||
|
||||
return {
|
||||
id: String(dto.id),
|
||||
title: dto.name || 'Достижение',
|
||||
description: dto.description || dto.condition || '',
|
||||
icon: dto.iconUrl || '⭐',
|
||||
unlocked: Boolean(awardedAt),
|
||||
unlockedAt: awardedAt,
|
||||
coins: dto.coinReward,
|
||||
}
|
||||
}
|
||||
|
||||
export function mapApiCoinTransaction(transaction: CoinTransactionDto): CoinTransaction {
|
||||
return {
|
||||
id: String(transaction.id),
|
||||
date: transaction.createdAt.slice(0, 10),
|
||||
description: transaction.description || transaction.type,
|
||||
amount: transaction.amount,
|
||||
type: transaction.amount >= 0 ? 'earned' : 'spent',
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user