@page "/admin/faqs" @attribute [Authorize] @using TaxBaik.Web.Services @using TaxBaik.Domain.Entities @inject IFaqBrowserClient FaqClient @inject NavigationManager Navigation @inject IDialogService DialogService @inject ISnackbar Snackbar FAQ 관리
홈페이지 FAQ 관리 홈페이지 자주 묻는 질문을 등록하고 순서를 관리합니다.
FAQ 등록
@if (faqs is null) { } else if (!FilteredFaqs.Any()) {
검색 조건에 맞는 FAQ가 없습니다.
} else { 순서 질문 카테고리 상태 @foreach (var item in FilteredFaqs) {
@item.SortOrder
@item.Question @if (!string.IsNullOrEmpty(item.Category)) { @item.Category } @if (item.IsActive) { 노출 중 } else { 비활성 } 수정 삭제 }
검색 결과 @(FilteredFaqs.Count())개 · 총 @(faqs.Count)개 · 노출 중 @(faqs.Count(f => f.IsActive))개 }
@code { [CascadingParameter] private Task? AuthStateTask { get; set; } private List? faqs; private string searchQuery = ""; private RenderFragment FaqListSkeleton => builder => { builder.OpenComponent(0); builder.AddAttribute(1, "Rows", 5); builder.AddAttribute(2, "Columns", 4); builder.CloseComponent(); }; private IEnumerable FilteredFaqs => faqs? .Where(f => string.IsNullOrEmpty(searchQuery) || f.Question.Contains(searchQuery, StringComparison.OrdinalIgnoreCase) || (f.Answer != null && f.Answer.Contains(searchQuery, StringComparison.OrdinalIgnoreCase))) .OrderBy(f => f.SortOrder) ?? Enumerable.Empty(); protected override async Task OnInitializedAsync() { if (AuthStateTask != null) { var authState = await AuthStateTask; if (authState.User.Identity?.IsAuthenticated == true) { await LoadAsync(); } } } private async Task LoadAsync() { try { faqs = (await FaqClient.GetAllAsync()).OrderBy(f => f.SortOrder).ToList(); } catch (Exception ex) { Snackbar.Add($"오류: {ex.Message}", Severity.Error); faqs = []; } } private async Task MoveUpAsync(Faq item) { if (faqs == null) return; var sorted = faqs.OrderBy(f => f.SortOrder).ToList(); var index = sorted.IndexOf(item); if (index <= 0) return; var prev = sorted[index - 1]; var temp = item.SortOrder; item.SortOrder = prev.SortOrder; prev.SortOrder = temp; if (item.SortOrder == prev.SortOrder) { prev.SortOrder = item.SortOrder + 1; } try { await FaqClient.UpdateAsync(item.Id, item); await FaqClient.UpdateAsync(prev.Id, prev); Snackbar.Add("순서가 상향되었습니다.", Severity.Success); await LoadAsync(); } catch (Exception ex) { Snackbar.Add($"순서 조정 실패: {ex.Message}", Severity.Error); } } private async Task MoveDownAsync(Faq item) { if (faqs == null) return; var sorted = faqs.OrderBy(f => f.SortOrder).ToList(); var index = sorted.IndexOf(item); if (index < 0 || index >= sorted.Count - 1) return; var next = sorted[index + 1]; var temp = item.SortOrder; item.SortOrder = next.SortOrder; next.SortOrder = temp; if (item.SortOrder == next.SortOrder) { next.SortOrder = item.SortOrder + 1; } try { await FaqClient.UpdateAsync(item.Id, item); await FaqClient.UpdateAsync(next.Id, next); Snackbar.Add("순서가 하향되었습니다.", Severity.Success); await LoadAsync(); } catch (Exception ex) { Snackbar.Add($"순서 조정 실패: {ex.Message}", Severity.Error); } } private async Task DeleteAsync(Faq item) { var confirmed = await DialogService.ShowMessageBox( "FAQ 삭제", $"'{item.Question}' 항목을 삭제하시겠습니까?", yesText: "삭제", cancelText: "취소"); if (confirmed != true) return; try { var success = await FaqClient.DeleteAsync(item.Id); if (success) { Snackbar.Add("FAQ가 삭제되었습니다.", Severity.Success); await LoadAsync(); } else { Snackbar.Add("삭제 실패", Severity.Error); } } catch (Exception ex) { Snackbar.Add($"오류: {ex.Message}", Severity.Error); } } }