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
@@ -134,11 +134,11 @@ public class ReviewModel : PageModel
Error = "شهری برای انتشار آگهی «آماده به کار» موجود نیست.";
return RedirectToPage(new { id });
}
// Re-parse the raw text to recover all contact channels (phones/email/socials).
// Re-parse the raw text to recover all contact channels (phones/email/socials) + tags.
var roleNames = await _db.Roles.Select(r => r.Name).ToListAsync();
var parsedContacts = _parser
.Parse(Raw.RawText, roleNames, await CityNamesAsync(), await DistrictNamesAsync())
.Contacts.Select((c, i) => new ContactMethod { Type = c.Type, Value = c.Value, SortOrder = i })
var reparsed = _parser.Parse(Raw.RawText, roleNames, await CityNamesAsync(), await DistrictNamesAsync());
var parsedContacts = reparsed.Contacts
.Select((c, i) => new ContactMethod { Type = c.Type, Value = c.Value, SortOrder = i })
.ToList();
// Include the admin-typed phone if it isn't already captured.
if (!string.IsNullOrWhiteSpace(Phone))
@@ -167,6 +167,7 @@ public class ReviewModel : PageModel
Source = ShiftSource.Aggregated,
SourceUrl = Raw.SourceUrl,
Contacts = parsedContacts,
Tags = string.Join(" ", reparsed.Tags.Distinct()),
};
_db.TalentListings.Add(talent);
await _db.SaveChangesAsync();