[Alerts] Customizable job alerts + Help capabilities showcase
Job alerts (هشدار شغلی): users save what they want — scope (shift/job/both), role, city, shift type, employment type, minimum pay — and get notified when an employer posts a match. New JobAlert model + AlertScope enum + DbContext (user-cascade, role set-null, IsActive index) + migration. /Me/Alerts page to create/pause/delete alerts; entry point added to the کارجو panel. NotificationService.NotifyNewShift/Job now unions preference matches with active-alert matches (deduped) so alert owners are notified on publish. Help page gains an 'امکانات همکادر' capability showcase grid (with a 'ساخت هشدار شغلی' CTA) so the page demonstrates what the app does. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
using System.Security.Claims;
|
||||
using JobsMedical.Web.Data;
|
||||
using JobsMedical.Web.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace JobsMedical.Web.Pages.Me;
|
||||
|
||||
/// <summary>Job alerts (هشدار شغلی) — saved searches that notify the user on a new matching listing.</summary>
|
||||
[Authorize]
|
||||
public class AlertsModel : PageModel
|
||||
{
|
||||
private readonly AppDbContext _db;
|
||||
public AlertsModel(AppDbContext db) => _db = db;
|
||||
|
||||
public List<Role> Roles { get; private set; } = new();
|
||||
public List<City> Cities { get; private set; } = new();
|
||||
public List<JobAlert> Alerts { get; private set; } = new();
|
||||
[TempData] public string? Msg { get; set; }
|
||||
|
||||
[BindProperty] public string? Label { get; set; }
|
||||
[BindProperty] public AlertScope Scope { get; set; } = AlertScope.Any;
|
||||
[BindProperty] public int? RoleId { get; set; }
|
||||
[BindProperty] public int? CityId { get; set; }
|
||||
[BindProperty] public ShiftType? ShiftType { get; set; }
|
||||
[BindProperty] public EmploymentType? EmploymentType { get; set; }
|
||||
[BindProperty] public long? MinPay { get; set; }
|
||||
|
||||
private int Uid => int.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)!);
|
||||
|
||||
public async Task OnGetAsync() => await LoadAsync();
|
||||
|
||||
public async Task<IActionResult> OnPostCreateAsync()
|
||||
{
|
||||
if (await _db.JobAlerts.CountAsync(a => a.UserId == Uid) >= 20)
|
||||
{
|
||||
Msg = "حداکثر تعداد هشدار شغلی ساخته شده است.";
|
||||
return RedirectToPage();
|
||||
}
|
||||
_db.JobAlerts.Add(new JobAlert
|
||||
{
|
||||
UserId = Uid,
|
||||
Label = string.IsNullOrWhiteSpace(Label) ? null : Label.Trim(),
|
||||
Scope = Scope,
|
||||
RoleId = RoleId,
|
||||
CityId = CityId,
|
||||
ShiftType = Scope == AlertScope.Jobs ? null : ShiftType,
|
||||
EmploymentType = Scope == AlertScope.Shifts ? null : EmploymentType,
|
||||
MinPay = MinPay is > 0 ? MinPay : null,
|
||||
});
|
||||
await _db.SaveChangesAsync();
|
||||
Msg = "هشدار شغلی ساخته شد. بهمحض ثبت آگهی متناسب، باخبر میشوی.";
|
||||
return RedirectToPage();
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostToggleAsync(int id)
|
||||
{
|
||||
var a = await _db.JobAlerts.FirstOrDefaultAsync(x => x.Id == id && x.UserId == Uid);
|
||||
if (a is not null) { a.IsActive = !a.IsActive; await _db.SaveChangesAsync(); }
|
||||
return RedirectToPage();
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostDeleteAsync(int id)
|
||||
{
|
||||
var a = await _db.JobAlerts.FirstOrDefaultAsync(x => x.Id == id && x.UserId == Uid);
|
||||
if (a is not null) { _db.JobAlerts.Remove(a); await _db.SaveChangesAsync(); }
|
||||
return RedirectToPage();
|
||||
}
|
||||
|
||||
private async Task LoadAsync()
|
||||
{
|
||||
Roles = await _db.Roles.Where(r => r.IsActive).OrderBy(r => r.SortOrder).ToListAsync();
|
||||
Cities = await _db.Cities.Where(c => c.IsActive).OrderBy(c => c.Name).ToListAsync();
|
||||
Alerts = await _db.JobAlerts.Include(a => a.Role).Include(a => a.City)
|
||||
.Where(a => a.UserId == Uid).OrderByDescending(a => a.CreatedAt).ToListAsync();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user