Add facility verification (admin verify/unverify → verified badge)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
soroush.asadi
2026-06-03 06:31:15 +03:30
parent 563a40d1f4
commit 82c94c89a6
4 changed files with 117 additions and 0 deletions
+1
View File
@@ -43,6 +43,7 @@ Then open the URL printed in the console (e.g. http://localhost:5020).
| `/Account/Profile` | پروفایل: شیفت‌ها/موقعیت‌های ذخیره‌شده و اعلام تمایل‌ها |
| `/Admin` | پنل مدیریت (نقش Admin): صف آگهی‌های خام |
| `/Admin/Review/{id}` | بررسی خودکار (پارسر) و انتشار آگهی به‌صورت شیفت یا استخدام |
| `/Admin/Facilities` | تأیید/لغو تأیید مراکز درمانی (نشان «تأیید شده») |
| `/Employer` | **پنل کارفرما**: مراکز من + شمار شیفت/استخدام/متقاضی |
| `/Employer/RegisterFacility` | ثبت مرکز درمانی (خودسرویس → نقش FacilityAdmin) |
| `/Employer/PostShift`، `/PostJob` | انتشار شیفت یا موقعیت استخدامی |
@@ -0,0 +1,74 @@
@page
@model JobsMedical.Web.Pages.Admin.FacilitiesModel
@{
ViewData["Title"] = "مدیریت مراکز درمانی";
string TypeLabel(FacilityType t) => t switch
{
FacilityType.Hospital => "بیمارستان",
FacilityType.Clinic => "کلینیک",
_ => "درمانگاه",
};
}
<div class="page-head">
<div class="container">
<h1>تأیید مراکز درمانی</h1>
<p class="muted">
<a asp-page="/Admin/Index">← صف آگهی‌ها</a>
· @JalaliDate.ToPersianDigits(Model.Pending.Count.ToString()) مرکز در انتظار تأیید
</p>
</div>
</div>
<div class="container section">
<h2 style="font-size:20px;">در انتظار تأیید</h2>
@if (Model.Pending.Count == 0)
{
<div class="card empty-state">مرکزی در انتظار تأیید نیست.</div>
}
else
{
foreach (var f in Model.Pending)
{
<div class="card card-pad" style="margin-bottom:10px;">
<div class="row" style="display:flex; justify-content:space-between; align-items:center; gap:10px;">
<div>
<strong>@f.Name</strong> — @TypeLabel(f.Type)
<div class="muted" style="font-size:13px;">
📍 @f.City?.Name@(f.District is not null ? "، " + f.District.Name : "")
@if (f.OwnerUser is not null) { <text> · مالک: <span dir="ltr">@JalaliDate.ToPersianDigits(f.OwnerUser.Phone)</span></text> }
@if (!string.IsNullOrEmpty(f.Phone)) { <text> · تلفن: <span dir="ltr">@JalaliDate.ToPersianDigits(f.Phone)</span></text> }
</div>
@if (!string.IsNullOrEmpty(f.Address)) { <div class="muted" style="font-size:13px;">@f.Address</div> }
</div>
<form method="post">
<button asp-page-handler="Verify" asp-route-id="@f.Id" class="btn btn-accent" style="white-space:nowrap;">✓ تأیید</button>
</form>
</div>
</div>
}
}
<h2 style="font-size:20px; margin-top:30px;">مراکز تأییدشده</h2>
@if (Model.Verified.Count == 0)
{
<div class="card empty-state">هنوز مرکزی تأیید نشده.</div>
}
else
{
foreach (var f in Model.Verified)
{
<div class="card card-pad" style="margin-bottom:10px;">
<div class="row" style="display:flex; justify-content:space-between; align-items:center; gap:10px;">
<div>
<strong>@f.Name</strong> <span class="badge badge-verified">✓ تأیید شده</span>
<div class="muted" style="font-size:13px;">📍 @f.City?.Name — @TypeLabel(f.Type)</div>
</div>
<form method="post">
<button asp-page-handler="Unverify" asp-route-id="@f.Id" class="btn btn-outline" style="white-space:nowrap;">لغو تأیید</button>
</form>
</div>
</div>
}
}
</div>
@@ -0,0 +1,41 @@
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.Admin;
[Authorize(Roles = "Admin")]
public class FacilitiesModel : PageModel
{
private readonly AppDbContext _db;
public FacilitiesModel(AppDbContext db) => _db = db;
public List<Facility> Pending { get; private set; } = new();
public List<Facility> Verified { get; private set; } = new();
public async Task OnGetAsync() => await LoadAsync();
public async Task<IActionResult> OnPostVerifyAsync(int id) => await SetVerified(id, true);
public async Task<IActionResult> OnPostUnverifyAsync(int id) => await SetVerified(id, false);
private async Task<IActionResult> SetVerified(int id, bool value)
{
var f = await _db.Facilities.FindAsync(id);
if (f is null) return NotFound();
f.IsVerified = value;
await _db.SaveChangesAsync();
return RedirectToPage();
}
private async Task LoadAsync()
{
var all = await _db.Facilities
.Include(f => f.City).Include(f => f.District).Include(f => f.OwnerUser)
.OrderBy(f => f.Name).ToListAsync();
Pending = all.Where(f => !f.IsVerified).ToList();
Verified = all.Where(f => f.IsVerified).ToList();
}
}
@@ -10,6 +10,7 @@
<p class="muted">
آگهی‌های جمع‌آوری‌شده از کانال‌ها را اینجا بررسی، ساختارمند و منتشر کن.
(@JalaliDate.ToPersianDigits(Model.Queue.Count.ToString()) در انتظار بررسی)
· <a asp-page="/Admin/Facilities">تأیید مراکز درمانی</a>
</p>
</div>
</div>