Files
backend/src/products/dto/product.dto.ts
T
Alireza HassaniandCursor 1a49576752 Add OTP-first signup and product catalog PDF uploads.
Signup verifies phone before password; existing Meshkee accounts keep their password. Products can attach an optional PDF catalog (max 2MB) via Pars Pack media.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-27 08:57:08 +03:30

204 lines
3.1 KiB
TypeScript

import { ContentStatus } from '@prisma/client';
import { Transform, Type } from 'class-transformer';
import {
IsArray,
IsBoolean,
IsEnum,
IsInt,
IsNumber,
IsOptional,
IsString,
Matches,
Min,
MinLength,
MaxLength,
} from 'class-validator';
export class ListProductsDto {
@IsOptional()
@Type(() => Number)
@IsInt()
@Min(1)
page?: number;
@IsOptional()
@Type(() => Number)
@IsInt()
@Min(1)
pageSize?: number;
@IsOptional()
@IsEnum(ContentStatus)
status?: ContentStatus;
@IsOptional()
@IsString()
name?: string;
}
export class ListPublicProductsDto {
@IsOptional()
@Type(() => Number)
@IsInt()
@Min(1)
page?: number;
@IsOptional()
@Type(() => Number)
@IsInt()
@Min(1)
pageSize?: number;
@IsOptional()
@IsString()
name?: string;
@IsOptional()
@IsString()
categoryId?: string;
@IsOptional()
@IsString()
brandId?: string;
@IsOptional()
@IsString()
tag?: string;
@IsOptional()
@Transform(({ value }) => value === 'true' || value === true)
@IsBoolean()
inStore?: boolean;
}
export class CreateProductDto {
@IsString()
@MinLength(2)
title!: string;
@IsOptional()
@IsString()
nameFa?: string;
@IsOptional()
@IsString()
summary?: string;
@IsOptional()
@IsString()
descriptionHtml?: string;
@IsOptional()
@IsString()
categoryId?: string;
@IsOptional()
@IsString()
brandId?: string;
@IsOptional()
@IsEnum(ContentStatus)
status?: ContentStatus;
@IsOptional()
@IsString()
featuredMediaId?: string;
/** Optional PDF catalog file (media id; application/pdf, max 2MB). */
@IsOptional()
@IsString()
catalogMediaId?: string;
@IsOptional()
@IsArray()
@IsString({ each: true })
galleryMediaIds?: string[];
@IsOptional()
@IsArray()
@IsString({ each: true })
tags?: string[];
@IsOptional()
@IsString()
@MaxLength(70)
seoMetaTitle?: string | null;
@IsOptional()
@IsString()
@MaxLength(160)
seoMetaDescription?: string | null;
@IsOptional()
@IsString()
@Matches(/^[a-z0-9]+(?:-[a-z0-9]+)*$/)
slug?: string;
}
export class UpdateProductDto {
@IsOptional()
@IsString()
@MinLength(2)
title?: string;
@IsOptional()
@IsString()
nameFa?: string | null;
@IsOptional()
@IsString()
summary?: string | null;
@IsOptional()
@IsString()
descriptionHtml?: string | null;
@IsOptional()
@IsString()
categoryId?: string | null;
@IsOptional()
@IsString()
brandId?: string | null;
@IsOptional()
@IsEnum(ContentStatus)
status?: ContentStatus;
@IsOptional()
@IsString()
featuredMediaId?: string | null;
/** Optional PDF catalog file (media id). Pass null to clear. */
@IsOptional()
@IsString()
catalogMediaId?: string | null;
@IsOptional()
@IsArray()
@IsString({ each: true })
galleryMediaIds?: string[];
@IsOptional()
@IsArray()
@IsString({ each: true })
tags?: string[];
@IsOptional()
@IsString()
@MaxLength(70)
seoMetaTitle?: string | null;
@IsOptional()
@IsString()
@MaxLength(160)
seoMetaDescription?: string | null;
@IsOptional()
@IsString()
@Matches(/^[a-z0-9]+(?:-[a-z0-9]+)*$/)
slug?: string;
}