Files
kjh2064 1b173376ee
TaxBaik CI/CD / build-and-deploy (push) Failing after 1m53s
refactor: admin ui를 fluent v5와 html 기반으로 전환
2026-06-29 22:37:40 +09:00

148 lines
5.5 KiB
Plaintext

@page "/admin/clients/create"
@page "/admin/clients/{Id:int}/edit"
@attribute [Authorize]
@using TaxBaik.Application.DTOs
@using TaxBaik.Web.Services
@using TaxBaik.Domain.Entities
@inject IClientBrowserClient ClientClient
@inject NavigationManager Navigation
@inject IJSRuntime JS
<PageTitle>@(Id.HasValue ? "고객 수정" : "고객 등록")</PageTitle>
<section class="admin-page-hero">
<div>
<div class="admin-eyebrow">CRM</div>
<h1 class="admin-page-title">@(Id.HasValue ? "고객 수정" : "고객 등록")</h1>
</div>
<button type="button" class="site-button secondary" @onclick='() => Navigation.NavigateTo("/taxbaik/admin/clients")'>목록으로</button>
</section>
<div class="admin-surface" style="max-width:720px;">
@if (isLoading)
{
<Skeleton Count="5" CssClass="taxbaik-skeleton-grid" />
}
else
{
<form class="admin-dialog-card" @onsubmit="SaveAsync" @onsubmit:preventDefault="true">
<label>고객명 * <input class="admin-input" @bind="dto.Name" /></label>
<label>회사명 <input class="admin-input" @bind="dto.CompanyName" /></label>
<label>연락처 <input class="admin-input" @bind="dto.Phone" /></label>
<label>이메일 <input class="admin-input" type="email" @bind="dto.Email" /></label>
<label>서비스 유형
<select class="admin-input" @bind="dto.ServiceType">
<option value="">선택하세요</option>
@foreach (var t in ClientService.ServiceTypes)
{
<option value="@t">@t</option>
}
</select>
</label>
<label>세금 유형
<select class="admin-input" @bind="dto.TaxType">
<option value="">선택하세요</option>
@foreach (var t in ClientService.TaxTypes)
{
<option value="@t">@t</option>
}
</select>
</label>
<label>상태
<select class="admin-input" @bind="dto.Status">
<option value="active">활성</option>
<option value="inactive">비활성</option>
</select>
</label>
<label>유입 경로
<select class="admin-input" @bind="dto.Source">
<option value="">선택하세요</option>
@foreach (var s in ClientService.Sources)
{
<option value="@s">@s</option>
}
</select>
</label>
<label>메모 <textarea class="admin-input" rows="4" @bind="dto.Memo"></textarea></label>
<div class="admin-dialog-actions">
<button type="submit" class="site-button primary" disabled="@isSaving">저장</button>
<button type="button" class="site-button secondary" @onclick='() => Navigation.NavigateTo("/taxbaik/admin/clients")'>취소</button>
</div>
</form>
}
</div>
@code {
[Parameter] public int? Id { get; set; }
private CreateClientDto dto = new() { Status = "active" };
private bool isLoading = true;
private bool isSaving;
protected override async Task OnInitializedAsync()
{
if (Id.HasValue)
{
try
{
var client = await ClientClient.GetByIdAsync(Id.Value);
if (client is null)
{
await JS.InvokeVoidAsync("alert", "고객을 찾을 수 없습니다.");
Navigation.NavigateTo("/taxbaik/admin/clients");
return;
}
dto = new CreateClientDto
{
Name = client.Name,
CompanyName = client.CompanyName,
Phone = client.Phone,
Email = client.Email,
ServiceType = client.ServiceType,
TaxType = client.TaxType,
Status = client.Status,
Source = client.Source,
Memo = client.Memo
};
}
catch (Exception ex)
{
await JS.InvokeVoidAsync("alert", $"오류: {ex.Message}");
Navigation.NavigateTo("/taxbaik/admin/clients");
return;
}
}
isLoading = false;
}
private async Task SaveAsync()
{
isSaving = true;
try
{
if (string.IsNullOrWhiteSpace(dto.Name))
{
await JS.InvokeVoidAsync("alert", "고객명을 입력하세요.");
return;
}
if (Id.HasValue)
{
var result = await ClientClient.UpdateAsync(Id.Value, dto);
await JS.InvokeVoidAsync("alert", result != null ? "고객 정보가 수정되었습니다." : "수정에 실패했습니다.");
}
else
{
var result = await ClientClient.CreateAsync(dto);
await JS.InvokeVoidAsync("alert", result != null ? "고객이 등록되었습니다." : "등록에 실패했습니다.");
}
Navigation.NavigateTo("/taxbaik/admin/clients");
}
catch (Exception ex)
{
await JS.InvokeVoidAsync("alert", $"저장 실패: {ex.Message}");
}
finally
{
isSaving = false;
}
}
}