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 Shifts { get; private set; } = new(); public List 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 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 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 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; } } }