feat: CRM Phase 1-2 완성 + 시즌 시뮬레이터 + 개인정보처리방침/이용약관
TaxBaik CI/CD / build-and-deploy (push) Successful in 55s
TaxBaik Browser E2E / browser-e2e (push) Failing after 1m53s

- WBS-CRM-02: 상담 이력 (consultations 테이블 V008, ClientDetail.razor)
- WBS-CRM-03: 문의→고객 전환 (V009 client_id FK, InquiryDetail 고객등록 버튼)
- WBS-CRM-04: 신고 일정 캘린더 (tax_filings 테이블 V010, TaxFilingList.razor)
- WBS-CRM-05: 문의 상태 5단계 확장 (V011, InquiryStatus enum, InquiryList 탭)
- WBS-MKT-04: 시즌 시뮬레이터 어드민 페이지 (SeasonSimulator.razor)
- WBS-UX-04: 개인정보처리방침 /taxbaik/privacy, 이용약관 /taxbaik/terms
- Dashboard.razor 마감 임박 신고 위젯 추가

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-28 00:01:16 +09:00
parent 9c96f15f86
commit 79492184d0
35 changed files with 1447 additions and 104 deletions
@@ -2,6 +2,7 @@
@attribute [Authorize]
@using TaxBaik.Application.Services
@inject AdminDashboardService DashboardService
@inject TaxFilingService FilingService
<PageTitle>대시보드</PageTitle>
@@ -50,6 +51,50 @@
</MudItem>
</MudGrid>
@if (upcomingFilings.Count > 0)
{
<MudPaper Class="admin-surface mt-4" Elevation="0">
<div class="admin-section-header">
<div>
<MudText Typo="Typo.h6">이번 달 마감 임박 신고</MudText>
<MudText Typo="Typo.body2">30일 이내 신고 예정 건</MudText>
</div>
<MudButton Variant="Variant.Outlined" Color="Color.Primary" Href="/taxbaik/admin/tax-filings">전체 일정 보기</MudButton>
</div>
<MudSimpleTable Striped="true" Dense="true" Class="admin-table">
<thead>
<tr>
<th>고객</th>
<th>신고 유형</th>
<th>기한</th>
<th>D-day</th>
</tr>
</thead>
<tbody>
@foreach (var f in upcomingFilings)
{
var dday = (f.DueDate.Date - DateTime.Today).Days;
<tr>
<td>@f.ClientName</td>
<td>@f.FilingType</td>
<td>@f.DueDate.ToString("yyyy-MM-dd")</td>
<td>
@if (dday <= 7)
{
<MudChip T="string" Size="Size.Small" Color="Color.Error">D-@dday</MudChip>
}
else
{
<span>D-@dday</span>
}
</td>
</tr>
}
</tbody>
</MudSimpleTable>
</MudPaper>
}
<MudPaper Class="admin-surface mt-4" Elevation="0">
<div class="admin-section-header">
<div>
@@ -76,8 +121,7 @@
<td>@inquiry.Phone</td>
<td>@inquiry.ServiceType</td>
<td>
<MudChip Size="Size.Small"
Color="@(inquiry.Status == "new" ? Color.Warning : inquiry.Status == "contacted" ? Color.Info : Color.Success)">
<MudChip T="string" Size="Size.Small" Color="@StatusColor(inquiry.Status)">
@GetStatusLabel(inquiry.Status)
</MudChip>
</td>
@@ -90,17 +134,26 @@
@code {
private AdminDashboardSummary summary = new(0, 0, 0, 0, []);
private List<Domain.Entities.TaxFiling> upcomingFilings = [];
protected override async Task OnInitializedAsync()
{
summary = await DashboardService.GetSummaryAsync();
}
var summaryTask = DashboardService.GetSummaryAsync();
var filingsTask = FilingService.GetUpcomingAsync(30);
await Task.WhenAll(summaryTask, filingsTask);
summary = await summaryTask;
upcomingFilings = (await filingsTask).ToList();
}
private static string GetStatusLabel(string status) => status switch
private static string GetStatusLabel(string status) => InquiryStatusMapper.Labels.GetValueOrDefault(status, status);
private static Color StatusColor(string status) => status switch
{
"new" => "신규",
"contacted" => "연락함",
"completed" => "완료",
_ => status
"new" => Color.Warning,
"consulting" => Color.Info,
"contracted" => Color.Success,
"rejected" => Color.Error,
"closed" => Color.Dark,
_ => Color.Default
};
}