Spaces:
Sleeping
Sleeping
File size: 9,735 Bytes
6f32ae8 b0a0ed0 36144b0 b0a0ed0 36144b0 b0a0ed0 36144b0 b0a0ed0 6f32ae8 | 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 | @model Frontend.Models.PagedResult<LibraryManagement.Shared.Models.UserDto>
@{
ViewData["Title"] = "Members Directory";
}
<div class="flex flex-col md:flex-row md:items-center justify-between gap-4 mb-8">
<div>
<h1 class="text-3xl font-bold tracking-tight text-slate-900">Members Directory</h1>
<p class="mt-2 text-slate-500">
Manage library members and administrator accounts.
<span class="ml-2 text-xs text-slate-400">(@Model.TotalCount total)</span>
</p>
</div>
<div class="flex items-center gap-3">
<a asp-action="Create" class="btn-primary">
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path></svg>
Add New Member
</a>
</div>
</div>
<div class="card overflow-hidden">
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-slate-200">
<thead class="bg-slate-50">
<tr>
<th scope="col" class="px-6 py-3 text-left text-xs font-semibold text-slate-500 uppercase tracking-wider">Member</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-semibold text-slate-500 uppercase tracking-wider">Contact</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-semibold text-slate-500 uppercase tracking-wider">Role</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-semibold text-slate-500 uppercase tracking-wider">Status</th>
<th scope="col" class="relative px-6 py-3"><span class="sr-only">Actions</span></th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-slate-200">
@foreach (var user in Model.Items)
{
<tr class="hover:bg-slate-50 transition-colors">
<td class="px-6 py-4 whitespace-nowrap">
<div class="flex items-center">
<div class="h-10 w-10 flex-shrink-0 rounded-full bg-slate-900 flex items-center justify-center text-white font-bold text-sm">
@(user.FullName?.Substring(0, 2).ToUpper() ?? "U")
</div>
<div class="ml-4">
<div class="text-sm font-medium text-slate-900">
<a asp-action="Details" asp-route-id="@user.Id" class="hover:underline">@user.FullName</a>
</div>
@if (!string.IsNullOrEmpty(user.StudentId))
{
<div class="text-xs text-slate-500 text-slate-500">ID: @user.StudentId</div>
}
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-slate-900">@user.Email</div>
<div class="text-xs text-slate-500">@(string.IsNullOrEmpty(user.PhoneNumber) ? "No phone" : user.PhoneNumber)</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<span class="inline-flex rounded-full px-2 text-xs font-semibold leading-5 @(user.Role == "Admin" ? "bg-amber-100 text-amber-800" : "bg-blue-100 text-blue-800")">
@user.Role
</span>
</td>
<td class="px-6 py-4 whitespace-nowrap">
@if (user.BanStatus == true)
{
<span class="inline-flex rounded-full bg-rose-100 px-2 text-xs font-semibold leading-5 text-rose-800">
Suspended
</span>
}
else if (user.IsActive)
{
<span class="inline-flex rounded-full bg-emerald-100 px-2 text-xs font-semibold leading-5 text-emerald-800">
Active
</span>
}
else
{
<span class="inline-flex rounded-full bg-slate-100 px-2 text-xs font-semibold leading-5 text-slate-800">
Inactive
</span>
}
</td>
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
<div class="flex items-center justify-end gap-3">
<a asp-action="Details" asp-route-id="@user.Id" class="text-slate-600 hover:text-slate-900 transition-colors">Details</a>
<a asp-action="Edit" asp-route-id="@user.Id" class="text-indigo-600 hover:text-indigo-900 transition-colors">Edit</a>
</div>
</td>
</tr>
}
</tbody>
</table>
</div>
@* Pagination *@
@if (Model.TotalPages > 1)
{
<div class="px-6 py-4 border-t border-slate-200 flex items-center justify-between bg-white">
<p class="text-sm text-slate-500">
Showing <span class="font-medium text-slate-700">@((Model.CurrentPage - 1) * Model.PageSize + 1)</span>
–
<span class="font-medium text-slate-700">@(Math.Min(Model.CurrentPage * Model.PageSize, Model.TotalCount))</span>
of <span class="font-medium text-slate-700">@Model.TotalCount</span> members
</p>
<nav class="flex items-center gap-1" aria-label="Pagination">
@* Previous *@
@if (Model.HasPreviousPage)
{
<a asp-action="Index" asp-route-page="@(Model.CurrentPage - 1)"
class="inline-flex items-center px-3 py-1.5 rounded-md border border-slate-200 text-sm font-medium text-slate-600 hover:bg-slate-50 hover:text-slate-900 transition-colors">
<svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
</svg>
Prev
</a>
}
else
{
<span class="inline-flex items-center px-3 py-1.5 rounded-md border border-slate-100 text-sm font-medium text-slate-300 cursor-not-allowed select-none">
<svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
</svg>
Prev
</span>
}
@* Page numbers *@
@for (int p = 1; p <= Model.TotalPages; p++)
{
if (p == Model.CurrentPage)
{
<span class="inline-flex items-center justify-center w-8 h-8 rounded-md bg-slate-900 text-white text-sm font-semibold">@p</span>
}
else if (p == 1 || p == Model.TotalPages || (p >= Model.CurrentPage - 2 && p <= Model.CurrentPage + 2))
{
<a asp-action="Index" asp-route-page="@p"
class="inline-flex items-center justify-center w-8 h-8 rounded-md border border-slate-200 text-sm font-medium text-slate-600 hover:bg-slate-50 hover:text-slate-900 transition-colors">@p</a>
}
else if (p == Model.CurrentPage - 3 || p == Model.CurrentPage + 3)
{
<span class="inline-flex items-center justify-center w-8 h-8 text-sm text-slate-400">…</span>
}
}
@* Next *@
@if (Model.HasNextPage)
{
<a asp-action="Index" asp-route-page="@(Model.CurrentPage + 1)"
class="inline-flex items-center px-3 py-1.5 rounded-md border border-slate-200 text-sm font-medium text-slate-600 hover:bg-slate-50 hover:text-slate-900 transition-colors">
Next
<svg class="w-4 h-4 ml-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</a>
}
else
{
<span class="inline-flex items-center px-3 py-1.5 rounded-md border border-slate-100 text-sm font-medium text-slate-300 cursor-not-allowed select-none">
Next
<svg class="w-4 h-4 ml-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</span>
}
</nav>
</div>
}
</div>
|