feat: WBS-UX-03 FAQ 관리 기능 구현 — 어드민 CRUD + 홈페이지 DB 연동
DB: - V007__CreateFaqs.sql: faqs 테이블 (question, answer, category, sort_order, is_active) + 기본 FAQ 4개 시드 Domain: - Faq 엔티티 - IFaqRepository (GetActiveAsync, GetAllAsync, CRUD) Infrastructure: - FaqRepository: sort_order 정렬, CRUD Application: - FaqService: Categories 상수, Validate (질문·답변 필수) Admin UI (Blazor): - FaqList.razor: 전체 목록, 활성/비활성 상태 칩, 삭제 확인 - FaqEdit.razor: 질문/답변/카테고리/순서/활성 토글 폼 - MainLayout: 홈페이지 그룹 하위에 FAQ 관리 메뉴 추가 홈페이지: - Index.cshtml 하드코딩 FAQ → ActiveFaqs DB 루프로 교체 - FAQ 없으면 섹션 전체 숨김 (빈 DB에 안전) - IndexModel: FaqService 주입, Task.WhenAll 병렬 로드 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -10,35 +10,42 @@ public class IndexModel : PageModel
|
||||
private readonly BlogService _blogService;
|
||||
private readonly SeasonalMarketingService _seasonalMarketingService;
|
||||
private readonly AnnouncementService _announcementService;
|
||||
private readonly FaqService _faqService;
|
||||
|
||||
public List<BlogPost> RecentPosts { get; set; } = [];
|
||||
public List<BlogPost> SeasonalPosts { get; set; } = [];
|
||||
public CurrentSeasonDto? CurrentSeason { get; set; }
|
||||
public List<Announcement> ActiveAnnouncements { get; set; } = [];
|
||||
public List<Faq> ActiveFaqs { get; set; } = [];
|
||||
|
||||
public IndexModel(
|
||||
BlogService blogService,
|
||||
SeasonalMarketingService seasonalMarketingService,
|
||||
AnnouncementService announcementService)
|
||||
AnnouncementService announcementService,
|
||||
FaqService faqService)
|
||||
{
|
||||
_blogService = blogService;
|
||||
_seasonalMarketingService = seasonalMarketingService;
|
||||
_announcementService = announcementService;
|
||||
_faqService = faqService;
|
||||
}
|
||||
|
||||
public async Task OnGetAsync()
|
||||
{
|
||||
CurrentSeason = _seasonalMarketingService.GetCurrentSeason();
|
||||
|
||||
try
|
||||
{
|
||||
ActiveAnnouncements = (await _announcementService.GetActiveAsync()).ToList();
|
||||
}
|
||||
catch
|
||||
{
|
||||
ActiveAnnouncements = [];
|
||||
}
|
||||
var announcementsTask = LoadSafeAsync(() => _announcementService.GetActiveAsync());
|
||||
var faqsTask = LoadSafeAsync(() => _faqService.GetActiveAsync());
|
||||
var blogTask = LoadBlogAsync();
|
||||
|
||||
await Task.WhenAll(announcementsTask, faqsTask, blogTask);
|
||||
|
||||
ActiveAnnouncements = (await announcementsTask)?.ToList() ?? [];
|
||||
ActiveFaqs = (await faqsTask)?.ToList() ?? [];
|
||||
}
|
||||
|
||||
private async Task LoadBlogAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (CurrentSeason is not null && !string.IsNullOrEmpty(CurrentSeason.RelatedCategorySlug))
|
||||
@@ -60,4 +67,10 @@ public class IndexModel : PageModel
|
||||
SeasonalPosts = [];
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<IEnumerable<T>?> LoadSafeAsync<T>(Func<Task<IEnumerable<T>>> loader)
|
||||
{
|
||||
try { return await loader(); }
|
||||
catch { return null; }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user