Applicants: auto-tags + deep search w/ highlight; never delete (archive instead)
CI/CD / CI · dotnet build (push) Successful in 2m1s
CI/CD / Deploy · hamkadr (push) Successful in 2m36s

- Tags: parser extracts cert/skill keywords (mmt, ICU/CCU, دیالیز, اتاق عمل,
  اورژانس, مسئول فنی, پروانه‌دار…) + role + city into TalentListing.Tags
  (+ migration); shown as chips on cards.
- Deep search on /Talent: «جستجوی عمیق» box does Postgres ILIKE across
  tags, description, person, area, role, city (every term must match);
  matches are highlighted with <mark> via SearchHighlight.
- Never delete: ShiftStatus.Archived + the admin «بایگانی گروهی» action now
  ARCHIVES aggregated posts (hidden from site, kept in DB) and leaves the
  raw crawl rows intact — a permanent archive for future analytics.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
soroush.asadi
2026-06-08 11:25:32 +03:30
parent e4dc5180ad
commit 6b657c7795
15 changed files with 1752 additions and 22 deletions
@@ -16,6 +16,7 @@ public class IndexModel : PageModel
[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
public List<TalentListing> Results { get; private set; } = new();
public List<City> Cities { get; private set; } = new();
@@ -42,6 +43,20 @@ public class IndexModel : PageModel
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));
}
Results = await q.OrderByDescending(t => t.CreatedAt).ToListAsync();
}
}