diff --git a/TaxBaik.Web/Components/Admin/Pages/Announcements/AnnouncementList.razor b/TaxBaik.Web/Components/Admin/Pages/Announcements/AnnouncementList.razor index df47db0..2d17888 100644 --- a/TaxBaik.Web/Components/Admin/Pages/Announcements/AnnouncementList.razor +++ b/TaxBaik.Web/Components/Admin/Pages/Announcements/AnnouncementList.razor @@ -22,14 +22,22 @@ +
+ +
+ @if (announcements is null) { } - else if (!announcements.Any()) + else if (!FilteredAnnouncements.Any()) { - 등록된 공지사항이 없습니다. +
+ + 검색 조건에 맞는 공지사항이 없습니다. +
} else { @@ -45,7 +53,7 @@ - @foreach (var item in announcements) + @foreach (var item in FilteredAnnouncements) { @item.Title @@ -86,6 +94,9 @@ } + + 검색 결과 @(FilteredAnnouncements.Count())개 · 총 @(announcements.Count)개 + }
@@ -94,6 +105,12 @@ private Task? AuthStateTask { get; set; } private List? announcements; + private string searchQuery = ""; + + private IEnumerable FilteredAnnouncements => announcements? + .Where(a => string.IsNullOrEmpty(searchQuery) || + a.Title.Contains(searchQuery, StringComparison.OrdinalIgnoreCase)) + .OrderBy(a => a.SortOrder) ?? Enumerable.Empty(); protected override async Task OnAfterRenderAsync(bool firstRender) { diff --git a/TaxBaik.Web/Components/Admin/Pages/Blog/BlogCreate.razor b/TaxBaik.Web/Components/Admin/Pages/Blog/BlogCreate.razor index 5999b08..d91a271 100644 --- a/TaxBaik.Web/Components/Admin/Pages/Blog/BlogCreate.razor +++ b/TaxBaik.Web/Components/Admin/Pages/Blog/BlogCreate.razor @@ -21,8 +21,8 @@ - + @@ -32,8 +32,24 @@ } - + + + + + +
+ @if (string.IsNullOrWhiteSpace(model.Content)) + { +

작성 중인 본문 내용이 이곳에 실시간으로 표시됩니다.

+ } + else + { + @((MarkupString)model.Content) + } +
+
+
diff --git a/TaxBaik.Web/Components/Admin/Pages/Blog/BlogEdit.razor b/TaxBaik.Web/Components/Admin/Pages/Blog/BlogEdit.razor index de0d296..0e51b92 100644 --- a/TaxBaik.Web/Components/Admin/Pages/Blog/BlogEdit.razor +++ b/TaxBaik.Web/Components/Admin/Pages/Blog/BlogEdit.razor @@ -32,8 +32,8 @@ else { - + @@ -43,8 +43,24 @@ else } - + + + + + +
+ @if (string.IsNullOrWhiteSpace(model.Content)) + { +

작성 중인 본문 내용이 이곳에 실시간으로 표시됩니다.

+ } + else + { + @((MarkupString)model.Content) + } +
+
+
diff --git a/TaxBaik.Web/Components/Admin/Pages/Blog/BlogList.razor b/TaxBaik.Web/Components/Admin/Pages/Blog/BlogList.razor index d8d982d..0a480a2 100644 --- a/TaxBaik.Web/Components/Admin/Pages/Blog/BlogList.razor +++ b/TaxBaik.Web/Components/Admin/Pages/Blog/BlogList.razor @@ -15,14 +15,19 @@ Href="/taxbaik/admin/blog/create">새 포스트 작성 +
+ +
+ - @($"전체 포스트 {totalPosts}개") + @($"검색 결과 {FilteredPosts.Count()}개 / 전체 포스트 {totalPosts}개") 페이지 @currentPage / @totalPages - + @@ -54,12 +59,18 @@ private Task? AuthStateTask { get; set; } private List posts = []; + private string searchQuery = ""; private bool isLoading = true; private int currentPage = 1; private int totalPages = 1; private int totalPosts = 0; private const int PageSize = 20; + private IEnumerable FilteredPosts => posts? + .Where(p => string.IsNullOrEmpty(searchQuery) || + p.Title.Contains(searchQuery, StringComparison.OrdinalIgnoreCase) || + (p.Content != null && p.Content.Contains(searchQuery, StringComparison.OrdinalIgnoreCase))) ?? Enumerable.Empty(); + protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) diff --git a/TaxBaik.Web/Components/Admin/Pages/Faqs/FaqList.razor b/TaxBaik.Web/Components/Admin/Pages/Faqs/FaqList.razor index 678d87b..8b9ecab 100644 --- a/TaxBaik.Web/Components/Admin/Pages/Faqs/FaqList.razor +++ b/TaxBaik.Web/Components/Admin/Pages/Faqs/FaqList.razor @@ -22,16 +22,21 @@ +
+ +
+ @if (faqs is null) { } - else if (!faqs.Any()) + else if (!FilteredFaqs.Any()) {
- 등록된 FAQ가 없습니다. + 검색 조건에 맞는 FAQ가 없습니다.
} else @@ -39,7 +44,7 @@ - 순서 + 순서 질문 카테고리 상태 @@ -47,11 +52,15 @@ - @foreach (var item in faqs) + @foreach (var item in FilteredFaqs) { - - @item.SortOrder + +
+ @item.SortOrder + + +
@@ -77,10 +86,10 @@ - 수정 + 수정 - 삭제 + 삭제 @@ -89,7 +98,7 @@
- 총 @(faqs.Count)개 · 노출 중 @(faqs.Count(f => f.IsActive))개 + 검색 결과 @(FilteredFaqs.Count())개 · 총 @(faqs.Count)개 · 노출 중 @(faqs.Count(f => f.IsActive))개 }
@@ -99,6 +108,13 @@ private Task? AuthStateTask { get; set; } private List? faqs; + private string searchQuery = ""; + + 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 OnAfterRenderAsync(bool firstRender) { @@ -120,7 +136,7 @@ { try { - faqs = (await FaqClient.GetAllAsync()).ToList(); + faqs = (await FaqClient.GetAllAsync()).OrderBy(f => f.SortOrder).ToList(); } catch (Exception ex) { @@ -129,6 +145,66 @@ } } + 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(