From f8f3fa528e61d420d4a65e5412ceeabb1c85221d Mon Sep 17 00:00:00 2001 From: morteza-mortezai Date: Sat, 4 Jul 2026 15:43:13 +0330 Subject: [PATCH] background pattern --- ...n20260704120000_AddShopBackgroundFields.ts | 21 ++++++++++++++ ...ation20260704130000_AddBackgroundsTable.ts | 15 ++++++++++ .../shops/controllers/shops.controller.ts | 20 +++++++++++++ .../shops/dto/update-shop-background.dto.ts | 29 +++++++++++++++++++ .../shops/entities/background.entity.ts | 9 ++++++ src/modules/shops/entities/shop.entity.ts | 15 ++++++++++ src/modules/shops/providers/shops.service.ts | 19 ++++++++++++ src/modules/shops/shops.module.ts | 3 +- 8 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 database/migrations/Migration20260704120000_AddShopBackgroundFields.ts create mode 100644 database/migrations/Migration20260704130000_AddBackgroundsTable.ts create mode 100644 src/modules/shops/dto/update-shop-background.dto.ts create mode 100644 src/modules/shops/entities/background.entity.ts diff --git a/database/migrations/Migration20260704120000_AddShopBackgroundFields.ts b/database/migrations/Migration20260704120000_AddShopBackgroundFields.ts new file mode 100644 index 0000000..8b1c285 --- /dev/null +++ b/database/migrations/Migration20260704120000_AddShopBackgroundFields.ts @@ -0,0 +1,21 @@ +import { Migration } from '@mikro-orm/migrations'; + +export class Migration20260704120000_AddShopBackgroundFields extends Migration { + + override async up(): Promise { + this.addSql(`alter table "shops" add column "bg_type" varchar(255) null;`); + this.addSql(`alter table "shops" add column "bg_url" varchar(255) null;`); + this.addSql(`alter table "shops" add column "bg_opacity" varchar(255) null;`); + this.addSql(`alter table "shops" add column "bg_blur" varchar(255) null;`); + this.addSql(`alter table "shops" add column "bg_overlay" varchar(255) null;`); + } + + override async down(): Promise { + this.addSql(`alter table "shops" drop column "bg_overlay";`); + this.addSql(`alter table "shops" drop column "bg_blur";`); + this.addSql(`alter table "shops" drop column "bg_opacity";`); + this.addSql(`alter table "shops" drop column "bg_url";`); + this.addSql(`alter table "shops" drop column "bg_type";`); + } + +} diff --git a/database/migrations/Migration20260704130000_AddBackgroundsTable.ts b/database/migrations/Migration20260704130000_AddBackgroundsTable.ts new file mode 100644 index 0000000..de352b5 --- /dev/null +++ b/database/migrations/Migration20260704130000_AddBackgroundsTable.ts @@ -0,0 +1,15 @@ +import { Migration } from '@mikro-orm/migrations'; + +export class Migration20260704130000_AddBackgroundsTable extends Migration { + + override async up(): Promise { + this.addSql(`create table "backgrounds" ("id" char(26) not null, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, "url" varchar(255) not null, constraint "backgrounds_pkey" primary key ("id"));`); + this.addSql(`create index "backgrounds_created_at_index" on "backgrounds" ("created_at");`); + this.addSql(`create index "backgrounds_deleted_at_index" on "backgrounds" ("deleted_at");`); + } + + override async down(): Promise { + this.addSql(`drop table if exists "backgrounds" cascade;`); + } + +} diff --git a/src/modules/shops/controllers/shops.controller.ts b/src/modules/shops/controllers/shops.controller.ts index 532766b..368a505 100644 --- a/src/modules/shops/controllers/shops.controller.ts +++ b/src/modules/shops/controllers/shops.controller.ts @@ -3,6 +3,7 @@ import { ShopService } from '../providers/shops.service'; import { CreateRestaurantDto } from '../dto/create-shop.dto'; import { UpdateRestaurantDto } from '../dto/update-shop.dto'; import { UpdateSubscriptionDto } from '../dto/update-subscription.dto'; +import { UpdateShopBackgroundDto } from '../dto/update-shop-background.dto'; import { FindRestaurantsDto } from '../dto/find-shops.dto'; import { AdminAuthGuard } from 'src/modules/auth/guards/adminAuth.guard'; import { @@ -55,6 +56,25 @@ export class ShopController { return this.shopService.update(shopId, updateRestaurantDto); } + @UseGuards(AdminAuthGuard) + @ApiBearerAuth() + @Permissions(Permission.UPDATE_RESTAURANT) + @ApiOperation({ summary: 'Get all available backgrounds' }) + @Get('admin/backgrounds') + findAllBackgrounds() { + return this.shopService.findAllBackgrounds(); + } + + @UseGuards(AdminAuthGuard) + @ApiBearerAuth() + @Permissions(Permission.UPDATE_RESTAURANT) + @ApiOperation({ summary: 'Update shop background settings' }) + @ApiBody({ type: UpdateShopBackgroundDto }) + @Patch('admin/shops/my-shop/background') + updateMyShopBackground(@ShopId() shopId: string, @Body() dto: UpdateShopBackgroundDto) { + return this.shopService.updateBackground(shopId, dto); + } + /** Super Admin Endpoints */ @UseGuards(SuperAdminAuthGuard) diff --git a/src/modules/shops/dto/update-shop-background.dto.ts b/src/modules/shops/dto/update-shop-background.dto.ts new file mode 100644 index 0000000..02a01e6 --- /dev/null +++ b/src/modules/shops/dto/update-shop-background.dto.ts @@ -0,0 +1,29 @@ +import { ApiPropertyOptional } from '@nestjs/swagger'; +import { IsOptional, IsString } from 'class-validator'; + +export class UpdateShopBackgroundDto { + @ApiPropertyOptional({ example: 'preset', description: 'Background type (e.g. preset, custom)' }) + @IsOptional() + @IsString() + bgType?: string; + + @ApiPropertyOptional({ example: 'https://example.com/background.jpg', description: 'Background image URL' }) + @IsOptional() + @IsString() + bgUrl?: string; + + @ApiPropertyOptional({ example: '0.5', description: 'Background opacity' }) + @IsOptional() + @IsString() + bgOpacity?: string; + + @ApiPropertyOptional({ example: '8px', description: 'Background blur' }) + @IsOptional() + @IsString() + bgBlur?: string; + + @ApiPropertyOptional({ example: 'rgba(0, 0, 0, 0.4)', description: 'Background overlay color' }) + @IsOptional() + @IsString() + bgOverlay?: string; +} diff --git a/src/modules/shops/entities/background.entity.ts b/src/modules/shops/entities/background.entity.ts new file mode 100644 index 0000000..58ee7c2 --- /dev/null +++ b/src/modules/shops/entities/background.entity.ts @@ -0,0 +1,9 @@ +import { Entity, Property } from '@mikro-orm/core'; +import { BaseEntity } from '../../../common/entities/base.entity'; + +@Entity({ tableName: 'backgrounds' }) +export class Background extends BaseEntity { + @Property() + url: string; + +} diff --git a/src/modules/shops/entities/shop.entity.ts b/src/modules/shops/entities/shop.entity.ts index b042128..cce78c4 100644 --- a/src/modules/shops/entities/shop.entity.ts +++ b/src/modules/shops/entities/shop.entity.ts @@ -113,4 +113,19 @@ export class Shop extends BaseEntity { @OneToMany(() => Config, config => config.shop) configs = new Collection(this); + @Property({ nullable: true }) + bgType?: string; + + @Property({ nullable: true }) + bgUrl?: string; + + @Property({ nullable: true }) + bgOpacity?: string; + + @Property({ nullable: true }) + bgBlur?: string; + + @Property({ nullable: true }) + bgOverlay?: string; + } diff --git a/src/modules/shops/providers/shops.service.ts b/src/modules/shops/providers/shops.service.ts index b01026a..23baa14 100644 --- a/src/modules/shops/providers/shops.service.ts +++ b/src/modules/shops/providers/shops.service.ts @@ -2,7 +2,9 @@ import { BadRequestException, Injectable, NotFoundException } from '@nestjs/comm import { CreateRestaurantDto } from '../dto/create-shop.dto'; import { UpdateRestaurantDto } from '../dto/update-shop.dto'; import { UpdateSubscriptionDto } from '../dto/update-subscription.dto'; +import { UpdateShopBackgroundDto } from '../dto/update-shop-background.dto'; import { Shop } from '../entities/shop.entity'; +import { Background } from '../entities/background.entity'; import { EntityManager } from '@mikro-orm/postgresql'; import { ShopRepository } from '../repositories/rest.repository'; import { ShopMessage } from 'src/common/enums/message.enum'; @@ -147,6 +149,23 @@ export class ShopService { return shop; } + async findAllBackgrounds(): Promise { + return this.em.find(Background, {}, { orderBy: { createdAt: 'asc' } }); + } + + async updateBackground(id: string, dto: UpdateShopBackgroundDto): Promise { + const shop = await this.shopRepository.findOne({ id }); + + if (!shop) { + throw new NotFoundException(ShopMessage.NOT_FOUND); + } + + this.shopRepository.assign(shop, dto); + await this.em.flush(); + + return shop; + } + async update(id: string, dto: UpdateRestaurantDto): Promise { const shop = await this.shopRepository.findOne({ id: id }); diff --git a/src/modules/shops/shops.module.ts b/src/modules/shops/shops.module.ts index f13a9a3..0bf5f75 100644 --- a/src/modules/shops/shops.module.ts +++ b/src/modules/shops/shops.module.ts @@ -1,6 +1,7 @@ import { Module, forwardRef } from '@nestjs/common'; import { MikroOrmModule } from '@mikro-orm/nestjs'; import { Shop } from './entities/shop.entity'; +import { Background } from './entities/background.entity'; import { ShopRepository } from './repositories/rest.repository'; import { ScheduleRepository } from './repositories/schedule.repository'; import { Schedule } from './entities/schedule.entity'; @@ -15,7 +16,7 @@ import { ShopService } from './providers/shops.service'; @Module({ controllers: [ShopController, ScheduleController], providers: [ShopService, ShopRepository, ScheduleRepository, ScheduleService, ShopCrone], - imports: [MikroOrmModule.forFeature([Shop, Schedule]), JwtModule, forwardRef(() => AuthModule)], + imports: [MikroOrmModule.forFeature([Shop, Schedule, Background]), JwtModule, forwardRef(() => AuthModule)], exports: [ShopRepository, ScheduleRepository, ScheduleService,ShopService], }) export class ShopsModule { }