diff --git a/api/src/Kurs.Platform.Application.Contracts/Blog/BlogPostAndCategoriesDto.cs b/api/src/Kurs.Platform.Application.Contracts/Blog/BlogPostAndCategoriesDto.cs new file mode 100644 index 00000000..79caa2ce --- /dev/null +++ b/api/src/Kurs.Platform.Application.Contracts/Blog/BlogPostAndCategoriesDto.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; +using Volo.Abp.Application.Dtos; + +namespace Kurs.Platform.Blog; + +public class BlogPostAndCategoriesDto +{ + public PagedResultDto Posts { get; set; } + public List Categories { get; set; } +} \ No newline at end of file diff --git a/api/src/Kurs.Platform.Application.Contracts/Blog/IBlogAppService.cs b/api/src/Kurs.Platform.Application.Contracts/Blog/IBlogAppService.cs index 228ef359..5ff41101 100644 --- a/api/src/Kurs.Platform.Application.Contracts/Blog/IBlogAppService.cs +++ b/api/src/Kurs.Platform.Application.Contracts/Blog/IBlogAppService.cs @@ -9,7 +9,7 @@ namespace Kurs.Platform.Blog; public interface IBlogAppService : IApplicationService { // Blog Post methods - Task> GetPostsAsync(GetBlogPostsInput input); + Task GetPostListAsync(GetBlogPostsInput input); Task GetPostAsync(Guid id); Task GetPostBySlugAsync(string slug); Task CreatePostAsync(CreateUpdateBlogPostDto input); @@ -19,7 +19,7 @@ public interface IBlogAppService : IApplicationService Task UnpublishPostAsync(Guid id); // Blog Category methods - Task> GetCategoriesAsync(); + // Task> GetCategoriesAsync(); Task GetCategoryAsync(Guid id); Task CreateCategoryAsync(CreateUpdateBlogCategoryDto input); Task UpdateCategoryAsync(Guid id, CreateUpdateBlogCategoryDto input); diff --git a/api/src/Kurs.Platform.Application/Blog/BlogAppService.cs b/api/src/Kurs.Platform.Application/Blog/BlogAppService.cs index edfd11a0..86e19be3 100644 --- a/api/src/Kurs.Platform.Application/Blog/BlogAppService.cs +++ b/api/src/Kurs.Platform.Application/Blog/BlogAppService.cs @@ -11,302 +11,370 @@ using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Repositories; using Volo.Abp.Users; -namespace Kurs.Platform.Blog +namespace Kurs.Platform.Blog; + +[Authorize] +public class BlogAppService : PlatformAppService, IBlogAppService { - [Authorize] - public class BlogAppService : PlatformAppService, IBlogAppService + private readonly IRepository _postRepository; + private readonly IRepository _categoryRepository; + private readonly ICurrentUser _currentUser; + private readonly IStringLocalizer _localizer; + + public BlogAppService( + IRepository postRepository, + IRepository categoryRepository, + ICurrentUser currentUser, + IStringLocalizer localizer) { - private readonly IRepository _postRepository; - private readonly IRepository _categoryRepository; - private readonly ICurrentUser _currentUser; - private readonly IStringLocalizer _localizer; - - public BlogAppService( - IRepository postRepository, - IRepository categoryRepository, - ICurrentUser currentUser, - IStringLocalizer localizer) - { - _postRepository = postRepository; - _categoryRepository = categoryRepository; - _currentUser = currentUser; - _localizer = localizer; - } - - // Blog Post methods - [AllowAnonymous] - public async Task> GetPostsAsync(GetBlogPostsInput input) - { - var allPosts = await _postRepository.GetListAsync(); // Tüm kayıtlar memory'ye alınır - - var filtered = allPosts.Where(post => - { - var searchMatch = string.IsNullOrWhiteSpace(input.Search) || - post.ContentTr.Contains(input.Search, StringComparison.OrdinalIgnoreCase) || - post.ContentEn.Contains(input.Search, StringComparison.OrdinalIgnoreCase); - - var categoryMatch = !input.CategoryId.HasValue || post.CategoryId == input.CategoryId.Value; - - return searchMatch && categoryMatch; - }).ToList(); - - var totalCount = filtered.Count; - - var pagedPosts = filtered - .OrderByDescending(x => x.CreationTime) - .Skip(input.SkipCount) - .Take(input.MaxResultCount) - .ToList(); - - var categoryIds = pagedPosts.Select(x => x.CategoryId).Distinct().ToList(); - var categories = await _categoryRepository.GetListAsync(x => categoryIds.Contains(x.Id)); - var categoryDict = categories.ToDictionary(x => x.Id, x => x); - - var postIds = pagedPosts.Select(x => x.Id).ToList(); - - var postDtos = pagedPosts.Select(post => - { - var dto = ObjectMapper.Map(post); - - if (categoryDict.TryGetValue(post.CategoryId, out var category)) - { - dto.Category = ObjectMapper.Map(category); - } - - dto.Author = new AuthorDto - { - Id = post.AuthorId, - Name = "User" - }; - - return dto; - }).ToList(); - - return new PagedResultDto(totalCount, postDtos); - } - - [AllowAnonymous] - public async Task GetPostAsync(Guid id) - { - var post = await _postRepository.GetAsync(id); - var dto = ObjectMapper.Map(post); - - // Get category - dto.Category = ObjectMapper.Map( - await _categoryRepository.GetAsync(post.CategoryId) - ); - - // Get author info - dto.Author = new AuthorDto - { - Id = post.AuthorId, - Name = "User" - }; - - return dto; - } - - [AllowAnonymous] - public async Task GetPostBySlugAsync(string slug) - { - var post = await _postRepository.FirstOrDefaultAsync(x => x.Slug == slug); - if (post == null) - { - throw new EntityNotFoundException(typeof(BlogPost)); - } - - return await GetPostAsync(post.Id); - } - - public async Task CreatePostAsync(CreateUpdateBlogPostDto input) - { - var post = new BlogPost( - GuidGenerator.Create(), - input.Title, - input.Slug, - input.ContentTr, - input.ContentEn, - input.Summary, - input.ReadTime, - input.CoverImage, - input.CategoryId, - _currentUser.Id.Value, - true, - DateTime.UtcNow, - (Guid?)CurrentTenant.Id - ); - - await _postRepository.InsertAsync(post, autoSave: true); - - return await GetPostAsync(post.Id); - } - - public async Task UpdatePostAsync(Guid id, CreateUpdateBlogPostDto input) - { - var post = await _postRepository.GetAsync(id); - - if (post.AuthorId != _currentUser.Id && !await AuthorizationService.IsGrantedAsync("App.BlogManagement.Update")) - { - throw new Volo.Abp.Authorization.AbpAuthorizationException(); - } - - post.Title = input.Title; - post.Slug = input.Slug; - post.Summary = input.Summary; - post.CoverImage = input.CoverImage; - post.ContentTr = input.ContentTr; - post.ContentEn = input.ContentEn; - - if (input.IsPublished) post.Publish(); else post.Unpublish(); - - if (post.CategoryId != input.CategoryId) - { - var oldCategory = await _categoryRepository.GetAsync(post.CategoryId); - oldCategory.DecrementPostCount(); - await _categoryRepository.UpdateAsync(oldCategory); - - var newCategory = await _categoryRepository.GetAsync(input.CategoryId); - newCategory.IncrementPostCount(); - await _categoryRepository.UpdateAsync(newCategory); - - post.CategoryId = input.CategoryId; - } - - await _postRepository.UpdateAsync(post); - - return await GetPostAsync(post.Id); // ✅ DTO dönülüyor - } - - public async Task DeletePostAsync(Guid id) - { - var post = await _postRepository.GetAsync(id); - - // Check if user is author or has permission - if (post.AuthorId != _currentUser.Id && !await AuthorizationService.IsGrantedAsync("App.BlogManagement.Delete")) - { - throw new Volo.Abp.Authorization.AbpAuthorizationException(); - } - - // Update category post count - var category = await _categoryRepository.GetAsync(post.CategoryId); - category.DecrementPostCount(); - await _categoryRepository.UpdateAsync(category); - - await _postRepository.DeleteAsync(id); - } - - public async Task PublishPostAsync(Guid id) - { - var post = await _postRepository.GetAsync(id); - - // Check if user is author or has permission - if (post.AuthorId != _currentUser.Id && !await AuthorizationService.IsGrantedAsync("App.BlogManagement.Publish")) - { - throw new Volo.Abp.Authorization.AbpAuthorizationException(); - } - - post.Publish(); - await _postRepository.UpdateAsync(post); - - return await GetPostAsync(id); - } - - public async Task UnpublishPostAsync(Guid id) - { - var post = await _postRepository.GetAsync(id); - - // Check if user is author or has permission - if (post.AuthorId != _currentUser.Id && !await AuthorizationService.IsGrantedAsync("App.BlogManagement.Publish")) - { - throw new Volo.Abp.Authorization.AbpAuthorizationException(); - } - - post.Unpublish(); - await _postRepository.UpdateAsync(post); - - return await GetPostAsync(id); - } - - // Blog Category methods - [AllowAnonymous] - public async Task> GetCategoriesAsync() - { - var categories = await _categoryRepository.GetListAsync(); - - var postQuery = await _postRepository.GetQueryableAsync(); - - var groupedCounts = postQuery - .Where(p => p.IsPublished) // sadece yayınlanmış yazılar - .GroupBy(p => p.CategoryId) - .Select(g => new { CategoryId = g.Key, Count = g.Count() }) - .ToList(); - - var dtoList = ObjectMapper.Map, List>(categories); - - foreach (var dto in dtoList) - { - dto.PostCount = groupedCounts - .FirstOrDefault(x => x.CategoryId == dto.Id)?.Count ?? 0; - } - - return dtoList; - } - - public async Task GetCategoryAsync(Guid id) - { - var category = await _categoryRepository.GetAsync(id); - return ObjectMapper.Map(category); - } - - [Authorize("App.BlogManagement.Create")] - public async Task CreateCategoryAsync(CreateUpdateBlogCategoryDto input) - { - var category = new BlogCategory( - GuidGenerator.Create(), - input.Name, - input.Slug, - input.Description, - CurrentTenant.Id - ); - - category.Icon = input.Icon; - category.DisplayOrder = input.DisplayOrder; - category.IsActive = input.IsActive; - - await _categoryRepository.InsertAsync(category); - - return ObjectMapper.Map(category); - } - - [Authorize("App.BlogManagement.Update")] - public async Task UpdateCategoryAsync(Guid id, CreateUpdateBlogCategoryDto input) - { - var category = await _categoryRepository.GetAsync(id); - - category.Name = input.Name; - category.Slug = input.Slug; - category.Description = input.Description; - category.Icon = input.Icon; - category.DisplayOrder = input.DisplayOrder; - category.IsActive = input.IsActive; - - await _categoryRepository.UpdateAsync(category); - - return ObjectMapper.Map(category); - } - - [Authorize("App.BlogManagement.Delete")] - public async Task DeleteCategoryAsync(Guid id) - { - // Check if category has posts - var hasPost = await _postRepository.AnyAsync(x => x.CategoryId == id); - if (hasPost) - { - throw new Volo.Abp.BusinessException("Cannot delete category with posts"); - } - - await _categoryRepository.DeleteAsync(id); - } - + _postRepository = postRepository; + _categoryRepository = categoryRepository; + _currentUser = currentUser; + _localizer = localizer; } + + // Blog Post methods + [AllowAnonymous] + public async Task GetPostListAsync(GetBlogPostsInput input) + { + // IQueryable + var postQuery = await _postRepository.GetQueryableAsync(); + + // 🔎 Arama + if (!input.Search.IsNullOrWhiteSpace()) + { + postQuery = postQuery.Where(p => + p.ContentTr.Contains(input.Search) || + p.ContentEn.Contains(input.Search)); + } + + // 📁 Kategori filtresi + if (input.CategoryId.HasValue) + { + postQuery = postQuery.Where(p => p.CategoryId == input.CategoryId.Value); + } + + // Toplam adet (sayfalama öncesi) + var totalCount = await AsyncExecuter.CountAsync(postQuery); + + // Sayfalama + sıralama + var pagedPosts = await AsyncExecuter.ToListAsync( + postQuery + .OrderByDescending(p => p.CreationTime) + .PageBy(input) + ); + + // Sayfadaki kategori kayıtları + var categoryIds = pagedPosts.Select(x => x.CategoryId).Distinct().ToList(); + var pageCategories = await _categoryRepository.GetListAsync(x => categoryIds.Contains(x.Id)); + var categoryDict = pageCategories.ToDictionary(x => x.Id, x => x); + + // Post DTO mapping + var postDtos = pagedPosts.Select(post => + { + var dto = ObjectMapper.Map(post); + if (categoryDict.TryGetValue(post.CategoryId, out var c)) + { + dto.Category = ObjectMapper.Map(c); + } + + dto.Author = new AuthorDto { Id = post.AuthorId, Name = "User" }; + return dto; + }).ToList(); + + // ----------- KATEGORİLER (PostCount ile) ----------- + var allCategories = await _categoryRepository.GetListAsync(); + + var allPostQuery = await _postRepository.GetQueryableAsync(); + var counts = await AsyncExecuter.ToListAsync( + allPostQuery + .Where(p => p.IsPublished) + .GroupBy(p => p.CategoryId) + .Select(g => new { g.Key, Count = g.Count() }) + ); + + var countDict = counts.ToDictionary(x => x.Key, x => x.Count); + + var categoryDtos = ObjectMapper.Map, List>(allCategories); + foreach (var dto in categoryDtos) + { + dto.PostCount = countDict.GetOrDefault(dto.Id); + } + + return new BlogPostAndCategoriesDto + { + Posts = new PagedResultDto(totalCount, postDtos), + Categories = categoryDtos + }; + } + + // public async Task> GetPostsAsync(GetBlogPostsInput input) + // { + // var allPosts = await _postRepository.GetListAsync(); // Tüm kayıtlar memory'ye alınır + // var filtered = allPosts.Where(post => + // { + // var searchMatch = string.IsNullOrWhiteSpace(input.Search) || + // post.ContentTr.Contains(input.Search, StringComparison.OrdinalIgnoreCase) || + // post.ContentEn.Contains(input.Search, StringComparison.OrdinalIgnoreCase); + + // var categoryMatch = !input.CategoryId.HasValue || post.CategoryId == input.CategoryId.Value; + + // return searchMatch && categoryMatch; + // }).ToList(); + + // var totalCount = filtered.Count; + // var pagedPosts = filtered + // .OrderByDescending(x => x.CreationTime) + // .Skip(input.SkipCount) + // .Take(input.MaxResultCount) + // .ToList(); + + // var categoryIds = pagedPosts.Select(x => x.CategoryId).Distinct().ToList(); + // var categories = await _categoryRepository.GetListAsync(x => categoryIds.Contains(x.Id)); + // var categoryDict = categories.ToDictionary(x => x.Id, x => x); + + // var postIds = pagedPosts.Select(x => x.Id).ToList(); + // var postDtos = pagedPosts.Select(post => + // { + // var dto = ObjectMapper.Map(post); + // if (categoryDict.TryGetValue(post.CategoryId, out var category)) + // { + // dto.Category = ObjectMapper.Map(category); + // } + + // dto.Author = new AuthorDto + // { + // Id = post.AuthorId, + // Name = "User" + // }; + + // return dto; + // }).ToList(); + + // return new PagedResultDto(totalCount, postDtos); + // } + + [AllowAnonymous] + public async Task GetPostAsync(Guid id) + { + var post = await _postRepository.GetAsync(id); + var dto = ObjectMapper.Map(post); + + // Get category + dto.Category = ObjectMapper.Map( + await _categoryRepository.GetAsync(post.CategoryId) + ); + + // Get author info + dto.Author = new AuthorDto + { + Id = post.AuthorId, + Name = "User" + }; + + return dto; + } + + [AllowAnonymous] + public async Task GetPostBySlugAsync(string slug) + { + var post = await _postRepository.FirstOrDefaultAsync(x => x.Slug == slug); + if (post == null) + { + throw new EntityNotFoundException(typeof(BlogPost)); + } + + return await GetPostAsync(post.Id); + } + + public async Task CreatePostAsync(CreateUpdateBlogPostDto input) + { + var post = new BlogPost( + GuidGenerator.Create(), + input.Title, + input.Slug, + input.ContentTr, + input.ContentEn, + input.Summary, + input.ReadTime, + input.CoverImage, + input.CategoryId, + _currentUser.Id.Value, + true, + DateTime.UtcNow, + (Guid?)CurrentTenant.Id + ); + + await _postRepository.InsertAsync(post, autoSave: true); + + return await GetPostAsync(post.Id); + } + + public async Task UpdatePostAsync(Guid id, CreateUpdateBlogPostDto input) + { + var post = await _postRepository.GetAsync(id); + + if (post.AuthorId != _currentUser.Id && !await AuthorizationService.IsGrantedAsync("App.BlogManagement.Update")) + { + throw new Volo.Abp.Authorization.AbpAuthorizationException(); + } + + post.Title = input.Title; + post.Slug = input.Slug; + post.Summary = input.Summary; + post.CoverImage = input.CoverImage; + post.ContentTr = input.ContentTr; + post.ContentEn = input.ContentEn; + + if (input.IsPublished) post.Publish(); else post.Unpublish(); + + if (post.CategoryId != input.CategoryId) + { + var oldCategory = await _categoryRepository.GetAsync(post.CategoryId); + oldCategory.DecrementPostCount(); + await _categoryRepository.UpdateAsync(oldCategory); + + var newCategory = await _categoryRepository.GetAsync(input.CategoryId); + newCategory.IncrementPostCount(); + await _categoryRepository.UpdateAsync(newCategory); + + post.CategoryId = input.CategoryId; + } + + await _postRepository.UpdateAsync(post); + + return await GetPostAsync(post.Id); // ✅ DTO dönülüyor + } + + public async Task DeletePostAsync(Guid id) + { + var post = await _postRepository.GetAsync(id); + + // Check if user is author or has permission + if (post.AuthorId != _currentUser.Id && !await AuthorizationService.IsGrantedAsync("App.BlogManagement.Delete")) + { + throw new Volo.Abp.Authorization.AbpAuthorizationException(); + } + + // Update category post count + var category = await _categoryRepository.GetAsync(post.CategoryId); + category.DecrementPostCount(); + await _categoryRepository.UpdateAsync(category); + + await _postRepository.DeleteAsync(id); + } + + public async Task PublishPostAsync(Guid id) + { + var post = await _postRepository.GetAsync(id); + + // Check if user is author or has permission + if (post.AuthorId != _currentUser.Id && !await AuthorizationService.IsGrantedAsync("App.BlogManagement.Publish")) + { + throw new Volo.Abp.Authorization.AbpAuthorizationException(); + } + + post.Publish(); + await _postRepository.UpdateAsync(post); + + return await GetPostAsync(id); + } + + public async Task UnpublishPostAsync(Guid id) + { + var post = await _postRepository.GetAsync(id); + + // Check if user is author or has permission + if (post.AuthorId != _currentUser.Id && !await AuthorizationService.IsGrantedAsync("App.BlogManagement.Publish")) + { + throw new Volo.Abp.Authorization.AbpAuthorizationException(); + } + + post.Unpublish(); + await _postRepository.UpdateAsync(post); + + return await GetPostAsync(id); + } + + // // Blog Category methods + // [AllowAnonymous] + // public async Task> GetCategoriesAsync() + // { + // var categories = await _categoryRepository.GetListAsync(); + + // var postQuery = await _postRepository.GetQueryableAsync(); + + // var groupedCounts = postQuery + // .Where(p => p.IsPublished) // sadece yayınlanmış yazılar + // .GroupBy(p => p.CategoryId) + // .Select(g => new { CategoryId = g.Key, Count = g.Count() }) + // .ToList(); + + // var dtoList = ObjectMapper.Map, List>(categories); + + // foreach (var dto in dtoList) + // { + // dto.PostCount = groupedCounts + // .FirstOrDefault(x => x.CategoryId == dto.Id)?.Count ?? 0; + // } + + // return dtoList; + // } + + public async Task GetCategoryAsync(Guid id) + { + var category = await _categoryRepository.GetAsync(id); + return ObjectMapper.Map(category); + } + + [Authorize("App.BlogManagement.Create")] + public async Task CreateCategoryAsync(CreateUpdateBlogCategoryDto input) + { + var category = new BlogCategory( + GuidGenerator.Create(), + input.Name, + input.Slug, + input.Description, + CurrentTenant.Id + ); + + category.Icon = input.Icon; + category.DisplayOrder = input.DisplayOrder; + category.IsActive = input.IsActive; + + await _categoryRepository.InsertAsync(category); + + return ObjectMapper.Map(category); + } + + [Authorize("App.BlogManagement.Update")] + public async Task UpdateCategoryAsync(Guid id, CreateUpdateBlogCategoryDto input) + { + var category = await _categoryRepository.GetAsync(id); + + category.Name = input.Name; + category.Slug = input.Slug; + category.Description = input.Description; + category.Icon = input.Icon; + category.DisplayOrder = input.DisplayOrder; + category.IsActive = input.IsActive; + + await _categoryRepository.UpdateAsync(category); + + return ObjectMapper.Map(category); + } + + [Authorize("App.BlogManagement.Delete")] + public async Task DeleteCategoryAsync(Guid id) + { + // Check if category has posts + var hasPost = await _postRepository.AnyAsync(x => x.CategoryId == id); + if (hasPost) + { + throw new Volo.Abp.BusinessException("Cannot delete category with posts"); + } + + await _categoryRepository.DeleteAsync(id); + } + } diff --git a/api/src/Kurs.Platform.HttpApi.Host/Program.cs b/api/src/Kurs.Platform.HttpApi.Host/Program.cs index 59e68958..092dce80 100644 --- a/api/src/Kurs.Platform.HttpApi.Host/Program.cs +++ b/api/src/Kurs.Platform.HttpApi.Host/Program.cs @@ -42,7 +42,7 @@ public class Program case DatabaseProvider.PostgreSql: loggerConfig = loggerConfig.WriteTo.PostgreSQL( connectionString: configuration.GetConnectionString(DefaultDatabaseProvider), - tableName: PlatformConsts.DbTablePrefix + "LogEntry", + tableName: PlatformConsts.SelectCommandByTableName("LogEntry"), columnOptions: columnWriters, needAutoCreateTable: true, respectCase: true @@ -52,7 +52,7 @@ public class Program case DatabaseProvider.SqlServer: loggerConfig = loggerConfig.WriteTo.MSSqlServer( connectionString: configuration.GetConnectionString(DefaultDatabaseProvider), - tableName: PlatformConsts.DbTablePrefix + "LogEntry", + tableName: PlatformConsts.SelectCommandByTableName("LogEntry"), autoCreateSqlTable: true, columnOptions: new Serilog.Sinks.MSSqlServer.ColumnOptions() ); diff --git a/ui/dev-dist/sw.js b/ui/dev-dist/sw.js index 82ac9c87..945da89c 100644 --- a/ui/dev-dist/sw.js +++ b/ui/dev-dist/sw.js @@ -82,7 +82,7 @@ define(['./workbox-54d0af47'], (function (workbox) { 'use strict'; "revision": "3ca0b8505b4bec776b69afdba2768812" }, { "url": "index.html", - "revision": "0.vah6gtb83uo" + "revision": "0.3u9qv452np" }], {}); workbox.cleanupOutdatedCaches(); workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), { diff --git a/ui/src/proxy/blog/blog.ts b/ui/src/proxy/blog/blog.ts index c67848c7..6cca8b30 100644 --- a/ui/src/proxy/blog/blog.ts +++ b/ui/src/proxy/blog/blog.ts @@ -1,3 +1,5 @@ +import { PagedResultDto } from '../abp' + export interface BlogPost { id: string title: string @@ -39,6 +41,11 @@ export interface BlogCategory { tenantId?: string } +export interface BlogPostAndCategoriesDto { + posts: PagedResultDto + categories: BlogCategory[] +} + export interface CreateUpdateBlogPostDto { title: string slug: string @@ -71,11 +78,3 @@ export interface BlogListParams { authorId?: string sortBy?: 'latest' | 'popular' | 'trending' } - -export interface PaginatedResponse { - items: T[] - totalCount: number - pageNumber: number - pageSize: number - totalPages: number -} \ No newline at end of file diff --git a/ui/src/services/blog.service.ts b/ui/src/services/blog.service.ts index 57759ee8..9ec7d495 100644 --- a/ui/src/services/blog.service.ts +++ b/ui/src/services/blog.service.ts @@ -1,10 +1,17 @@ -import { BlogCategory, BlogListParams, BlogPost, CreateUpdateBlogCategoryDto, CreateUpdateBlogPostDto, PaginatedResponse } from '@/proxy/blog/blog'; +import { + BlogCategory, + BlogListParams, + BlogPost, + BlogPostAndCategoriesDto, + CreateUpdateBlogCategoryDto, + CreateUpdateBlogPostDto, +} from '@/proxy/blog/blog' import apiService from '@/services/api.service' class BlogService { - async getPosts(params: BlogListParams = {}): Promise> { - const response = await apiService.fetchData>({ - url: '/api/app/blog/posts', + async getPosts(params: BlogListParams = {}): Promise { + const response = await apiService.fetchData({ + url: '/api/app/blog/post-list', method: 'GET', params, }) @@ -13,10 +20,10 @@ class BlogService { async getPostBySlug(slug: string): Promise { const response = await apiService.fetchData({ - url : `/api/app/blog/post-by-slug?slug=${slug}`, + url: `/api/app/blog/post-by-slug?slug=${slug}`, method: 'GET', }) - return response.data; + return response.data } async getPost(idOrSlug: string): Promise { @@ -68,13 +75,13 @@ class BlogService { return response.data } - async getCategories(): Promise { - const response = await apiService.fetchData({ - url: '/api/app/blog/categories', - method: 'GET', - }) - return response.data - } + // async getCategories(): Promise { + // const response = await apiService.fetchData({ + // url: '/api/app/blog/categories', + // method: 'GET', + // }) + // return response.data + // } async deleteComment(id: string): Promise { await apiService.fetchData({ diff --git a/ui/src/views/public/Blog.tsx b/ui/src/views/public/Blog.tsx index 89be5742..6aaaae4d 100644 --- a/ui/src/views/public/Blog.tsx +++ b/ui/src/views/public/Blog.tsx @@ -1,11 +1,6 @@ import React, { useEffect, useState } from 'react' import { Link } from 'react-router-dom' -import { - FaCalendarAlt, - FaUser, - FaTag, - FaSearch -} from 'react-icons/fa'; +import { FaCalendarAlt, FaUser, FaTag, FaSearch } from 'react-icons/fa' import dayjs from 'dayjs' import 'dayjs/locale/tr' import { BlogCategory, BlogPost } from '@/proxy/blog/blog' @@ -33,19 +28,24 @@ const Blog = () => { const loadBlogData = async () => { try { setLoading(true) - const [postsData, categoriesData] = await Promise.all([ - blogService.getPosts({ - page: currentPage, - pageSize: 10, - categoryId: selectedCategory, - search: searchQuery, - }), - blogService.getCategories(), - ]) - setPosts(postsData.items.filter((a) => a.isPublished)) - setTotalPages(postsData.totalPages) - setCategories(categoriesData.filter((a) => a.isActive)) + const postsData = await blogService.getPosts({ + page: currentPage, + pageSize: 10, + categoryId: selectedCategory, + search: searchQuery, + }) + + if ( + postsData.posts && + postsData.posts.items && + postsData.posts.totalCount && + postsData.categories + ) { + setPosts(postsData.posts.items.filter((a) => a.isPublished)) + setTotalPages(postsData.posts.totalCount / 10) + setCategories(postsData.categories.filter((a) => a.isActive)) + } } catch (error) { console.error('Blog verileri yüklenemedi:', error) setPosts([]) diff --git a/ui/src/views/public/BlogDetail.tsx b/ui/src/views/public/BlogDetail.tsx index 5717cd2c..46c590ae 100644 --- a/ui/src/views/public/BlogDetail.tsx +++ b/ui/src/views/public/BlogDetail.tsx @@ -116,7 +116,9 @@ const BlogDetail: React.FC = () => { className="prose max-w-none text-gray-800" dangerouslySetInnerHTML={{ __html: - currentLang == 'tr' ? translate(blogPost.contentTr!) : translate(blogPost.contentEn!), + currentLang == 'tr' + ? translate('::' + blogPost.contentTr!) + : translate('::' + blogPost.contentEn!), }} />