Files
FrontOffice/src/FrontOffice.Main/Pages/_Host.cshtml
T
masoodafar-web 2573729db5
Build and Deploy to Kubernetes / build-and-deploy (push) Has been cancelled
feat: implement SEO enhancements and sitemap generation
- Added SEO configuration settings in appsettings for both development and staging environments, including site URL, name, and default description.
- Registered SEO-related services in the dependency injection container, including `SeoMetadataProvider` and `SitemapGenerator`.
- Updated the main program to configure SEO settings and map a new endpoint for generating the sitemap.
- Enhanced the `_Host.cshtml` page to utilize SEO metadata, including title, description, and Open Graph tags, improving search engine visibility and user engagement.

These changes significantly enhance the SEO capabilities of the application, ensuring better indexing and presentation in search results.
2026-07-01 21:45:24 +03:30

179 lines
7.6 KiB
Plaintext

@page "/"
@model FrontOffice.Main.Pages.HostModel
@using Microsoft.AspNetCore.Components.Web
@namespace FrontOffice.Main.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@Model.Seo.Title</title>
<meta name="description" content="@Model.Seo.Description" />
<link rel="canonical" href="@Model.Seo.CanonicalUrl" />
@if (Model.Seo.NoIndex)
{
<meta name="robots" content="noindex, nofollow" />
}
else
{
<meta name="robots" content="index, follow" />
}
<meta property="og:type" content="website" />
<meta property="og:locale" content="fa_IR" />
<meta property="og:title" content="@Model.Seo.Title" />
<meta property="og:description" content="@Model.Seo.Description" />
<meta property="og:url" content="@Model.Seo.CanonicalUrl" />
<meta property="og:site_name" content="کارابازار سلامت" />
<meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="@Model.Seo.Title" />
<meta name="twitter:description" content="@Model.Seo.Description" />
<meta name="theme-color" content="#7c4dff" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
<base href="~/" />
<link rel="icon" type="image/png" href="favicon.png"/>
<component type="typeof(HeadOutlet)" render-mode="Server" />
@* <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" rel="stylesheet" /> *@
<!-- MudBlazor CSS (باید قبل از site.css باشه تا override بشه) -->
<link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet" asp-append-version="true" />
<!-- Custom styles (بعد از MudBlazor برای override) -->
<link href="css/site.css" rel="stylesheet" asp-append-version="true" />
<link href="FrontOffice.Main.styles.css" rel="stylesheet" />
<!-- d3-org-chart custom styles -->
<link href="css/org-chart.css" rel="stylesheet" asp-append-version="true" />
<style>
.seo-crawlable {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
</style>
</head>
<body>
@if (!string.IsNullOrWhiteSpace(Model.Seo.CrawlableContent))
{
<div class="seo-crawlable">@Model.Seo.CrawlableContent</div>
}
<component type="typeof(App)" render-mode="Server" />
<div id="blazor-error-ui">
<environment include="Staging,Production">
یک خطا رخ داده است. این برنامه ممکن است تا زمان بارگذاری مجدد پاسخگو نباشد.
</environment>
<environment include="Development">
خطای مدیریت‌نشده ای اتفاق افتاده است. برای مشاهده جزئیات، ابزار توسعه (DevTools) مرورگر را بررسی نمایید.
</environment>
<a href="" class="reload">بارگذاری مجدد</a>
<a class="dismiss">🗙</a>
</div>
<!-- Load MudBlazor JS before Blazor to avoid early JS interop calls failing; add cache-busting -->
<script src="_content/MudBlazor/MudBlazor.min.js" asp-append-version="true"></script>
<!-- d3.js and d3-org-chart for network tree visualization -->
<script src="js/d3.v7.min.js"></script>
<script src="js/d3-flextree.min.js"></script>
<script src="js/d3-org-chart3.js"></script>
<script src="js/org-chart.js" asp-append-version="true"></script>
<script src="js/landing.js" asp-append-version="true"></script>
<script src="_framework/blazor.server.js"></script>
<script>
window.fetchAndDownloadPdf = async function(html, fileName){
try {
const res = await fetch('/contract/generate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ html: html, fileName: fileName })
});
if(!res.ok){
throw new Error('PDF generation failed: ' + res.status);
}
const blob = await res.blob();
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = (fileName || 'contract') + '.pdf';
document.body.appendChild(a);
a.click();
a.remove();
setTimeout(()=>URL.revokeObjectURL(url), 5000);
} catch(e){
console.error(e);
}
};
</script>
<script>
// elementId: id نوار (مثلاً "top")
// containerSelector: کانتینری که اسکرول می‌خوره؛ برای MudLayout معمولا ".mud-main-content"
// threshold: آستانه پیکسل
function changeNavBgOnBodyScroll(elementId, containerSelector = null, threshold = 10) {
var navbar = document.getElementById(elementId);
if (!navbar) return;
var container = containerSelector ? document.querySelector(containerSelector) : window;
var getScrollTop = function () {
if (container === window) {
return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
}
return container.scrollTop || 0;
};
var update = function () {
var y = getScrollTop();
if (y >= threshold) {
navbar.classList.add("white", "mud-elevation-2");
} else {
navbar.classList.remove("white", "mud-elevation-2");
}
};
// گوش دادن به اسکرول روی کانتینر درست
(container === window ? window : container).addEventListener("scroll", update, { passive: true });
// برای بارگذاری اولیه / تغییر اندازه / بازگشت از تاریخچه
window.addEventListener("load", update);
window.addEventListener("resize", update);
window.addEventListener("pageshow", update);
// اجرای اولیه (حتی اگر کاربر اسکرول نکرده)
requestAnimationFrame(update);
}
// پاک کردن کش مرورگر (Cache Storage و Service Worker)
window.clearBrowserCache = async function() {
// پاک کردن Cache Storage (Service Worker cache)
if ('caches' in window) {
const cacheNames = await caches.keys();
await Promise.all(
cacheNames.map(cacheName => caches.delete(cacheName))
);
console.log('Cache Storage cleared:', cacheNames.length, 'caches deleted');
}
// پاک کردن Service Worker registration
if ('serviceWorker' in navigator) {
const registrations = await navigator.serviceWorker.getRegistrations();
await Promise.all(
registrations.map(registration => registration.unregister())
);
console.log('Service Workers unregistered:', registrations.length);
}
return true;
};
</script>
</body>
</html>