mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
194 lines
4.2 KiB
TypeScript
194 lines
4.2 KiB
TypeScript
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
|
import { Type } from 'class-transformer';
|
|
import {
|
|
IsEmail,
|
|
IsEnum,
|
|
IsInt,
|
|
IsOptional,
|
|
IsString,
|
|
Length,
|
|
Max,
|
|
MaxLength,
|
|
Min,
|
|
MinLength,
|
|
} from 'class-validator';
|
|
|
|
export enum SupportStatusDto {
|
|
OPEN = 'OPEN',
|
|
RESOLVED = 'RESOLVED',
|
|
CLOSED = 'CLOSED',
|
|
}
|
|
|
|
export class CreateConversationDto {
|
|
@ApiProperty({ description: 'Short subject / topic of the request.' })
|
|
@IsString()
|
|
@Length(3, 200)
|
|
subject!: string;
|
|
|
|
@ApiProperty({ description: 'The first message body.' })
|
|
@IsString()
|
|
@MinLength(1)
|
|
@MaxLength(4000)
|
|
initialMessage!: string;
|
|
}
|
|
|
|
/**
|
|
* Text is optional across the send DTOs because a message may be nothing but
|
|
* attachments. "Neither text nor files" is rejected in the service rather than
|
|
* here — the validator can't see the multipart file parts.
|
|
*/
|
|
export class SendMessageDto {
|
|
@ApiPropertyOptional({
|
|
description: 'Message text. Optional only when attachments are present.',
|
|
})
|
|
@IsOptional()
|
|
@IsString()
|
|
@MaxLength(4000)
|
|
text?: string;
|
|
}
|
|
|
|
export class CreateGuestConversationDto {
|
|
@ApiProperty({ description: 'Client-generated anonymous id (localStorage).' })
|
|
@IsString()
|
|
@Length(8, 120)
|
|
guestId!: string;
|
|
|
|
@ApiProperty({ description: 'Guest full name.' })
|
|
@IsString()
|
|
@Length(1, 120)
|
|
name!: string;
|
|
|
|
@ApiProperty({ description: 'Guest email for follow-up.' })
|
|
@IsEmail()
|
|
email!: string;
|
|
|
|
@ApiPropertyOptional({ description: 'Guest phone (optional).' })
|
|
@IsOptional()
|
|
@IsString()
|
|
@MaxLength(40)
|
|
phone?: string;
|
|
|
|
@ApiProperty()
|
|
@IsString()
|
|
@Length(3, 200)
|
|
subject!: string;
|
|
|
|
@ApiProperty()
|
|
@IsString()
|
|
@MinLength(1)
|
|
@MaxLength(4000)
|
|
initialMessage!: string;
|
|
}
|
|
|
|
export class GuestSendMessageDto {
|
|
@ApiProperty({ description: 'The guest id that owns the conversation.' })
|
|
@IsString()
|
|
@Length(8, 120)
|
|
guestId!: string;
|
|
|
|
@ApiPropertyOptional({
|
|
description: 'Message text. Optional only when attachments are present.',
|
|
})
|
|
@IsOptional()
|
|
@IsString()
|
|
@MaxLength(4000)
|
|
text?: string;
|
|
}
|
|
|
|
export class GuestIdBodyDto {
|
|
@ApiProperty()
|
|
@IsString()
|
|
@Length(8, 120)
|
|
guestId!: string;
|
|
}
|
|
|
|
export class DeviceSendMessageDto {
|
|
@ApiProperty({ description: 'Client device id (localStorage).' })
|
|
@IsString()
|
|
@Length(8, 120)
|
|
deviceId!: string;
|
|
|
|
@ApiPropertyOptional({
|
|
description: 'Message text. Optional only when attachments are present.',
|
|
})
|
|
@IsOptional()
|
|
@IsString()
|
|
@MaxLength(4000)
|
|
text?: string;
|
|
}
|
|
|
|
export class DeviceIdBodyDto {
|
|
@ApiProperty()
|
|
@IsString()
|
|
@Length(8, 120)
|
|
deviceId!: string;
|
|
}
|
|
|
|
export class UpdateStatusDto {
|
|
@ApiProperty({ enum: SupportStatusDto })
|
|
@IsEnum(SupportStatusDto)
|
|
status!: SupportStatusDto;
|
|
}
|
|
|
|
export class ListConversationsQueryDto {
|
|
@ApiPropertyOptional({ enum: SupportStatusDto })
|
|
@IsOptional()
|
|
@IsEnum(SupportStatusDto)
|
|
status?: SupportStatusDto;
|
|
|
|
@ApiPropertyOptional({ description: 'Search subject / passenger name.' })
|
|
@IsOptional()
|
|
@IsString()
|
|
search?: string;
|
|
|
|
@ApiPropertyOptional({ minimum: 1, default: 1 })
|
|
@IsOptional()
|
|
@Type(() => Number)
|
|
@IsInt()
|
|
@Min(1)
|
|
page?: number;
|
|
|
|
@ApiPropertyOptional({ minimum: 1, maximum: 100, default: 100 })
|
|
@IsOptional()
|
|
@Type(() => Number)
|
|
@IsInt()
|
|
@Min(1)
|
|
@Max(100)
|
|
limit?: number;
|
|
}
|
|
|
|
/** Default page size for a thread — roughly two screens of bubbles. */
|
|
export const SUPPORT_MESSAGES_DEFAULT_LIMIT = 30;
|
|
export const SUPPORT_MESSAGES_MAX_LIMIT = 100;
|
|
|
|
export class ListMessagesQueryDto {
|
|
@ApiPropertyOptional({
|
|
description:
|
|
"Opaque cursor from a previous response's `nextCursor`. Returns the page " +
|
|
'of messages immediately OLDER than the cursor. Omit for the newest page.',
|
|
})
|
|
@IsOptional()
|
|
@IsString()
|
|
before?: string;
|
|
|
|
@ApiPropertyOptional({
|
|
minimum: 1,
|
|
maximum: SUPPORT_MESSAGES_MAX_LIMIT,
|
|
default: SUPPORT_MESSAGES_DEFAULT_LIMIT,
|
|
})
|
|
@IsOptional()
|
|
@Type(() => Number)
|
|
@IsInt()
|
|
@Min(1)
|
|
@Max(SUPPORT_MESSAGES_MAX_LIMIT)
|
|
limit?: number;
|
|
}
|
|
|
|
/** Query form of {@link ListMessagesQueryDto} for the device-scoped thread. */
|
|
export class DeviceThreadQueryDto extends ListMessagesQueryDto {
|
|
@ApiProperty({ description: 'Client device id (localStorage).' })
|
|
@IsString()
|
|
@Length(8, 120)
|
|
deviceId!: string;
|
|
}
|