first commit
CI/CD / CI · dotnet build (push) Failing after 0s
CI/CD / Deploy · drsousan (push) Has been skipped

This commit is contained in:
soroush.asadi
2026-05-31 00:42:08 +03:30
commit 96e73bf633
39 changed files with 8144 additions and 0 deletions
+153
View File
@@ -0,0 +1,153 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using DrSousan.Api.Data;
using DrSousan.Api.Models;
namespace DrSousan.Api.Pages.Blog;
public class PostModel : PageModel
{
private readonly AppDbContext _db;
public PostModel(AppDbContext db) => _db = db;
public BlogPost? Post { get; private set; }
public List<CommentVm> Comments { get; private set; } = new();
public bool CommentSent { get; private set; } = false;
// Comment form binding
[BindProperty]
[Required(ErrorMessage = "نام الزامی است.")]
[MaxLength(100)]
public string CommentAuthor { get; set; } = "";
[BindProperty]
[MaxLength(200)]
[EmailAddress]
public string CommentEmail { get; set; } = "";
[BindProperty]
[Required(ErrorMessage = "متن نظر الزامی است.")]
public string CommentBody { get; set; } = "";
public async Task<IActionResult> OnGetAsync(string slug)
{
var post = await _db.BlogPosts
.Include(p => p.Category)
.FirstOrDefaultAsync(p => p.Slug == slug && p.IsPublished);
if (post is null) return NotFound();
// Increment view count
post.ViewCount++;
await _db.SaveChangesAsync();
Post = post;
await LoadCommentsAsync(post.Id);
await SetViewDataAsync(post);
return Page();
}
public async Task<IActionResult> OnPostAsync(string slug)
{
var post = await _db.BlogPosts
.Include(p => p.Category)
.FirstOrDefaultAsync(p => p.Slug == slug && p.IsPublished);
if (post is null) return NotFound();
Post = post;
await LoadCommentsAsync(post.Id);
await SetViewDataAsync(post);
if (!ModelState.IsValid) return Page();
// Sanitise
var body = System.Text.RegularExpressions.Regex.Replace(CommentBody ?? "", "<[^>]*>", "").Trim();
var authorName = System.Text.RegularExpressions.Regex.Replace(CommentAuthor ?? "", "<[^>]*>", "").Trim();
if (string.IsNullOrWhiteSpace(body) || string.IsNullOrWhiteSpace(authorName))
{
ModelState.AddModelError("", "نام و متن نظر الزامی است.");
return Page();
}
_db.Comments.Add(new Comment
{
BlogPostId = post.Id,
AuthorName = authorName,
AuthorEmail = CommentEmail ?? "",
Body = body,
IsApproved = false,
CreatedAt = DateTime.UtcNow
});
await _db.SaveChangesAsync();
CommentSent = true;
// Clear form
CommentAuthor = "";
CommentEmail = "";
CommentBody = "";
ModelState.Clear();
return Page();
}
private async Task LoadCommentsAsync(int postId)
{
var raw = await _db.Comments
.Where(c => c.BlogPostId == postId && c.IsApproved && c.ParentId == null)
.OrderBy(c => c.CreatedAt)
.Select(c => new
{
c.Id, c.AuthorName, c.Body, c.CreatedAt, c.IsAdminReply,
Replies = _db.Comments
.Where(r => r.ParentId == c.Id && r.IsApproved)
.OrderBy(r => r.CreatedAt)
.Select(r => new { r.Id, r.AuthorName, r.Body, r.CreatedAt, r.IsAdminReply })
.ToList()
}).ToListAsync();
Comments = raw.Select(c => new CommentVm
{
Id = c.Id, AuthorName = c.AuthorName, Body = c.Body,
CreatedAt = c.CreatedAt, IsAdminReply = c.IsAdminReply,
Replies = c.Replies.Select(r => new CommentVm
{
Id = r.Id, AuthorName = r.AuthorName, Body = r.Body,
CreatedAt = r.CreatedAt, IsAdminReply = r.IsAdminReply
}).ToList()
}).ToList();
}
private async Task SetViewDataAsync(BlogPost post)
{
var metaTitle = string.IsNullOrEmpty(post.MetaTitle) ? post.Title : post.MetaTitle;
var metaDesc = string.IsNullOrEmpty(post.MetaDescription) ? post.Excerpt : post.MetaDescription;
// Avoid duplicating the site name if MetaTitle already contains it
var suffix = " | دکتر سوسن آل‌طه";
ViewData["Title"] = metaTitle.Contains("دکتر سوسن") ? metaTitle : metaTitle + suffix;
ViewData["MetaDesc"] = metaDesc;
ViewData["Keywords"] = post.Keywords;
ViewData["OgImage"] = string.IsNullOrEmpty(post.OgImage) ? post.FeaturedImage : post.OgImage;
ViewData["ArticleType"] = post.ArticleType;
ViewData["Slug"] = post.Slug;
var s = await _db.SiteSettings
.FirstOrDefaultAsync(x => x.Section == "hero" && x.Key == "name");
ViewData["SiteName"] = s?.Value ?? "دکتر سوسن آل‌طه";
}
// View model for comments
public class CommentVm
{
public int Id { get; set; }
public string AuthorName { get; set; } = "";
public string Body { get; set; } = "";
public DateTime CreatedAt { get; set; }
public bool IsAdminReply { get; set; }
public List<CommentVm> Replies { get; set; } = new();
}
}