121 lines
3.8 KiB
Plaintext
121 lines
3.8 KiB
Plaintext
@page "/admin/faqs"
|
|
@attribute [Authorize]
|
|
@using TaxBaik.Web.Services
|
|
@using TaxBaik.Domain.Entities
|
|
@inject IFaqBrowserClient FaqClient
|
|
@inject NavigationManager Navigation
|
|
@inject IJSRuntime JS
|
|
|
|
<PageTitle>FAQ 관리</PageTitle>
|
|
|
|
<section class="admin-page-hero">
|
|
<div>
|
|
<div class="admin-eyebrow">홈페이지</div>
|
|
<h1 class="admin-page-title">FAQ 관리</h1>
|
|
<p class="admin-page-subtitle">홈페이지 자주 묻는 질문을 등록하고 순서를 관리합니다.</p>
|
|
</div>
|
|
<a class="site-button primary" href="/taxbaik/admin/faqs/create">FAQ 등록</a>
|
|
</section>
|
|
|
|
<div class="admin-surface">
|
|
@if (faqs is null)
|
|
{
|
|
<Skeleton Count="5" CssClass="taxbaik-skeleton-grid" />
|
|
}
|
|
else if (!faqs.Any())
|
|
{
|
|
<div class="muted">등록된 FAQ가 없습니다.</div>
|
|
}
|
|
else
|
|
{
|
|
<div class="admin-table-wrap">
|
|
<table class="admin-table">
|
|
<thead>
|
|
<tr>
|
|
<th>순서</th>
|
|
<th>질문</th>
|
|
<th>카테고리</th>
|
|
<th>상태</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach (var item in faqs)
|
|
{
|
|
<tr>
|
|
<td>@item.SortOrder</td>
|
|
<td>@item.Question</td>
|
|
<td>@(string.IsNullOrEmpty(item.Category) ? "" : item.Category)</td>
|
|
<td><span class="status-pill @(item.IsActive ? "success" : "default")">@(item.IsActive ? "노출 중" : "비활성")</span></td>
|
|
<td>
|
|
<div class="admin-actions">
|
|
<button type="button" class="admin-icon-button" @onclick="@(() => Navigation.NavigateTo($"/taxbaik/admin/faqs/{item.Id}/edit"))">✎</button>
|
|
<button type="button" class="admin-icon-button danger" @onclick="@(() => DeleteAsync(item))">✕</button>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<div class="muted mt-2">총 @(faqs.Count)개 · 노출 중 @(faqs.Count(f => f.IsActive))개</div>
|
|
}
|
|
</div>
|
|
|
|
@code {
|
|
[CascadingParameter]
|
|
private Task<AuthenticationState>? AuthStateTask { get; set; }
|
|
|
|
private List<Faq>? faqs;
|
|
|
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
|
{
|
|
if (firstRender && AuthStateTask != null)
|
|
{
|
|
var authState = await AuthStateTask;
|
|
if (authState.User.Identity?.IsAuthenticated == true)
|
|
{
|
|
await LoadAsync();
|
|
StateHasChanged();
|
|
}
|
|
}
|
|
}
|
|
|
|
private async Task LoadAsync()
|
|
{
|
|
try
|
|
{
|
|
faqs = (await FaqClient.GetAllAsync()).ToList();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await JS.InvokeVoidAsync("alert", $"오류: {ex.Message}");
|
|
faqs = [];
|
|
}
|
|
}
|
|
|
|
private async Task DeleteAsync(Faq item)
|
|
{
|
|
var confirmed = await JS.InvokeAsync<bool>("confirm", $"'{item.Question}' 항목을 삭제하시겠습니까?");
|
|
if (!confirmed) return;
|
|
|
|
try
|
|
{
|
|
var success = await FaqClient.DeleteAsync(item.Id);
|
|
if (success)
|
|
{
|
|
await JS.InvokeVoidAsync("alert", "FAQ가 삭제되었습니다.");
|
|
await LoadAsync();
|
|
}
|
|
else
|
|
{
|
|
await JS.InvokeVoidAsync("alert", "삭제 실패");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await JS.InvokeVoidAsync("alert", $"오류: {ex.Message}");
|
|
}
|
|
}
|
|
}
|