[Dashboard] Panel sub-nav menu + clearer profile button (name, not phone digit)
CI/CD / CI · dotnet build (push) Successful in 2m11s
CI/CD / Deploy · hamkadr (push) Failing after 2m37s

Logged-in panels (admin/employer/job-seeker) now show a sticky role-based dashboard menu (_PanelNav) on Employer/Index, Me/Index and Admin/Overview, with the active section highlighted — so users have an obvious menu and dashboard, not just a hidden avatar. Profile button: avatar fallback shows a 👤 glyph instead of the phone's first digit (the confusing '0'), and the desktop button now shows the user's name (or «حساب من») so it reads as a profile menu.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
soroush.asadi
2026-06-07 22:12:51 +03:30
parent 69e4f305e9
commit 33c13ec524
6 changed files with 62 additions and 1 deletions
@@ -5,6 +5,8 @@
string P(int n) => JalaliDate.ToPersianDigits(n.ToString()); string P(int n) => JalaliDate.ToPersianDigits(n.ToString());
} }
<partial name="_PanelNav" />
<div class="page-head"> <div class="page-head">
<div class="container"> <div class="container">
<h1>داشبورد مدیریت</h1> <h1>داشبورد مدیریت</h1>
@@ -10,6 +10,8 @@
}; };
} }
<partial name="_PanelNav" />
<div class="page-head"> <div class="page-head">
<div class="container"> <div class="container">
<h1>پنل مرکز درمانی</h1> <h1>پنل مرکز درمانی</h1>
@@ -16,6 +16,8 @@
}; };
} }
<partial name="_PanelNav" />
<div class="page-head"> <div class="page-head">
<div class="container"> <div class="container">
<h1>پنل کارجو</h1> <h1>پنل کارجو</h1>
@@ -16,7 +16,10 @@
meName = string.IsNullOrWhiteSpace(info?.FullName) ? info?.Phone : info!.FullName; meName = string.IsNullOrWhiteSpace(info?.FullName) ? info?.Phone : info!.FullName;
meHasAvatar = info?.HasAvatar ?? false; meHasAvatar = info?.HasAvatar ?? false;
} }
var meInitial = string.IsNullOrWhiteSpace(meName) ? "؟" : meName!.Trim().Substring(0, 1); // Person glyph when there's no real name yet (avoid showing a phone digit like "0").
var meInitial = (!string.IsNullOrWhiteSpace(meName) && !char.IsDigit(meName!.Trim()[0]))
? meName!.Trim().Substring(0, 1) : "👤";
var meLabel = (!string.IsNullOrWhiteSpace(meName) && !char.IsDigit(meName!.Trim()[0])) ? meName! : "حساب من";
// --- SEO context --- // --- SEO context ---
var baseUrl = $"{Context.Request.Scheme}://{Context.Request.Host}"; var baseUrl = $"{Context.Request.Scheme}://{Context.Request.Host}";
@@ -116,6 +119,7 @@
{ {
<span class="avatar-fallback">@meInitial</span> <span class="avatar-fallback">@meInitial</span>
} }
<span class="avatar-name">@meLabel</span>
<span class="avatar-caret">▾</span> <span class="avatar-caret">▾</span>
</label> </label>
<nav class="profile-dropdown"> <nav class="profile-dropdown">
@@ -0,0 +1,40 @@
@using System.Security.Claims
@*
Dashboard sub-menu for logged-in panels (admin / employer / job-seeker).
Render right under the page header on panel pages: <partial name="_PanelNav" />
*@
@{
var p = ViewContext.HttpContext.Request.Path.Value ?? "";
bool On(string path) => p.Equals(path, StringComparison.OrdinalIgnoreCase)
|| p.StartsWith(path + "/", StringComparison.OrdinalIgnoreCase);
}
<nav class="panel-nav">
<div class="container panel-nav-inner">
@if (User.IsInRole("Admin"))
{
<a class="@(On("/Admin/Overview") ? "active" : null)" asp-page="/Admin/Overview">📊 داشبورد</a>
<a class="@(On("/Admin/Index") ? "active" : null)" asp-page="/Admin/Index">📥 صف آگهی‌ها</a>
<a class="@(On("/Admin/Facilities") ? "active" : null)" asp-page="/Admin/Facilities">🏥 مراکز</a>
<a class="@(On("/Admin/Users") ? "active" : null)" asp-page="/Admin/Users">👥 کاربران</a>
<a class="@(On("/Admin/Reports") ? "active" : null)" asp-page="/Admin/Reports">🛡️ گزارش‌ها</a>
<a class="@(On("/Admin/Broadcast") ? "active" : null)" asp-page="/Admin/Broadcast">📣 اعلان همگانی</a>
<a class="@(On("/Admin/Settings") ? "active" : null)" asp-page="/Admin/Settings">⚙️ تنظیمات</a>
}
else if (User.IsInRole("FacilityAdmin"))
{
<a class="@(On("/Employer/Index") ? "active" : null)" asp-page="/Employer/Index">🏥 داشبورد مرکز</a>
<a class="@(On("/Employer/PostShift") ? "active" : null)" asp-page="/Employer/PostShift"> ثبت شیفت</a>
<a class="@(On("/Employer/PostJob") ? "active" : null)" asp-page="/Employer/PostJob"> ثبت استخدام</a>
<a class="@(On("/Me/Index") ? "active" : null)" asp-page="/Me/Index">🗂️ پنل کارجو</a>
<a class="@(On("/Me/Profile") ? "active" : null)" asp-page="/Me/Profile">👤 پروفایل</a>
}
else
{
<a class="@(On("/Me/Index") ? "active" : null)" asp-page="/Me/Index">🏠 داشبورد</a>
<a class="@(On("/Me/Alerts") ? "active" : null)" asp-page="/Me/Alerts">🔎 هشدارهای شغلی</a>
<a class="@(On("/Preferences/Index") ? "active" : null)" asp-page="/Preferences/Index">⭐ علاقه‌مندی‌ها</a>
<a class="@(On("/Me/Notifications") ? "active" : null)" asp-page="/Me/Notifications">🔔 اعلان‌ها</a>
<a class="@(On("/Me/Profile") ? "active" : null)" asp-page="/Me/Profile">👤 پروفایل</a>
}
</div>
</nav>
+11
View File
@@ -100,6 +100,17 @@ a { color: inherit; text-decoration: none; }
.avatar-img, .avatar-fallback { width: 34px; height: 34px; border-radius: 50%; object-fit: cover; display: block; } .avatar-img, .avatar-fallback { width: 34px; height: 34px; border-radius: 50%; object-fit: cover; display: block; }
.avatar-fallback { background: var(--primary); color: #fff; display: grid; place-items: center; font-weight: 800; } .avatar-fallback { background: var(--primary); color: #fff; display: grid; place-items: center; font-weight: 800; }
.avatar-caret { color: var(--muted); font-size: 11px; } .avatar-caret { color: var(--muted); font-size: 11px; }
.avatar-name { font-weight: 700; font-size: 14px; color: var(--ink); max-width: 120px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* ---------- Dashboard panel sub-nav ---------- */
.panel-nav { background: var(--surface); border-bottom: 1px solid var(--line); position: sticky; top: 64px; z-index: 30; }
.panel-nav-inner { display: flex; gap: 4px; overflow-x: auto; -webkit-overflow-scrolling: touch; padding: 6px 0; }
.panel-nav a {
white-space: nowrap; padding: 9px 14px; border-radius: 10px; font-weight: 600; font-size: 14px;
color: var(--muted); transition: background .15s, color .15s;
}
.panel-nav a:hover { background: var(--primary-soft); color: var(--primary-dark); }
.panel-nav a.active { background: var(--primary); color: #fff; }
.profile-dropdown { .profile-dropdown {
position: absolute; top: calc(100% + 8px); inset-inline-end: 0; min-width: 230px; z-index: 60; position: absolute; top: calc(100% + 8px); inset-inline-end: 0; min-width: 230px; z-index: 60;
background: var(--surface); border: 1px solid var(--line); border-radius: 14px; background: var(--surface); border: 1px solid var(--line); border-radius: 14px;