93 lines
4.0 KiB
C#
93 lines
4.0 KiB
C#
|
|
using System.Security.Claims;
|
||
|
|
using JobsMedical.Web.Data;
|
||
|
|
using JobsMedical.Web.Models;
|
||
|
|
using Microsoft.AspNetCore.Mvc;
|
||
|
|
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||
|
|
using Microsoft.EntityFrameworkCore;
|
||
|
|
|
||
|
|
namespace JobsMedical.Web.Pages.Facilities;
|
||
|
|
|
||
|
|
public class DetailsModel : PageModel
|
||
|
|
{
|
||
|
|
private readonly AppDbContext _db;
|
||
|
|
private readonly JobsMedical.Web.Services.Scraping.SettingsService _settings;
|
||
|
|
|
||
|
|
public DetailsModel(AppDbContext db, JobsMedical.Web.Services.Scraping.SettingsService settings)
|
||
|
|
{
|
||
|
|
_db = db;
|
||
|
|
_settings = settings;
|
||
|
|
}
|
||
|
|
|
||
|
|
public Facility? Facility { get; private set; }
|
||
|
|
public List<Shift> Shifts { get; private set; } = new();
|
||
|
|
public List<JobOpening> Jobs { get; private set; } = new();
|
||
|
|
public string? MapKey { get; private set; }
|
||
|
|
public bool Reported { get; private set; }
|
||
|
|
|
||
|
|
public record ReviewRow(string Who, int Stars, string? Comment, DateTime When);
|
||
|
|
public List<ReviewRow> Reviews { get; private set; } = new();
|
||
|
|
public double AvgRating { get; private set; }
|
||
|
|
public int RatingCount { get; private set; }
|
||
|
|
public bool CanReview { get; private set; } // logged in & not yet reviewed
|
||
|
|
public bool AlreadyReviewed { get; private set; }
|
||
|
|
[TempData] public string? ReviewMsg { get; set; }
|
||
|
|
|
||
|
|
public async Task<IActionResult> OnGetAsync(int id)
|
||
|
|
{
|
||
|
|
Facility = await _db.Facilities.Include(f => f.City).Include(f => f.District)
|
||
|
|
.FirstOrDefaultAsync(f => f.Id == id);
|
||
|
|
if (Facility is null) return NotFound();
|
||
|
|
|
||
|
|
var today = DateOnly.FromDateTime(DateTime.UtcNow);
|
||
|
|
Shifts = await _db.Shifts.Include(s => s.Role)
|
||
|
|
.Where(s => s.FacilityId == id && s.Status == ShiftStatus.Open && s.Date >= today)
|
||
|
|
.OrderBy(s => s.Date).Take(12).ToListAsync();
|
||
|
|
Jobs = await _db.JobOpenings.Include(j => j.Role)
|
||
|
|
.Where(j => j.FacilityId == id && j.Status == ShiftStatus.Open)
|
||
|
|
.OrderByDescending(j => j.CreatedAt).Take(12).ToListAsync();
|
||
|
|
|
||
|
|
MapKey = (await _settings.GetAsync()).NeshanMapKey;
|
||
|
|
Reported = Request.Query["reported"] == "1";
|
||
|
|
|
||
|
|
await LoadReviewsAsync(id);
|
||
|
|
return Page();
|
||
|
|
}
|
||
|
|
|
||
|
|
public async Task<IActionResult> OnPostReviewAsync(int id, int stars, string? comment)
|
||
|
|
{
|
||
|
|
if (User.Identity?.IsAuthenticated != true)
|
||
|
|
return RedirectToPage("/Account/Login", new { returnUrl = $"/Facilities/Details/{id}" });
|
||
|
|
|
||
|
|
var uid = int.Parse(User.FindFirstValue(System.Security.Claims.ClaimTypes.NameIdentifier)!);
|
||
|
|
if (!await _db.Facilities.AnyAsync(f => f.Id == id)) return NotFound();
|
||
|
|
stars = Math.Clamp(stars, 1, 5);
|
||
|
|
|
||
|
|
var existing = await _db.Reviews.FirstOrDefaultAsync(r => r.FacilityId == id && r.UserId == uid);
|
||
|
|
if (existing is null)
|
||
|
|
_db.Reviews.Add(new Review { FacilityId = id, UserId = uid, Stars = stars, Comment = comment?.Trim() });
|
||
|
|
else { existing.Stars = stars; existing.Comment = comment?.Trim(); existing.CreatedAt = DateTime.UtcNow; }
|
||
|
|
await _db.SaveChangesAsync();
|
||
|
|
ReviewMsg = "نظر شما ثبت شد. متشکریم.";
|
||
|
|
return RedirectToPage(new { id });
|
||
|
|
}
|
||
|
|
|
||
|
|
private async Task LoadReviewsAsync(int id)
|
||
|
|
{
|
||
|
|
var rows = await _db.Reviews.Include(r => r.User)
|
||
|
|
.Where(r => r.FacilityId == id && r.IsApproved)
|
||
|
|
.OrderByDescending(r => r.CreatedAt).ToListAsync();
|
||
|
|
RatingCount = rows.Count;
|
||
|
|
AvgRating = rows.Count > 0 ? Math.Round(rows.Average(r => r.Stars), 1) : 0;
|
||
|
|
Reviews = rows.Take(20).Select(r => new ReviewRow(
|
||
|
|
r.User.FullName ?? "کاربر", r.Stars, r.Comment, r.CreatedAt)).ToList();
|
||
|
|
|
||
|
|
if (User.Identity?.IsAuthenticated == true &&
|
||
|
|
int.TryParse(User.FindFirstValue(System.Security.Claims.ClaimTypes.NameIdentifier), out var uid))
|
||
|
|
{
|
||
|
|
AlreadyReviewed = rows.Any(r => r.UserId == uid)
|
||
|
|
|| await _db.Reviews.AnyAsync(r => r.FacilityId == id && r.UserId == uid);
|
||
|
|
CanReview = true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|