using JobsMedical.Web.Data; using JobsMedical.Web.Models; using JobsMedical.Web.Services.Scraping; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.EntityFrameworkCore; namespace JobsMedical.Web.Pages.Talent; public class IndexModel : PageModel { private readonly AppDbContext _db; public IndexModel(AppDbContext db) => _db = db; [BindProperty(SupportsGet = true)] public int? CityId { get; set; } [BindProperty(SupportsGet = true)] public int? DistrictId { get; set; } [BindProperty(SupportsGet = true)] public int? RoleId { get; set; } [BindProperty(SupportsGet = true)] public Gender? GenderFilter { get; set; } [BindProperty(SupportsGet = true)] public string? Q { get; set; } // deep search [BindProperty(SupportsGet = true)] public int Page { get; set; } = 1; private const int PageSize = 24; public int TotalCount { get; private set; } public int TotalPages { get; private set; } public int CurrentPage { get; private set; } public List Results { get; private set; } = new(); public List Cities { get; private set; } = new(); public List Districts { get; private set; } = new(); public List Roles { get; private set; } = new(); /// Dynamic page heading/H1 + title, set from the active role/city for SEO. public string PageHeading { get; private set; } = "کادر درمان آماده به کار"; public async Task OnGetAsync() { Cities = await _db.Cities.Where(c => c.IsActive).OrderBy(c => c.Name).ToListAsync(); Roles = await _db.Roles.Where(r => r.IsActive).OrderBy(r => r.SortOrder).ToListAsync(); Districts = await _db.Districts .Where(d => d.IsActive && (CityId == null || d.CityId == CityId)) .OrderBy(d => d.Name).ToListAsync(); var q = _db.TalentListings .Include(t => t.City) .Include(t => t.District) .Include(t => t.Role) .Where(t => t.Status == ShiftStatus.Open && t.CreatedAt >= ListingPolicy.TalentCutoffUtc); if (CityId is not null) q = q.Where(t => t.CityId == CityId); if (DistrictId is not null) q = q.Where(t => t.DistrictId == DistrictId); if (RoleId is not null) q = q.Where(t => t.RoleId == RoleId); if (GenderFilter is Gender g && g != Gender.Any) q = q.Where(t => t.Gender == Gender.Any || t.Gender == g); // Deep search: every term must match somewhere (tags, role, city, person, area, description). if (!string.IsNullOrWhiteSpace(Q)) foreach (var term in Q.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)) { var like = $"%{term}%"; q = q.Where(t => EF.Functions.ILike(t.Tags ?? "", like) || EF.Functions.ILike(t.Description ?? "", like) || EF.Functions.ILike(t.PersonName ?? "", like) || EF.Functions.ILike(t.AreaNote ?? "", like) || EF.Functions.ILike(t.Role.Name, like) || EF.Functions.ILike(t.City.Name, like)); } TotalCount = await q.CountAsync(); TotalPages = Math.Max(1, (int)Math.Ceiling(TotalCount / (double)PageSize)); CurrentPage = Math.Clamp(Page, 1, TotalPages); Results = await q.OrderByDescending(t => t.CreatedAt) .Skip((CurrentPage - 1) * PageSize).Take(PageSize).ToListAsync(); var role = Roles.FirstOrDefault(r => r.Id == RoleId)?.Name; var city = Cities.FirstOrDefault(c => c.Id == CityId)?.Name; PageHeading = role is not null && city is not null ? $"{role} آماده به کار در {city}" : role is not null ? $"{role} آماده به کار" : city is not null ? $"کادر درمان آماده به کار در {city}" : "کادر درمان آماده به کار"; ViewData["Title"] = PageHeading; ViewData["Description"] = $"فهرست «آماده به کار» {(role ?? "کادر درمان")}{(city is not null ? " در " + city : "")} — همکادر؛ مشاهده و تماس مستقیم."; } }