import { IsBoolean, IsDateString, IsNumber, IsOptional, IsString, Max, MaxLength, Min, MinLength, Matches, ValidateBy, ValidateIf } from 'class-validator' import { ApparatusNotes, isApparatusNotes, isPostureAssessment, LESSON_NOTE_MAX_LENGTH, PostureAssessment } from '@mp-pilates/shared' export class BodyMetricDto { @IsDateString() @Matches(/^\d{4}-\d{2}-\d{2}$/) recordedAt!: string @IsOptional() @IsNumber() @Min(30) @Max(250) height?: number | null @IsOptional() @IsNumber() @Min(1) @Max(500) weight?: number | null @IsOptional() @IsNumber() @Min(1) @Max(75) bodyFat?: number | null @IsOptional() @IsNumber() @Min(10) @Max(300) waist?: number | null @IsOptional() @IsNumber() @Min(10) @Max(300) hip?: number | null @IsOptional() @IsNumber() @Min(-50) @Max(100) flexibility?: number | null @IsOptional() @ValidateBy({ name: 'postureAssessment', validator: { validate: isPostureAssessment, defaultMessage: () => '体态检查内容无效,请检查选项及左右侧标记' } }) assessment?: PostureAssessment | null @IsOptional() @IsString() @MaxLength(200) remark?: string } export class MemberNoteDto { @IsOptional() @IsString() @MaxLength(LESSON_NOTE_MAX_LENGTH) content?: string @ValidateIf((_object, value) => value !== undefined) @ValidateBy({ name: 'apparatusNotes', validator: { validate: isApparatusNotes, defaultMessage: () => '器械记录无效,每项最多填写1000字' } }) apparatusNotes?: ApparatusNotes @IsBoolean() shared!: boolean @IsOptional() @IsString() @MinLength(1) bookingId?: string } export class ProgressPhotoDto { @IsDateString() @Matches(/^\d{4}-\d{2}-\d{2}$/) recordedAt!: string @IsString() @MaxLength(200) caption!: string @IsString() @MaxLength(100) fileName!: string } export class PhotoConsentDto { @IsBoolean() consent!: boolean }