diff --git a/TaxBaik.Application/DependencyInjection.cs b/TaxBaik.Application/DependencyInjection.cs new file mode 100644 index 0000000..324ecf3 --- /dev/null +++ b/TaxBaik.Application/DependencyInjection.cs @@ -0,0 +1,14 @@ +namespace TaxBaik.Application; + +using Microsoft.Extensions.DependencyInjection; +using TaxBaik.Application.Services; + +public static class DependencyInjection +{ + public static IServiceCollection AddApplication(this IServiceCollection services) + { + services.AddScoped(); + services.AddScoped(); + return services; + } +} diff --git a/TaxBaik.Application/Services/BlogService.cs b/TaxBaik.Application/Services/BlogService.cs new file mode 100644 index 0000000..2091ba3 --- /dev/null +++ b/TaxBaik.Application/Services/BlogService.cs @@ -0,0 +1,42 @@ +namespace TaxBaik.Application.Services; + +using System.Text.RegularExpressions; +using TaxBaik.Domain.Entities; +using TaxBaik.Domain.Interfaces; + +public class BlogService(IBlogPostRepository repository) +{ + public async Task GetBySlugAsync(string slug, CancellationToken ct = default) => + await repository.GetBySlugAsync(slug, ct); + + public async Task<(IEnumerable, int)> GetPublishedPagedAsync( + int page, int pageSize, int? categoryId = null, CancellationToken ct = default) => + await repository.GetPublishedPagedAsync(page, pageSize, categoryId, ct); + + public async Task> GetAllForAdminAsync(CancellationToken ct = default) => + await repository.GetAllForAdminAsync(ct); + + public async Task CreateAsync(BlogPost post, CancellationToken ct = default) + { + post.Slug = GenerateSlug(post.Title); + post.IsPublished = false; + return await repository.CreateAsync(post, ct); + } + + public async Task UpdateAsync(BlogPost post, CancellationToken ct = default) => + await repository.UpdateAsync(post, ct); + + public async Task DeleteAsync(int id, CancellationToken ct = default) => + await repository.DeleteAsync(id, ct); + + public async Task IncrementViewCountAsync(int id, CancellationToken ct = default) => + await repository.IncrementViewCountAsync(id, ct); + + private static string GenerateSlug(string title) + { + var slug = Regex.Replace(title.ToLowerInvariant(), @"[^\w\s-]", ""); + slug = Regex.Replace(slug, @"\s+", "-"); + slug = Regex.Replace(slug, @"-+", "-").Trim('-'); + return slug.Length > 100 ? slug[..100] : slug; + } +} diff --git a/TaxBaik.Application/Services/InquiryService.cs b/TaxBaik.Application/Services/InquiryService.cs new file mode 100644 index 0000000..c990674 --- /dev/null +++ b/TaxBaik.Application/Services/InquiryService.cs @@ -0,0 +1,52 @@ +namespace TaxBaik.Application.Services; + +using System.Text.RegularExpressions; +using TaxBaik.Domain.Entities; +using TaxBaik.Domain.Interfaces; + +public class InquiryService(IInquiryRepository repository) +{ + private static readonly Regex PhoneRegex = new(@"^01[0-9]-\d{3,4}-\d{4}$"); + + public async Task SubmitAsync( + string name, string phone, string serviceType, string message, + string? ipAddress = null, CancellationToken ct = default) + { + if (string.IsNullOrWhiteSpace(name)) + throw new ValidationException("이름을 입력하세요."); + + if (!PhoneRegex.IsMatch(phone)) + throw new ValidationException("올바른 전화번호를 입력하세요. (예: 010-1234-5678)"); + + if (string.IsNullOrWhiteSpace(message)) + throw new ValidationException("문의 내용을 입력하세요."); + + var inquiry = new Inquiry + { + Name = name.Trim(), + Phone = phone.Trim(), + ServiceType = serviceType ?? "기타", + Message = message.Trim(), + IpAddress = ipAddress, + Status = "new", + CreatedAt = DateTime.UtcNow + }; + + return await repository.CreateAsync(inquiry, ct); + } + + public async Task GetByIdAsync(int id, CancellationToken ct = default) => + await repository.GetByIdAsync(id, ct); + + public async Task<(IEnumerable, int)> GetPagedAsync( + int page, int pageSize, string? status = null, CancellationToken ct = default) => + await repository.GetPagedAsync(page, pageSize, status, ct); + + public async Task UpdateStatusAsync(int id, string status, CancellationToken ct = default) => + await repository.UpdateStatusAsync(id, status, ct); +} + +public class ValidationException : Exception +{ + public ValidationException(string message) : base(message) { } +}