Files
draletaha/DrSousan.Api/Pages/Blog/Index.cshtml
T
soroush.asadi d02a5963cf
CI/CD / CI · dotnet build (push) Failing after 5m22s
CI/CD / Deploy · drsousan (push) Has been skipped
fix: HTTPS URLs in sitemap, robots, canonical + og:image on homepage
- Add UseForwardedHeaders middleware so Request.Scheme = "https" behind nginx
- Add SITE_BASE_URL env var fallback for sitemap.xml, robots.txt, and all
  Razor page canonical/og URLs — set it to https://draletaha.ir in .env
- Add og:image to homepage using hero photo
- Add SITE_BASE_URL to docker-compose.yml environment block

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-06-08 22:30:55 +03:30

117 lines
7.8 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
@page "/blog"
@model DrSousan.Api.Pages.Blog.BlogIndexModel
@section Head {
<title>@ViewData["Title"]</title>
<meta name="description" content="مقالات تخصصی دکتر سوسن آل‌طه درباره زیبایی پوست، بوتاکس، فیلر، لیزر و مراقبت از پوست." />
<link rel="canonical" href="@((Environment.GetEnvironmentVariable("SITE_BASE_URL")?.TrimEnd('/') ?? (Request.Scheme + "://" + Request.Host)) + "/blog")" />
<style>
/* ─── Blog Hero ─────────────────────────────────────────────── */
.blog-hero{background:linear-gradient(135deg,var(--gold-pale) 0%,#EDE0CA 100%);padding:6rem 2rem 3rem;text-align:center}
.blog-hero h1{font-size:clamp(1.8rem,4vw,2.5rem);font-weight:700;color:var(--dark);margin-bottom:.6rem}
.blog-hero p{font-size:1rem;color:var(--mid);max-width:520px;margin:0 auto}
/* ─── Search ─────────────────────────────────────────────────── */
.search-wrap{max-width:480px;margin:1.5rem auto 0;position:relative}
.search-wrap input{width:100%;border:1.5px solid var(--border);border-radius:50px;padding:.65rem 1.2rem .65rem 3rem;font-family:'Vazirmatn',sans-serif;font-size:.9rem;direction:rtl;outline:none;background:var(--white);transition:border-color .2s}
.search-wrap input:focus{border-color:var(--gold)}
.search-wrap svg{position:absolute;left:1rem;top:50%;transform:translateY(-50%);width:18px;height:18px;color:var(--light)}
/* ─── Filter ─────────────────────────────────────────────────── */
.filter-bar{max-width:1100px;margin:2rem auto 0;padding:0 2rem;display:flex;gap:.6rem;flex-wrap:wrap}
.filter-btn{background:transparent;border:1.5px solid var(--border);color:var(--mid);padding:.4rem 1.1rem;border-radius:50px;font-family:'Vazirmatn',sans-serif;font-size:.85rem;cursor:pointer;transition:all .2s;text-decoration:none;display:inline-block}
.filter-btn.active,.filter-btn:hover{background:var(--gold);border-color:var(--gold);color:var(--white)}
/* ─── Blog Grid ──────────────────────────────────────────────── */
.blog-grid{max-width:1100px;margin:2rem auto;padding:0 2rem;display:grid;grid-template-columns:repeat(3,1fr);gap:1.5rem}
@@media(max-width:900px){.blog-grid{grid-template-columns:repeat(2,1fr)}}
@@media(max-width:600px){.blog-grid{grid-template-columns:1fr}}
.post-card{background:var(--white);border-radius:16px;border:1px solid var(--border);overflow:hidden;transition:transform .3s,box-shadow .3s;display:flex;flex-direction:column}
.post-card:hover{transform:translateY(-4px);box-shadow:0 12px 40px rgba(184,149,90,.15)}
.post-card-img{aspect-ratio:16/9;background:linear-gradient(135deg,var(--gold-pale),#EDE0CA);display:flex;align-items:center;justify-content:center;color:var(--gold);font-size:2rem;overflow:hidden}
.post-card-img img{width:100%;height:100%;object-fit:cover}
.post-card-body{padding:1.3rem;flex:1;display:flex;flex-direction:column;gap:.6rem}
.post-cat{font-size:.72rem;font-weight:600;color:var(--gold);background:var(--gold-pale);padding:.2rem .7rem;border-radius:50px;display:inline-block}
.post-title{font-size:1rem;font-weight:600;color:var(--dark);line-height:1.5}
.post-title:hover{color:var(--gold)}
.post-excerpt{font-size:.85rem;color:var(--mid);line-height:1.7;flex:1}
.post-meta{display:flex;align-items:center;justify-content:space-between;font-size:.75rem;color:var(--light);margin-top:auto;padding-top:.6rem;border-top:1px solid var(--border)}
.read-more{color:var(--gold);font-weight:500;font-size:.82rem}
/* ─── Empty ──────────────────────────────────────────────────── */
.empty{text-align:center;padding:4rem 2rem;color:var(--light);grid-column:1/-1}
/* ─── Pagination ─────────────────────────────────────────────── */
.pagination{display:flex;gap:.5rem;justify-content:center;padding:2rem;margin-top:1rem;max-width:1100px;margin-left:auto;margin-right:auto}
.page-btn{width:38px;height:38px;border-radius:8px;border:1.5px solid var(--border);background:transparent;font-family:'Vazirmatn',sans-serif;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s;text-decoration:none;color:var(--dark);font-size:.9rem}
.page-btn.active,.page-btn:hover{background:var(--gold);border-color:var(--gold);color:var(--white)}
</style>
}
<div class="blog-hero">
<h1>وبلاگ تخصصی پوست و زیبایی</h1>
<p>آخرین مقالات و راهنماهای تخصصی درباره مراقبت از پوست، زیبایی و درمان‌های تخصصی</p>
<div class="search-wrap">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
<input type="text" id="searchInput" placeholder="جستجو در مقالات..." />
</div>
</div>
<div class="filter-bar">
<a href="/blog" class="filter-btn @(string.IsNullOrEmpty(Model.ActiveCat) ? "active" : "")">همه</a>
@foreach (var cat in Model.Categories)
{
var active = Model.ActiveCat == cat.Slug;
var count = cat.Posts.Count(p => p.IsPublished);
<a href="/blog?category=@cat.Slug" class="filter-btn @(active ? "active" : "")">@cat.Name (@count)</a>
}
</div>
<div class="blog-grid" id="blogGrid">
@if (!Model.Posts.Any())
{
<div class="empty"><p>مقاله‌ای یافت نشد.</p></div>
}
else
{
@foreach (var post in Model.Posts)
{
<div class="post-card">
<div class="post-card-img">
@if (!string.IsNullOrEmpty(post.FeaturedImage))
{
<img src="@post.FeaturedImage" alt="@post.Title" loading="lazy" />
}
else { <span>📝</span> }
</div>
<div class="post-card-body">
@if (post.Category != null)
{
<span class="post-cat">@post.Category.Name</span>
}
<a href="/blog/@post.Slug" class="post-title">@post.Title</a>
<p class="post-excerpt">@(post.Excerpt.Length > 120 ? post.Excerpt.Substring(0, 120) + "..." : post.Excerpt)</p>
<div class="post-meta">
<span>🕐 @post.ReadingTimeMinutes دقیقه | 👁 @post.ViewCount</span>
<a href="/blog/@post.Slug" class="read-more">ادامه مطلب ←</a>
</div>
</div>
</div>
}
}
</div>
@if (Model.TotalPages > 1)
{
<div class="pagination">
@if (Model.CurrentPage > 1)
{
<a class="page-btn" href="/blog?page=@(Model.CurrentPage - 1)@(!string.IsNullOrEmpty(Model.ActiveCat) ? "&category=" + Model.ActiveCat : "")"></a>
}
@for (int p = 1; p <= Model.TotalPages; p++)
{
<a class="page-btn @(p == Model.CurrentPage ? "active" : "")"
href="/blog?page=@p@(!string.IsNullOrEmpty(Model.ActiveCat) ? "&category=" + Model.ActiveCat : "")">@p</a>
}
@if (Model.CurrentPage < Model.TotalPages)
{
<a class="page-btn" href="/blog?page=@(Model.CurrentPage + 1)@(!string.IsNullOrEmpty(Model.ActiveCat) ? "&category=" + Model.ActiveCat : "")"></a>
}
</div>
}