140 lines
5.1 KiB
Plaintext
140 lines
5.1 KiB
Plaintext
@page "/admin/blog/{id:int}/edit"
|
|
@attribute [Authorize]
|
|
@using TaxBaik.Application.DTOs
|
|
@using TaxBaik.Application.Services
|
|
@using TaxBaik.Domain.Interfaces
|
|
@inject BlogService BlogService
|
|
@inject ICategoryRepository CategoryRepository
|
|
@inject NavigationManager Navigation
|
|
@inject IJSRuntime JS
|
|
|
|
<PageTitle>포스트 수정</PageTitle>
|
|
<section class="admin-page-hero">
|
|
<div>
|
|
<div class="admin-eyebrow">Content</div>
|
|
<h1 class="admin-page-title">포스트 수정</h1>
|
|
<p class="admin-page-subtitle">블로그 포스트를 수정합니다.</p>
|
|
</div>
|
|
<button type="button" class="site-button secondary" @onclick='() => Navigation.NavigateTo("/taxbaik/admin/blog")'>취소</button>
|
|
</section>
|
|
|
|
@if (isLoading)
|
|
{
|
|
<div class="admin-surface mt-4"><Skeleton Count="4" CssClass="taxbaik-skeleton-grid" /></div>
|
|
}
|
|
else if (post == null)
|
|
{
|
|
<div class="admin-surface mt-4">포스트를 찾을 수 없습니다.</div>
|
|
}
|
|
else
|
|
{
|
|
<div class="admin-surface mt-4">
|
|
<form class="admin-dialog-card" @onsubmit="SavePost" @onsubmit:preventDefault="true">
|
|
<label>제목 * <input class="admin-input" @bind="model.Title" /></label>
|
|
<label>카테고리
|
|
<select class="admin-input" @bind="CategoryIdText">
|
|
<option value="">선택하세요</option>
|
|
@foreach (var category in categories)
|
|
{
|
|
<option value="@category.Id.ToString()">@category.Name</option>
|
|
}
|
|
</select>
|
|
</label>
|
|
<label>본문 * <textarea class="admin-input" rows="10" @bind="model.Content"></textarea></label>
|
|
<label>태그 (쉼표로 구분) <input class="admin-input" @bind="model.Tags" /></label>
|
|
<label>SEO 제목 <input class="admin-input" @bind="model.SeoTitle" /></label>
|
|
<label>SEO 설명 <textarea class="admin-input" rows="3" @bind="model.SeoDescription"></textarea></label>
|
|
<label><input type="checkbox" @bind="model.IsPublished" /> 발행</label>
|
|
<div class="admin-dialog-actions">
|
|
<button type="submit" class="site-button primary">저장</button>
|
|
<button type="button" class="site-button secondary" @onclick="DeletePost">삭제</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
}
|
|
|
|
@code {
|
|
[Parameter] public int Id { get; set; }
|
|
private Domain.Entities.BlogPost? post;
|
|
private List<Domain.Entities.Category> categories = [];
|
|
private EditPostModel model = new();
|
|
private bool isLoading = true;
|
|
private string CategoryIdText { get => model.CategoryId?.ToString() ?? ""; set => model.CategoryId = int.TryParse(value, out var id) ? id : null; }
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
try
|
|
{
|
|
post = await BlogService.GetByIdAsync(Id);
|
|
if (post != null)
|
|
{
|
|
categories = (await CategoryRepository.GetAllAsync()).ToList();
|
|
MapPostToModel(post);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await JS.InvokeVoidAsync("alert", $"포스트 로드 실패: {ex.Message}");
|
|
}
|
|
finally
|
|
{
|
|
isLoading = false;
|
|
}
|
|
}
|
|
|
|
private void MapPostToModel(Domain.Entities.BlogPost post)
|
|
{
|
|
model.Title = post.Title;
|
|
model.Content = post.Content;
|
|
model.CategoryId = post.CategoryId;
|
|
model.Tags = post.Tags;
|
|
model.SeoTitle = post.SeoTitle;
|
|
model.SeoDescription = post.SeoDescription;
|
|
model.IsPublished = post.IsPublished;
|
|
}
|
|
|
|
private async Task SavePost()
|
|
{
|
|
if (post == null) return;
|
|
try
|
|
{
|
|
await BlogService.UpdateAsync(post.Id, new CreateBlogPostDto
|
|
{
|
|
Title = model.Title,
|
|
Content = model.Content,
|
|
CategoryId = model.CategoryId,
|
|
Tags = model.Tags,
|
|
SeoTitle = model.SeoTitle,
|
|
SeoDescription = model.SeoDescription,
|
|
IsPublished = model.IsPublished
|
|
});
|
|
await JS.InvokeVoidAsync("alert", "포스트가 저장되었습니다.");
|
|
Navigation.NavigateTo("/taxbaik/admin/blog");
|
|
}
|
|
catch (ValidationException ex)
|
|
{
|
|
await JS.InvokeVoidAsync("alert", ex.Message);
|
|
}
|
|
}
|
|
|
|
private async Task DeletePost()
|
|
{
|
|
if (post == null) return;
|
|
if (!await JS.InvokeAsync<bool>("confirm", "정말 삭제하시겠습니까? 이 작업은 취소할 수 없습니다.")) return;
|
|
await BlogService.DeleteAsync(post.Id);
|
|
await JS.InvokeVoidAsync("alert", "포스트가 삭제되었습니다.");
|
|
Navigation.NavigateTo("/taxbaik/admin/blog");
|
|
}
|
|
|
|
private class EditPostModel
|
|
{
|
|
public string Title { get; set; } = "";
|
|
public string Content { get; set; } = "";
|
|
public int? CategoryId { get; set; }
|
|
public string? Tags { get; set; }
|
|
public string? SeoTitle { get; set; }
|
|
public string? SeoDescription { get; set; }
|
|
public bool IsPublished { get; set; }
|
|
}
|
|
}
|