revert: rollback Fluent UI and Blazor homepage to last successful state (3be3794)
This commit is contained in:
@@ -1,66 +1,60 @@
|
||||
@using TaxBaik.Web.Services
|
||||
@using TaxBaik.Domain.Entities
|
||||
@inject ITaxFilingBrowserClient FilingClient
|
||||
@inject IJSRuntime JS
|
||||
@inject ISnackbar Snackbar
|
||||
|
||||
@if (Filings == null || Filings.Count == 0)
|
||||
{
|
||||
<div class="muted">항목이 없습니다.</div>
|
||||
<MudText Class="pa-4" Color="Color.Secondary">항목이 없습니다.</MudText>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="admin-table-wrap">
|
||||
<table class="admin-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>고객</th>
|
||||
<th>신고 유형</th>
|
||||
<th>기한</th>
|
||||
<th>D-day</th>
|
||||
<th>메모</th>
|
||||
<th>처리</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var filing in Filings)
|
||||
{
|
||||
var dday = (filing.DueDate.Date - DateTime.Today).Days;
|
||||
<tr>
|
||||
<td>@filing.ClientName</td>
|
||||
<td>@filing.FilingType</td>
|
||||
<td>@filing.DueDate.ToString("yyyy-MM-dd")</td>
|
||||
<td>
|
||||
@if (dday < 0)
|
||||
{
|
||||
<span class="status-pill danger">D+@(-dday)</span>
|
||||
}
|
||||
else if (dday <= 7)
|
||||
{
|
||||
<span class="status-pill warning">D-@dday</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span>D-@dday</span>
|
||||
}
|
||||
</td>
|
||||
<td>@(filing.Memo ?? "")</td>
|
||||
<td>
|
||||
<div class="admin-row-actions">
|
||||
@if (filing.Status == "pending")
|
||||
{
|
||||
<button type="button" class="site-button secondary" @onclick="@(() => MarkFiled(filing))">완료</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="status-pill success">완료</span>
|
||||
}
|
||||
<button type="button" class="admin-icon-button danger" @onclick="@(() => DeleteFiling(filing.Id))">✕</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<MudTable Items="Filings" Hover="true" Dense="true" Class="mt-2">
|
||||
<HeaderContent>
|
||||
<MudTh>고객</MudTh>
|
||||
<MudTh>신고 유형</MudTh>
|
||||
<MudTh>기한</MudTh>
|
||||
<MudTh>D-day</MudTh>
|
||||
<MudTh>메모</MudTh>
|
||||
<MudTh>처리</MudTh>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd>@context.ClientName</MudTd>
|
||||
<MudTd>@context.FilingType</MudTd>
|
||||
<MudTd>@context.DueDate.ToString("yyyy-MM-dd")</MudTd>
|
||||
<MudTd>
|
||||
@{
|
||||
var dday = (context.DueDate.Date - DateTime.Today).Days;
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@if (dday < 0)
|
||||
{
|
||||
<MudChip T="string" Size="Size.Small" Color="Color.Error">D+@(-dday)</MudChip>
|
||||
}
|
||||
else if (dday <= 7)
|
||||
{
|
||||
<MudChip T="string" Size="Size.Small" Color="Color.Warning">D-@dday</MudChip>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudText Typo="Typo.body2">D-@dday</MudText>
|
||||
}
|
||||
</MudTd>
|
||||
<MudTd>@(context.Memo ?? "")</MudTd>
|
||||
<MudTd>
|
||||
@if (context.Status == "pending")
|
||||
{
|
||||
<MudButton Size="Size.Small" Variant="Variant.Filled" Color="Color.Success"
|
||||
OnClick="@(() => MarkFiled(context))">완료</MudButton>
|
||||
}
|
||||
else if (context.Status == "filed")
|
||||
{
|
||||
<MudChip T="string" Size="Size.Small" Color="Color.Success">완료</MudChip>
|
||||
}
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Delete" Size="Size.Small" Color="Color.Error"
|
||||
OnClick="@(() => DeleteFiling(context.Id))" />
|
||||
</MudTd>
|
||||
</RowTemplate>
|
||||
</MudTable>
|
||||
}
|
||||
|
||||
@code {
|
||||
@@ -72,33 +66,44 @@ else
|
||||
|
||||
private async Task MarkFiled(TaxFiling filing)
|
||||
{
|
||||
filing.Status = "filed";
|
||||
var result = await FilingClient.UpdateAsync(filing.Id, filing);
|
||||
if (result != null)
|
||||
try
|
||||
{
|
||||
await JS.InvokeVoidAsync("alert", "신고 완료 처리되었습니다.");
|
||||
await OnStatusChange.InvokeAsync();
|
||||
filing.Status = "filed";
|
||||
var result = await FilingClient.UpdateAsync(filing.Id, filing);
|
||||
if (result != null)
|
||||
{
|
||||
Snackbar.Add("신고 완료 처리되었습니다.", Severity.Success);
|
||||
await OnStatusChange.InvokeAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
Snackbar.Add("처리 실패", Severity.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (Exception ex)
|
||||
{
|
||||
await JS.InvokeVoidAsync("alert", "처리 실패");
|
||||
Snackbar.Add($"오류: {ex.Message}", Severity.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DeleteFiling(int id)
|
||||
{
|
||||
var confirmed = await JS.InvokeAsync<bool>("confirm", "이 항목을 삭제하시겠습니까?");
|
||||
if (!confirmed) return;
|
||||
|
||||
var success = await FilingClient.DeleteAsync(id);
|
||||
if (success)
|
||||
try
|
||||
{
|
||||
await JS.InvokeVoidAsync("alert", "삭제되었습니다.");
|
||||
await OnStatusChange.InvokeAsync();
|
||||
var success = await FilingClient.DeleteAsync(id);
|
||||
if (success)
|
||||
{
|
||||
Snackbar.Add("삭제되었습니다.", Severity.Info);
|
||||
await OnStatusChange.InvokeAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
Snackbar.Add("삭제 실패", Severity.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (Exception ex)
|
||||
{
|
||||
await JS.InvokeVoidAsync("alert", "삭제 실패");
|
||||
Snackbar.Add($"오류: {ex.Message}", Severity.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,165 +4,130 @@
|
||||
@using TaxBaik.Domain.Entities
|
||||
@inject ITaxFilingBrowserClient FilingClient
|
||||
@inject IClientBrowserClient ClientClient
|
||||
@inject IJSRuntime JS
|
||||
@inject ISnackbar Snackbar
|
||||
|
||||
<PageTitle>신고 일정 관리</PageTitle>
|
||||
|
||||
<section class="admin-page-hero">
|
||||
<div>
|
||||
<div class="admin-eyebrow">Tax Schedule</div>
|
||||
<h1 class="admin-page-title">신고 일정</h1>
|
||||
<p class="admin-page-subtitle">고객별 세금 신고 마감일을 관리하고 완료 처리합니다.</p>
|
||||
<MudText Typo="Typo.caption" Class="admin-eyebrow">Tax Schedule</MudText>
|
||||
<MudText Typo="Typo.h4" Class="admin-page-title">신고 일정</MudText>
|
||||
<MudText Typo="Typo.body2" Class="admin-page-subtitle">고객별 세금 신고 마감일을 관리하고 완료 처리합니다.</MudText>
|
||||
</div>
|
||||
<button type="button" class="site-button primary" @onclick="@(() => showAddForm = !showAddForm)">일정 추가</button>
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary"
|
||||
OnClick="@(() => showAddForm = !showAddForm)"
|
||||
StartIcon="@Icons.Material.Filled.Add">
|
||||
일정 추가
|
||||
</MudButton>
|
||||
</section>
|
||||
|
||||
@if (showAddForm)
|
||||
{
|
||||
<div class="admin-surface mb-4">
|
||||
<h3 class="admin-section-title">새 신고 일정</h3>
|
||||
<form class="admin-dialog-card" @onsubmit="AddFiling" @onsubmit:preventDefault="true">
|
||||
<label>고객 검색
|
||||
<select class="admin-input" @bind="SelectedClientIdText">
|
||||
<option value="">선택하세요</option>
|
||||
@foreach (var client in clients)
|
||||
{
|
||||
<option value="@client.Id">@GetClientDisplayName(client)</option>
|
||||
}
|
||||
</select>
|
||||
</label>
|
||||
<label>신고 유형
|
||||
<select class="admin-input" @bind="newFilingType">
|
||||
<option value="">선택하세요</option>
|
||||
<MudPaper Class="pa-4 mb-4" Elevation="1">
|
||||
<MudText Typo="Typo.h6" Class="mb-3">새 신고 일정</MudText>
|
||||
<MudGrid Spacing="2">
|
||||
<MudItem xs="12" sm="6" md="4">
|
||||
<MudAutocomplete T="Domain.Entities.Client" @bind-Value="selectedClient"
|
||||
Label="고객 검색 *"
|
||||
SearchFunc="SearchClients"
|
||||
ToStringFunc="@(c => c == null ? "" : $"{c.Name} {c.CompanyName ?? ""}")"
|
||||
Variant="Variant.Outlined" />
|
||||
</MudItem>
|
||||
<MudItem xs="12" sm="6" md="4">
|
||||
<MudSelect T="string" @bind-Value="newFilingType" Label="신고 유형 *" Variant="Variant.Outlined">
|
||||
@foreach (var t in TaxFilingService.FilingTypes)
|
||||
{
|
||||
<option value="@t">@t</option>
|
||||
<MudSelectItem Value="@t">@t</MudSelectItem>
|
||||
}
|
||||
</select>
|
||||
</label>
|
||||
<label>신고 기한 <input class="admin-input" type="text" placeholder="yyyy-MM-dd" @bind="DueDateText" /></label>
|
||||
<label>메모 <textarea class="admin-input" rows="3" @bind="newMemo"></textarea></label>
|
||||
<div class="admin-dialog-actions">
|
||||
<button type="submit" class="site-button primary">저장</button>
|
||||
<button type="button" class="site-button secondary" @onclick='() => showAddForm = false'>취소</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</MudSelect>
|
||||
</MudItem>
|
||||
<MudItem xs="12" sm="6" md="4">
|
||||
<MudDatePicker @bind-Date="newDueDate" Label="신고 기한 *" DateFormat="yyyy-MM-dd" />
|
||||
</MudItem>
|
||||
<MudItem xs="12">
|
||||
<MudTextField T="string" @bind-Value="newMemo" Label="메모" Variant="Variant.Outlined" />
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
<MudStack Row="true" Class="mt-3" Spacing="2">
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" OnClick="AddFiling">저장</MudButton>
|
||||
<MudButton Variant="Variant.Outlined" OnClick="@(() => showAddForm = false)">취소</MudButton>
|
||||
</MudStack>
|
||||
</MudPaper>
|
||||
}
|
||||
|
||||
<div class="admin-surface">
|
||||
<div class="admin-tabbar">
|
||||
<button type="button" class="admin-tab @(activeTab == "pending" ? "active" : "")" @onclick='() => activeTab = "pending"'>신고 예정</button>
|
||||
<button type="button" class="admin-tab @(activeTab == "filed" ? "active" : "")" @onclick='() => activeTab = "filed"'>신고 완료</button>
|
||||
<button type="button" class="admin-tab @(activeTab == "overdue" ? "active" : "")" @onclick='() => activeTab = "overdue"'>기한 초과</button>
|
||||
</div>
|
||||
|
||||
@if (CurrentFilings.Count == 0)
|
||||
{
|
||||
<div class="muted">항목이 없습니다.</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="admin-table-wrap">
|
||||
<table class="admin-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>고객</th>
|
||||
<th>신고 유형</th>
|
||||
<th>기한</th>
|
||||
<th>D-day</th>
|
||||
<th>메모</th>
|
||||
<th>처리</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var filing in CurrentFilings)
|
||||
{
|
||||
var dday = (filing.DueDate.Date - DateTime.Today).Days;
|
||||
<tr>
|
||||
<td>@filing.ClientName</td>
|
||||
<td>@filing.FilingType</td>
|
||||
<td>@filing.DueDate.ToString("yyyy-MM-dd")</td>
|
||||
<td>
|
||||
@if (dday < 0)
|
||||
{
|
||||
<span class="status-pill danger">D+@(-dday)</span>
|
||||
}
|
||||
else if (dday <= 7)
|
||||
{
|
||||
<span class="status-pill warning">D-@dday</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span>D-@dday</span>
|
||||
}
|
||||
</td>
|
||||
<td>@(filing.Memo ?? "")</td>
|
||||
<td>
|
||||
<div class="admin-row-actions">
|
||||
@if (filing.Status == "pending")
|
||||
{
|
||||
<button type="button" class="site-button secondary" @onclick="@(() => MarkFiled(filing))">완료</button>
|
||||
}
|
||||
<button type="button" class="admin-icon-button danger" @onclick="@(() => DeleteFiling(filing.Id))">✕</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<MudPaper Class="admin-surface" Elevation="0">
|
||||
<MudTabs Rounded="true" Elevation="0" Class="admin-tabs">
|
||||
<MudTabPanel Text="신고 예정">
|
||||
<FilingTable Filings="@pending" OnStatusChange="Reload" />
|
||||
</MudTabPanel>
|
||||
<MudTabPanel Text="신고 완료">
|
||||
<FilingTable Filings="@filed" OnStatusChange="Reload" />
|
||||
</MudTabPanel>
|
||||
<MudTabPanel Text="기한 초과">
|
||||
<FilingTable Filings="@overdue" OnStatusChange="Reload" />
|
||||
</MudTabPanel>
|
||||
</MudTabs>
|
||||
</MudPaper>
|
||||
|
||||
@code {
|
||||
private List<TaxFiling> allFilings = [];
|
||||
private List<Client> clients = [];
|
||||
private List<Domain.Entities.TaxFiling> pending = [];
|
||||
private List<Domain.Entities.TaxFiling> filed = [];
|
||||
private List<Domain.Entities.TaxFiling> overdue = [];
|
||||
|
||||
private bool showAddForm;
|
||||
private string activeTab = "pending";
|
||||
private int selectedClientId;
|
||||
private Domain.Entities.Client? selectedClient;
|
||||
private string newFilingType = "";
|
||||
private DateTime? newDueDate = DateTime.Today.AddDays(30);
|
||||
private string newMemo = "";
|
||||
|
||||
private string SelectedClientIdText { get => selectedClientId > 0 ? selectedClientId.ToString() : ""; set => selectedClientId = int.TryParse(value, out var id) ? id : 0; }
|
||||
private string DueDateText { get => newDueDate?.ToString("yyyy-MM-dd") ?? ""; set => newDueDate = DateTime.TryParse(value, out var dt) ? dt : null; }
|
||||
private List<TaxFiling> CurrentFilings => activeTab switch
|
||||
{
|
||||
"filed" => allFilings.Where(x => x.Status == "filed").ToList(),
|
||||
"overdue" => allFilings.Where(x => x.Status == "overdue").ToList(),
|
||||
_ => allFilings.Where(x => x.Status == "pending").ToList()
|
||||
};
|
||||
|
||||
protected override async Task OnInitializedAsync() => await Reload();
|
||||
|
||||
private async Task Reload()
|
||||
{
|
||||
try
|
||||
{
|
||||
allFilings = (await FilingClient.GetUpcomingAsync(365)).ToList();
|
||||
var (clientItems, _) = await ClientClient.GetPagedAsync(pageSize: 1000);
|
||||
clients = clientItems.ToList();
|
||||
var all = (await FilingClient.GetUpcomingAsync(365)).ToList();
|
||||
pending = all.Where(x => x.Status == "pending").ToList();
|
||||
filed = all.Where(x => x.Status == "filed").ToList();
|
||||
overdue = all.Where(x => x.Status == "overdue").ToList();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await JS.InvokeVoidAsync("alert", $"오류: {ex.Message}");
|
||||
Snackbar.Add($"오류: {ex.Message}", Severity.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<IEnumerable<Client>> SearchClients(string value)
|
||||
{
|
||||
try
|
||||
{
|
||||
var (items, _) = await ClientClient.GetPagedAsync(1, 100, search: value);
|
||||
return items;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetClientDisplayName(Client client)
|
||||
=> !string.IsNullOrWhiteSpace(client.CompanyName)
|
||||
? client.CompanyName
|
||||
: !string.IsNullOrWhiteSpace(client.Name)
|
||||
? client.Name
|
||||
: $"Client #{client.Id}";
|
||||
private async Task AddFiling()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (selectedClientId <= 0)
|
||||
if (selectedClient == null)
|
||||
{
|
||||
await JS.InvokeVoidAsync("alert", "고객을 선택하세요.");
|
||||
Snackbar.Add("고객을 선택하세요.", Severity.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
var filing = new TaxFiling
|
||||
{
|
||||
ClientId = selectedClientId,
|
||||
ClientId = selectedClient.Id,
|
||||
FilingType = newFilingType,
|
||||
DueDate = newDueDate?.ToUniversalTime() ?? DateTime.UtcNow,
|
||||
Status = "pending",
|
||||
@@ -172,36 +137,17 @@
|
||||
if (result != null)
|
||||
{
|
||||
showAddForm = false;
|
||||
await JS.InvokeVoidAsync("alert", "신고 일정이 추가되었습니다.");
|
||||
Snackbar.Add("신고 일정이 추가되었습니다.", Severity.Success);
|
||||
await Reload();
|
||||
}
|
||||
else
|
||||
{
|
||||
await JS.InvokeVoidAsync("alert", "추가 실패");
|
||||
Snackbar.Add("추가 실패", Severity.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await JS.InvokeVoidAsync("alert", $"오류: {ex.Message}");
|
||||
Snackbar.Add($"오류: {ex.Message}", Severity.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task MarkFiled(TaxFiling filing)
|
||||
{
|
||||
filing.Status = "filed";
|
||||
await FilingClient.UpdateAsync(filing.Id, filing);
|
||||
await JS.InvokeVoidAsync("alert", "신고 완료 처리되었습니다.");
|
||||
await Reload();
|
||||
}
|
||||
|
||||
private async Task DeleteFiling(int id)
|
||||
{
|
||||
if (!await JS.InvokeAsync<bool>("confirm", "삭제하시겠습니까?")) return;
|
||||
await FilingClient.DeleteAsync(id);
|
||||
await JS.InvokeVoidAsync("alert", "삭제되었습니다.");
|
||||
await Reload();
|
||||
}
|
||||
|
||||
private static string GetClientDisplayName(Client client)
|
||||
=> !string.IsNullOrWhiteSpace(client.CompanyName) ? client.CompanyName : !string.IsNullOrWhiteSpace(client.Name) ? client.Name : $"Client #{client.Id}";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user