Files
kjh2064 ccba017e3e 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>
2026-06-27 23:39:59 +09:00

43 lines
1.4 KiB
C#

namespace TaxBaik.Application.Services;
using TaxBaik.Domain.Entities;
using TaxBaik.Domain.Interfaces;
public class FaqService(IFaqRepository repository)
{
public static readonly string[] Categories =
["기장·세금신고", "부동산", "증여·상속", "기타"];
public async Task<IEnumerable<Faq>> GetActiveAsync(CancellationToken ct = default) =>
await repository.GetActiveAsync(ct);
public async Task<IEnumerable<Faq>> GetAllAsync(CancellationToken ct = default) =>
await repository.GetAllAsync(ct);
public async Task<Faq?> GetByIdAsync(int id, CancellationToken ct = default) =>
await repository.GetByIdAsync(id, ct);
public async Task<int> CreateAsync(Faq faq, CancellationToken ct = default)
{
Validate(faq);
return await repository.CreateAsync(faq, ct);
}
public async Task UpdateAsync(Faq faq, CancellationToken ct = default)
{
Validate(faq);
await repository.UpdateAsync(faq, ct);
}
public async Task DeleteAsync(int id, CancellationToken ct = default) =>
await repository.DeleteAsync(id, ct);
private static void Validate(Faq faq)
{
if (string.IsNullOrWhiteSpace(faq.Question))
throw new ValidationException("질문을 입력하세요.");
if (string.IsNullOrWhiteSpace(faq.Answer))
throw new ValidationException("답변을 입력하세요.");
}
}