add and delete seasons and episodes in title.

This commit is contained in:
THE_KONDRAT 2025-01-20 00:49:11 +03:00
parent b347753f1a
commit a336b40b34
15 changed files with 103 additions and 26 deletions

View File

@ -11,7 +11,7 @@ public class RateTitleCommand : IRequest<Unit>
public ushort RatePercentage { get; set; } public ushort RatePercentage { get; set; }
} }
public class RateTitleCommandHandler(IAnimeTitleGateway titleGateway, UserContext userContext, IMediator mediator) : IRequestHandler<RateTitleCommand, Unit> public class VoteTitleCommandHandler(IAnimeTitleGateway titleGateway, UserContext userContext, IMediator mediator) : IRequestHandler<RateTitleCommand, Unit>
{ {
public async Task<Unit> Handle(RateTitleCommand request, CancellationToken cancellationToken) public async Task<Unit> Handle(RateTitleCommand request, CancellationToken cancellationToken)
{ {
@ -24,7 +24,7 @@ public class RateTitleCommandHandler(IAnimeTitleGateway titleGateway, UserContex
var title = await titleGateway.GetById(request.TitleId); var title = await titleGateway.GetById(request.TitleId);
if (title != null && !title.Deleted) if (title != null && !title.Deleted)
{ {
await mediator.Send(new RateObjectCommand { ObjectId = title.Id, SubjectId = subjectId, RatePercentage = request.RatePercentage }); await mediator.Send(new VoteForObjectCommand { ObjectId = title.Id, SubjectId = subjectId, RatingPercentage = request.RatePercentage });
} }
return Unit.Value; return Unit.Value;
} }

View File

@ -12,7 +12,7 @@ public class RateObjectCommand : IRequest<Unit>
} }
public class RateObjectCommandHandler(RateRepository repository) : IRequestHandler<RateObjectCommand, Unit> public class VoteForObjectCommandHandler(RatingRepository repository) : IRequestHandler<RateObjectCommand, Unit>
{ {
public async Task<Unit> Handle(RateObjectCommand request, CancellationToken cancellationToken) public async Task<Unit> Handle(RateObjectCommand request, CancellationToken cancellationToken)
{ {
@ -26,12 +26,12 @@ public class RateObjectCommandHandler(RateRepository repository) : IRequestHandl
if (!await repository.IsRateExists(request.ObjectId, request.SubjectId)) if (!await repository.IsRateExists(request.ObjectId, request.SubjectId))
{ {
//await repository.AddAsync(new Rate { Key = key, RatePercentage = request.RatePercentage, }); //await repository.AddAsync(new Rate { Key = key, RatePercentage = request.RatePercentage, });
await repository.AddAsync(new Rate { ObjectId = request.ObjectId, SubjectId = request.SubjectId, RatePercentage = request.RatePercentage, }); await repository.AddAsync(new Vote { ObjectId = request.ObjectId, SubjectId = request.SubjectId, RatePercentage = request.RatePercentage, });
} }
else else
{ {
//await repository.UpdateAsync(new Rate { Key = key, RatePercentage = request.RatePercentage, }); //await repository.UpdateAsync(new Rate { Key = key, RatePercentage = request.RatePercentage, });
await repository.UpdateAsync(new Rate { ObjectId = request.ObjectId, SubjectId = request.SubjectId, RatePercentage = request.RatePercentage, }); await repository.UpdateAsync(new Vote { ObjectId = request.ObjectId, SubjectId = request.SubjectId, RatePercentage = request.RatePercentage, });
} }
return Unit.Value; return Unit.Value;
} }

View File

@ -1,7 +0,0 @@
namespace Modules.Rating.Api.Database.Entities;
public class RateKey
{
public Guid ObjectId { get; set; } = default!;
public Guid SubjectId { get; set; } = default!;
}

View File

@ -8,16 +8,16 @@ namespace Modules.Rating.Api.Repositories;
public class RateRepository(RatingDbContext context) public class RateRepository(RatingDbContext context)
{ {
private readonly RatingDbContext _context = context; private readonly RatingDbContext _context = context;
public async Task AddAsync(Rate entity) public async Task AddAsync(Vote entity)
{ {
if (await IsRateExists(entity.ObjectId, entity.SubjectId)) throw new Exception("Object is already rated by subject"); if (await IsRateExists(entity.ObjectId, entity.SubjectId)) throw new Exception("Object is already rated by subject");
_context.Rates.Add(entity); _context.Votes.Add(entity);
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
} }
public async Task<bool> UpdateAsync(Rate entity) public async Task<bool> UpdateAsync(Vote entity)
{ {
var rate = await _context.Rates var rate = await _context.Votes
.FirstOrDefaultAsync(q => q.ObjectId == entity.ObjectId && q.SubjectId == entity.SubjectId) .FirstOrDefaultAsync(q => q.ObjectId == entity.ObjectId && q.SubjectId == entity.SubjectId)
?? throw new Exception("Rate not found"); ?? throw new Exception("Rate not found");
rate.RatePercentage = entity.RatePercentage; rate.RatePercentage = entity.RatePercentage;
@ -27,21 +27,21 @@ public class RateRepository(RatingDbContext context)
public async Task<bool> DeleteAsync(Guid objectId, Guid subjectId) public async Task<bool> DeleteAsync(Guid objectId, Guid subjectId)
{ {
var rate = await _context.Rates.FirstOrDefaultAsync(q => q.ObjectId == objectId && q.SubjectId == subjectId); var rate = await _context.Votes.FirstOrDefaultAsync(q => q.ObjectId == objectId && q.SubjectId == subjectId);
if (rate != null) _context.Rates?.Remove(rate); if (rate != null) _context.Votes?.Remove(rate);
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
return rate != null; return rate != null;
} }
public async Task<Rate?> GetFirstOrDefaultWhere(Expression<Func<Rate, bool>> predicate) => public async Task<Vote?> GetFirstOrDefaultWhere(Expression<Func<Vote, bool>> predicate) =>
await _context.Rates.Where(predicate).SingleOrDefaultAsync(); await _context.Votes.Where(predicate).SingleOrDefaultAsync();
public async Task<List<Rate>> GetWhere(Expression<Func<Rate, bool>> predicate) => public async Task<List<Vote>> GetWhere(Expression<Func<Vote, bool>> predicate) =>
await _context.Rates.Where(predicate).ToListAsync(); await _context.Votes.Where(predicate).ToListAsync();
internal async Task<List<RateItem>> GetRates(IEnumerable<Guid> objectIds, Guid? subjectId) internal async Task<List<RateItem>> GetRates(IEnumerable<Guid> objectIds, Guid? subjectId)
{ {
var query = _context.Rates.AsQueryable(); var query = _context.Votes.AsQueryable();
return await query return await query
.Where(q => objectIds.Contains(q.ObjectId)) .Where(q => objectIds.Contains(q.ObjectId))
.GroupBy(q => q.ObjectId, (o, r) => new { ObjectId = o, Rate = r.Average(q => q.RatePercentage) }) .GroupBy(q => q.ObjectId, (o, r) => new { ObjectId = o, Rate = r.Average(q => q.RatePercentage) })
@ -137,8 +137,8 @@ public class RateRepository(RatingDbContext context)
public async Task<double?> GetAverageObjectRate(Guid objectId) public async Task<double?> GetAverageObjectRate(Guid objectId)
{ {
if (!await _context.Rates.AnyAsync(q => q.ObjectId == objectId)) return null; if (!await _context.Votes.AnyAsync(q => q.ObjectId == objectId)) return null;
return await _context.Rates return await _context.Votes
.Where(q => q.ObjectId == objectId) .Where(q => q.ObjectId == objectId)
.GroupBy(q => q.ObjectId) .GroupBy(q => q.ObjectId)
.Select(q => q.Average(q => q.RatePercentage)) .Select(q => q.Average(q => q.RatePercentage))
@ -146,5 +146,5 @@ public class RateRepository(RatingDbContext context)
} }
public async Task<bool> IsRateExists(Guid objectId, Guid subjectId) => public async Task<bool> IsRateExists(Guid objectId, Guid subjectId) =>
await _context.Rates.Where(q => q.ObjectId == objectId && q.SubjectId == subjectId).AnyAsync(); await _context.Votes.Where(q => q.ObjectId == objectId && q.SubjectId == subjectId).AnyAsync();
} }

View File

@ -0,0 +1,76 @@
import React, {ReactElement} from "react";
import ModalWindowComponentBase, {ModalWindowFullscreenMode, ModalWindowSize} from "./ModalWindowComponentBase.tsx";
import {GetCombinedClassesArray} from "../../../common/Helper.tsx";
export interface ITwoButtonModalWindowComponentProps extends React.PropsWithChildren{
title: string,
first_button_text: string,
first_button_classes: string,
// first_button_small?: boolean | undefined | null,
on_first_button_clicked?: () => void,
second_button_text: string,
second_button_classes: string,
// second_button_small?: boolean | undefined | null,
on_second_button_clicked?: () => void,
id? : string | undefined | null,
labelId? : string | undefined | null,
tabIndex? : number | null,
size?: ModalWindowSize | undefined | null,
fullscreen_mode?: ModalWindowFullscreenMode | undefined | null,
fade?: boolean | undefined | null,
vertically_centered?: boolean | undefined | null,
show?: boolean | undefined | null,
onExit?: () => void,
children: ReactElement
}
export default function TwoButtonModalWindowComponent(props: ITwoButtonModalWindowComponentProps){
const id = props.id != null && props.id != '' ? props.id : Math.random().toString(36).substring(2, 9);
return (
<ModalWindowComponentBase show={props.show} id={id} fade={props.fade} showBackdrop={true}
vertically_centered={props.vertically_centered}
respectMouseInsideOut={true}
onOutsideClicked={() => props.onExit?.()}
>
<>
<div className="modal-header">
<h5 className="modal-title" id="exampleModalLabel">{props.title}</h5>
<button type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Close"
onClick={() => props.onExit?.()}></button>
</div>
<div className="modal-body">
<ul className="nav nav-tabs">
<li className="nav-item">
<a className="nav-link active" aria-current="page" href="#">"Сезон"</a>
</li>
<li className="nav-item">
<a className="nav-link" href="#">Эпизод</a>
</li>
</ul>
{props.children}
</div>
<div className="modal-footer">
{React.cloneElement((
<button type="button" data-bs-dismiss="modal"
onClick={() => props.on_first_button_clicked?.()}>
{props.first_button_text}
</button>
),
{className: GetCombinedClassesArray(['btn'], props.first_button_classes?.trim() ?? '')})}
{React.cloneElement((
<button type="button" data-bs-dismiss="modal"
onClick={() => props.on_second_button_clicked?.()}>
{props.second_button_text}
</button>
),
{className: GetCombinedClassesArray(['btn'], props.second_button_classes?.trim() ?? '')})}
</div>
</>
</ModalWindowComponentBase>
);
}

View File

@ -0,0 +1,8 @@
import React, {ReactElement} from "react";
export interface IModalWindowComponentProps extends React.PropsWithChildren{
children: ReactElement
}
export default function ModalWindowComponent(props: IModalWindowComponentProps){
return (props.children);
}