feat: rename project hierarchy search components and add validation for search query

This commit is contained in:
2026-01-04 15:50:56 +03:30
parent 1f365f3642
commit c2fca9f9eb
6 changed files with 17 additions and 30 deletions

View File

@@ -6,6 +6,6 @@ namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProj
/// درخواست جستجو در سراسر سلسله‌مراتب پروژه (پروژه، فاز، تسک).
/// نتایج با اطلاعات مسیر سلسله‌مراتب برای پشتیبانی از ناوبری درخت در رابط کاربری بازگردانده می‌شود.
/// </summary>
public record GetProjectHierarchySearchQuery(
string SearchQuery) : IBaseQuery<GetProjectHierarchySearchResponse>;
public record GetProjectSearchQuery(
string SearchQuery) : IBaseQuery<GetProjectSearchResponse>;

View File

@@ -10,18 +10,18 @@ namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProj
/// این handler در تمام سطح‌های پروژه، فاز و تسک جستجو می‌کند و از تمام فیلدهای متنی (نام، توضیحات) استفاده می‌کند.
/// همچنین در زیرمجموعه‌های هر سطح (ProjectSections، PhaseSections، TaskSections) جستجو می‌کند.
/// </summary>
public class GetProjectHierarchySearchQueryHandler : IBaseQueryHandler<GetProjectHierarchySearchQuery, GetProjectHierarchySearchResponse>
public class GetProjectSearchQueryHandler : IBaseQueryHandler<GetProjectSearchQuery, GetProjectSearchResponse>
{
private readonly IProgramManagerDbContext _context;
private const int MaxResults = 50;
public GetProjectHierarchySearchQueryHandler(IProgramManagerDbContext context)
public GetProjectSearchQueryHandler(IProgramManagerDbContext context)
{
_context = context;
}
public async Task<OperationResult<GetProjectHierarchySearchResponse>> Handle(
GetProjectHierarchySearchQuery request,
public async Task<OperationResult<GetProjectSearchResponse>> Handle(
GetProjectSearchQuery request,
CancellationToken cancellationToken)
{
var searchQuery = request.SearchQuery.ToLower();
@@ -41,13 +41,13 @@ public class GetProjectHierarchySearchQueryHandler : IBaseQueryHandler<GetProjec
// مرتب‌سازی نتایج: ابتدا بر اساس سطح سلسله‌مراتب (پروژه → فاز → تسک)، سپس بر اساس نام
var sortedResults = results
.OrderBy(r => GetLevelOrder(r.Level))
.OrderBy(r => r.Level)
.ThenBy(r => r.Title)
.Take(MaxResults)
.ToList();
var response = new GetProjectHierarchySearchResponse(sortedResults);
return OperationResult<GetProjectHierarchySearchResponse>.Success(response);
var response = new GetProjectSearchResponse(sortedResults);
return OperationResult<GetProjectSearchResponse>.Success(response);
}
/// <summary>
@@ -66,7 +66,7 @@ public class GetProjectHierarchySearchQueryHandler : IBaseQueryHandler<GetProjec
Id = p.Id,
Title = p.Name,
Level = ProjectHierarchyLevel.Project,
ProjectId = p.Id,
ProjectId = null,
PhaseId = null
})
.ToListAsync(cancellationToken);
@@ -126,20 +126,7 @@ public class GetProjectHierarchySearchQueryHandler : IBaseQueryHandler<GetProjec
return tasks;
}
/// <summary>
/// ترتیب سطح برای مرتب‌سازی: پروژه (1) → فاز (2) → تسک (3)
/// </summary>
private static int GetLevelOrder(ProjectHierarchyLevel level)
{
return level switch
{
ProjectHierarchyLevel.Project => 1,
ProjectHierarchyLevel.Phase => 2,
ProjectHierarchyLevel.Task => 3,
_ => 4
};
}
}

View File

@@ -5,9 +5,9 @@ namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProj
/// <summary>
/// اعتبارسنج برای درخواست جستجوی سراسری
/// </summary>
public class GetProjectHierarchySearchQueryValidator : AbstractValidator<GetProjectHierarchySearchQuery>
public class GetProjectSearchQueryValidator : AbstractValidator<GetProjectSearchQuery>
{
public GetProjectHierarchySearchQueryValidator()
public GetProjectSearchQueryValidator()
{
RuleFor(x => x.SearchQuery)
.NotEmpty().WithMessage("متن جستجو نمی‌تواند خالی باشد.")

View File

@@ -3,6 +3,6 @@ namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProj
/// <summary>
/// پوسته‌ی پاسخ برای نتایج جستجوی سراسری
/// </summary>
public record GetProjectHierarchySearchResponse(
public record GetProjectSearchResponse(
List<ProjectHierarchySearchResultDto> Results);

View File

@@ -26,7 +26,7 @@ public record ProjectHierarchySearchResultDto
/// <summary>
/// شناسه پروژه - همیشه برای فاز و تسک پر شده است، برای پروژه با شناسه خود پر می‌شود
/// </summary>
public Guid ProjectId { get; init; }
public Guid? ProjectId { get; init; }
/// <summary>
/// شناسه فاز - فقط برای تسک پر شده است، برای پروژه و فاز خالی است

View File

@@ -42,10 +42,10 @@ public class ProjectController : ProgramManagerBaseController
}
[HttpGet("search")]
public async Task<ActionResult<OperationResult<GetProjectHierarchySearchResponse>>> Search(
public async Task<ActionResult<OperationResult<GetProjectSearchResponse>>> Search(
[FromQuery] string query)
{
var searchQuery = new GetProjectHierarchySearchQuery(query);
var searchQuery = new GetProjectSearchQuery(query);
var res = await _mediator.Send(searchQuery);
return res;
}