SurveyVista/Web/Areas/Admin/Views/Shared/_AdminLayout.cshtml
2026-03-07 02:37:33 +01:00

291 lines
22 KiB
Text

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - NVKN</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/Web.styles.css" asp-append-version="true" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/css/toastr.min.css" />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" />
<style>
:root{
--bg-deep:#060a13;--bg-card:#182036;
--text-primary:#e8edf4;--text-secondary:#94a3b8;--text-muted:#5e6e82;--text-faint:#3d4e63;
--accent-blue:#3b82f6;--accent-teal:#14b8a6;--accent-orange:#f97316;
--accent-red:#ef4444;--accent-green:#10b981;
--glass-border:rgba(255,255,255,0.06);--glass-hover:rgba(255,255,255,0.12);
--nv-w:72px;--nv-exp:260px;--nv-top:60px;
--ease:cubic-bezier(0.4,0,0.2,1);
}
/* Kill site.css originals */
body{font-family:'Inter',-apple-system,sans-serif;background:none;-webkit-font-smoothing:antialiased;overflow-x:hidden}
#sidebar{display:none !important}
#content{display:none !important}
/* ===== SIDEBAR ===== */
#nvkn-sidebar{
position:fixed;top:0;left:0;height:100vh;width:var(--nv-w);
background:rgba(8,12,24,0.94);backdrop-filter:blur(30px) saturate(1.6);
border-right:1px solid var(--glass-border);z-index:1100;
display:flex;flex-direction:column;transition:width 0.3s var(--ease);overflow:hidden;
}
#nvkn-sidebar::before{content:'';position:absolute;inset:0;background:linear-gradient(180deg,rgba(59,130,246,0.04),transparent 40%,rgba(20,184,166,0.03));pointer-events:none}
#nvkn-sidebar.expanded{width:var(--nv-exp)}
.nv-logo{display:flex;align-items:center;justify-content:center;height:var(--nv-top);padding:0 16px;border-bottom:1px solid var(--glass-border);flex-shrink:0;position:relative;z-index:1}
.nv-logo-mark{width:36px;height:36px;border-radius:10px;background:linear-gradient(135deg,var(--accent-blue),var(--accent-teal));display:flex;align-items:center;justify-content:center;font-family:'JetBrains Mono',monospace;font-weight:800;font-size:14px;color:#fff;flex-shrink:0;box-shadow:0 4px 16px rgba(59,130,246,0.25)}
.nv-logo-text{font-family:'JetBrains Mono',monospace;font-weight:800;font-size:18px;letter-spacing:.08em;background:linear-gradient(135deg,var(--accent-blue),var(--accent-teal),var(--accent-orange));-webkit-background-clip:text;-webkit-text-fill-color:transparent;margin-left:14px;white-space:nowrap;display:none}
#nvkn-sidebar.expanded .nv-logo-text{display:inline}
.nv-nav{flex:1;padding:12px 0;overflow-y:auto;overflow-x:hidden;position:relative;z-index:1}
.nv-nav::-webkit-scrollbar{width:3px}
.nv-nav::-webkit-scrollbar-thumb{background:rgba(59,130,246,0.2);border-radius:3px}
.nv-nav ul{list-style:none;padding:0;margin:0}
.nv-link{display:flex;align-items:center;justify-content:center;height:44px;margin:2px 8px;border-radius:10px;color:var(--text-secondary);text-decoration:none;transition:all .25s var(--ease);position:relative;border:1px solid transparent}
#nvkn-sidebar.expanded .nv-link{justify-content:flex-start;padding:0 16px;margin:2px 10px}
.nv-link:hover{color:#fff;background:rgba(59,130,246,0.1);border-color:rgba(59,130,246,0.15);text-decoration:none}
.nv-link:hover .nv-icon{color:var(--accent-blue)}
.nv-link.active{background:rgba(20,184,166,0.1);border-color:rgba(20,184,166,0.2);color:#fff}
.nv-link.active .nv-icon{color:var(--accent-teal)}
.nv-link.active::after{content:'';position:absolute;left:0;top:8px;bottom:8px;width:3px;background:var(--accent-teal);border-radius:0 3px 3px 0}
.nv-icon{font-size:18px;width:24px;text-align:center;flex-shrink:0;transition:color .2s}
.nv-text{font-size:13px;font-weight:500;white-space:nowrap;margin-left:14px;opacity:0;width:0;overflow:hidden;transition:opacity .15s,width .25s var(--ease)}
#nvkn-sidebar.expanded .nv-text{opacity:1;width:auto}
.nv-tip{position:absolute;left:calc(100% + 12px);top:50%;transform:translateY(-50%) scale(.9);background:var(--bg-card);color:var(--text-primary);padding:6px 12px;border-radius:8px;font-size:12px;font-weight:500;white-space:nowrap;pointer-events:none;opacity:0;transition:opacity .15s,transform .15s;border:1px solid var(--glass-border);box-shadow:0 8px 24px rgba(0,0,0,.4);z-index:9999}
.nv-link:hover .nv-tip{opacity:1;transform:translateY(-50%) scale(1)}
#nvkn-sidebar.expanded .nv-tip{display:none}
.nv-footer{padding:12px;border-top:1px solid var(--glass-border);flex-shrink:0;position:relative;z-index:1;font-family:'JetBrains Mono',monospace;font-size:9px;color:var(--text-faint);text-align:center;letter-spacing:.05em}
#nvkn-sidebar.expanded .nv-footer{text-align:left;padding-left:20px}
/* ===== CONTENT WRAPPER ===== */
.nv-content{margin-left:var(--nv-w);min-height:100vh;display:flex;flex-direction:column;transition:margin-left .3s var(--ease)}
#nvkn-sidebar.expanded ~ .nv-overlay ~ .nv-content,
#nvkn-sidebar.expanded ~ .nv-content{margin-left:var(--nv-exp)}
/* ===== TOPBAR ===== */
.nv-topbar{height:var(--nv-top);background:rgba(8,12,24,0.92);backdrop-filter:blur(30px) saturate(1.6);border-bottom:1px solid var(--glass-border);display:flex;align-items:center;padding:0 24px;gap:16px;position:sticky;top:0;z-index:1050;flex-shrink:0}
.nv-topbar::before{content:'';position:absolute;inset:0;background:linear-gradient(90deg,rgba(59,130,246,0.03),transparent,rgba(20,184,166,0.02));pointer-events:none}
#nvkn-toggle{width:40px;height:40px;border-radius:10px;background:rgba(59,130,246,0.15);border:1px solid rgba(59,130,246,0.3);color:rgba(255,255,255,0.9);display:flex;align-items:center;justify-content:center;font-size:20px;cursor:pointer;transition:all .25s var(--ease);flex-shrink:0;position:relative;z-index:10;outline:none;box-shadow:0 2px 8px rgba(59,130,246,0.2)}
#nvkn-toggle:hover{background:rgba(59,130,246,0.25);border-color:rgba(59,130,246,0.5);color:#fff;transform:scale(1.05);box-shadow:0 4px 16px rgba(59,130,246,0.3)}
.nv-ctx{display:flex;align-items:center;gap:10px;flex:1;position:relative;z-index:1}
.nv-divider{width:1px;height:24px;background:var(--glass-border)}
.nv-crumbs{display:flex;align-items:center;gap:8px;font-size:13px}
.nv-crumbs .c-m{color:var(--text-muted);font-weight:500}
.nv-crumbs .c-a{color:var(--text-primary);font-weight:600}
.nv-crumbs .c-s{color:var(--text-faint);font-size:10px}
.nv-actions{display:flex;align-items:center;gap:8px;position:relative;z-index:1001}
.nv-bell{width:38px;height:38px;border-radius:10px;background:rgba(255,255,255,0.03);border:1px solid var(--glass-border);color:var(--text-secondary);display:flex;align-items:center;justify-content:center;font-size:16px;cursor:pointer;transition:all .25s var(--ease);position:relative}
.nv-bell:hover{background:rgba(255,255,255,0.06);border-color:var(--glass-hover);color:var(--text-primary)}
.nv-badge{position:absolute;top:-2px;right:-2px;min-width:18px;height:18px;border-radius:9px;background:linear-gradient(135deg,var(--accent-red),#dc2626);color:#fff;font-size:9px;font-weight:700;display:flex;align-items:center;justify-content:center;padding:0 4px;border:2px solid var(--bg-deep);box-shadow:0 2px 8px rgba(239,68,68,0.4)}
.nv-acct{display:flex;align-items:center;gap:10px;padding:6px 14px 6px 6px;border-radius:10px;background:rgba(20,184,166,0.06);border:1px solid rgba(20,184,166,0.15);color:var(--text-secondary);cursor:pointer;transition:all .25s var(--ease);font-size:13px;font-weight:500;font-family:inherit}
.nv-acct:hover{background:rgba(20,184,166,0.12);border-color:rgba(20,184,166,0.3);color:var(--text-primary)}
.nv-avatar{width:28px;height:28px;border-radius:8px;background:linear-gradient(135deg,var(--accent-teal),var(--accent-blue));display:flex;align-items:center;justify-content:center;font-size:12px;color:#fff;font-weight:700}
/* ===== DROPDOWNS ===== */
.nv-actions .dropdown{position:relative;z-index:1001}
.nv-actions .dropdown-menu{background:rgba(12,16,30,0.97) !important;backdrop-filter:blur(32px) saturate(1.8) !important;border:1px solid rgba(59,130,246,0.18) !important;border-radius:14px !important;box-shadow:0 20px 60px rgba(0,0,0,0.6),0 0 80px rgba(59,130,246,0.08) !important;padding:10px !important;margin-top:8px !important;min-width:220px !important;z-index:9999 !important;}
@@keyframes nvdd{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:translateY(0)}}
.nv-actions .dropdown-header{color:var(--text-muted) !important;font-family:'JetBrains Mono',monospace;font-size:10px !important;font-weight:600 !important;text-transform:uppercase !important;letter-spacing:.8px !important;padding:8px 14px 6px !important}
.nv-actions .dropdown-divider{border-color:rgba(255,255,255,0.06) !important;margin:6px 0 !important}
.nv-actions .dropdown-item{color:var(--text-secondary) !important;font-size:13px;font-weight:500;padding:10px 14px;border-radius:8px;transition:all .25s var(--ease);display:flex;align-items:center;gap:10px;margin:2px 0;border:1px solid transparent}
.nv-actions .dropdown-item:hover{background:rgba(59,130,246,0.12) !important;color:#fff !important;border-color:rgba(59,130,246,0.15)}
.nv-actions .dropdown-item.text-danger{color:rgba(239,68,68,0.85) !important}
.nv-actions .dropdown-item.text-danger:hover{background:rgba(239,68,68,0.12) !important;color:#fff !important}
.nv-notif-dd{min-width:340px !important;max-height:440px;overflow-y:auto}
.nv-notif-wrap{padding:4px 6px;list-style:none}
.nv-notif-wrap:hover{background:none !important}
#notifications{display:flex;flex-direction:column;gap:6px}
#notifications .list-group-item{display:flex;align-items:center;gap:12px;background:rgba(20,184,166,0.06);border:1px solid rgba(20,184,166,0.12);border-radius:10px;padding:12px 14px;transition:all .25s var(--ease);cursor:pointer;color:transparent;font-size:0}
#notifications .list-group-item::before{content:'\F4C3';font-family:'bootstrap-icons';color:var(--accent-teal);font-size:14px;flex-shrink:0;width:32px;height:32px;display:flex;align-items:center;justify-content:center;background:rgba(20,184,166,0.1);border-radius:8px;border:1px solid rgba(20,184,166,0.2)}
#notifications .list-group-item:hover{background:rgba(20,184,166,0.14);border-color:rgba(20,184,166,0.28);transform:translateX(3px)}
#notifications .list-group-item a{color:var(--text-primary);text-decoration:none;font-size:13px;font-weight:500;line-height:1.4;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
#notifications .list-group-item a:hover{color:var(--accent-teal)}
.nv-overlay{display:none;position:fixed;background:rgba(0,0,0,0.5);z-index:1050;backdrop-filter:blur(4px)}
#nvkn-sidebar.expanded ~ .nv-overlay{display:block}
main{flex:1}
@@media(max-width:991.98px){
#nvkn-sidebar{left:-280px;width:260px}
#nvkn-sidebar.expanded{left:0;width:260px}
.nv-content{margin-left:0 !important}
#nvkn-sidebar.expanded ~ .nv-overlay ~ .nv-content,#nvkn-sidebar.expanded ~ .nv-content{margin-left:0 !important}
.nv-link{justify-content:flex-start;padding:0 16px}
.nv-text{opacity:1;width:auto}
.nv-tip{display:none}
.nv-logo-text{display:inline}
}
@@media(max-width:768px){
.nv-topbar{padding:0 16px}
.nv-crumbs,.nv-divider{display:none}
.nv-acct-label{display:none}
}
</style>
</head>
<body>
<div class="wrapper align-items-stretch">
<!-- Sidebar (new ID avoids site.css conflicts) -->
<nav id="nvkn-sidebar">
<div class="nv-logo">
<span class="nv-logo-text">NVKN</span>
</div>
<div class="nv-nav">
<ul>
<li><a asp-controller="Admin" asp-action="Index" class="nv-link"><span class="nv-icon bi bi-speedometer2"></span><span class="nv-text">Admin</span><span class="nv-tip">Admin</span></a></li>
<li><a asp-controller="Page" asp-action="Index" class="nv-link"><span class="nv-icon bi bi-file-earmark-fill"></span><span class="nv-text">Pages</span><span class="nv-tip">Pages</span></a></li>
<li><a asp-controller="Banner" asp-action="Index" class="nv-link"><span class="nv-icon bi bi-card-image"></span><span class="nv-text">Banners</span><span class="nv-tip">Banners</span></a></li>
<li><a asp-controller="Footer" asp-action="Index" class="nv-link"><span class="nv-icon bi bi-c-circle-fill"></span><span class="nv-text">Footer</span><span class="nv-tip">Footer</span></a></li>
<li><a asp-controller="Address" asp-action="Index" class="nv-link"><span class="nv-icon bi bi-pin-map"></span><span class="nv-text">Address</span><span class="nv-tip">Address</span></a></li>
<li><a asp-controller="SocialMedia" asp-action="Index" class="nv-link"><span class="nv-icon bi bi-collection-play-fill"></span><span class="nv-text">Social Media</span><span class="nv-tip">Social Media</span></a></li>
<li><a asp-controller="Questionnaire" asp-action="Index" class="nv-link"><span class="nv-icon bi bi-question-circle"></span><span class="nv-text">Survey</span><span class="nv-tip">Survey</span></a></li>
<li><a asp-controller="SurveyAnalysis" asp-action="Index" class="nv-link"><span class="nv-icon bi bi-graph-up-arrow"></span><span class="nv-text">Analyzer</span><span class="nv-tip">Analyzer</span></a></li>
<li><a asp-controller="UserResponse" asp-action="Index" class="nv-link"><span class="nv-icon bi bi-clipboard-data"></span><span class="nv-text">Response</span><span class="nv-tip">Response</span></a></li>
<li><a asp-controller="UserResponseStatus" asp-action="Index" class="nv-link"><span class="nv-icon bi bi-heart-pulse"></span><span class="nv-text">User status</span><span class="nv-tip">User status</span></a></li>
<li><a asp-controller="Newsletters" asp-action="Index" class="nv-link"><span class="nv-icon bi bi-newspaper"></span><span class="nv-text">Subscribers</span><span class="nv-tip">Subscribers</span></a></li>
</ul>
</div>
<div class="nv-footer">v1.0</div>
</nav>
<div class="nv-overlay" id="nvkn-overlay"></div>
<!-- Content -->
<div class="nv-content">
<div class="nv-topbar">
<button type="button" id="nvkn-toggle"><i class="bi bi-list"></i></button>
<div class="nv-ctx">
<div class="nv-divider"></div>
<div class="nv-crumbs">
<span class="c-m">Admin</span>
<span class="c-s"><i class="bi bi-chevron-right"></i></span>
<span class="c-a">@ViewData["Title"]</span>
</div>
</div>
<div class="nv-actions">
<span class="dropdown">
<button class="nv-bell" type="button" data-bs-toggle="dropdown" aria-expanded="false">
<i class="bi bi-bell"></i>
<span class="nv-badge" id="notificationCount">0</span>
</button>
<ul class="dropdown-menu dropdown-menu-end nv-notif-dd" id="notificationDropdown">
<li><h6 class="dropdown-header"><i class="bi bi-bell me-1"></i> Notifications</h6></li>
<li><hr class="dropdown-divider"></li>
<li class="nv-notif-wrap"><div id="notifications"></div></li>
</ul>
</span>
<span class="dropdown">
<button class="nv-acct" type="button" data-bs-toggle="dropdown" aria-expanded="false">
<span class="nv-avatar"><i class="bi bi-person-fill"></i></span>
<span class="nv-acct-label">Account</span>
<i class="bi bi-chevron-down" style="font-size:10px;color:var(--text-muted)"></i>
</button>
<ul class="dropdown-menu dropdown-menu-end">
<li><h6 class="dropdown-header"><i class="bi bi-gear me-1"></i> User Management</h6></li>
<li><a class="dropdown-item" asp-controller="Users" asp-action="Index"><i class="bi bi-people"></i> Users</a></li>
<li><a class="dropdown-item" asp-controller="Roles" asp-action="Index"><i class="bi bi-shield-check"></i> Roles</a></li>
<li><hr class="dropdown-divider"></li>
<li>
<form asp-area="Admin" asp-controller="Admin" asp-action="Logout" method="post" class="d-inline w-100">
<button type="submit" class="dropdown-item text-danger w-100" style="border:none;background:none"><i class="bi bi-box-arrow-left"></i> Logout</button>
</form>
</li>
</ul>
</span>
</div>
</div>
<main>
@RenderBody()
<partial name="_AccessDeniedModal" />
</main>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/sortablejs@1.15.0/Sortable.min.js"></script>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/5.0.11/signalr.min.js"></script>
<script>
$(document).ready(function(){
$('#nvkn-toggle').on('click',function(e){
e.preventDefault();
$('#nvkn-sidebar').toggleClass('expanded');
});
$('#nvkn-overlay').on('click',function(){
$('#nvkn-sidebar').removeClass('expanded');
});
var p=window.location.pathname.toLowerCase();
$('.nv-link').each(function(){
var h=$(this).attr('href');
if(h&&p.indexOf(h.toLowerCase())!==-1)$(this).addClass('active');
});
});
var connection=new signalR.HubConnectionBuilder().withUrl("/notificationHub").build();
function loadNotifications(){
var nl=document.getElementById("notifications"),nc=document.getElementById("notificationCount");
var sn=JSON.parse(localStorage.getItem("notifications"))||[];
nc.textContent=sn.length;
nc.style.display=sn.length===0?'none':'flex';
sn.forEach(function(n){
var d=document.createElement("div");d.className="list-group-item";
var a=document.createElement("a");
a.href="/admin/UserResponseStatus/UserResponsesStatus?UserEmail="+n.email;
a.textContent=n.text;
a.addEventListener("click",function(){removeNotification(d,n.id)});
d.appendChild(a);nl.appendChild(d);
});
}
function addNotification(u,e){
var nl=document.getElementById("notifications"),nc=document.getElementById("notificationCount");
var id=Date.now(),d=document.createElement("div");d.className="list-group-item";
var a=document.createElement("a");
a.href="/admin/UserResponseStatus/UserResponsesStatus?UserEmail="+e;
a.textContent=" "+u;
a.addEventListener("click",function(){removeNotification(d,id)});
d.appendChild(a);nl.appendChild(d);
var c=parseInt(nc.textContent)+1;nc.textContent=c;nc.style.display='flex';
var sn=JSON.parse(localStorage.getItem("notifications"))||[];
sn.push({id:id,text:a.textContent,email:e});
localStorage.setItem("notifications",JSON.stringify(sn));
}
function removeNotification(d,id){
d.remove();
var nc=document.getElementById("notificationCount");
var c=parseInt(nc.textContent)-1;nc.textContent=c;
if(c<=0)nc.style.display='none';
var sn=JSON.parse(localStorage.getItem("notifications"))||[];
sn=sn.filter(function(n){return n.id!==id});
localStorage.setItem("notifications",JSON.stringify(sn));
}
connection.on("ReceiveNotification",function(u,e){addNotification(u,e)});
connection.start().then(loadNotifications).catch(function(err){console.error(err.toString())});
</script>
@await RenderSectionAsync("Scripts", required: false)
@await RenderSectionAsync("Styles", required: false)
</body>
</html>