Add admin layout and customer pagination
TaxBaik CI/CD / build-and-deploy (push) Failing after 2m32s
TaxBaik CI/CD / build-and-deploy (push) Failing after 2m32s
This commit is contained in:
@@ -62,7 +62,9 @@
|
||||
@if (Model.Items.Count == 0)
|
||||
{
|
||||
<tr>
|
||||
<td colspan="6" class="text-center text-muted py-5">고객 데이터가 없습니다.</td>
|
||||
<td colspan="6">
|
||||
<partial name="_EmptyState" model="@("검색 결과가 없습니다.")" />
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
else
|
||||
@@ -73,7 +75,7 @@
|
||||
<td class="fw-semibold">@item.Name</td>
|
||||
<td>@item.CompanyName</td>
|
||||
<td>@item.Phone</td>
|
||||
<td><span class="badge text-bg-secondary">@item.Status</span></td>
|
||||
<td><partial name="_StatusBadge" model="item.Status" /></td>
|
||||
<td>@item.CreatedAt.ToString("yyyy-MM-dd")</td>
|
||||
<td class="text-end">
|
||||
<a class="btn btn-sm btn-outline-secondary" href="/admin/customers/@item.Id">상세</a>
|
||||
@@ -86,5 +88,6 @@
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<partial name="_Pagination" model="new { Page = Model.CurrentPage, TotalPages = Model.TotalPages, BuildPageUrl = new Func<int, string>(Model.BuildPageUrl) }" />
|
||||
</section>
|
||||
|
||||
@@ -9,18 +9,27 @@ namespace TaxBaik.Web.Pages.Admin.Customers;
|
||||
public class IndexModel(ClientService clientService) : PageModel
|
||||
{
|
||||
public List<TaxBaik.Domain.Entities.Client> Items { get; private set; } = [];
|
||||
public int CurrentPage { get; private set; } = 1;
|
||||
public int TotalPages { get; private set; } = 1;
|
||||
public int TotalCount { get; private set; }
|
||||
|
||||
public string? Search { get; set; }
|
||||
public string? Status { get; set; }
|
||||
public int PageSize { get; set; } = 10;
|
||||
|
||||
public async Task OnGetAsync(string? search, string? status, int pageSize = 10, CancellationToken ct = default)
|
||||
public async Task OnGetAsync(string? search, string? status, int page = 1, int pageSize = 10, CancellationToken ct = default)
|
||||
{
|
||||
Search = search;
|
||||
Status = status;
|
||||
PageSize = pageSize;
|
||||
CurrentPage = Math.Max(1, page);
|
||||
|
||||
var (items, _) = await clientService.GetPagedAsync(1, pageSize, status, search, ct);
|
||||
var (items, total) = await clientService.GetPagedAsync(CurrentPage, pageSize, status, search, ct);
|
||||
Items = items.ToList();
|
||||
TotalCount = total;
|
||||
TotalPages = Math.Max(1, (int)Math.Ceiling(total / (double)pageSize));
|
||||
}
|
||||
|
||||
public string BuildPageUrl(int page) =>
|
||||
$"/admin/customers?search={Uri.EscapeDataString(Search ?? string.Empty)}&status={Uri.EscapeDataString(Status ?? string.Empty)}&page={page}&pageSize={PageSize}";
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@page "/admin/login"
|
||||
@model TaxBaik.Web.Pages.Admin.LoginModel
|
||||
@{
|
||||
Layout = null;
|
||||
ViewData["Title"] = "관리자 로그인";
|
||||
ViewData["Description"] = "관리자 로그인 페이지입니다.";
|
||||
ViewData["CanonicalUrl"] = $"{Request.Scheme}://{Request.Host}/admin/login";
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ko">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>@(ViewData["Title"] ?? "TaxBaik Admin")</title>
|
||||
<meta name="theme-color" content="#111827" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" />
|
||||
<link rel="stylesheet" href="~/css/admin.css" asp-append-version="true" />
|
||||
</head>
|
||||
<body class="admin-app">
|
||||
<partial name="_AdminTopbar" />
|
||||
<div class="admin-shell container-fluid">
|
||||
<div class="row g-0">
|
||||
<aside class="col-lg-2 admin-sidebar">
|
||||
<partial name="_AdminSidebar" />
|
||||
</aside>
|
||||
<main class="col-lg-10 admin-content">
|
||||
@RenderBody()
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" defer></script>
|
||||
@await RenderSectionAsync("Scripts", required: false)
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
@{
|
||||
Layout = "_AdminLayout";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<nav class="p-3">
|
||||
<div class="list-group list-group-flush">
|
||||
<a class="list-group-item list-group-item-action" href="/admin/dashboard">대시보드</a>
|
||||
<a class="list-group-item list-group-item-action" href="/admin/customers">고객 관리</a>
|
||||
<a class="list-group-item list-group-item-action" href="/admin/login">로그인</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<header class="admin-topbar border-bottom bg-white">
|
||||
<div class="container-fluid py-3 d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<div class="fw-semibold">TaxBaik Admin</div>
|
||||
<div class="text-muted small">Razor Pages + Cookie Authentication</div>
|
||||
</div>
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<span class="text-muted small">@User.Identity?.Name</span>
|
||||
<a class="btn btn-sm btn-outline-secondary" href="/admin/logout">로그아웃</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
@model string
|
||||
<div class="text-center text-muted py-5">
|
||||
<div class="fw-semibold mb-1">@(string.IsNullOrWhiteSpace(Model) ? "데이터가 없습니다." : Model)</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
@model dynamic
|
||||
@if (Model.TotalPages > 1)
|
||||
{
|
||||
<nav class="mt-4">
|
||||
<ul class="pagination justify-content-center">
|
||||
@for (var i = 1; i <= Model.TotalPages; i++)
|
||||
{
|
||||
<li class="page-item @(i == Model.Page ? "active" : "")">
|
||||
<a class="page-link" href="@Model.BuildPageUrl(i)">@i</a>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</nav>
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
@model string
|
||||
@{
|
||||
var badgeClass = Model?.ToLowerInvariant() switch
|
||||
{
|
||||
"active" => "text-bg-success",
|
||||
"inactive" => "text-bg-secondary",
|
||||
_ => "text-bg-light"
|
||||
};
|
||||
}
|
||||
<span class="badge @badgeClass">@Model</span>
|
||||
|
||||
Reference in New Issue
Block a user