import { ApiProperty } from '@nestjs/swagger'; import { IsArray, IsEnum, IsNotEmpty, ArrayMinSize, ArrayUnique, IsOptional, IsInt } from 'class-validator'; import { ClaimVehicleTypeV2, OuterPartSideV2, } from "src/static/outer-car-parts-catalog"; import { DamageSelectedPartV2BodyDto } from "./damage-selected-part-v2.dto"; /** * Enum for valid outer car parts that can be damaged * Follows the naming convention from workflow step definition */ export enum OuterCarPart { // Hood HOOD = 'hood', // Doors FRONT_RIGHT_DOOR = 'front_right_door', FRONT_LEFT_DOOR = 'front_left_door', REAR_RIGHT_DOOR = 'rear_right_door', REAR_LEFT_DOOR = 'rear_left_door', // Bumpers FRONT_BUMPER = 'front_bumper', REAR_BUMPER = 'rear_bumper', // Fenders FRONT_RIGHT_FENDER = 'front_right_fender', FRONT_LEFT_FENDER = 'front_left_fender', REAR_RIGHT_FENDER = 'rear_right_fender', REAR_LEFT_FENDER = 'rear_left_fender', // Trunk & Roof TRUNK = 'trunk', ROOF = 'roof', } /** * V2 DTO for selecting damaged outer car parts * Much cleaner than the nested boolean structure */ export class SelectOuterPartsV2Dto { @ApiProperty({ description: 'Array of selected damaged outer car parts', example: ['hood', 'front_right_door', 'rear_bumper', 'roof'], enum: OuterCarPart, isArray: true, minItems: 1, maxItems: 13, }) @IsOptional() @IsArray({ message: 'selectedParts must be an array' }) @ArrayMinSize(1, { message: 'At least one damaged part must be selected' }) @ArrayUnique({ message: 'Duplicate parts are not allowed' }) @IsEnum(OuterCarPart, { each: true, message: 'Invalid part name. Must be one of the valid outer car parts', }) selectedParts?: OuterCarPart[]; @ApiProperty({ description: 'Selected outer part IDs from catalog', example: [9, 10, 4], type: [Number], required: false, }) @IsOptional() @IsArray({ message: 'selectedPartIds must be an array' }) @ArrayMinSize(1, { message: 'At least one part ID must be selected' }) @ArrayUnique({ message: 'Duplicate part IDs are not allowed' }) @IsInt({ each: true, message: 'Each selected part ID must be an integer' }) selectedPartIds?: number[]; @ApiProperty({ description: 'Vehicle type for validating available outer parts', enum: ClaimVehicleTypeV2, required: true, }) @IsNotEmpty() @IsEnum(ClaimVehicleTypeV2) carType?: ClaimVehicleTypeV2; } /** * Response DTO for select outer parts V2 */ export class SelectOuterPartsV2ResponseDto { @ApiProperty({ description: 'Claim request ID', example: '507f1f77bcf86cd799439011', }) claimRequestId: string; @ApiProperty({ description: 'Public ID shared across blame and claim', example: 'A14235', }) publicId: string; @ApiProperty({ description: "Ordered selected parts: id, side-agnostic name, side, label_fa (and optional catalogKey)", type: [DamageSelectedPartV2BodyDto], }) selectedParts: DamageSelectedPartV2BodyDto[]; @ApiProperty({ description: 'Selected part IDs', example: [9, 7, 11], type: [Number], }) selectedPartIds: number[]; @ApiProperty({ description: 'Current workflow step', example: 'SELECT_OUTER_PARTS', }) currentStep: string; @ApiProperty({ description: 'Next possible workflow step', example: 'SELECT_OTHER_PARTS', }) nextStep: string; @ApiProperty({ description: 'Success message', example: 'Outer parts selected successfully. Please proceed to select other parts.', }) message: string; } export class SetClaimVehicleTypeV2Dto { @ApiProperty({ description: "Vehicle type selected by user", enum: ClaimVehicleTypeV2, }) @IsNotEmpty() @IsEnum(ClaimVehicleTypeV2) carType: ClaimVehicleTypeV2; } /** * Shape returned by `GET .../outer-parts-catalog` (both user and expert * controllers). It mirrors how items are persisted under * `damage.selectedParts` (see `DamageSelectedPartV2BodyDto`) so the front-end * can match catalog rows to stored selections without any field renaming: * `name` is side-agnostic, `label_fa` is disambiguated with the side in * parentheses, and the original full catalog key (`left_backfender`) is * exposed as `catalogKey`. */ export class OuterPartCatalogItemDto { @ApiProperty({ description: "Static catalog id (unique across all car types)", example: 102, }) id: number; @ApiProperty({ description: "Side-agnostic part name (matches stored part `name`)", example: "backWheel", }) name: string; @ApiProperty({ description: "Vehicle side / region", enum: OuterPartSideV2, example: "left", }) side: string; @ApiProperty({ description: "Display label in Farsi, with side disambiguator in parentheses when needed", example: "چرخ عقب (چپ)", }) label_fa: string; @ApiProperty({ description: "Original full catalog key (matches stored `catalogKey`)", example: "left_backWheel", required: false, }) catalogKey?: string; @ApiProperty({ description: "Vehicle type this catalog row belongs to", enum: ClaimVehicleTypeV2, required: false, example: "suv", }) carType?: ClaimVehicleTypeV2; }