cc72a67355
- 연간 세무 캘린더(7개 시즌) 기반 자동 Hero 섹션 전환 - 시즌 감지 시 D-Day 카운트다운, 긴박감 배지, 시즌 CTA 표시 - 서비스 카드 순서 시즌 관련 항목 우선 정렬 - 어드민 공지사항 CRUD (등록·수정·삭제, 기간·유형 설정) - 홈페이지 상단 공지 배너 자동 노출 (일반/배너/긴급) - CLAUDE.md에 세무 캘린더 및 마케팅 방향 하네스 추가 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
149 lines
5.1 KiB
Plaintext
149 lines
5.1 KiB
Plaintext
@page "/admin/announcements"
|
|
@attribute [Authorize]
|
|
@using TaxBaik.Application.Services
|
|
@using TaxBaik.Domain.Entities
|
|
@inject AnnouncementService AnnouncementService
|
|
@inject NavigationManager Navigation
|
|
@inject IDialogService DialogService
|
|
@inject ISnackbar Snackbar
|
|
|
|
<PageTitle>공지사항 관리</PageTitle>
|
|
|
|
<section class="admin-page-hero">
|
|
<div>
|
|
<MudText Typo="Typo.caption" Class="admin-eyebrow">Homepage</MudText>
|
|
<MudText Typo="Typo.h4" Class="admin-page-title">공지사항 관리</MudText>
|
|
<MudText Typo="Typo.body2" Class="admin-page-subtitle">홈페이지 상단에 노출되는 공지사항을 등록하고 관리합니다.</MudText>
|
|
</div>
|
|
<MudButton Variant="Variant.Filled" Color="Color.Primary"
|
|
StartIcon="@Icons.Material.Filled.Add"
|
|
Href="/taxbaik/admin/announcements/create">
|
|
공지 등록
|
|
</MudButton>
|
|
</section>
|
|
|
|
<MudPaper Class="admin-surface" Elevation="0">
|
|
@if (announcements is null)
|
|
{
|
|
<MudProgressLinear Indeterminate="true" />
|
|
}
|
|
else if (!announcements.Any())
|
|
{
|
|
<MudText Class="pa-4 text-muted">등록된 공지사항이 없습니다.</MudText>
|
|
}
|
|
else
|
|
{
|
|
<MudSimpleTable Striped="true" Dense="true" Class="admin-table">
|
|
<thead>
|
|
<tr>
|
|
<th>제목</th>
|
|
<th>유형</th>
|
|
<th>상태</th>
|
|
<th>게시 기간</th>
|
|
<th>순서</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach (var item in announcements)
|
|
{
|
|
<tr>
|
|
<td>@item.Title</td>
|
|
<td>
|
|
<MudChip Size="Size.Small" Color="@GetTypeColor(item.DisplayType)">
|
|
@GetTypeLabel(item.DisplayType)
|
|
</MudChip>
|
|
</td>
|
|
<td>
|
|
@if (IsCurrentlyActive(item))
|
|
{
|
|
<MudChip Size="Size.Small" Color="Color.Success">노출 중</MudChip>
|
|
}
|
|
else if (!item.IsActive)
|
|
{
|
|
<MudChip Size="Size.Small" Color="Color.Default">비활성</MudChip>
|
|
}
|
|
else
|
|
{
|
|
<MudChip Size="Size.Small" Color="Color.Warning">기간 외</MudChip>
|
|
}
|
|
</td>
|
|
<td class="small">
|
|
@FormatPeriod(item)
|
|
</td>
|
|
<td>@item.SortOrder</td>
|
|
<td>
|
|
<MudButtonGroup Size="Size.Small" Variant="Variant.Outlined">
|
|
<MudButton @onclick="@(() => Navigation.NavigateTo($"/taxbaik/admin/announcements/{item.Id}/edit"))">
|
|
수정
|
|
</MudButton>
|
|
<MudButton Color="Color.Error" @onclick="@(() => DeleteAsync(item))">
|
|
삭제
|
|
</MudButton>
|
|
</MudButtonGroup>
|
|
</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</MudSimpleTable>
|
|
}
|
|
</MudPaper>
|
|
|
|
@code {
|
|
private List<Announcement>? announcements;
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
await LoadAsync();
|
|
}
|
|
|
|
private async Task LoadAsync()
|
|
{
|
|
announcements = (await AnnouncementService.GetAllAsync()).ToList();
|
|
}
|
|
|
|
private async Task DeleteAsync(Announcement item)
|
|
{
|
|
var confirmed = await DialogService.ShowMessageBox(
|
|
"공지 삭제",
|
|
$"'{item.Title}' 공지를 삭제하시겠습니까?",
|
|
yesText: "삭제", cancelText: "취소");
|
|
|
|
if (confirmed != true) return;
|
|
|
|
await AnnouncementService.DeleteAsync(item.Id);
|
|
Snackbar.Add("공지사항이 삭제되었습니다.", Severity.Success);
|
|
await LoadAsync();
|
|
}
|
|
|
|
private static bool IsCurrentlyActive(Announcement a)
|
|
{
|
|
if (!a.IsActive) return false;
|
|
var now = DateTime.UtcNow;
|
|
if (a.StartsAt.HasValue && a.StartsAt > now) return false;
|
|
if (a.EndsAt.HasValue && a.EndsAt < now) return false;
|
|
return true;
|
|
}
|
|
|
|
private static string FormatPeriod(Announcement a)
|
|
{
|
|
var start = a.StartsAt?.ToLocalTime().ToString("MM/dd") ?? "즉시";
|
|
var end = a.EndsAt?.ToLocalTime().ToString("MM/dd") ?? "무기한";
|
|
return $"{start} ~ {end}";
|
|
}
|
|
|
|
private static Color GetTypeColor(string type) => type switch
|
|
{
|
|
"urgent" => Color.Error,
|
|
"banner" => Color.Warning,
|
|
_ => Color.Info
|
|
};
|
|
|
|
private static string GetTypeLabel(string type) => type switch
|
|
{
|
|
"urgent" => "긴급",
|
|
"banner" => "배너",
|
|
_ => "일반"
|
|
};
|
|
}
|