Skip to content

Commit

Permalink
End of section 14
Browse files Browse the repository at this point in the history
  • Loading branch information
TryCatchLearn committed Aug 5, 2023
1 parent 3ddb556 commit be8e599
Show file tree
Hide file tree
Showing 22 changed files with 527 additions and 18 deletions.
63 changes: 63 additions & 0 deletions API/Controllers/LikesController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using API.Controllers;
using API.DTOs;
using API.Entities;
using API.Extensions;
using API.Helpers;
using API.Interfaces;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace API;

[Authorize]
public class LikesController : BaseApiController
{
private readonly IUserRepository _userRepository;
private readonly ILikesRepository _likesRepository;
public LikesController(IUserRepository userRepository, ILikesRepository likesRepository)
{
_likesRepository = likesRepository;
_userRepository = userRepository;
}

[HttpPost("{username}")]
public async Task<ActionResult> AddLike(string username)
{
var sourceUserId = User.GetUserId();
var likedUser = await _userRepository.GetUserByUsernameAsync(username);
var sourceUser = await _likesRepository.GetUserWithLikes(sourceUserId);

if (likedUser == null) return NotFound();

if (sourceUser.UserName == username) return BadRequest("You cannot like yourself");

var userLike = await _likesRepository.GetUserLike(sourceUserId, likedUser.Id);

if (userLike != null) return BadRequest("You already like this user");

userLike = new UserLike
{
SourceUserId = sourceUserId,
TargetUserId = likedUser.Id
};

sourceUser.LikedUsers.Add(userLike);

if (await _userRepository.SaveAllAsync()) return Ok();

return BadRequest("Failed to like user");
}

[HttpGet]
public async Task<ActionResult<PagedList<LikeDto>>> GetUserLikes([FromQuery]LikesParams likesParams)
{
likesParams.UserId = User.GetUserId();

var users = await _likesRepository.GetUserLikes(likesParams);

Response.AddPaginationHeader(new PaginationHeader(users.CurrentPage, users.PageSize,
users.TotalCount, users.TotalPages));

return Ok(users);
}
}
11 changes: 11 additions & 0 deletions API/DTOs/LikeDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace API.DTOs;

public class LikeDto
{
public int Id { get; set; }
public string UserName { get; set; }
public int Age { get; set; }
public string KnownAs { get; set; }
public string PhotoUrl { get; set; }
public string City { get; set; }
}
21 changes: 21 additions & 0 deletions API/Data/DataContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,25 @@ public DataContext(DbContextOptions options) : base(options)
}

public DbSet<AppUser> Users { get; set; }
public DbSet<UserLike> Likes { get; set; }

protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);

builder.Entity<UserLike>()
.HasKey(k => new { k.SourceUserId, k.TargetUserId });

builder.Entity<UserLike>()
.HasOne(s => s.SourceUser)
.WithMany(l => l.LikedUsers)
.HasForeignKey(s => s.SourceUserId)
.OnDelete(DeleteBehavior.Cascade);

builder.Entity<UserLike>()
.HasOne(s => s.TargetUser)
.WithMany(l => l.LikedByUsers)
.HasForeignKey(s => s.TargetUserId)
.OnDelete(DeleteBehavior.Cascade);
}
}
60 changes: 60 additions & 0 deletions API/Data/LikesRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using API.DTOs;
using API.Entities;
using API.Extensions;
using API.Helpers;
using API.Interfaces;
using Microsoft.EntityFrameworkCore;

namespace API.Data;

public class LikesRepository : ILikesRepository
{
private readonly DataContext _context;
public LikesRepository(DataContext context)
{
_context = context;

}

public async Task<UserLike> GetUserLike(int sourceUserId, int targetUserId)
{
return await _context.Likes.FindAsync(sourceUserId, targetUserId);
}

public async Task<PagedList<LikeDto>> GetUserLikes(LikesParams likesParams)
{
var users = _context.Users.OrderBy(u => u.UserName).AsQueryable();
var likes = _context.Likes.AsQueryable();

if (likesParams.Predicate == "liked")
{
likes = likes.Where(like => like.SourceUserId == likesParams.UserId);
users = likes.Select(like => like.TargetUser);
}

if (likesParams.Predicate == "likedBy")
{
likes = likes.Where(like => like.TargetUserId == likesParams.UserId);
users = likes.Select(like => like.SourceUser);
}

var likedUsers = users.Select(user => new LikeDto
{
UserName = user.UserName,
KnownAs = user.KnownAs,
Age = user.DateOfBirth.CalculateAge(),
PhotoUrl = user.Photos.FirstOrDefault(x => x.IsMain).Url,
City = user.City,
Id = user.Id
});

return await PagedList<LikeDto>.CreateAsync(likedUsers, likesParams.PageNumber, likesParams.PageSize);
}

public async Task<AppUser> GetUserWithLikes(int userId)
{
return await _context.Users
.Include(x => x.LikedUsers)
.FirstOrDefaultAsync(x => x.Id == userId);
}
}
154 changes: 154 additions & 0 deletions API/Data/Migrations/20230802041920_LikeEntityAdded.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 50 additions & 0 deletions API/Data/Migrations/20230802041920_LikeEntityAdded.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using Microsoft.EntityFrameworkCore.Migrations;

#nullable disable

namespace API.Data.Migrations
{
/// <inheritdoc />
public partial class LikeEntityAdded : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Likes",
columns: table => new
{
SourceUserId = table.Column<int>(type: "INTEGER", nullable: false),
TargetUserId = table.Column<int>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Likes", x => new { x.SourceUserId, x.TargetUserId });
table.ForeignKey(
name: "FK_Likes_Users_SourceUserId",
column: x => x.SourceUserId,
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Likes_Users_TargetUserId",
column: x => x.TargetUserId,
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});

migrationBuilder.CreateIndex(
name: "IX_Likes_TargetUserId",
table: "Likes",
column: "TargetUserId");
}

/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Likes");
}
}
}
Loading

0 comments on commit be8e599

Please sign in to comment.