139 lines
6.0 KiB
Plaintext
139 lines
6.0 KiB
Plaintext
@page "/admin/season-simulator"
|
|
@attribute [Authorize]
|
|
@using TaxBaik.Application.Seasonal
|
|
@using TaxBaik.Application.Services
|
|
|
|
<PageTitle>시즌 시뮬레이터</PageTitle>
|
|
|
|
<section class="admin-page-hero">
|
|
<div>
|
|
<div class="admin-eyebrow">Season Preview</div>
|
|
<h1 class="admin-page-title">시즌 시뮬레이터</h1>
|
|
<p class="admin-page-subtitle">날짜를 선택해 홈페이지 시즌 화면이 어떻게 보이는지 미리 확인합니다.</p>
|
|
</div>
|
|
</section>
|
|
|
|
<div class="admin-detail-grid">
|
|
<section class="admin-surface">
|
|
<h3 class="admin-section-title">시뮬레이션 날짜</h3>
|
|
<input class="admin-input" type="text" placeholder="yyyy-MM-dd" @bind="SimulationDateText" />
|
|
<div class="admin-divider"></div>
|
|
<div class="admin-stack">
|
|
@foreach (var season in TaxSeasonCalendar.Seasons)
|
|
{
|
|
<button type="button" class="site-button secondary" @onclick="@(() => JumpToSeason(season))">@season.StartMonth/@season.StartDay - @season.Name</button>
|
|
}
|
|
</div>
|
|
</section>
|
|
|
|
<section class="admin-surface">
|
|
<h3 class="admin-section-title">홈페이지 미리보기</h3>
|
|
<p class="muted">@(simulationDate?.ToString("yyyy년 MM월 dd일") ?? "날짜를 선택하세요")</p>
|
|
@if (activeSeason != null)
|
|
{
|
|
<span class="status-pill warning">@activeSeason.Name 시즌 활성</span>
|
|
<div class="season-preview">
|
|
@if (activeSeason.DaysUntilDeadline <= 7 && activeSeason.DaysUntilDeadline >= 0)
|
|
{
|
|
<div class="season-badge">D-@activeSeason.DaysUntilDeadline 마감 임박</div>
|
|
}
|
|
<div class="season-headline">@activeSeason.HeroHeadline</div>
|
|
<div class="season-subtext">@activeSeason.HeroSubtext</div>
|
|
<div class="season-cta">@activeSeason.CtaText</div>
|
|
</div>
|
|
<div class="admin-kv-grid mt-4">
|
|
<div><span>활성 시즌 키</span><strong><code>@activeSeason.Key</code></strong></div>
|
|
<div><span>마감까지</span><strong>@(activeSeason.DaysUntilDeadline >= 0 ? $"D-{activeSeason.DaysUntilDeadline}" : $"마감 후 @(-activeSeason.DaysUntilDeadline)일")</strong></div>
|
|
<div><span>포커스 서비스</span><strong>@activeSeason.FocusService</strong></div>
|
|
<div><span>블로그 카테고리</span><strong>@activeSeason.RelatedCategorySlug</strong></div>
|
|
<div class="span-2"><span>긴박감 배지 문구</span><strong><code>@activeSeason.UrgencyBadge</code></strong></div>
|
|
</div>
|
|
}
|
|
else
|
|
{
|
|
<div class="muted">선택한 날짜는 시즌 비활성 기간입니다. 홈페이지는 기본 Hero를 표시합니다.</div>
|
|
<div class="season-preview mt-4">
|
|
<div class="season-headline">사업자 세금, 부동산,<br />가족자산까지</div>
|
|
<div class="season-subtext">세무사·부동산중개사·보험설계사 자격 보유 | 온라인 맞춤 상담</div>
|
|
<div class="season-cta">무료 상담 신청</div>
|
|
</div>
|
|
}
|
|
</section>
|
|
</div>
|
|
|
|
<div class="admin-surface mt-4">
|
|
<h3 class="admin-section-title">연간 시즌 타임라인</h3>
|
|
<div class="admin-table-wrap">
|
|
<table class="admin-table">
|
|
<thead>
|
|
<tr>
|
|
<th>기간</th>
|
|
<th>시즌</th>
|
|
<th>블로그 카테고리</th>
|
|
<th>상태</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach (var s in TaxSeasonCalendar.Seasons)
|
|
{
|
|
var isActive = activeSeason?.Key == s.Key;
|
|
<tr>
|
|
<td>@s.StartMonth/@s.StartDay ~ @s.EndMonth/@s.EndDay</td>
|
|
<td>@s.Name</td>
|
|
<td><code>@s.RelatedCategorySlug</code></td>
|
|
<td>@(isActive ? "활성" : "비활성")</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
@code {
|
|
private DateTime? simulationDate = DateTime.Today;
|
|
private CurrentSeasonDto? activeSeason;
|
|
private string SimulationDateText { get => simulationDate?.ToString("yyyy-MM-dd") ?? ""; set { simulationDate = DateTime.TryParse(value, out var dt) ? dt : null; ComputeSeason(); } }
|
|
|
|
protected override void OnInitialized() => ComputeSeason();
|
|
|
|
private void ComputeSeason()
|
|
{
|
|
if (simulationDate == null) { activeSeason = null; return; }
|
|
var date = simulationDate.Value;
|
|
var season = TaxSeasonCalendar.Seasons.FirstOrDefault(s =>
|
|
{
|
|
var start = new DateTime(date.Year, s.StartMonth, s.StartDay);
|
|
var endYear = (s.EndMonth < s.StartMonth) ? date.Year + 1 : date.Year;
|
|
var end = new DateTime(endYear, s.EndMonth, s.EndDay);
|
|
return date >= start && date <= end;
|
|
});
|
|
|
|
if (season == null) { activeSeason = null; return; }
|
|
|
|
var endYearCalc = (season.EndMonth < season.StartMonth) ? date.Year + 1 : date.Year;
|
|
var deadline = new DateTime(endYearCalc, season.EndMonth, season.EndDay);
|
|
var ddays = (deadline.Date - date.Date).Days;
|
|
var badge = ddays <= 7 && ddays >= 0 ? season.UrgencyBadge.Replace("{n}", ddays.ToString()) : season.UrgencyBadge;
|
|
|
|
activeSeason = new CurrentSeasonDto
|
|
{
|
|
Key = season.Key,
|
|
Name = season.Name,
|
|
HeroHeadline = season.HeroHeadline,
|
|
HeroSubtext = season.HeroSubtext,
|
|
UrgencyBadge = badge,
|
|
FocusService = season.FocusService,
|
|
RelatedCategorySlug = season.RelatedCategorySlug,
|
|
CtaText = season.CtaText,
|
|
DaysUntilDeadline = ddays,
|
|
Deadline = deadline
|
|
};
|
|
}
|
|
|
|
private void JumpToSeason(TaxSeason season)
|
|
{
|
|
simulationDate = new DateTime(DateTime.Today.Year, season.StartMonth, season.StartDay);
|
|
ComputeSeason();
|
|
}
|
|
}
|