SurveyVista/Web/Areas/Admin/Views/Shared/_AdminLayout.cshtml
2025-12-14 16:56:10 +01:00

594 lines
No EOL
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"] - Web</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">
<style>
/* Override default styles while preserving functionality */
/* Modern Glassmorphism Sidebar - Icons only by default */
#sidebar {
position: sticky !important;
top: 0 !important;
height: 100vh !important;
min-width: 80px; /* Small width by default - icons only */
max-width: 80px;
background: rgba(10, 15, 25, 0.85) !important;
backdrop-filter: blur(25px) saturate(1.8) !important;
border-right: 1px solid rgba(59, 130, 246, 0.15) !important;
box-shadow: 8px 0 32px rgba(0, 0, 0, 0.4), 0 0 60px rgba(59, 130, 246, 0.05), inset -1px 0 0 rgba(255, 255, 255, 0.05) !important;
color: #fff;
-webkit-transition: all 0.3s;
-o-transition: all 0.3s;
transition: all 0.3s;
overflow-y: auto;
overflow-x: hidden;
z-index: 1000;
text-align: center; /* Center icons by default */
}
#sidebar::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(135deg, rgba(59, 130, 246, 0.08) 0%, transparent 30%, rgba(20, 184, 166, 0.05) 70%, rgba(249, 115, 22, 0.03) 100%);
z-index: -1;
}
/* Default: Hide text, show only icons centered */
#sidebar ul.components li a {
padding: 15px 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: rgba(255, 255, 255, 0.85);
text-decoration: none;
font-weight: 500;
font-size: 0.9rem;
border-radius: 12px;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
overflow: hidden;
background: rgba(255, 255, 255, 0.02);
backdrop-filter: blur(10px);
border: 1px solid transparent;
margin: 4px 8px;
}
#sidebar ul.components li a span.bi {
margin-right: 0;
margin-bottom: 0;
font-size: 1.2rem;
}
/* Hide text by default */
#sidebar ul.components li a .nav-text {
display: none;
}
/* Expanded state: Show both icons and text */
#sidebar.active {
min-width: 280px; /* Wide when expanded */
max-width: 280px;
text-align: left;
}
#sidebar.active ul.components li a {
padding: 14px 18px;
flex-direction: row;
align-items: center;
justify-content: flex-start;
margin: 4px 12px;
}
#sidebar.active ul.components li a span.bi {
margin-right: 15px;
margin-bottom: 0;
font-size: 1.1rem;
}
#sidebar.active ul.components li a .nav-text {
display: inline; /* Show text when expanded */
}
/* Logo styling */
#sidebar .logo {
display: block;
color: #fff !important;
font-weight: 900;
font-size: 1.2rem !important; /* Smaller by default */
padding: 20px 0;
-webkit-transition: 0.3s;
-o-transition: 0.3s;
transition: 0.3s;
text-decoration: none;
background: linear-gradient(135deg, #3b82f6 0%, #14b8a6 50%, #f97316 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
letter-spacing: -0.02em;
text-transform: uppercase;
border-bottom: 1px solid rgba(59, 130, 246, 0.15);
margin-bottom: 10px;
}
#sidebar.active .logo {
font-size: 1.8rem !important; /* Larger when expanded */
padding: 20px 30px;
}
/* Navigation List Styling */
#sidebar ul.components {
padding: 0;
-webkit-transition: 0.3s;
-o-transition: 0.3s;
transition: 0.3s;
}
#sidebar ul li {
font-size: 16px;
}
#sidebar ul li > ul {
margin-left: 10px;
}
#sidebar ul li > ul li {
font-size: 14px;
}
#sidebar ul li a:hover {
color: #fff;
background: rgba(59, 130, 246, 0.12) !important;
transform: translateX(4px);
border: 1px solid rgba(59, 130, 246, 0.2);
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.15);
}
#sidebar ul li.active > a {
background: rgba(20, 184, 166, 0.15) !important;
color: #fff;
border: 1px solid rgba(20, 184, 166, 0.3);
box-shadow: 0 2px 8px rgba(20, 184, 166, 0.2);
}
/* Responsive behavior */
@@media (max-width: 991.98px) {
#sidebar {
position: fixed !important;
height: 100vh;
z-index: 1001;
left: -80px !important; /* Hide by default on mobile */
}
#sidebar.active {
left: 0 !important; /* Show when active on mobile */
}
#sidebarCollapse span {
display: none;
}
}
/* Content Area */
.wrapper {
width: 100%;
}
#content {
width: 100%;
padding: 0;
min-height: 100vh;
-webkit-transition: all 0.3s;
-o-transition: all 0.3s;
transition: all 0.3s;
}
/* Modern Navbar Styling */
.navbar {
padding: 15px 10px;
background: rgba(5, 8, 18, 0.85) !important;
backdrop-filter: blur(25px) saturate(1.8);
border: none;
border-radius: 0;
margin-bottom: 40px;
border-bottom: 1px solid rgba(59, 130, 246, 0.15);
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4), 0 0 60px rgba(59, 130, 246, 0.05), inset 0 1px 0 rgba(255, 255, 255, 0.05);
}
.navbar::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(135deg, rgba(59, 130, 246, 0.08) 0%, transparent 30%, rgba(20, 184, 166, 0.05) 70%, rgba(249, 115, 22, 0.03) 100%);
border-radius: inherit;
z-index: -1;
}
/* Modern Button Styling */
.btn.btn-primary {
background: linear-gradient(135deg, #3b82f6, #14b8a6) !important;
border: 1px solid rgba(59, 130, 246, 0.3) !important;
color: #ffffff !important;
font-weight: 600;
border-radius: 8px;
transition: all 0.3s ease;
backdrop-filter: blur(15px);
}
.btn.btn-primary:hover,
.btn.btn-primary:focus {
background: linear-gradient(135deg, #2563eb, #0d9488) !important;
border-color: rgba(59, 130, 246, 0.5) !important;
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3);
}
.btn-danger {
background: linear-gradient(135deg, #ef4444, #dc2626) !important;
border: 1px solid rgba(239, 68, 68, 0.3) !important;
color: #ffffff !important;
font-weight: 600;
border-radius: 8px;
transition: all 0.3s ease;
}
.btn-danger:hover {
background: linear-gradient(135deg, #dc2626, #b91c1c) !important;
border-color: rgba(239, 68, 68, 0.5) !important;
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(239, 68, 68, 0.3);
}
/* Dropdown Styling */
.dropdown-menu {
background: rgba(5, 8, 18, 0.95) !important;
backdrop-filter: blur(25px) saturate(1.8) !important;
border: 1px solid rgba(59, 130, 246, 0.2) !important;
border-radius: 12px !important;
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.5), 0 0 60px rgba(59, 130, 246, 0.1) !important;
padding: 8px !important;
}
.dropdown-item {
color: rgba(255, 255, 255, 0.85) !important;
font-weight: 500;
padding: 10px 12px;
border-radius: 8px;
transition: all 0.3s ease;
margin: 2px 0;
}
.dropdown-item:hover {
background: rgba(59, 130, 246, 0.15) !important;
color: #ffffff !important;
}
/* Badge Styling */
.badge-danger {
background: linear-gradient(135deg, #ef4444, #dc2626) !important;
color: white !important;
border-radius: 50%;
padding: 4px 8px;
font-size: 0.75rem;
font-weight: 600;
}
/* Text colors */
.text-white {
color: rgba(255, 255, 255, 0.9) !important;
}
/* Custom Scrollbar */
#sidebar::-webkit-scrollbar {
width: 4px;
}
#sidebar::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.05);
}
#sidebar::-webkit-scrollbar-thumb {
background: rgba(59, 130, 246, 0.3);
border-radius: 2px;
}
#sidebar::-webkit-scrollbar-thumb:hover {
background: rgba(59, 130, 246, 0.5);
}
/* Preserve original footer styling */
.footer {
padding: 0 30px;
}
@@media (max-width: 991.98px) {
.footer {
display: block;
}
}
/* Preserve original dropdown toggle */
a[data-toggle="collapse"] {
position: relative;
}
.dropdown-toggle::after {
display: block;
position: absolute;
top: 50%;
right: 0;
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
}
/* Navbar button styling */
.navbar-btn {
-webkit-box-shadow: none;
box-shadow: none;
outline: none !important;
border: none;
}
</style>
</head>
<body>
<div class="wrapper d-flex align-items-stretch">
<nav id="sidebar">
<h1><a class="logo">NVKN</a></h1>
<ul class="list-unstyled components mb-5">
<li class="sidebarCollapse">
<a asp-controller="admin" asp-action="index">
<span class="bi bi-speedometer"></span>
<span class="nav-text">Admin</span>
</a>
</li>
<li>
<a asp-controller="Page" asp-action="index">
<span class="bi bi-file-earmark-fill"></span>
<span class="nav-text">Pages</span>
</a>
</li>
<li>
<a asp-controller="banner" asp-action="index">
<span class="bi bi-card-image"></span>
<span class="nav-text">Banners</span>
</a>
</li>
<li>
<a asp-controller="footer" asp-action="index">
<span class="bi bi-c-circle-fill"></span>
<span class="nav-text">Footer</span>
</a>
</li>
<li>
<a asp-controller="address" asp-action="index">
<span class="bi bi-pin-map"></span>
<span class="nav-text">Address</span>
</a>
</li>
<li>
<a asp-controller="SocialMedia" asp-action="index">
<span class="bi bi-collection-play-fill"></span>
<span class="nav-text">Social Media</span>
</a>
</li>
<li>
<a asp-controller="Questionnaire" asp-action="index">
<span class="bi bi-question-circle"></span>
<span class="nav-text">Survey</span>
</a>
</li>
<li>
<a asp-controller="SurveyAnalysis" asp-action="index">
<span class="bi bi-graph-up-arrow"></span>
<span class="nav-text">Analyzer</span>
</a>
</li>
<li>
<a asp-controller="UserResponse" asp-action="index">
<span class="bi bi-clipboard-data"></span>
<span class="nav-text">Response</span>
</a>
</li>
<li>
<a asp-controller="UserResponseStatus" asp-action="index">
<span class="bi bi-heart-pulse"></span>
<span class="nav-text">User status</span>
</a>
</li>
<li>
<a asp-controller="newsletters" asp-action="index">
<span class="bi bi-newspaper"></span>
<span class="nav-text">Subscibers</span>
</a>
</li>
</ul>
</nav>
<!-- Page Content -->
<div id="content">
<nav class="navbar navbar-expand-lg navbar-light bg-brimary">
<div class="container-fluid">
<button type="button" id="sidebarCollapse" class="btn btn-primary">
<i class="bi bi-list"></i>
<span class="sr-only">Toggle Menu</span>
</button>
<button class="navbar-toggler btn btn-primary" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<i class="bi bi-list"></i>
<span class="sr-only"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="nav navbar-nav ml-auto">
<span class="dropdown m-2">
<button class="bg-transparent text-white btn-sm dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
<span class="badge badge-danger" id="notificationCount">0</span>
</button>
<ul class="dropdown-menu" id="notificationDropdown">
<li>
<a class="dropdown-item" href="#">
<div id="notifications">
</div>
</a>
</li>
</ul>
</span>
<span class="dropdown m-2">
<button class="btn btn-primary btn-sm dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
Account
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" asp-controller="Roles" asp-action="index">Roles</a></li>
<li><a class="dropdown-item" asp-controller="Users" asp-action="index">Users</a></li>
</ul>
</span>
<li class="nav-item m-2">
<form asp-area="Admin" asp-controller="Admin" asp-action="Logout" method="post">
<button type="submit" class="btn btn-danger btn-sm"><span class="bi bi-box-arrow-left"></span> Logout</button>
</form>
</li>
</ul>
</div>
</div>
</nav>
<main>
@RenderBody()
</main>
</div>
</div>
<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 type="text/javascript">
// Establish a connection to the SignalR hub
const connection = new signalR.HubConnectionBuilder()
.withUrl("/notificationHub")
.build();
// Function to load notifications from local storage
function loadNotifications() {
const notificationsList = document.getElementById("notifications");
const notificationCount = document.getElementById("notificationCount");
// Retrieve notifications from local storage
const storedNotifications = JSON.parse(localStorage.getItem("notifications")) || [];
// Update the notification count
notificationCount.textContent = storedNotifications.length;
// Add each stored notification to the list
storedNotifications.forEach(notification => {
const div = document.createElement("div");
div.className = "list-group-item";
const link = document.createElement("a");
link.href = `/admin/UserResponseStatus/UserResponsesStatus?UserEmail=${notification.email}`;
link.textContent = notification.text;
link.addEventListener("click", () => {
removeNotification(div, notification.id);
});
div.appendChild(link);
notificationsList.appendChild(div);
});
}
// Function to add a notification to the list
function addNotification(userName, email) {
const notificationsList = document.getElementById("notifications");
const notificationCount = document.getElementById("notificationCount");
// Create a unique ID for the notification
const notificationId = Date.now();
// Create notification item
const div = document.createElement("div");
div.className = "list-group-item";
const link = document.createElement("a");
link.href = `/admin/UserResponseStatus/UserResponsesStatus?UserEmail=${email}`;
link.textContent = ` ${userName}`;
link.addEventListener("click", () => {
removeNotification(div, notificationId);
});
div.appendChild(link);
notificationsList.appendChild(div);
// Update the notification count
notificationCount.textContent = parseInt(notificationCount.textContent) + 1;
// Store the notification in local storage
const storedNotifications = JSON.parse(localStorage.getItem("notifications")) || [];
storedNotifications.push({ id: notificationId, text: link.textContent, email: email });
localStorage.setItem("notifications", JSON.stringify(storedNotifications));
}
// Function to remove a notification
function removeNotification(div, id) {
div.remove();
// Update the notification count
const notificationCount = document.getElementById("notificationCount");
notificationCount.textContent = parseInt(notificationCount.textContent) - 1;
// Remove the notification from local storage
let storedNotifications = JSON.parse(localStorage.getItem("notifications")) || [];
storedNotifications = storedNotifications.filter(notification => notification.id !== id);
localStorage.setItem("notifications", JSON.stringify(storedNotifications));
}
// Receive notification from the server
connection.on("ReceiveNotification", function (userName, email) {
addNotification(userName, email);
});
// Start the connection
connection.start().then(loadNotifications).catch(function (err) {
return console.error(err.toString());
});
</script>
@await RenderSectionAsync("Scripts", required: false)
@await RenderSectionAsync("Styles", required: false)
</body>
</html>