Skip to content

Commit

Permalink
Merge branch 'dev' into feat/paystack-integration
Browse files Browse the repository at this point in the history
  • Loading branch information
mfontosco authored Mar 3, 2025
2 parents 1ef7cb8 + 612da62 commit 9c0f8ad
Show file tree
Hide file tree
Showing 6 changed files with 670 additions and 37 deletions.
9 changes: 8 additions & 1 deletion src/modules/blogs/blogs.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,14 @@ export class BlogController {
@ApiResponse({ status: 200, description: 'Blog fetched successfully.', type: BlogDto })
@ApiResponse({ status: 404, description: 'Blog not found.' })
@ApiResponse({ status: 500, description: 'Internal server error.' })
async getSingleBlog(@Param('id', new ParseUUIDPipe()) id: string, @Request() req): Promise<BlogDto> {
async getSingleBlog(
@Param('id', new ParseUUIDPipe()) id: string,
@Request() req
): Promise<{
status_code: number;
message: string;
data: BlogDto;
}> {
return await this.blogService.getSingleBlog(id, req.user);
}

Expand Down
120 changes: 91 additions & 29 deletions src/modules/blogs/blogs.service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as SYS_MSG from '@shared/constants/SystemMessages';
import { HttpStatus, Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, Like, MoreThanOrEqual, FindOptionsWhere } from 'typeorm';
import { Repository, Like, MoreThanOrEqual, FindOptionsWhere, Not, IsNull } from 'typeorm';
import { Blog } from './entities/blog.entity';
import { CreateBlogDto } from './dtos/create-blog.dto';
import { UpdateBlogDto } from './dtos/update-blog.dto';
Expand Down Expand Up @@ -52,8 +52,15 @@ export class BlogService {
};
}

async getSingleBlog(blogId: string, user: User): Promise<any> {
const singleBlog = await this.blogRepository.findOneBy({ id: blogId });
async getSingleBlog(
blogId: string,
user: User
): Promise<{
status_code: number;
message: string;
data: BlogResponseDto;
}> {
const singleBlog = await this.blogRepository.findOneBy({ id: blogId, deletedAt: null });
const fullName = await this.fetchUserById(user.id);

if (!singleBlog) {
Expand All @@ -66,7 +73,7 @@ export class BlogService {
return {
status_code: 200,
message: SYS_MSG.BLOG_FETCHED_SUCCESSFUL,
data: { blog_id: id, ...rest, author, published_date: created_at },
data: { blog_id: id, ...rest, author, published_date: created_at, created_at },
};
}

Expand Down Expand Up @@ -96,46 +103,56 @@ export class BlogService {
created_at: updatedBlog.created_at,
};
}

async deleteBlogPost(id: string): Promise<void> {
const blog = await this.blogRepository.findOne({ where: { id } });
if (!blog) {
throw new CustomHttpException('Blog post with this id does not exist.', HttpStatus.NOT_FOUND);
} else await this.blogRepository.remove(blog);
} else await this.blogRepository.softRemove(blog);
}

async getAllBlogs(
page: number,
pageSize: number
pageSize: number,
includeDeleted: boolean = false
): Promise<{
status_code: number;
message: string;
data: { currentPage: number; totalPages: number; totalResults: number; blogs: BlogResponseDto[]; meta: any };
}> {
const skip = (page - 1) * pageSize;

const [result, total] = await this.blogRepository.findAndCount({
skip,
take: pageSize,
relations: ['author'],
});

const data = this.mapBlogResults(result);
const totalPages = Math.ceil(total / pageSize);
const result = await this.getBlogs(page, pageSize, includeDeleted ? {} : { deletedAt: null });
return {
status_code: result.status_code,
message: result.message,
data: {
...result.data,
blogs: includeDeleted
? result.data.blogs
: result.data.blogs
.filter(blog => !blog.deletedAt)
.map(blog => {
const { deletedAt, ...rest } = blog;
return rest;
}),
},
};
}

async getDeletedBlogs(
page: number,
pageSize: number
): Promise<{
status_code: number;
message: string;
data: { currentPage: number; totalPages: number; totalResults: number; blogs: BlogResponseDto[]; meta: any };
}> {
const result = await this.getBlogs(page, pageSize, { deletedAt: Not(IsNull()) });
return {
status_code: HttpStatus.OK,
message: SYS_MSG.BLOG_FETCHED_SUCCESSFUL,
status_code: result.status_code,
message: result.message,
data: {
currentPage: page,
totalPages,
totalResults: total,
blogs: data,
meta: {
hasNext: page < totalPages,
total,
nextPage: page < totalPages ? page + 1 : null,
prevPage: page > 1 ? page - 1 : null,
},
...result.data,
blogs: result.data.blogs,
},
};
}
Expand Down Expand Up @@ -188,7 +205,12 @@ export class BlogService {
current_page: page,
total_pages: totalPages,
total_results: total,
blogs: data,
blogs: data
.filter(blog => !blog.deletedAt)
.map(blog => {
const { deletedAt, ...rest } = blog;
return rest;
}),
meta: {
has_next: page < totalPages,
total,
Expand All @@ -199,6 +221,45 @@ export class BlogService {
};
}

private async getBlogs(
page: number,
pageSize: number,
whereCondition: FindOptionsWhere<Blog>
): Promise<{
status_code: number;
message: string;
data: { currentPage: number; totalPages: number; totalResults: number; blogs: BlogResponseDto[]; meta: any };
}> {
const skip = (page - 1) * pageSize;

const [result, total] = await this.blogRepository.findAndCount({
where: whereCondition,
skip,
take: pageSize,
relations: ['author'],
});

const data = this.mapBlogResults(result);
const totalPages = Math.ceil(total / pageSize);

return {
status_code: HttpStatus.OK,
message: SYS_MSG.BLOG_FETCHED_SUCCESSFUL,
data: {
currentPage: page,
totalPages,
totalResults: total,
blogs: data,
meta: {
hasNext: page < totalPages,
total,
nextPage: page < totalPages ? page + 1 : null,
prevPage: page > 1 ? page - 1 : null,
},
},
};
}

private buildWhereClause(query: any): FindOptionsWhere<Blog> {
const where: FindOptionsWhere<Blog> = {};

Expand Down Expand Up @@ -249,6 +310,7 @@ export class BlogService {
image_urls: blog.image_urls,
author: author_name,
created_at: blog.created_at,
deletedAt: blog.deletedAt,
};
});
}
Expand Down
6 changes: 6 additions & 0 deletions src/modules/blogs/dtos/blog-response.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,10 @@ export class BlogResponseDto {

@ApiProperty({ description: 'The creation date of the blog' })
created_at: Date;

@ApiProperty({ description: 'The published date of the blog' })
published_date?: Date;

@ApiProperty({ description: 'The deletion date of the blog', required: false })
deletedAt?: Date;
}
2 changes: 1 addition & 1 deletion src/modules/blogs/dtos/blog.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ export class BlogDto {
author: string;

@ApiProperty({ description: 'The creation date of the blog' })
published_date: Date;
published_date?: Date;
}
8 changes: 7 additions & 1 deletion src/modules/blogs/entities/blog.entity.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Entity, Column, ManyToOne } from 'typeorm';
import { Entity, Column, ManyToOne, DeleteDateColumn, BeforeUpdate } from 'typeorm';
import { AbstractBaseEntity } from '../../../entities/base.entity';
import { User } from '../../user/entities/user.entity';

Expand All @@ -16,6 +16,12 @@ export class Blog extends AbstractBaseEntity {
@Column('simple-array', { nullable: true })
image_urls?: string[];

@DeleteDateColumn({ nullable: true, default: null })
deletedAt?: Date;

@Column({ nullable: true, default: null })
published_date?: Date;

@ManyToOne(() => User, user => user.blogs)
author: User;
}
Loading

0 comments on commit 9c0f8ad

Please sign in to comment.