refactor: complete WebAssembly migration - proper architecture
TaxBaik CI/CD / build-and-deploy (push) Failing after 2m17s
TaxBaik CI/CD / build-and-deploy (push) Failing after 2m17s
Phase 8: Complete WebAssembly 렌더 모드 전환 (정공법) Migration Summary: - ALL Admin components → TaxBaik.Web.Client - Routes.razor, Pages/*, Layout/*, Shared/*, Forms/* - App.razor → TaxBaik.WasmClient (호스트 컴포넌트) - Shared utilities → TaxBaik.Application.Utils Architecture: ✅ App.razor: TaxBaik.WasmClient (WebAssembly, 호스트) ✅ Routes + Pages: TaxBaik.WasmClient (WebAssembly) ✅ Layout + Shared + Forms: TaxBaik.WasmClient (WebAssembly) ✅ Services: TaxBaik.Web (API-First) Key Changes: - Namespaces: TaxBaik.Web.Components.Admin → TaxBaik.WasmClient.Components.Admin - Shared utilities: TaxBaik.Application.Utils (single source of truth) - Program.cs: MapRazorComponents<TaxBaik.WasmClient.Components.Admin.App>() - _Imports.razor: Components/Admin 폴더에 재구성 Build Status: ✅ 0 errors, 0 warnings Benefits: - Stateless server (no Circuit memory) - Client-side rendering (WebAssembly) - Unlimited concurrent users (horizontal scaling) - ERP-ready architecture Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,164 @@
|
||||
@page "/admin/inquiries/{id:int}/edit"
|
||||
@attribute [Authorize]
|
||||
@using TaxBaik.Application.DTOs
|
||||
@using TaxBaik.WasmClient.Components.Admin.Forms
|
||||
@inject IInquiryBrowserClient InquiryClient
|
||||
@inject NavigationManager Navigation
|
||||
@inject ISnackbar Snackbar
|
||||
@inject IDialogService DialogService
|
||||
|
||||
<PageTitle>문의 수정</PageTitle>
|
||||
|
||||
<AdminCrudPageShell Title="문의 수정"
|
||||
Eyebrow="Customer Relations"
|
||||
Subtitle="고객 문의 정보를 수정합니다."
|
||||
Loading="@isLoading"
|
||||
SkeletonContent="@EditorSkeleton"
|
||||
OnCancel="@GoBack">
|
||||
@if (inquiry == null)
|
||||
{
|
||||
<MudAlert Severity="Severity.Error" Class="mt-4">문의를 찾을 수 없습니다.</MudAlert>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudPaper Class="pa-4 mt-4" Elevation="1">
|
||||
<InquiryForm ButtonText="수정" InitialData="formModel" OnSubmit="HandleUpdate" OnCancel="GoBack" />
|
||||
|
||||
<MudDivider Class="my-4" />
|
||||
|
||||
<MudButton Variant="Variant.Outlined" Color="Color.Error" @onclick="DeleteInquiry" Class="mt-2">
|
||||
문의 삭제
|
||||
</MudButton>
|
||||
</MudPaper>
|
||||
}
|
||||
</AdminCrudPageShell>
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public int Id { get; set; }
|
||||
|
||||
private Domain.Entities.Inquiry? inquiry;
|
||||
private InquiryForm.InquiryFormModel? formModel;
|
||||
private bool isLoading = true;
|
||||
|
||||
private RenderFragment EditorSkeleton => builder =>
|
||||
{
|
||||
builder.OpenComponent<AdminSkeletonRows>(0);
|
||||
builder.AddAttribute(1, "Rows", 5);
|
||||
builder.AddAttribute(2, "Columns", 3);
|
||||
builder.CloseComponent();
|
||||
};
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
inquiry = await InquiryClient.GetByIdAsync(Id);
|
||||
if (inquiry != null)
|
||||
{
|
||||
formModel = new InquiryForm.InquiryFormModel
|
||||
{
|
||||
Name = inquiry.Name,
|
||||
Phone = inquiry.Phone,
|
||||
Email = inquiry.Email,
|
||||
ServiceType = inquiry.ServiceType,
|
||||
Message = inquiry.Message,
|
||||
Status = inquiry.Status,
|
||||
AdminMemo = inquiry.AdminMemo
|
||||
};
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Snackbar.Add($"문의 로드 실패: {ex.Message}", Severity.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
isLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void GoBack()
|
||||
{
|
||||
Navigation.NavigateTo("/taxbaik/admin/inquiries");
|
||||
}
|
||||
|
||||
private async Task HandleUpdate(InquiryForm.InquiryFormModel model)
|
||||
{
|
||||
if (inquiry == null)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
var updated = await InquiryClient.UpdateAsync(inquiry.Id, new UpdateInquiryDto
|
||||
{
|
||||
Name = model.Name,
|
||||
Phone = model.Phone,
|
||||
Email = model.Email,
|
||||
ServiceType = model.ServiceType,
|
||||
Message = model.Message,
|
||||
Status = model.Status,
|
||||
AdminMemo = model.AdminMemo
|
||||
});
|
||||
|
||||
if (updated == null)
|
||||
{
|
||||
Snackbar.Add("문의 수정에 실패했습니다.", Severity.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
inquiry = updated;
|
||||
formModel = new InquiryForm.InquiryFormModel
|
||||
{
|
||||
Name = inquiry.Name,
|
||||
Phone = inquiry.Phone,
|
||||
Email = inquiry.Email,
|
||||
ServiceType = inquiry.ServiceType,
|
||||
Message = inquiry.Message,
|
||||
Status = inquiry.Status,
|
||||
AdminMemo = inquiry.AdminMemo
|
||||
};
|
||||
|
||||
Snackbar.Add("문의가 수정되었습니다.", Severity.Success);
|
||||
Navigation.NavigateTo("/taxbaik/admin/inquiries");
|
||||
}
|
||||
catch (ValidationException ex)
|
||||
{
|
||||
Snackbar.Add(ex.Message, Severity.Error);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Snackbar.Add($"수정 실패: {ex.Message}", Severity.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DeleteInquiry()
|
||||
{
|
||||
if (inquiry == null)
|
||||
return;
|
||||
|
||||
var result = await DialogService.ShowMessageBox(
|
||||
"문의 삭제",
|
||||
"정말 삭제하시겠습니까? 이 작업은 취소할 수 없습니다.",
|
||||
"삭제", "취소");
|
||||
|
||||
if (result != true)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
var deleted = await InquiryClient.DeleteAsync(inquiry.Id);
|
||||
if (!deleted)
|
||||
{
|
||||
Snackbar.Add("문의 삭제에 실패했습니다.", Severity.Error);
|
||||
return;
|
||||
}
|
||||
Snackbar.Add("문의가 삭제되었습니다.", Severity.Success);
|
||||
Navigation.NavigateTo("/taxbaik/admin/inquiries");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Snackbar.Add($"삭제 실패: {ex.Message}", Severity.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user