diff --git a/src/app.module.ts b/src/app.module.ts index 73b2f99..bc6f031 100755 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -7,13 +7,13 @@ import { ConfigModule } from "@nestjs/config"; import { ThrottlerModule } from "@nestjs/throttler"; import { TypeOrmModule } from "@nestjs/typeorm"; import { MailerModule } from "@nestjs-modules/mailer"; -import { TelegrafModule } from "nestjs-telegraf"; +// import { TelegrafModule } from "nestjs-telegraf"; import { bullMqConfig } from "./configs/bullmq.config"; import { cacheConfig } from "./configs/cache.config"; import { mailerConfig } from "./configs/mailer.config"; import { rateLimitConfig } from "./configs/rateLimit.config"; -import { telegrafConfig } from "./configs/telegraf.config"; +// import { telegrafConfig } from "./configs/telegraf.config"; import { databaseConfigs } from "./configs/typeorm.config"; import { HTTPLogger } from "./core/middlewares/logger.middleware"; import { AddressModule } from "./modules/address/address.module"; @@ -26,8 +26,9 @@ import { CriticismModule } from "./modules/criticisms/criticisms.module"; import { DanakServicesModule } from "./modules/danak-services/danak-services.module"; import { DashboardModule } from "./modules/dashboards/dashboard.module"; import { InvoicesModule } from "./modules/invoices/invoices.module"; +import { LandingModule } from "./modules/landing/landing.module"; import { LearningModule } from "./modules/learnings/learning.module"; -import { LoggerModule } from "./modules/logger/logger.module"; +// import { LoggerModule } from "./modules/logger/logger.module"; import { NotificationModule } from "./modules/notifications/notifications.module"; import { PaymentsModule } from "./modules/payments/payments.module"; import { SettingModule } from "./modules/settings/settings.module"; @@ -36,9 +37,10 @@ import { TicketsModule } from "./modules/tickets/tickets.module"; import { UploaderModule } from "./modules/uploader/uploader.module"; import { UsersModule } from "./modules/users/users.module"; import { WalletsModule } from "./modules/wallets/wallets.module"; + @Module({ imports: [ - TelegrafModule.forRootAsync(telegrafConfig()), + // TelegrafModule.forRootAsync(telegrafConfig()), MailerModule.forRootAsync(mailerConfig()), BullModule.forRootAsync(bullMqConfig()), ThrottlerModule.forRootAsync(rateLimitConfig()), @@ -66,7 +68,8 @@ import { WalletsModule } from "./modules/wallets/wallets.module"; AddressModule, DashboardModule, BlogsModule, - LoggerModule, + // LoggerModule, + LandingModule, ], controllers: [], }) diff --git a/src/modules/blogs/DTO/create-blog.dto.ts b/src/modules/blogs/DTO/create-blog.dto.ts index 675f714..182cab9 100644 --- a/src/modules/blogs/DTO/create-blog.dto.ts +++ b/src/modules/blogs/DTO/create-blog.dto.ts @@ -25,6 +25,7 @@ export class CreateBlogDto { @IsNotEmpty({ message: BlogMessage.IMAGE_URL_REQUIRED }) @IsString({ message: BlogMessage.IMAGE_URL_STRING }) @MaxLength(150, { message: BlogMessage.IMAGE_URL_MAX_LENGTH }) + @ApiProperty({ description: "Image URL of the blog", example: "https://example.com/image.jpg" }) imageUrl: string; @IsNotEmpty({ message: BlogMessage.META_TITLE_REQUIRED }) diff --git a/src/modules/blogs/controllers/blogs.controller.ts b/src/modules/blogs/controllers/blogs.controller.ts index 86bb8c4..4dea3d5 100644 --- a/src/modules/blogs/controllers/blogs.controller.ts +++ b/src/modules/blogs/controllers/blogs.controller.ts @@ -1,4 +1,4 @@ -import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Patch, Post, Put, Query } from "@nestjs/common"; +import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Patch, Post, Query } from "@nestjs/common"; import { ApiOperation } from "@nestjs/swagger"; import { AdminRoute } from "../../../common/decorators/admin.decorator"; @@ -32,6 +32,13 @@ export class BlogsController { return this.blogsService.getBlogsPublic(queryDto); } + @ApiOperation({ summary: "Get most visited and pinned blogs" }) + @SkipAuth() + @Get("combined") + getCombinedBlogs() { + return this.blogsService.getCombinedBlogs(); + } + @ApiOperation({ summary: "Get all blogs (admin route)" }) @AdminRoute() @PermissionsDec(PermissionEnum.BLOGS) @@ -127,7 +134,7 @@ export class BlogsController { @ApiOperation({ summary: "Update the status of a comment (admin route)" }) @AdminRoute() @PermissionsDec(PermissionEnum.BLOGS) - @Put("comments/:id/status") + @Patch("comments/:id/status") updateCommentStatus(@Param() paramDto: ParamDto, @Body() updateCommentStatusDto: UpdateCommentStatusDto) { return this.blogsService.updateCommentStatus(paramDto.id, updateCommentStatusDto); } @@ -162,7 +169,7 @@ export class BlogsController { } @ApiOperation({ summary: "Update a category (admin route)" }) - @Put("categories/:id") + @Patch("categories/:id") @AdminRoute() @PermissionsDec(PermissionEnum.BLOGS) updateCategory(@Param() paramDto: ParamDto, @Body() updateCategoryDto: UpdateCategoryDto) { diff --git a/src/modules/blogs/providers/blogs.service.ts b/src/modules/blogs/providers/blogs.service.ts index 59c7c05..7cd4972 100644 --- a/src/modules/blogs/providers/blogs.service.ts +++ b/src/modules/blogs/providers/blogs.service.ts @@ -175,8 +175,23 @@ export class BlogsService { //*********************************** */ async getBlogsPublic(queryDto: BlogSearchQueryDto) { - const blogs = await this.blogsRepository.getBlogsForUserSide(queryDto); - return { blogs }; + const [blogs, count] = await this.blogsRepository.getBlogsForUserSide(queryDto); + + //; + return { + blogs, + count, + paginate: true, + }; + } + //*********************************** */ + + async getCombinedBlogs() { + const [pinnedBlogs, mostVisitedBlogs] = await Promise.all([ + this.blogsRepository.getPinnedBlogs(), + this.blogsRepository.getMostVisitedBlogs(), + ]); + return { pinnedBlogs, mostVisitedBlogs }; } //*********************************** */ @@ -244,17 +259,20 @@ export class BlogsService { return category; } + //*********************************** */ async incrementViewCount(id: string) { const blog = await this.findBlogById(id); blog.viewCount += 1; await this.blogsRepository.save(blog); return { message: "View count incremented successfully" }; } + //*********************************** */ async getMostVisitedBlogs() { const blogs = await this.blogsRepository.getMostVisitedBlogs(); return { blogs }; } + //*********************************** */ async getPinnedBlogs() { const blogs = await this.blogsRepository.getPinnedBlogs(); diff --git a/src/modules/danak-services/danak-services.controller.ts b/src/modules/danak-services/danak-services.controller.ts index 063c80b..15f5fe0 100755 --- a/src/modules/danak-services/danak-services.controller.ts +++ b/src/modules/danak-services/danak-services.controller.ts @@ -49,7 +49,7 @@ export class DanakServicesController { return this.danakServicesService.getCategoryList(queryDto); } - @AuthGuards() + // @AuthGuards() @ApiOperation({ summary: "Get all service categories user side" }) @Get("categories/public") getCategoriesUserSide() { @@ -106,7 +106,7 @@ export class DanakServicesController { } @ApiOperation({ summary: "get all danak services for user side" }) - @AuthGuards() + // @AuthGuards() @Get("public") getServicesForUser(@Query() queryDto: DanakServicesQueryDto) { return this.danakServicesService.getServicesListForUser(queryDto); diff --git a/src/modules/landing/landing.controller.ts b/src/modules/landing/landing.controller.ts new file mode 100644 index 0000000..cab4b80 --- /dev/null +++ b/src/modules/landing/landing.controller.ts @@ -0,0 +1,15 @@ +import { Controller, Get } from "@nestjs/common"; +import { ApiOperation } from "@nestjs/swagger"; + +import { LandingService } from "./providers/landing.service"; + +@Controller("landing") +export class LandingController { + constructor(private readonly landingService: LandingService) {} + + @ApiOperation({ summary: "Get all landing page data" }) + @Get() + async getLandingData() { + return this.landingService.getLandingData(); + } +} diff --git a/src/modules/landing/landing.module.ts b/src/modules/landing/landing.module.ts new file mode 100644 index 0000000..41946f8 --- /dev/null +++ b/src/modules/landing/landing.module.ts @@ -0,0 +1,15 @@ +import { Module } from "@nestjs/common"; + +import { LandingController } from "./landing.controller"; +import { LandingService } from "./providers/landing.service"; +import { BlogsModule } from "../blogs/blogs.module"; +import { DanakServicesModule } from "../danak-services/danak-services.module"; +import { SlidersModule } from "../sliders/sliders.module"; + +@Module({ + imports: [SlidersModule, BlogsModule, DanakServicesModule], + controllers: [LandingController], + providers: [LandingService], + exports: [LandingService], +}) +export class LandingModule {} diff --git a/src/modules/landing/providers/landing.service.ts b/src/modules/landing/providers/landing.service.ts new file mode 100644 index 0000000..ceee004 --- /dev/null +++ b/src/modules/landing/providers/landing.service.ts @@ -0,0 +1,27 @@ +import { Injectable } from "@nestjs/common"; + +import { BlogsService } from "../../blogs/providers/blogs.service"; +import { DanakServicesService } from "../../danak-services/providers/danak-services.service"; +import { SlidersService } from "../../sliders/providers/sliders.service"; +@Injectable() +export class LandingService { + constructor( + private readonly slidersService: SlidersService, + private readonly blogsService: BlogsService, + private readonly danakServices: DanakServicesService, + ) {} + + async getLandingData() { + const [sliders, pinnedBlogs, danakSuggestServices] = await Promise.all([ + this.slidersService.getSlidersListForLanding(), + this.blogsService.getPinnedBlogs(), + this.danakServices.getDanakSuggestServices(), + ]); + + return { + sliders, + pinnedBlogs: pinnedBlogs.blogs, + danakSuggestServices: danakSuggestServices.danakServices, + }; + } +} diff --git a/src/modules/sliders/entities/slider.entity.ts b/src/modules/sliders/entities/slider.entity.ts index 0f39ebd..2fb6729 100644 --- a/src/modules/sliders/entities/slider.entity.ts +++ b/src/modules/sliders/entities/slider.entity.ts @@ -14,7 +14,7 @@ export class Slider extends BaseEntity { imageUrl: string; @Column({ length: 255, nullable: true }) - link: string; + link?: string; @Column({ default: 0 }) order: number; diff --git a/src/modules/sliders/providers/slider.service.ts b/src/modules/sliders/providers/slider.service.ts deleted file mode 100644 index f19ae50..0000000 --- a/src/modules/sliders/providers/slider.service.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { Injectable, NotFoundException } from "@nestjs/common"; -import { InjectRepository } from "@nestjs/typeorm"; -import { Repository } from "typeorm"; - -import { SliderMessage } from "../../../common/enums/message.enum"; -import { CreateSliderDto } from "../DTO/create-slider.dto"; -import { UpdateSliderDto } from "../DTO/update-slider.dto"; -import { Slider } from "../entities/slider.entity"; - -@Injectable() -export class SliderService { - constructor( - @InjectRepository(Slider) - private readonly sliderRepository: Repository, - ) {} - - async create(createSliderDto: CreateSliderDto): Promise { - const slider = this.sliderRepository.create(createSliderDto); - return await this.sliderRepository.save(slider); - } - - async findAll(): Promise { - return await this.sliderRepository.find({ - order: { - order: "ASC", - }, - }); - } - - async getSliderById(id: string): Promise { - const slider = await this.sliderRepository.findOne({ where: { id } }); - if (!slider) { - throw new NotFoundException(SliderMessage.SLIDER_NOT_FOUND); - } - return slider; - } - - async update(id: string, updateSliderDto: UpdateSliderDto): Promise { - const slider = await this.getSliderById(id); - Object.assign(slider, updateSliderDto); - return await this.sliderRepository.save(slider); - } - - async remove(id: string): Promise { - const slider = await this.getSliderById(id); - await this.sliderRepository.remove(slider); - } -} diff --git a/src/modules/sliders/providers/sliders.service.ts b/src/modules/sliders/providers/sliders.service.ts new file mode 100644 index 0000000..2c9b99d --- /dev/null +++ b/src/modules/sliders/providers/sliders.service.ts @@ -0,0 +1,73 @@ +import { Injectable, NotFoundException } from "@nestjs/common"; + +import { PaginationDto } from "../../../common/DTO/pagination.dto"; +import { CommonMessage, SliderMessage } from "../../../common/enums/message.enum"; +import { CreateSliderDto } from "../DTO/create-slider.dto"; +import { UpdateSliderDto } from "../DTO/update-slider.dto"; +import { SlidersRepository } from "../repositories/sliders.repository"; +@Injectable() +export class SlidersService { + constructor(private readonly slidersRepository: SlidersRepository) {} + + async create(createSliderDto: CreateSliderDto) { + const slider = this.slidersRepository.create(createSliderDto); + await this.slidersRepository.save(slider); + return { + message: CommonMessage.CREATED, + slider, + }; + } + //*************************** */ + async getSlidersList(queryDto: PaginationDto) { + const [sliders, count] = await this.slidersRepository.getSlidersListForAdmin(queryDto); + return { + sliders, + count, + paginate: true, + }; + } + //************************* */ + async getSliderById(id: string) { + const slider = await this.slidersRepository.findOne({ where: { id } }); + if (!slider) throw new NotFoundException(SliderMessage.SLIDER_NOT_FOUND); + + return { + slider, + }; + } + //****************** */ + async update(id: string, updateSliderDto: UpdateSliderDto) { + const { slider } = await this.getSliderById(id); + + await this.slidersRepository.save({ ...slider, ...updateSliderDto }); + return { + message: CommonMessage.UPDATE_SUCCESS, + }; + } + //****************** */ + async remove(id: string) { + const { slider } = await this.getSliderById(id); + await this.slidersRepository.remove(slider); + + return { + message: CommonMessage.DELETED, + }; + } + //****************** */ + + async toggleSliderStatus(id: string) { + const { slider } = await this.getSliderById(id); + slider.isActive = !slider.isActive; + await this.slidersRepository.save(slider); + return { + message: CommonMessage.UPDATE_SUCCESS, + }; + } + //****************** */ + + async getSlidersListForLanding() { + const sliders = await this.slidersRepository.find({ where: { isActive: true } }); + return sliders; + } + //****************** */ +} diff --git a/src/modules/sliders/repositories/sliders.repository.ts b/src/modules/sliders/repositories/sliders.repository.ts index 61b363c..2ed1deb 100644 --- a/src/modules/sliders/repositories/sliders.repository.ts +++ b/src/modules/sliders/repositories/sliders.repository.ts @@ -2,6 +2,8 @@ import { Injectable } from "@nestjs/common"; import { InjectRepository } from "@nestjs/typeorm"; import { Repository } from "typeorm"; +import { PaginationDto } from "../../../common/DTO/pagination.dto"; +import { PaginationUtils } from "../../utils/providers/pagination.utils"; import { Slider } from "../entities/slider.entity"; @Injectable() @@ -9,4 +11,16 @@ export class SlidersRepository extends Repository { constructor(@InjectRepository(Slider) repository: Repository) { super(repository.target, repository.manager, repository.queryRunner); } + + async getSlidersListForAdmin(queryDto: PaginationDto) { + const { skip, limit } = PaginationUtils(queryDto); + + return this.findAndCount({ + skip, + take: limit, + order: { + order: "ASC", + }, + }); + } } diff --git a/src/modules/sliders/slider.controller.ts b/src/modules/sliders/sliders.controller.ts similarity index 55% rename from src/modules/sliders/slider.controller.ts rename to src/modules/sliders/sliders.controller.ts index 7b31b6b..369e9fd 100644 --- a/src/modules/sliders/slider.controller.ts +++ b/src/modules/sliders/sliders.controller.ts @@ -1,49 +1,53 @@ -import { Body, Controller, Delete, Get, Param, Patch, Post } from "@nestjs/common"; +import { Body, Controller, Delete, Get, Param, Patch, Post, Query } from "@nestjs/common"; import { ApiOperation } from "@nestjs/swagger"; import { CreateSliderDto } from "./DTO/create-slider.dto"; import { UpdateSliderDto } from "./DTO/update-slider.dto"; -import { SliderService } from "./providers/slider.service"; +import { SlidersService } from "./providers/sliders.service"; +import { AdminRoute } from "../../common/decorators/admin.decorator"; import { AuthGuards } from "../../common/decorators/auth-guard.decorator"; -import { SkipAuth } from "../../common/decorators/skip-auth.decorator"; +import { PaginationDto } from "../../common/DTO/pagination.dto"; import { ParamDto } from "../../common/DTO/param.dto"; // import { PermissionsDec } from "../../common/decorators/permission.decorator"; @Controller("sliders") @AuthGuards() -export class SliderController { - constructor(private readonly sliderService: SliderService) {} +export class SlidersController { + constructor(private readonly slidersService: SlidersService) {} @ApiOperation({ summary: "create slider (admin route)" }) + @AdminRoute() // @PermissionsDec(PermissionEnum.SLIDER) @Post() create(@Body() createSliderDto: CreateSliderDto) { - return this.sliderService.create(createSliderDto); + return this.slidersService.create(createSliderDto); } @ApiOperation({ summary: "Get all sliders" }) - @SkipAuth() + @AdminRoute() @Get() - findAll() { - return this.sliderService.findAll(); + getSlidersList(@Query() queryDto: PaginationDto) { + return this.slidersService.getSlidersList(queryDto); } - @Get(":id") @ApiOperation({ summary: "Get a slider by id" }) - @SkipAuth() + @AdminRoute() + @Get(":id") getSliderById(@Param() paramDto: ParamDto) { - return this.sliderService.getSliderById(paramDto.id); + return this.slidersService.getSliderById(paramDto.id); } @ApiOperation({ summary: "Update a slider" }) + @AdminRoute() @Patch(":id") update(@Param() paramDto: ParamDto, @Body() updateSliderDto: UpdateSliderDto) { - return this.sliderService.update(paramDto.id, updateSliderDto); + return this.slidersService.update(paramDto.id, updateSliderDto); } @ApiOperation({ summary: "Delete a slider" }) + @AdminRoute() @Delete(":id") remove(@Param() paramDto: ParamDto) { - return this.sliderService.remove(paramDto.id); + return this.slidersService.remove(paramDto.id); } } diff --git a/src/modules/sliders/slider.module.ts b/src/modules/sliders/sliders.module.ts similarity index 51% rename from src/modules/sliders/slider.module.ts rename to src/modules/sliders/sliders.module.ts index f43f77e..dae852a 100644 --- a/src/modules/sliders/slider.module.ts +++ b/src/modules/sliders/sliders.module.ts @@ -2,14 +2,14 @@ import { Module } from "@nestjs/common"; import { TypeOrmModule } from "@nestjs/typeorm"; import { Slider } from "./entities/slider.entity"; -import { SliderService } from "./providers/slider.service"; +import { SlidersService } from "./providers/sliders.service"; import { SlidersRepository } from "./repositories/sliders.repository"; -import { SliderController } from "./slider.controller"; +import { SlidersController } from "./sliders.controller"; @Module({ imports: [TypeOrmModule.forFeature([Slider])], - controllers: [SliderController], - providers: [SliderService, SlidersRepository], - exports: [SliderService], + controllers: [SlidersController], + providers: [SlidersService, SlidersRepository], + exports: [SlidersService], }) -export class SliderModule {} +export class SlidersModule {}