Add hiring, AI parser+admin, OTP auth, employer dashboard, profit-share pay

- Hiring (استخدام) listings: JobOpening + /Jobs browse/detail + home section
- Heuristic Persian listing-parser + admin queue (/Admin) → publish shift/job
- Phone-OTP cookie auth + visitor-history linking + profile; Admin role gate
- Employer side: self-serve facility registration, dashboard, post/manage shifts & jobs, applicants list with contact
- Compensation models: fixed / hourly / profit-share (درصدی) / negotiable / choice (به انتخاب شما); SharePercent + JalaliDate.PayLabel; parser + filter

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
soroush.asadi
2026-06-03 06:26:54 +03:30
parent 2fb86a435e
commit 563a40d1f4
30 changed files with 1761 additions and 27 deletions
@@ -84,16 +84,8 @@ public class LoginModel : PageModel
await _db.SaveChangesAsync();
}
var claims = new List<Claim>
{
new(ClaimTypes.NameIdentifier, user.Id.ToString()),
new(ClaimTypes.MobilePhone, user.Phone),
new(ClaimTypes.Name, user.FullName ?? user.Phone),
new(ClaimTypes.Role, user.Role.ToString()),
};
var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(identity));
AuthHelper.BuildPrincipal(user));
return LocalRedirect(string.IsNullOrEmpty(returnUrl) ? "/" : returnUrl);
}
@@ -29,6 +29,16 @@
<a class="btn btn-outline" asp-page="/Preferences/Index">تنظیم علاقه‌مندی‌ها</a>
</div>
@if (User.IsInRole("FacilityAdmin") || User.IsInRole("Admin"))
{
<p><a asp-page="/Employer/Index">→ ورود به پنل کارفرما</a></p>
}
else
{
<p class="muted">مرکز درمانی هستی و می‌خواهی شیفت یا استخدام منتشر کنی؟
<a asp-page="/Employer/RegisterFacility">مرکز خود را ثبت کن</a></p>
}
<h2 style="font-size:20px;">شیفت‌های ذخیره‌شده</h2>
@if (Model.SavedShifts.Count == 0)
{