using Socialize.Api.Modules.Feedback.Data; namespace Socialize.Api.Modules.Feedback.Contracts; public record FeedbackContextDto( Guid? WorkspaceId, string? WorkspaceName, Guid? ClientId, string? ClientName, Guid? ProjectId, string? ProjectName, Guid? ContentItemId, string? ContentItemTitle); public record FeedbackMetadataDto( string SubmittedPath, string? BrowserUserAgent, int? ViewportWidth, int? ViewportHeight, string? AppVersion); public record FeedbackScreenshotDto( Guid Id, string FileName, string ContentType, long SizeBytes, string DownloadPath, DateTimeOffset CreatedAt); public record FeedbackReportDto( Guid Id, string Type, string Status, string Description, Guid ReporterUserId, string ReporterDisplayName, string ReporterEmail, FeedbackMetadataDto Metadata, FeedbackContextDto Context, FeedbackScreenshotDto? Screenshot, IReadOnlyCollection Tags, IReadOnlyCollection Timeline, DateTimeOffset CreatedAt, DateTimeOffset LastActivityAt, DateTimeOffset? CancelledAt, string? CancellationReason); public record FeedbackTimelineItemDto( Guid Id, string Kind, Guid ActorUserId, string ActorDisplayName, string ActorEmail, string? ActorRole, string? Body, string? ActivityType, string? FromValue, string? ToValue, string? Note, DateTimeOffset CreatedAt); public static class FeedbackDtoMapper { public static FeedbackReportDto ToDto(this FeedbackReport report) { return new FeedbackReportDto( report.Id, ToDisplayString(report.Type), ToDisplayString(report.Status), report.Description, report.ReporterUserId, report.ReporterDisplayName, report.ReporterEmail, new FeedbackMetadataDto( report.SubmittedPath, report.BrowserUserAgent, report.ViewportWidth, report.ViewportHeight, report.AppVersion), new FeedbackContextDto( report.WorkspaceId, report.WorkspaceName, report.ClientId, report.ClientName, report.ProjectId, report.ProjectName, report.ContentItemId, report.ContentItemTitle), report.Screenshot is null ? null : new FeedbackScreenshotDto( report.Screenshot.Id, report.Screenshot.FileName, report.Screenshot.ContentType, report.Screenshot.SizeBytes, $"/api/feedback/{report.Id}/screenshot", report.Screenshot.CreatedAt), report.Tags.OrderBy(tag => tag.Name).Select(tag => tag.Name).ToArray(), report.Comments .Select(comment => comment.ToTimelineDto()) .Concat(report.ActivityEntries.Select(activity => activity.ToTimelineDto())) .OrderBy(item => item.CreatedAt) .ThenBy(item => item.Kind) .ToArray(), report.CreatedAt, report.LastActivityAt, report.CancelledAt, report.CancellationReason); } private static string ToDisplayString(FeedbackType type) { return type.ToString(); } private static string ToDisplayString(FeedbackStatus status) { return status == FeedbackStatus.WontDo ? "Won't Do" : status.ToString(); } public static FeedbackTimelineItemDto ToTimelineDto(this FeedbackComment comment) { return new FeedbackTimelineItemDto( comment.Id, "Comment", comment.AuthorUserId, comment.AuthorDisplayName, comment.AuthorEmail, comment.AuthorRole, comment.Body, null, null, null, null, comment.CreatedAt); } public static FeedbackTimelineItemDto ToTimelineDto(this FeedbackActivityEntry activity) { return new FeedbackTimelineItemDto( activity.Id, "Activity", activity.ActorUserId, activity.ActorDisplayName, activity.ActorEmail, null, null, activity.ActivityType, activity.FromValue, activity.ToValue, activity.Note, activity.CreatedAt); } public static string ToFeedbackDisplayString(this FeedbackType type) { return ToDisplayString(type); } public static string ToFeedbackDisplayString(this FeedbackStatus status) { return ToDisplayString(status); } }