Spaces:
Sleeping
Sleeping
File size: 12,338 Bytes
cf599e0 0acba57 cf599e0 0acba57 cf599e0 0acba57 b866d20 0acba57 cf599e0 0acba57 cf599e0 0acba57 cf599e0 0acba57 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | @inherits LayoutComponentBase
@using BlazorFrontend.Providers
@using Microsoft.AspNetCore.Components.Authorization
@inject AuthenticationStateProvider AuthStateProvider
<div class="flex h-full overflow-hidden">
<!-- Sidebar -->
<aside class="hidden md:flex md:w-64 md:flex-col md:fixed md:inset-y-0 z-50">
<div class="flex flex-col flex-grow border-r border-slate-200 bg-white pt-5 pb-4 overflow-y-auto">
<div class="flex items-center flex-shrink-0 px-4 gap-2">
<div class="bg-slate-900 rounded-lg p-1.5 text-white">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m16 6 4 14"/><path d="M12 6v14"/><path d="M8 8v12"/><path d="M4 4v16"/><path d="M4 12V4l4 4"/><path d="m12 6 4 4"/></svg>
</div>
<span class="text-lg font-bold tracking-tight">Library OS</span>
</div>
<div class="mt-8 flex-grow flex flex-col">
<nav class="flex-1 px-2 space-y-1">
<NavLink href="" Match="NavLinkMatch.All" class="nav-link" ActiveClass="active">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="flex-shrink-0 mr-3"><rect width="7" height="9" x="3" y="3" rx="1"/><rect width="7" height="5" x="14" y="3" rx="1"/><rect width="7" height="9" x="14" y="12" rx="1"/><rect width="7" height="5" x="3" y="15" rx="1"/></svg>
Dashboard
</NavLink>
<NavLink href="Books" class="nav-link" ActiveClass="active">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="flex-shrink-0 mr-3"><path d="M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H20v20H6.5a2.5 2.5 0 0 1 0-5H20"/></svg>
Books Catalog
</NavLink>
<AuthorizeView>
<NotAuthorized>
<NavLink href="Borrowings" class="nav-link" ActiveClass="active">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="flex-shrink-0 mr-3"><path d="m21 21-6-6m6 6v-4.8m0 4.8h-4.8"/><path d="M3 16.2V21m0 0h4.8M3 21l6-6"/><path d="M21 7.8V3m0 0h-4.8M21 3l-6 6"/><path d="M3 7.8V3m0 0h4.8M3 3l6 6"/></svg>
Active Loans
</NavLink>
</NotAuthorized>
</AuthorizeView>
<AuthorizeView>
<Authorized Context="authContext">
@if (!authContext.User.IsInRole("Librarian"))
{
<NavLink href="Borrowings" class="nav-link" ActiveClass="active">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="flex-shrink-0 mr-3"><path d="m21 21-6-6m6 6v-4.8m0 4.8h-4.8"/><path d="M3 16.2V21m0 0h4.8M3 21l6-6"/><path d="M21 7.8V3m0 0h-4.8M21 3l-6 6"/><path d="M3 7.8V3m0 0h4.8M3 3l6 6"/></svg>
Active Loans
</NavLink>
<NavLink href="Membership" class="nav-link" ActiveClass="active">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="flex-shrink-0 mr-3"><rect width="20" height="14" x="2" y="5" rx="2"/><line x1="2" x2="22" y1="10" y2="10"/></svg>
My Membership
</NavLink>
<NavLink href="Rewards" class="nav-link" ActiveClass="active">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="flex-shrink-0 mr-3"><path d="M20 7h-9"/><path d="M14 17H5"/><circle cx="17" cy="17" r="3"/><circle cx="7" cy="7" r="3"/></svg>
Rewards
</NavLink>
}
</Authorized>
</AuthorizeView>
<AuthorizeView Roles="Librarian">
<Authorized>
<NavLink href="Members" class="nav-link" ActiveClass="active">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="flex-shrink-0 mr-3"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>
Members
</NavLink>
<NavLink href="Borrowings/Manage" class="nav-link" ActiveClass="active">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="flex-shrink-0 mr-3"><path d="M11 15h2a2 2 0 1 0 0-4h-2a2 2 0 1 1 0-4h2"/><path d="M12 5v14"/><path d="M18 19V5l-4 4"/><circle cx="12" cy="12" r="10"/></svg>
Manage Borrowings
</NavLink>
<NavLink href="Rewards/Manage" class="nav-link" ActiveClass="active">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="flex-shrink-0 mr-3"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
Manage Rewards
</NavLink>
</Authorized>
</AuthorizeView>
</nav>
</div>
<div class="px-4 py-4 border-t border-slate-100">
<AuthorizeView>
<Authorized Context="authContext">
<div class="flex items-center gap-3">
<div class="h-8 w-8 rounded-full bg-slate-900 flex items-center justify-center text-white font-bold text-xs uppercase">
@(authContext.User.Identity?.Name?.Substring(0, 2) ?? "US")
</div>
<div class="flex flex-col">
<span class="text-sm font-medium">@authContext.User.Identity?.Name</span>
<span class="text-xs text-slate-500">@authContext.User.Claims.FirstOrDefault(c => c.Type == System.Security.Claims.ClaimTypes.Role || c.Type == "role")?.Value</span>
</div>
</div>
</Authorized>
<NotAuthorized>
<div class="flex items-center gap-3">
<div class="h-8 w-8 rounded-full bg-slate-900 flex items-center justify-center text-white font-bold text-xs uppercase">
GU
</div>
<div class="flex flex-col">
<span class="text-sm font-medium">Guest User</span>
<span class="text-xs text-slate-500">Sign in to borrow</span>
</div>
</div>
</NotAuthorized>
</AuthorizeView>
</div>
</div>
</aside>
<!-- Main Content Wrapper -->
<div class="md:pl-64 flex flex-col flex-1 w-0">
<!-- Topbar -->
<header class="flex-shrink-0 flex h-16 bg-white border-b border-slate-200">
<div class="flex-1 px-4 flex justify-between">
<div class="flex-1 flex items-center">
<div class="w-full max-w-sm">
<label for="search" class="sr-only">Search</label>
<div class="relative">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<svg class="h-4 w-4 text-slate-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z" clip-rule="evenodd" />
</svg>
</div>
<input id="search" name="search" class="block w-full pl-10 pr-3 py-2 border border-slate-200 rounded-md leading-5 bg-slate-50 placeholder-slate-400 focus:outline-none focus:ring-1 focus:ring-slate-900 focus:border-slate-900 sm:text-sm transition-all" placeholder="Search books, authors, ISBN..." type="search">
</div>
</div>
</div>
<div class="ml-4 flex items-center md:ml-6 gap-4">
<button type="button" class="bg-white p-1 rounded-full text-slate-400 hover:text-slate-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-slate-900">
<span class="sr-only">View notifications</span>
<svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9" />
</svg>
</button>
<AuthorizeView>
<Authorized>
<a href="/logout" class="btn-secondary py-1.5">Logout</a>
</Authorized>
<NotAuthorized>
<a href="/login" class="btn-primary py-1.5">Sign In</a>
</NotAuthorized>
</AuthorizeView>
</div>
</div>
</header>
<!-- Main Content -->
<main class="flex-1 relative overflow-y-auto focus:outline-none">
<div class="py-8 px-4 sm:px-6 md:px-8 max-w-7xl mx-auto">
@if (_isReady)
{
@Body
}
else
{
<div class="flex items-center justify-center h-64">
<div class="animate-spin rounded-full h-12 w-12 border-b-2 border-slate-900"></div>
</div>
}
</div>
</main>
</div>
</div>
<div id="blazor-error-ui" class="hidden">
An unhandled error has occurred.
<a href="" class="reload text-blue-500 hover:underline">Reload</a>
<a class="dismiss cursor-pointer">🗙</a>
</div>
@code {
private bool _isReady;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
var jwtProvider = AuthStateProvider as JwtAuthenticationStateProvider;
if (jwtProvider != null)
{
await jwtProvider.LoadTokenAsync();
}
_isReady = true;
StateHasChanged();
}
}
}
|