import { Transform, Type } from 'class-transformer' import { ArrayMaxSize, ArrayMinSize, IsArray, IsBoolean, IsIn, IsInt, IsOptional, IsString, Length, Max, MaxLength, Min, ValidateNested } from 'class-validator' const Trim = () => Transform(({ value }: { value: unknown }) => typeof value === 'string' ? value.trim() : value) export class TeachingCaseFrameDto { @IsIn(['pair', 'composite']) kind!: 'pair' | 'composite' @IsString() @Length(1, 100) beforeId!: string @IsOptional() @IsString() @Length(1, 100) afterId?: string @Trim() @IsString() @MaxLength(100) caption!: string } export class SaveTeachingCaseDto { @Trim() @IsString() @Length(1, 80) title!: string @Trim() @IsString() @Length(1, 30) displayName!: string @IsInt() @Min(1) @Max(9999) lessonCount!: number @Trim() @IsString() @MaxLength(500) background!: string @Trim() @IsString() @Length(1, 1000) achievement!: string @IsArray() @ArrayMinSize(1) @ArrayMaxSize(9) @ValidateNested({ each: true }) @Type(() => TeachingCaseFrameDto) frames!: TeachingCaseFrameDto[] @IsInt() @Min(0) @Max(9999) sortOrder!: number @IsBoolean() published!: boolean @IsBoolean() consentConfirmed!: boolean @Trim() @IsString() @MaxLength(500) consentNote!: string @IsInt() @Min(0) version!: number } export class TeachingCaseQueryDto { @IsOptional() @Type(() => Number) @IsInt() @Min(1) @Max(100000) page = 1 @IsOptional() @Type(() => Number) @IsInt() @Min(1) @Max(20) limit = 10 } export class TeachingCaseUploadDto { @IsString() @Length(1, 200) fileName!: string }