using JobsMedical.Web.Data; using JobsMedical.Web.Models; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.EntityFrameworkCore; namespace JobsMedical.Web.Pages.Facilities; public class IndexModel : PageModel { private readonly AppDbContext _db; public IndexModel(AppDbContext db) => _db = db; public record FacilityRow(Facility Facility, int OpenListings); public List Rows { get; private set; } = new(); // The shared placeholder for unnamed aggregated ads is not a real, browseable facility. private const string PlaceholderName = "نامشخص / ثبت نشده"; public async Task OnGetAsync() { var today = DateOnly.FromDateTime(DateTime.UtcNow); var jobCutoff = JobsMedical.Web.Services.Scraping.ListingPolicy.JobCutoffUtc; var facilities = await _db.Facilities.Include(f => f.City) .Where(f => f.Name != PlaceholderName).ToListAsync(); // "Active listings" = open shifts + open (fresh) job openings — a facility that is hiring // shouldn't read «۰ شیفت باز» just because it posted a job rather than a dated shift. var shiftCounts = await _db.Shifts .Where(s => s.Status == ShiftStatus.Open && s.Date >= today) .GroupBy(s => s.FacilityId).Select(g => new { g.Key, C = g.Count() }) .ToDictionaryAsync(x => x.Key, x => x.C); var jobCounts = await _db.JobOpenings .Where(j => j.Status == ShiftStatus.Open && j.CreatedAt >= jobCutoff) .GroupBy(j => j.FacilityId).Select(g => new { g.Key, C = g.Count() }) .ToDictionaryAsync(x => x.Key, x => x.C); Rows = facilities .Select(f => new FacilityRow(f, shiftCounts.GetValueOrDefault(f.Id) + jobCounts.GetValueOrDefault(f.Id))) .OrderByDescending(r => r.OpenListings) // active facilities first .ThenByDescending(r => r.Facility.IsVerified) .ThenBy(r => r.Facility.Name) .ToList(); } }