diff --git a/backend/UniVerse.Application/DTOs/Achievements/AchievementDtos.cs b/backend/UniVerse.Application/DTOs/Achievements/AchievementDtos.cs new file mode 100644 index 0000000..203cd66 --- /dev/null +++ b/backend/UniVerse.Application/DTOs/Achievements/AchievementDtos.cs @@ -0,0 +1,36 @@ +namespace UniVerse.Application.DTOs.Achievements; + +public record AchievementDto( + int Id, + string Name, + string? Description, + string? IconUrl, + int XpReward, + int CoinReward, + string? Condition, + DateTime CreatedAt +); + +public record UserAchievementDto( + int Id, + AchievementDto Achievement, + DateTime AwardedAt +); + +public record CreateAchievementRequest( + string Name, + string? Description, + string? IconUrl, + int XpReward, + int CoinReward, + string? Condition +); + +public record UpdateAchievementRequest( + string Name, + string? Description, + string? IconUrl, + int XpReward, + int CoinReward, + string? Condition +); diff --git a/backend/UniVerse.Application/DTOs/Auth/AuthDtos.cs b/backend/UniVerse.Application/DTOs/Auth/AuthDtos.cs new file mode 100644 index 0000000..e7c5f3c --- /dev/null +++ b/backend/UniVerse.Application/DTOs/Auth/AuthDtos.cs @@ -0,0 +1,11 @@ +using UniVerse.Domain.Enums; + +namespace UniVerse.Application.DTOs.Auth; + +public record AuthResponse(string AccessToken, DateTime ExpiresAt, UserAuthDto User); + +public record UserAuthDto(int Id, string Email, string? DisplayName, UserRole Role); + +public record LoginMicrosoftRequest(string AuthorizationCode); + +public record DevLoginRequest(string Email, string? DisplayName = null, UserRole Role = UserRole.Student); diff --git a/backend/UniVerse.Application/DTOs/Common/PaginationDtos.cs b/backend/UniVerse.Application/DTOs/Common/PaginationDtos.cs new file mode 100644 index 0000000..aa47e0e --- /dev/null +++ b/backend/UniVerse.Application/DTOs/Common/PaginationDtos.cs @@ -0,0 +1,18 @@ +namespace UniVerse.Application.DTOs.Common; + +public record PaginationRequest(int Page = 1, int PageSize = 20); + +public record PagedResult( + List Items, + int TotalCount, + int Page, + int PageSize, + int TotalPages +) +{ + public static PagedResult Create(List items, int totalCount, int page, int pageSize) + { + var totalPages = (int)Math.Ceiling(totalCount / (double)pageSize); + return new PagedResult(items, totalCount, page, pageSize, totalPages); + } +} diff --git a/backend/UniVerse.Application/DTOs/Courses/CourseDtos.cs b/backend/UniVerse.Application/DTOs/Courses/CourseDtos.cs new file mode 100644 index 0000000..bc533d8 --- /dev/null +++ b/backend/UniVerse.Application/DTOs/Courses/CourseDtos.cs @@ -0,0 +1,24 @@ +using UniVerse.Application.DTOs.Tags; + +namespace UniVerse.Application.DTOs.Courses; + +public record CourseDto( + int Id, + string Name, + string? Description, + bool IsSynced, + List Tags, + DateTime CreatedAt +); + +public record CreateCourseRequest(string Name, string? Description); + +public record UpdateCourseRequest(string Name, string? Description); + +public record CourseFilterRequest( + int? TagId, + string? Search, + bool? IsSynced, + int Page = 1, + int PageSize = 20 +); diff --git a/backend/UniVerse.Application/DTOs/Gamification/GamificationDtos.cs b/backend/UniVerse.Application/DTOs/Gamification/GamificationDtos.cs new file mode 100644 index 0000000..3248165 --- /dev/null +++ b/backend/UniVerse.Application/DTOs/Gamification/GamificationDtos.cs @@ -0,0 +1,13 @@ +using UniVerse.Domain.Enums; + +namespace UniVerse.Application.DTOs.Gamification; + +public record CoinTransactionDto( + int Id, + int Amount, + CoinTransactionType Type, + int? ReviewId, + int? AchievementId, + string? Description, + DateTime CreatedAt +); diff --git a/backend/UniVerse.Application/DTOs/Lectures/LectureDtos.cs b/backend/UniVerse.Application/DTOs/Lectures/LectureDtos.cs new file mode 100644 index 0000000..37f3340 --- /dev/null +++ b/backend/UniVerse.Application/DTOs/Lectures/LectureDtos.cs @@ -0,0 +1,86 @@ +using UniVerse.Domain.Enums; + +namespace UniVerse.Application.DTOs.Lectures; + +public record LectureDto( + int Id, + int CourseId, + string CourseName, + int? TeacherId, + string? TeacherName, + int? LocationId, + string? LocationName, + string Title, + string? Description, + LectureFormat Format, + DateTime StartsAt, + DateTime EndsAt, + bool IsOpen, + int MaxEnrollments, + int EnrollmentsCount, + string? OnlineUrl, + DateTime CreatedAt +); + +public record LectureDetailDto( + int Id, + int CourseId, + string CourseName, + int? TeacherId, + string? TeacherName, + int? LocationId, + string? LocationName, + string Title, + string? Description, + LectureFormat Format, + DateTime StartsAt, + DateTime EndsAt, + bool IsOpen, + int MaxEnrollments, + int EnrollmentsCount, + string? OnlineUrl, + DateTime CreatedAt, + bool IsEnrolled +); + +public record CreateLectureRequest( + int CourseId, + int? TeacherId, + int? LocationId, + string Title, + string? Description, + LectureFormat Format, + DateTime StartsAt, + DateTime EndsAt, + bool IsOpen, + int MaxEnrollments, + string? OnlineUrl +); + +public record UpdateLectureRequest( + int? TeacherId, + int? LocationId, + string Title, + string? Description, + LectureFormat Format, + DateTime StartsAt, + DateTime EndsAt, + bool IsOpen, + int MaxEnrollments, + string? OnlineUrl +); + +public record LectureFilterRequest( + DateOnly? DateFrom, + DateOnly? DateTo, + int? CourseId, + int? TeacherId, + LectureFormat? Format, + bool? IsOpen, + int? TagId, + string? Search, + int Page = 1, + int PageSize = 20 +); + +public record EnrollmentDto(int Id, int UserId, string? UserName, string? UserEmail, bool Attended, DateTime CreatedAt); diff --git a/backend/UniVerse.Application/DTOs/Locations/LocationDtos.cs b/backend/UniVerse.Application/DTOs/Locations/LocationDtos.cs new file mode 100644 index 0000000..60470ae --- /dev/null +++ b/backend/UniVerse.Application/DTOs/Locations/LocationDtos.cs @@ -0,0 +1,7 @@ +namespace UniVerse.Application.DTOs.Locations; + +public record LocationDto(int Id, string Name, string? Building, string? Room, string? Address, DateTime CreatedAt); + +public record CreateLocationRequest(string Name, string? Building, string? Room, string? Address); + +public record UpdateLocationRequest(string Name, string? Building, string? Room, string? Address); diff --git a/backend/UniVerse.Application/DTOs/Reviews/ReviewDtos.cs b/backend/UniVerse.Application/DTOs/Reviews/ReviewDtos.cs new file mode 100644 index 0000000..416ee41 --- /dev/null +++ b/backend/UniVerse.Application/DTOs/Reviews/ReviewDtos.cs @@ -0,0 +1,23 @@ +using UniVerse.Domain.Enums; + +namespace UniVerse.Application.DTOs.Reviews; + +public record ReviewDto( + int Id, + int LectureId, + string? LectureTitle, + int UserId, + string? UserName, + ReviewRating Rating, + string? Text, + ReviewLlmStatus LlmStatus, + ReviewSentiment? Sentiment, + double? QualityScore, + bool? IsInformative, + string[]? LlmTags, + DateTime CreatedAt +); + +public record CreateReviewRequest(int LectureId, ReviewRating Rating, string? Text); + +public record UpdateReviewRequest(ReviewRating Rating, string? Text); diff --git a/backend/UniVerse.Application/DTOs/Sync/SyncDtos.cs b/backend/UniVerse.Application/DTOs/Sync/SyncDtos.cs new file mode 100644 index 0000000..c55263e --- /dev/null +++ b/backend/UniVerse.Application/DTOs/Sync/SyncDtos.cs @@ -0,0 +1,14 @@ +namespace UniVerse.Application.DTOs.Sync; + +public record SyncScheduleRequest( + string? SpecialtyCode, + DateTime? TimeMin, + DateTime? TimeMax, + string? TypeId +); + +public record SyncResultDto(int Created, int Updated, int Skipped, string? Error); + +public record SyncStatusDto(DateTime? LastSyncAt, string Status, SyncResultDto? LastResult); + +public record EmployeeDto(string? Id, string FullName, string? Department); diff --git a/backend/UniVerse.Application/DTOs/Tags/TagDtos.cs b/backend/UniVerse.Application/DTOs/Tags/TagDtos.cs new file mode 100644 index 0000000..60e98c4 --- /dev/null +++ b/backend/UniVerse.Application/DTOs/Tags/TagDtos.cs @@ -0,0 +1,11 @@ +using UniVerse.Domain.Enums; + +namespace UniVerse.Application.DTOs.Tags; + +public record TagDto(int Id, string Name, TagType Type, int? ParentId, DateTime CreatedAt); + +public record TagTreeDto(int Id, string Name, TagType Type, List Children); + +public record CreateTagRequest(string Name, TagType Type, int? ParentId); + +public record UpdateTagRequest(string Name, TagType Type, int? ParentId); diff --git a/backend/UniVerse.Application/DTOs/Users/UserDtos.cs b/backend/UniVerse.Application/DTOs/Users/UserDtos.cs new file mode 100644 index 0000000..2a79aa9 --- /dev/null +++ b/backend/UniVerse.Application/DTOs/Users/UserDtos.cs @@ -0,0 +1,55 @@ +using UniVerse.Domain.Enums; + +namespace UniVerse.Application.DTOs.Users; + +public record UserDto( + int Id, + string Email, + string? DisplayName, + string? AvatarUrl, + UserRole Role, + bool IsActive, + int Xp, + int Coins, + int Level, + DateTime CreatedAt +); + +public record UserStatsDto( + int TotalLectures, + int AttendedLectures, + int TotalReviews, + int Xp, + int Coins, + int Level, + int AchievementsCount +); + +public record UpdateUserRequest( + string? DisplayName, + string? AvatarUrl +); + +public record UserFilterRequest( + string? Search, + UserRole? Role, + bool? IsActive, + int Page = 1, + int PageSize = 20 +); + +public record StudentProfileDto( + int Id, + string? StudentId, + string? GroupName, + int? EnrollmentYear, + string? Faculty, + string? Specialty +); + +public record TeacherProfileDto( + int Id, + string? Department, + string? Title, + string? Bio +); diff --git a/backend/UniVerse.Application/Interfaces/IAchievementService.cs b/backend/UniVerse.Application/Interfaces/IAchievementService.cs new file mode 100644 index 0000000..3e3b8d3 --- /dev/null +++ b/backend/UniVerse.Application/Interfaces/IAchievementService.cs @@ -0,0 +1,12 @@ +using UniVerse.Application.DTOs.Achievements; + +namespace UniVerse.Application.Interfaces; + +public interface IAchievementService +{ + Task> GetAllAsync(); + Task GetByIdAsync(int id); + Task CreateAsync(CreateAchievementRequest request); + Task UpdateAsync(int id, UpdateAchievementRequest request); + Task DeleteAsync(int id); +} diff --git a/backend/UniVerse.Application/Interfaces/IAuthService.cs b/backend/UniVerse.Application/Interfaces/IAuthService.cs new file mode 100644 index 0000000..26a8b4c --- /dev/null +++ b/backend/UniVerse.Application/Interfaces/IAuthService.cs @@ -0,0 +1,13 @@ +using UniVerse.Application.DTOs.Auth; +using UniVerse.Application.DTOs.Users; + +namespace UniVerse.Application.Interfaces; + +public interface IAuthService +{ + Task LoginWithMicrosoftAsync(string authorizationCode); + Task DevLoginAsync(string email, string? displayName, Domain.Enums.UserRole role); + Task RefreshTokenAsync(string refreshToken); + Task RevokeRefreshTokenAsync(string refreshToken); + Task GetCurrentUserAsync(int userId); +} diff --git a/backend/UniVerse.Application/Interfaces/ICourseService.cs b/backend/UniVerse.Application/Interfaces/ICourseService.cs new file mode 100644 index 0000000..62710fc --- /dev/null +++ b/backend/UniVerse.Application/Interfaces/ICourseService.cs @@ -0,0 +1,15 @@ +using UniVerse.Application.DTOs.Common; +using UniVerse.Application.DTOs.Courses; + +namespace UniVerse.Application.Interfaces; + +public interface ICourseService +{ + Task> GetAllAsync(CourseFilterRequest filter); + Task GetByIdAsync(int id); + Task CreateAsync(CreateCourseRequest request); + Task UpdateAsync(int id, UpdateCourseRequest request); + Task DeleteAsync(int id); + Task AddTagAsync(int courseId, int tagId); + Task RemoveTagAsync(int courseId, int tagId); +} diff --git a/backend/UniVerse.Application/Interfaces/IGamificationService.cs b/backend/UniVerse.Application/Interfaces/IGamificationService.cs new file mode 100644 index 0000000..387b60c --- /dev/null +++ b/backend/UniVerse.Application/Interfaces/IGamificationService.cs @@ -0,0 +1,16 @@ +using UniVerse.Application.DTOs.Achievements; +using UniVerse.Application.DTOs.Common; +using UniVerse.Application.DTOs.Gamification; +using UniVerse.Domain.Enums; + +namespace UniVerse.Application.Interfaces; + +public interface IGamificationService +{ + Task AwardCoinsAsync(int userId, int amount, CoinTransactionType type, + int? reviewId = null, int? achievementId = null, string? description = null); + Task CheckAndAwardAchievementsAsync(int userId); + int CalculateLevel(int xp); + Task> GetUserAchievementsAsync(int userId); + Task> GetTransactionsAsync(int userId, PaginationRequest pagination); +} diff --git a/backend/UniVerse.Application/Interfaces/ILectureService.cs b/backend/UniVerse.Application/Interfaces/ILectureService.cs new file mode 100644 index 0000000..2dd11ad --- /dev/null +++ b/backend/UniVerse.Application/Interfaces/ILectureService.cs @@ -0,0 +1,17 @@ +using UniVerse.Application.DTOs.Common; +using UniVerse.Application.DTOs.Lectures; + +namespace UniVerse.Application.Interfaces; + +public interface ILectureService +{ + Task> GetAllAsync(LectureFilterRequest filter); + Task GetByIdAsync(int id, int? currentUserId = null); + Task CreateAsync(CreateLectureRequest request); + Task UpdateAsync(int id, UpdateLectureRequest request); + Task DeleteAsync(int id); + Task EnrollAsync(int lectureId, int userId); + Task UnenrollAsync(int lectureId, int userId); + Task MarkAttendanceAsync(int lectureId, int userId, bool attended); + Task> GetEnrollmentsAsync(int lectureId, PaginationRequest pagination); +} diff --git a/backend/UniVerse.Application/Interfaces/ILlmAnalysisService.cs b/backend/UniVerse.Application/Interfaces/ILlmAnalysisService.cs new file mode 100644 index 0000000..7f5af0a --- /dev/null +++ b/backend/UniVerse.Application/Interfaces/ILlmAnalysisService.cs @@ -0,0 +1,7 @@ +namespace UniVerse.Application.Interfaces; + +public interface ILlmAnalysisService +{ + Task AnalyzeReviewAsync(int reviewId); + Task ProcessPendingReviewsAsync(); +} diff --git a/backend/UniVerse.Application/Interfaces/ILlmClient.cs b/backend/UniVerse.Application/Interfaces/ILlmClient.cs new file mode 100644 index 0000000..dccefda --- /dev/null +++ b/backend/UniVerse.Application/Interfaces/ILlmClient.cs @@ -0,0 +1,13 @@ +namespace UniVerse.Application.Interfaces; + +public record LlmReviewAnalysis( + double QualityScore, + string Sentiment, + string[] Tags, + bool IsInformative +); + +public interface ILlmClient +{ + Task AnalyzeReviewAsync(string reviewText, string lectureContext); +} diff --git a/backend/UniVerse.Application/Interfaces/ILocationService.cs b/backend/UniVerse.Application/Interfaces/ILocationService.cs new file mode 100644 index 0000000..1487088 --- /dev/null +++ b/backend/UniVerse.Application/Interfaces/ILocationService.cs @@ -0,0 +1,12 @@ +using UniVerse.Application.DTOs.Locations; + +namespace UniVerse.Application.Interfaces; + +public interface ILocationService +{ + Task> GetAllAsync(); + Task GetByIdAsync(int id); + Task CreateAsync(CreateLocationRequest request); + Task UpdateAsync(int id, UpdateLocationRequest request); + Task DeleteAsync(int id); +} diff --git a/backend/UniVerse.Application/Interfaces/IReviewService.cs b/backend/UniVerse.Application/Interfaces/IReviewService.cs new file mode 100644 index 0000000..8d3330a --- /dev/null +++ b/backend/UniVerse.Application/Interfaces/IReviewService.cs @@ -0,0 +1,16 @@ +using UniVerse.Application.DTOs.Common; +using UniVerse.Application.DTOs.Reviews; + +namespace UniVerse.Application.Interfaces; + +public interface IReviewService +{ + Task CreateAsync(int userId, CreateReviewRequest request); + Task GetByIdAsync(int id); + Task UpdateAsync(int id, int userId, UpdateReviewRequest request); + Task DeleteAsync(int id, int userId, bool isAdmin = false); + Task> GetByLectureAsync(int lectureId, PaginationRequest pagination); + Task> GetByUserAsync(int userId, PaginationRequest pagination); + Task> GetPendingAsync(PaginationRequest pagination); + Task ReanalyzeAsync(int id); +} diff --git a/backend/UniVerse.Application/Interfaces/IScheduleSyncService.cs b/backend/UniVerse.Application/Interfaces/IScheduleSyncService.cs new file mode 100644 index 0000000..7558af7 --- /dev/null +++ b/backend/UniVerse.Application/Interfaces/IScheduleSyncService.cs @@ -0,0 +1,25 @@ +using UniVerse.Application.DTOs.Sync; + +namespace UniVerse.Application.Interfaces; + +public interface IScheduleSyncService +{ + Task SyncScheduleAsync(SyncScheduleRequest request); + Task SyncRoomsAsync(); + Task> SearchEmployeesAsync(string fullname); + Task GetLastSyncStatusAsync(); +} + +public interface IModeusApiClient +{ + Task SearchEventsAsync(SyncScheduleRequest request); + Task SearchRoomsAsync(); + Task> SearchEmployeeAsync(string fullname); +} + +// Modeus API response models +public record ModeusEvent(string Id, string Name, DateTime StartsAt, DateTime EndsAt, string? RoomId, string? TeacherId, string? TypeId); +public record ModeusEventsResponse(List Events); +public record ModeusRoom(string Id, string Name, string? Building); +public record ModeusRoomsResponse(List Rooms); +public record ModeusEmployee(string? Id, string FullName, string? Department); diff --git a/backend/UniVerse.Application/Interfaces/ITagService.cs b/backend/UniVerse.Application/Interfaces/ITagService.cs new file mode 100644 index 0000000..e492dcc --- /dev/null +++ b/backend/UniVerse.Application/Interfaces/ITagService.cs @@ -0,0 +1,15 @@ +using UniVerse.Application.DTOs.Common; +using UniVerse.Application.DTOs.Tags; +using UniVerse.Domain.Enums; + +namespace UniVerse.Application.Interfaces; + +public interface ITagService +{ + Task> GetAllAsync(TagType? type = null, int? parentId = null); + Task GetByIdAsync(int id); + Task CreateAsync(CreateTagRequest request); + Task UpdateAsync(int id, UpdateTagRequest request); + Task DeleteAsync(int id); + Task> GetTreeAsync(); +} diff --git a/backend/UniVerse.Application/Interfaces/IUserService.cs b/backend/UniVerse.Application/Interfaces/IUserService.cs new file mode 100644 index 0000000..4625450 --- /dev/null +++ b/backend/UniVerse.Application/Interfaces/IUserService.cs @@ -0,0 +1,15 @@ +using UniVerse.Application.DTOs.Common; +using UniVerse.Application.DTOs.Users; +using UniVerse.Domain.Enums; + +namespace UniVerse.Application.Interfaces; + +public interface IUserService +{ + Task GetByIdAsync(int id); + Task UpdateProfileAsync(int id, UpdateUserRequest request); + Task GetStatsAsync(int id); + Task> GetAllAsync(UserFilterRequest filter); + Task SetRoleAsync(int id, UserRole role); + Task SetActiveAsync(int id, bool isActive); +} diff --git a/backend/UniVerse.Application/Mappings/MappingExtensions.cs b/backend/UniVerse.Application/Mappings/MappingExtensions.cs new file mode 100644 index 0000000..a332e41 --- /dev/null +++ b/backend/UniVerse.Application/Mappings/MappingExtensions.cs @@ -0,0 +1,98 @@ +using UniVerse.Application.DTOs.Achievements; +using UniVerse.Application.DTOs.Auth; +using UniVerse.Application.DTOs.Courses; +using UniVerse.Application.DTOs.Gamification; +using UniVerse.Application.DTOs.Lectures; +using UniVerse.Application.DTOs.Locations; +using UniVerse.Application.DTOs.Reviews; +using UniVerse.Application.DTOs.Tags; +using UniVerse.Application.DTOs.Users; +using UniVerse.Domain.Entities; + +namespace UniVerse.Application.Mappings; + +public static class MappingExtensions +{ + // --- User --- + public static UserDto ToDto(this User user, int level) => new( + user.Id, user.Email, user.DisplayName, user.AvatarUrl, + user.Role, user.IsActive, user.Xp, user.Coins, level, user.CreatedAt + ); + + public static UserAuthDto ToAuthDto(this User user) => new( + user.Id, user.Email, user.DisplayName, user.Role + ); + + // --- Tag --- + public static TagDto ToDto(this Tag tag) => new( + tag.Id, tag.Name, tag.Type, tag.ParentId, tag.CreatedAt + ); + + public static TagTreeDto ToTreeDto(this Tag tag) => new( + tag.Id, tag.Name, tag.Type, + tag.Children.Select(c => c.ToTreeDto()).ToList() + ); + + // --- Location --- + public static LocationDto ToDto(this Location loc) => new( + loc.Id, loc.Name, loc.Building, loc.Room, loc.Address, loc.CreatedAt + ); + + // --- Course --- + public static CourseDto ToDto(this Course course) => new( + course.Id, course.Name, course.Description, course.IsSynced, + course.CourseTags.Select(ct => ct.Tag.ToDto()).ToList(), + course.CreatedAt + ); + + // --- Lecture --- + public static LectureDto ToDto(this Lecture lecture) => new( + lecture.Id, lecture.CourseId, lecture.Course?.Name ?? "", + lecture.TeacherId, lecture.Teacher?.DisplayName, + lecture.LocationId, lecture.Location?.Name, + lecture.Title, lecture.Description, lecture.Format, + lecture.StartsAt, lecture.EndsAt, lecture.IsOpen, + lecture.MaxEnrollments, lecture.Enrollments.Count, + lecture.OnlineUrl, lecture.CreatedAt + ); + + public static LectureDetailDto ToDetailDto(this Lecture lecture, bool isEnrolled) => new( + lecture.Id, lecture.CourseId, lecture.Course?.Name ?? "", + lecture.TeacherId, lecture.Teacher?.DisplayName, + lecture.LocationId, lecture.Location?.Name, + lecture.Title, lecture.Description, lecture.Format, + lecture.StartsAt, lecture.EndsAt, lecture.IsOpen, + lecture.MaxEnrollments, lecture.Enrollments.Count, + lecture.OnlineUrl, lecture.CreatedAt, isEnrolled + ); + + // --- Enrollment --- + public static EnrollmentDto ToDto(this LectureEnrollment enrollment) => new( + enrollment.Id, enrollment.UserId, + enrollment.User?.DisplayName, enrollment.User?.Email, + enrollment.Attended, enrollment.CreatedAt + ); + + // --- Review --- + public static ReviewDto ToDto(this Review review) => new( + review.Id, review.LectureId, review.Lecture?.Title, + review.UserId, review.User?.DisplayName, + review.Rating, review.Text, review.LlmStatus, + review.Sentiment, review.QualityScore, review.IsInformative, + review.LlmTags, review.CreatedAt + ); + + // --- Achievement --- + public static AchievementDto ToDto(this Achievement a) => new( + a.Id, a.Name, a.Description, a.IconUrl, a.XpReward, a.CoinReward, a.Condition, a.CreatedAt + ); + + public static UserAchievementDto ToDto(this UserAchievement ua) => new( + ua.Id, ua.Achievement.ToDto(), ua.AwardedAt + ); + + // --- CoinTransaction --- + public static CoinTransactionDto ToDto(this CoinTransaction ct) => new( + ct.Id, ct.Amount, ct.Type, ct.ReviewId, ct.AchievementId, ct.Description, ct.CreatedAt + ); +} diff --git a/backend/UniVerse.Application/UniVerse.Application.csproj b/backend/UniVerse.Application/UniVerse.Application.csproj new file mode 100644 index 0000000..d83e800 --- /dev/null +++ b/backend/UniVerse.Application/UniVerse.Application.csproj @@ -0,0 +1,23 @@ + + + + net10.0 + enable + enable + UniVerse.Application + + + + + + + + + + + + + + + +