From 845d0c901388e5e805486e3aa84bf2f8559e152a Mon Sep 17 00:00:00 2001 From: "soroush.asadi" Date: Sun, 21 Jun 2026 16:21:50 +0330 Subject: [PATCH] Show job counts, not shifts-only, on public pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The platform has ~1600 open استخدام but only ~4 dated شیفت (the VPN-free sources are hiring boards, not shift channels), so the shifts-only counters read misleadingly low: - Homepage stat pill «۴ شیفت باز» -> «موقعیت استخدام» (open job count). - Facility cards «۰ شیفت باز» -> «N آگهی فعال» = open shifts + open (fresh) jobs, so a facility that is hiring no longer reads zero. Also hide the «نامشخص / ثبت نشده» placeholder from the facilities list and sort active facilities (then verified, then name) first, so real hiring centers surface. Co-Authored-By: Claude Opus 4.8 --- .../Pages/Facilities/Index.cshtml | 2 +- .../Pages/Facilities/Index.cshtml.cs | 29 ++++++++++++++----- src/JobsMedical.Web/Pages/Index.cshtml | 2 +- src/JobsMedical.Web/Pages/Index.cshtml.cs | 3 ++ 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/JobsMedical.Web/Pages/Facilities/Index.cshtml b/src/JobsMedical.Web/Pages/Facilities/Index.cshtml index 6ae0978..76c496b 100644 --- a/src/JobsMedical.Web/Pages/Facilities/Index.cshtml +++ b/src/JobsMedical.Web/Pages/Facilities/Index.cshtml @@ -32,7 +32,7 @@

- @JalaliDate.ToPersianDigits(row.OpenShifts.ToString()) شیفت باز + @JalaliDate.ToPersianDigits(row.OpenListings.ToString()) آگهی فعال مشاهده مرکز
diff --git a/src/JobsMedical.Web/Pages/Facilities/Index.cshtml.cs b/src/JobsMedical.Web/Pages/Facilities/Index.cshtml.cs index f8af997..a4ee9f7 100644 --- a/src/JobsMedical.Web/Pages/Facilities/Index.cshtml.cs +++ b/src/JobsMedical.Web/Pages/Facilities/Index.cshtml.cs @@ -10,21 +10,36 @@ public class IndexModel : PageModel private readonly AppDbContext _db; public IndexModel(AppDbContext db) => _db = db; - public record FacilityRow(Facility Facility, int OpenShifts); + 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 facilities = await _db.Facilities.Include(f => f.City).OrderBy(f => f.Name).ToListAsync(); - var counts = await _db.Shifts + 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, Count = g.Count() }) - .ToDictionaryAsync(x => x.Key, x => x.Count); + .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, counts.GetValueOrDefault(f.Id))) + .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(); } } diff --git a/src/JobsMedical.Web/Pages/Index.cshtml b/src/JobsMedical.Web/Pages/Index.cshtml index 88f9d4b..1a7d827 100644 --- a/src/JobsMedical.Web/Pages/Index.cshtml +++ b/src/JobsMedical.Web/Pages/Index.cshtml @@ -34,7 +34,7 @@
-
@JalaliDate.ToPersianDigits(Model.OpenShiftCount.ToString())شیفت باز
+
@JalaliDate.ToPersianDigits(Model.OpenJobCount.ToString())موقعیت استخدام
@JalaliDate.ToPersianDigits(Model.FacilityCount.ToString())مرکز درمانی
@JalaliDate.ToPersianDigits(Model.CityCount.ToString())شهر فعال
diff --git a/src/JobsMedical.Web/Pages/Index.cshtml.cs b/src/JobsMedical.Web/Pages/Index.cshtml.cs index 3742815..6344df5 100644 --- a/src/JobsMedical.Web/Pages/Index.cshtml.cs +++ b/src/JobsMedical.Web/Pages/Index.cshtml.cs @@ -27,6 +27,7 @@ public class IndexModel : PageModel public List Cities { get; private set; } = new(); public List Roles { get; private set; } = new(); public int OpenShiftCount { get; private set; } + public int OpenJobCount { get; private set; } public int FacilityCount { get; private set; } public int CityCount { get; private set; } @@ -68,6 +69,8 @@ public class IndexModel : PageModel 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(); OpenShiftCount = await _db.Shifts.CountAsync(s => s.Status == ShiftStatus.Open && s.Date >= today); + OpenJobCount = await _db.JobOpenings.CountAsync(j => j.Status == ShiftStatus.Open + && j.CreatedAt >= JobsMedical.Web.Services.Scraping.ListingPolicy.JobCutoffUtc); FacilityCount = await _db.Facilities.CountAsync(); CityCount = await _db.Cities.CountAsync(c => c.IsActive); }