[Applications] Applicant pipeline: employer accept/reject + status to applicant
InterestEvent gains a Status (ApplicationStatus: Interested→Accepted/Rejected; migration, default Interested). Employer/Listings shows each applicant's status with پذیرفتن/رد buttons (ownership-checked handlers update the status and notify the applicant via bell/SSE/push linking to the listing). The کارجو panel (/Me) now shows a status badge (در انتظار بررسی / پذیرفته شد / رد شد) on each applied shift/job. Reusable _ApplicantRow partial for the employer list. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,12 @@
|
||||
UserRole.FacilityAdmin => "کارفرما",
|
||||
_ => "کارجو (کادر درمان)",
|
||||
};
|
||||
(string cls, string txt) AppBadge(JobsMedical.Web.Models.ApplicationStatus s) => s switch
|
||||
{
|
||||
JobsMedical.Web.Models.ApplicationStatus.Accepted => ("badge-verified", "✓ پذیرفته شد"),
|
||||
JobsMedical.Web.Models.ApplicationStatus.Rejected => ("badge-gender", "رد شد"),
|
||||
_ => ("badge-type", "در انتظار بررسی"),
|
||||
};
|
||||
}
|
||||
|
||||
<div class="page-head">
|
||||
@@ -73,8 +79,22 @@
|
||||
else
|
||||
{
|
||||
<div class="grid grid-3">
|
||||
@foreach (var s in Model.AppliedShifts) { <partial name="_ShiftCard" model="s" /> }
|
||||
@foreach (var j in Model.AppliedJobs) { <partial name="_JobCard" model="j" /> }
|
||||
@foreach (var s in Model.AppliedShifts)
|
||||
{
|
||||
var b = AppBadge(Model.ShiftAppStatus.GetValueOrDefault(s.Id, JobsMedical.Web.Models.ApplicationStatus.Interested));
|
||||
<div>
|
||||
<span class="badge @b.cls" style="margin-bottom:6px; display:inline-block;">@b.txt</span>
|
||||
<partial name="_ShiftCard" model="s" />
|
||||
</div>
|
||||
}
|
||||
@foreach (var j in Model.AppliedJobs)
|
||||
{
|
||||
var b = AppBadge(Model.JobAppStatus.GetValueOrDefault(j.Id, JobsMedical.Web.Models.ApplicationStatus.Interested));
|
||||
<div>
|
||||
<span class="badge @b.cls" style="margin-bottom:6px; display:inline-block;">@b.txt</span>
|
||||
<partial name="_JobCard" model="j" />
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -29,6 +29,8 @@ public class IndexModel : PageModel
|
||||
public List<Shift> SavedShifts { get; private set; } = new();
|
||||
public List<Shift> AppliedShifts { get; private set; } = new();
|
||||
public List<JobOpening> AppliedJobs { get; private set; } = new();
|
||||
public Dictionary<int, ApplicationStatus> ShiftAppStatus { get; private set; } = new();
|
||||
public Dictionary<int, ApplicationStatus> JobAppStatus { get; private set; } = new();
|
||||
|
||||
public async Task OnGetAsync()
|
||||
{
|
||||
@@ -52,6 +54,14 @@ public class IndexModel : PageModel
|
||||
AppliedJobs = await _db.JobOpenings
|
||||
.Include(j => j.Facility).ThenInclude(f => f.City).Include(j => j.Role)
|
||||
.Where(j => appliedJobIds.Contains(j.Id)).ToListAsync();
|
||||
|
||||
// Latest application status per applied listing (employer accept/reject shows here).
|
||||
ShiftAppStatus = events.Where(e => e.EventType == InterestEventType.Apply && e.ShiftId != null)
|
||||
.GroupBy(e => e.ShiftId!.Value)
|
||||
.ToDictionary(g => g.Key, g => g.OrderByDescending(e => e.CreatedAt).First().Status);
|
||||
JobAppStatus = events.Where(e => e.EventType == InterestEventType.Apply && e.JobOpeningId != null)
|
||||
.GroupBy(e => e.JobOpeningId!.Value)
|
||||
.ToDictionary(g => g.Key, g => g.OrderByDescending(e => e.CreatedAt).First().Status);
|
||||
}
|
||||
|
||||
private Task<List<Shift>> ShiftsByIds(List<int> ids) => _db.Shifts
|
||||
|
||||
Reference in New Issue
Block a user