84 lines
2.7 KiB
C#

using AutoMapper;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using OnlyPrompt.Backend.ApiModels.Prompt;
using OnlyPrompt.Backend.Database;
using OnlyPrompt.Backend.Utils;
using System.ComponentModel.DataAnnotations;
namespace OnlyPrompt.Backend.Controllers
{
[ApiController]
[Route("api/v1/feed")]
[Authorize(Roles = ModelConstants.UserRole)]
public class FeedController : BaseController
{
public FeedController(OnlyPromptContext db, IMapper mapper) : base(db, mapper)
{
}
[HttpGet]
public async Task<ApiMinimalPrompt[]> GetFeedAsync(
[Range(0, double.MaxValue)][FromQuery]int offset = 0,
[Range(1, 100)][FromQuery]int limit = 20,
[FromQuery]FeedSortType sortBy = FeedSortType.Date,
[FromQuery]bool ascending = false,
[FromQuery]Identifier? category = null,
[FromQuery]DateTime? fromDate = null,
[FromQuery]DateTime? toDate = null
)
{
var userId = User.GetUserId();
var query = _db.Prompts
.Where(x => x.CreatorId != userId)
.Where(x => x.Creator.Subscribers.Any(s => s.SubscriberId == userId));
if (category.HasValue)
query = query.Where(x => category.Value.Id.HasValue ? x.CategoryId == category.Value.Id.Value : x.Category.Slug == category.Value.Slug);
if (fromDate.HasValue)
query = query.Where(x => x.UpdatedAt >= fromDate.Value);
if (toDate.HasValue)
query = query.Where(x => x.UpdatedAt <= toDate.Value);
query = sortBy switch {
FeedSortType.Date => query.OrderBy(x => x.UpdatedAt, ascending),
FeedSortType.Rating => ascending
? query.OrderBy(x => x.Reviews.Average(r => (double?)r.Rating) ?? 0).ThenBy(x => x.Reviews.Count)
: query.OrderByDescending(x => x.Reviews.Average(r => (double?)r.Rating) ?? 0).ThenByDescending(x => x.Reviews.Count),
_ => query
};
var prompts = await query
.Skip(offset)
.Take(limit)
.Select(x => new ApiMinimalPrompt(
x.Id,
x.Title,
x.Description,
x.UpdatedAt,
x.CreatorId,
x.Creator.Profile.DisplayName,
x.Creator.Profile.AvatarUrl,
x.ExampleImageUrl,
x.Price,
x.Likes.Count,
x.Likes.Any(l => l.UserId == userId),
x.Saves.Count,
x.Saves.Any(s => s.UserId == userId),
x.SubscriptionTier == null ? (int?)null : x.SubscriptionTier.Level,
x.SubscriptionTier == null ? null : x.SubscriptionTier.Name,
x.SubscriptionTier == null ? (decimal?)null : x.SubscriptionTier.MonthlyPrice,
x.Reviews.Average(r => (double?)r.Rating),
x.Reviews.Count,
x.SubscriptionTier == null || x.Creator.Subscribers.Any(s => s.SubscriberId == userId && x.SubscriptionTier.Level <= s.SubscriptionTier.Level)
)).ToArrayAsync();
return prompts;
}
}
}