Expand filters logic
This commit is contained in:
parent
755f07af92
commit
58d605e090
|
|
@ -1,11 +1,11 @@
|
||||||
import { Controller, Get, Query, Param } from '@nestjs/common';
|
import { Controller, Get, Query, Param } from '@nestjs/common';
|
||||||
import { CatalogService } from './catalog.service';
|
import { CatalogService } from './catalog.service';
|
||||||
import { CatalogResponseDto } from './dto/catalog-response.dto';
|
import { CatalogResponseDto } from './dto/catalog-response.dto';
|
||||||
|
import { CatalogFiltersDto } from './dto/catalog-filters.dto';
|
||||||
import {
|
import {
|
||||||
CatalogItemShortDto,
|
CatalogItemShortDto,
|
||||||
CatalogItemLongDto,
|
CatalogItemLongDto,
|
||||||
} from './dto/catalog-item.dto';
|
} from './dto/catalog-item.dto';
|
||||||
import { CatalogParamsDto } from './dto/catalog-params.dto';
|
|
||||||
import {
|
import {
|
||||||
ApiQuery,
|
ApiQuery,
|
||||||
ApiResponse,
|
ApiResponse,
|
||||||
|
|
@ -18,44 +18,36 @@ import { MainPageCatalogResponseDto } from './dto/main-page-catalog-response.dto
|
||||||
export class CatalogController {
|
export class CatalogController {
|
||||||
constructor(private readonly catalogService: CatalogService) {}
|
constructor(private readonly catalogService: CatalogService) {}
|
||||||
|
|
||||||
@Get()
|
@Get('filter')
|
||||||
@ApiOperation({ summary: 'Get catalog with filters, search and sorting' })
|
@ApiOperation({ summary: 'Filter catalog items with query parameters' })
|
||||||
@ApiResponse({
|
@ApiResponse({
|
||||||
status: 200,
|
status: 200,
|
||||||
description: 'Catalog items with filters applied',
|
description: 'Filtered catalog items',
|
||||||
type: CatalogResponseDto,
|
type: CatalogResponseDto,
|
||||||
})
|
})
|
||||||
@ApiQuery({
|
@ApiQuery({ name: 'search', required: false, type: String })
|
||||||
name: 'params',
|
@ApiQuery({ name: 'minLength', required: false, type: Number })
|
||||||
required: false,
|
@ApiQuery({ name: 'maxLength', required: false, type: Number })
|
||||||
description: 'JSON string of filter parameters',
|
@ApiQuery({ name: 'minPrice', required: false, type: Number })
|
||||||
type: String,
|
@ApiQuery({ name: 'maxPrice', required: false, type: Number })
|
||||||
})
|
@ApiQuery({ name: 'minYear', required: false, type: Number })
|
||||||
async getCatalog(
|
@ApiQuery({ name: 'maxYear', required: false, type: Number })
|
||||||
@Query('params') paramsString?: string,
|
@ApiQuery({ name: 'guests', required: false, type: Number })
|
||||||
|
@ApiQuery({ name: 'sortByPrice', required: false, type: String })
|
||||||
|
@ApiQuery({ name: 'paymentType', required: false, type: String })
|
||||||
|
@ApiQuery({ name: 'quickBooking', required: false, type: Boolean })
|
||||||
|
@ApiQuery({ name: 'hasToilet', required: false, type: Boolean })
|
||||||
|
@ApiQuery({ name: 'date', required: false, type: Date })
|
||||||
|
@ApiQuery({ name: 'departureTime', required: false, type: String })
|
||||||
|
@ApiQuery({ name: 'arrivalTime', required: false, type: String })
|
||||||
|
async getFilteredCatalog(
|
||||||
|
@Query() filters: CatalogFiltersDto,
|
||||||
): Promise<CatalogResponseDto> {
|
): Promise<CatalogResponseDto> {
|
||||||
let params: CatalogParamsDto = {};
|
return this.catalogService.getCatalog(filters);
|
||||||
|
|
||||||
if (paramsString) {
|
|
||||||
try {
|
|
||||||
params = JSON.parse(decodeURIComponent(paramsString));
|
|
||||||
} catch (error) {
|
|
||||||
params = {};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.catalogService.getCatalog(params);
|
@Get()
|
||||||
}
|
@ApiOperation({ summary: 'Get all catalog items (deprecated, use /filter)' })
|
||||||
|
|
||||||
@Get('main-page')
|
|
||||||
@ApiOperation({ summary: 'Get catalog for main page' })
|
|
||||||
@ApiProperty({ type: MainPageCatalogResponseDto })
|
|
||||||
async getMainPageCatalog(): Promise<MainPageCatalogResponseDto | null> {
|
|
||||||
return this.catalogService.getMainPageCatalog();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Get('all')
|
|
||||||
@ApiOperation({ summary: 'Get all catalog items without filters' })
|
|
||||||
@ApiResponse({
|
@ApiResponse({
|
||||||
status: 200,
|
status: 200,
|
||||||
description: 'All catalog items',
|
description: 'All catalog items',
|
||||||
|
|
@ -65,12 +57,11 @@ export class CatalogController {
|
||||||
return this.catalogService.getAllCatalogItems();
|
return this.catalogService.getAllCatalogItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('filtered')
|
@Get('main-page')
|
||||||
@ApiOperation({ summary: 'Get catalog with explicit query parameters' })
|
@ApiOperation({ summary: 'Get catalog for main page' })
|
||||||
async getFilteredCatalog(
|
@ApiProperty({ type: MainPageCatalogResponseDto })
|
||||||
@Query() params: CatalogParamsDto,
|
async getMainPageCatalog(): Promise<MainPageCatalogResponseDto | null> {
|
||||||
): Promise<CatalogResponseDto> {
|
return this.catalogService.getMainPageCatalog();
|
||||||
return this.catalogService.getCatalog(params);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import {
|
||||||
import { CatalogParamsDto } from './dto/catalog-params.dto';
|
import { CatalogParamsDto } from './dto/catalog-params.dto';
|
||||||
import { CatalogResponseDto } from './dto/catalog-response.dto';
|
import { CatalogResponseDto } from './dto/catalog-response.dto';
|
||||||
import { MainPageCatalogResponseDto } from './dto/main-page-catalog-response.dto';
|
import { MainPageCatalogResponseDto } from './dto/main-page-catalog-response.dto';
|
||||||
|
import { CatalogFiltersDto } from './dto/catalog-filters.dto';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CatalogService {
|
export class CatalogService {
|
||||||
|
|
@ -493,46 +494,116 @@ export class CatalogService {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getCatalog(params?: CatalogParamsDto): Promise<CatalogResponseDto> {
|
async getCatalog(filters?: CatalogFiltersDto): Promise<CatalogResponseDto> {
|
||||||
|
// Start with all items converted to short DTO
|
||||||
let filteredItems = this.catalogItems.map((item) => this.toShortDto(item));
|
let filteredItems = this.catalogItems.map((item) => this.toShortDto(item));
|
||||||
|
|
||||||
if (params?.search) {
|
// Get the full items for filtering by properties not in short DTO
|
||||||
const searchTerm = params.search.toLowerCase();
|
const fullItems = this.catalogItems;
|
||||||
filteredItems = filteredItems.filter((item) =>
|
|
||||||
item.name.toLowerCase().includes(searchTerm),
|
// Search filter
|
||||||
|
if (filters?.search) {
|
||||||
|
const searchTerm = filters.search.toLowerCase();
|
||||||
|
filteredItems = filteredItems.filter((item) => {
|
||||||
|
const fullItem = fullItems.find((fi) => fi.id === item.id);
|
||||||
|
return (
|
||||||
|
item.name.toLowerCase().includes(searchTerm) ||
|
||||||
|
(fullItem && fullItem.description.toLowerCase().includes(searchTerm))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Length filter
|
||||||
|
if (filters?.minLength !== undefined) {
|
||||||
|
filteredItems = filteredItems.filter(
|
||||||
|
(item) => item.length >= filters.minLength!,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (filters?.maxLength !== undefined) {
|
||||||
|
filteredItems = filteredItems.filter(
|
||||||
|
(item) => item.length <= filters.maxLength!,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params?.filter?.price) {
|
// Price filter
|
||||||
const { minvalue, maxvalue } = params.filter.price;
|
if (filters?.minPrice !== undefined) {
|
||||||
|
filteredItems = filteredItems.filter(
|
||||||
|
(item) => item.minCost >= filters.minPrice!,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (filters?.maxPrice !== undefined) {
|
||||||
|
filteredItems = filteredItems.filter(
|
||||||
|
(item) => item.minCost <= filters.maxPrice!,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Year filter
|
||||||
|
if (filters?.minYear !== undefined || filters?.maxYear !== undefined) {
|
||||||
filteredItems = filteredItems.filter((item) => {
|
filteredItems = filteredItems.filter((item) => {
|
||||||
if (minvalue !== undefined && item.minCost < minvalue) return false;
|
const fullItem = fullItems.find((fi) => fi.id === item.id);
|
||||||
if (maxvalue !== undefined && item.minCost > maxvalue) return false;
|
if (!fullItem) return false;
|
||||||
|
|
||||||
|
if (filters.minYear !== undefined && fullItem.year < filters.minYear)
|
||||||
|
return false;
|
||||||
|
if (filters.maxYear !== undefined && fullItem.year > filters.maxYear)
|
||||||
|
return false;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params?.sort?.field) {
|
if (filters?.guests !== undefined) {
|
||||||
const { field, direction = 'asc' } = params.sort;
|
const totalPeople = filters?.guests!;
|
||||||
filteredItems.sort((a, b) => {
|
filteredItems = filteredItems.filter((item) => {
|
||||||
let valueA = a[field];
|
const fullItem = fullItems.find((fi) => fi.id === item.id);
|
||||||
let valueB = b[field];
|
return fullItem && fullItem.maxCapacity >= totalPeople;
|
||||||
|
|
||||||
if (typeof valueA === 'string') valueA = valueA.toLowerCase();
|
|
||||||
if (typeof valueB === 'string') valueB = valueB.toLowerCase();
|
|
||||||
|
|
||||||
if (valueA < valueB) return direction === 'asc' ? -1 : 1;
|
|
||||||
if (valueA > valueB) return direction === 'asc' ? 1 : -1;
|
|
||||||
return 0;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Quick booking filter
|
||||||
|
if (filters?.quickBooking !== undefined) {
|
||||||
|
filteredItems = filteredItems.filter(
|
||||||
|
(item) => item.hasQuickRent === filters.quickBooking,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Has toilet filter (check if cabinsCount > 0)
|
||||||
|
if (filters?.hasToilet !== undefined) {
|
||||||
|
filteredItems = filteredItems.filter((item) => {
|
||||||
|
const fullItem = fullItems.find((fi) => fi.id === item.id);
|
||||||
|
if (!fullItem) return false;
|
||||||
|
return filters.hasToilet
|
||||||
|
? fullItem.cabinsCount > 0
|
||||||
|
: fullItem.cabinsCount === 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Payment type filter (assuming all accept card payments)
|
||||||
|
if (filters?.paymentType) {
|
||||||
|
// For now, all yachts accept card payments
|
||||||
|
// You could add a paymentTypes array to CatalogItemLongDto if needed
|
||||||
|
console.log('Payment type filtering:', filters.paymentType);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Date/time filter (check reservations)
|
||||||
|
if (filters?.date || filters?.departureTime || filters?.arrivalTime) {
|
||||||
|
// This is more complex - would need to check reservations
|
||||||
|
// For now, we'll return all items
|
||||||
|
console.log('Date/time filtering available for future implementation');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filters?.sortByPrice === 'asc') {
|
||||||
|
filteredItems.sort((a, b) => a.minCost - b.minCost);
|
||||||
|
} else if (filters?.sortByPrice === 'desc') {
|
||||||
|
filteredItems.sort((a, b) => b.minCost - a.minCost);
|
||||||
|
} else {
|
||||||
|
filteredItems.sort((a, b) => a.name.localeCompare(b.name));
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
items: filteredItems,
|
items: filteredItems,
|
||||||
total: filteredItems.length,
|
total: filteredItems.length,
|
||||||
filters: params?.filter,
|
filters,
|
||||||
sort: params?.sort,
|
search: filters?.search,
|
||||||
search: params?.search,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,146 @@
|
||||||
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
import { Type } from 'class-transformer';
|
||||||
|
import {
|
||||||
|
IsOptional,
|
||||||
|
IsString,
|
||||||
|
IsNumber,
|
||||||
|
IsBoolean,
|
||||||
|
IsDate,
|
||||||
|
Min,
|
||||||
|
} from 'class-validator';
|
||||||
|
|
||||||
|
export class CatalogFiltersDto {
|
||||||
|
@ApiProperty({ required: false, description: 'Search by yacht name' })
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
search?: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
required: false,
|
||||||
|
description: 'Minimum length in meters',
|
||||||
|
example: 10,
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
@IsNumber()
|
||||||
|
@Min(0)
|
||||||
|
@Type(() => Number)
|
||||||
|
minLength?: number;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
required: false,
|
||||||
|
description: 'Maximum length in meters',
|
||||||
|
example: 20,
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
@IsNumber()
|
||||||
|
@Min(0)
|
||||||
|
@Type(() => Number)
|
||||||
|
maxLength?: number;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
required: false,
|
||||||
|
description: 'Minimum price',
|
||||||
|
example: 30000,
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
@IsNumber()
|
||||||
|
@Min(0)
|
||||||
|
@Type(() => Number)
|
||||||
|
minPrice?: number;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
required: false,
|
||||||
|
description: 'Maximum price',
|
||||||
|
example: 100000,
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
@IsNumber()
|
||||||
|
@Min(0)
|
||||||
|
@Type(() => Number)
|
||||||
|
maxPrice?: number;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
required: false,
|
||||||
|
description: 'Sort by price',
|
||||||
|
example: 100000,
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
@IsNumber()
|
||||||
|
@Min(0)
|
||||||
|
@Type(() => Number)
|
||||||
|
sortByPrice?: string;
|
||||||
|
|
||||||
|
@ApiProperty({ required: false, description: 'Minimum year', example: 2019 })
|
||||||
|
@IsOptional()
|
||||||
|
@IsNumber()
|
||||||
|
@Min(1900)
|
||||||
|
@Type(() => Number)
|
||||||
|
minYear?: number;
|
||||||
|
|
||||||
|
@ApiProperty({ required: false, description: 'Maximum year', example: 2023 })
|
||||||
|
@IsOptional()
|
||||||
|
@IsNumber()
|
||||||
|
@Min(1900)
|
||||||
|
@Type(() => Number)
|
||||||
|
maxYear?: number;
|
||||||
|
|
||||||
|
@ApiProperty({ required: false, description: 'Number of guests', example: 4 })
|
||||||
|
@IsOptional()
|
||||||
|
@IsNumber()
|
||||||
|
@Min(1)
|
||||||
|
@Type(() => Number)
|
||||||
|
guests?: number;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
required: false,
|
||||||
|
description: 'Payment type',
|
||||||
|
example: 'card',
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
paymentType?: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
required: false,
|
||||||
|
description: 'Quick booking available',
|
||||||
|
example: true,
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
@IsBoolean()
|
||||||
|
@Type(() => Boolean)
|
||||||
|
quickBooking?: boolean;
|
||||||
|
|
||||||
|
@ApiProperty({ required: false, description: 'Has toilet', example: true })
|
||||||
|
@IsOptional()
|
||||||
|
@IsBoolean()
|
||||||
|
@Type(() => Boolean)
|
||||||
|
hasToilet?: boolean;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
required: false,
|
||||||
|
description: 'Departure date',
|
||||||
|
example: '2025-12-20',
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
@IsDate()
|
||||||
|
@Type(() => Date)
|
||||||
|
date?: Date;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
required: false,
|
||||||
|
description: 'Departure time',
|
||||||
|
example: '08:00',
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
departureTime?: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
required: false,
|
||||||
|
description: 'Arrival time',
|
||||||
|
example: '20:00',
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
arrivalTime?: string;
|
||||||
|
}
|
||||||
|
|
@ -1,31 +1,133 @@
|
||||||
import { type Reservation } from 'src/reservations/reservations.service';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { type Review } from 'src/reviews/reviews.service';
|
export class UserDto {
|
||||||
import { User } from 'src/users/user.entity';
|
@ApiProperty({ example: 1 })
|
||||||
|
userId: number;
|
||||||
|
|
||||||
|
@ApiProperty({ example: 'Иван' })
|
||||||
|
firstName: string;
|
||||||
|
|
||||||
|
@ApiProperty({ example: 'Андреев' })
|
||||||
|
lastName: string;
|
||||||
|
|
||||||
|
@ApiProperty({ example: '+79009009090' })
|
||||||
|
phone: string;
|
||||||
|
|
||||||
|
@ApiProperty({ example: 'ivan@yachting.ru' })
|
||||||
|
email: string;
|
||||||
|
|
||||||
|
@ApiProperty({ example: 'Северный Флот', required: false })
|
||||||
|
companyName?: string;
|
||||||
|
|
||||||
|
@ApiProperty({ example: 1234567890, required: false })
|
||||||
|
inn?: number;
|
||||||
|
|
||||||
|
@ApiProperty({ example: 1122334455667, required: false })
|
||||||
|
ogrn?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ReviewDto {
|
||||||
|
@ApiProperty({ example: 1 })
|
||||||
|
id: number;
|
||||||
|
|
||||||
|
@ApiProperty({ example: 1 })
|
||||||
|
reviewerId: number;
|
||||||
|
|
||||||
|
@ApiProperty({ example: 1 })
|
||||||
|
yachtId: number;
|
||||||
|
|
||||||
|
@ApiProperty({ example: 5 })
|
||||||
|
starsCount: number;
|
||||||
|
|
||||||
|
@ApiProperty({ example: 'Excellent yacht!' })
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ReservationDto {
|
||||||
|
@ApiProperty({ example: 1 })
|
||||||
|
id: number;
|
||||||
|
|
||||||
|
@ApiProperty({ example: 1 })
|
||||||
|
yachtId: number;
|
||||||
|
|
||||||
|
@ApiProperty({ example: 1 })
|
||||||
|
reservatorId: number;
|
||||||
|
|
||||||
|
@ApiProperty({ example: 1733097600 })
|
||||||
|
startUtc: number;
|
||||||
|
|
||||||
|
@ApiProperty({ example: 1733133600 })
|
||||||
|
endUtc: number;
|
||||||
|
}
|
||||||
|
|
||||||
export class CatalogItemShortDto {
|
export class CatalogItemShortDto {
|
||||||
|
@ApiProperty({ example: 1 })
|
||||||
id?: number;
|
id?: number;
|
||||||
|
|
||||||
|
@ApiProperty({ example: 'Азимут 55' })
|
||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
|
@ApiProperty({ example: 16.7 })
|
||||||
length: number;
|
length: number;
|
||||||
|
|
||||||
|
@ApiProperty({ example: 32 })
|
||||||
speed: number;
|
speed: number;
|
||||||
|
|
||||||
|
@ApiProperty({ example: 85000 })
|
||||||
minCost: number;
|
minCost: number;
|
||||||
|
|
||||||
|
@ApiProperty({ example: 'api/uploads/1765727362318-238005198.jpg' })
|
||||||
mainImageUrl: string;
|
mainImageUrl: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
type: [String],
|
||||||
|
example: ['api/uploads/1765727362318-238005198.jpg'],
|
||||||
|
})
|
||||||
galleryUrls: string[];
|
galleryUrls: string[];
|
||||||
|
|
||||||
|
@ApiProperty({ example: true })
|
||||||
hasQuickRent: boolean;
|
hasQuickRent: boolean;
|
||||||
|
|
||||||
|
@ApiProperty({ example: true })
|
||||||
isFeatured: boolean;
|
isFeatured: boolean;
|
||||||
|
|
||||||
|
@ApiProperty({ required: false, example: '🔥 Лучшее предложение' })
|
||||||
topText?: string;
|
topText?: string;
|
||||||
|
|
||||||
|
@ApiProperty({ required: false, example: true })
|
||||||
isBestOffer?: boolean;
|
isBestOffer?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CatalogItemLongDto extends CatalogItemShortDto {
|
export class CatalogItemLongDto extends CatalogItemShortDto {
|
||||||
|
@ApiProperty({ example: 2022 })
|
||||||
year: number;
|
year: number;
|
||||||
|
|
||||||
|
@ApiProperty({ example: 8 })
|
||||||
comfortCapacity: number;
|
comfortCapacity: number;
|
||||||
|
|
||||||
|
@ApiProperty({ example: 12 })
|
||||||
maxCapacity: number;
|
maxCapacity: number;
|
||||||
|
|
||||||
|
@ApiProperty({ example: 4.8 })
|
||||||
width: number;
|
width: number;
|
||||||
|
|
||||||
|
@ApiProperty({ example: 3 })
|
||||||
cabinsCount: number;
|
cabinsCount: number;
|
||||||
|
|
||||||
|
@ApiProperty({ example: 'Стеклопластик' })
|
||||||
matherial: string;
|
matherial: string;
|
||||||
|
|
||||||
|
@ApiProperty({ example: 1200 })
|
||||||
power: number;
|
power: number;
|
||||||
|
|
||||||
|
@ApiProperty({ example: 'Роскошная моторная яхта...' })
|
||||||
description: string;
|
description: string;
|
||||||
owner: User;
|
|
||||||
reviews: Review[];
|
@ApiProperty({ type: UserDto })
|
||||||
reservations: Reservation[];
|
owner: UserDto;
|
||||||
|
|
||||||
|
@ApiProperty({ type: [ReviewDto] })
|
||||||
|
reviews: ReviewDto[];
|
||||||
|
|
||||||
|
@ApiProperty({ type: [ReservationDto] })
|
||||||
|
reservations: ReservationDto[];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,29 @@
|
||||||
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { CatalogItemShortDto } from './catalog-item.dto';
|
import { CatalogItemShortDto } from './catalog-item.dto';
|
||||||
|
import { CatalogFiltersDto } from './catalog-filters.dto';
|
||||||
|
|
||||||
export class CatalogResponseDto {
|
export class CatalogResponseDto {
|
||||||
|
@ApiProperty({ type: [CatalogItemShortDto] })
|
||||||
items: CatalogItemShortDto[];
|
items: CatalogItemShortDto[];
|
||||||
|
|
||||||
|
@ApiProperty({ example: 42 })
|
||||||
total: number;
|
total: number;
|
||||||
|
|
||||||
|
@ApiProperty({ required: false, example: 1 })
|
||||||
page?: number;
|
page?: number;
|
||||||
|
|
||||||
|
@ApiProperty({ required: false, example: 10 })
|
||||||
limit?: number;
|
limit?: number;
|
||||||
filters?: any;
|
|
||||||
|
@ApiProperty({ type: CatalogFiltersDto, required: false })
|
||||||
|
filters?: CatalogFiltersDto;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
required: false,
|
||||||
|
example: { field: 'name', direction: 'asc' },
|
||||||
|
})
|
||||||
sort?: any;
|
sort?: any;
|
||||||
|
|
||||||
|
@ApiProperty({ required: false, example: 'yacht' })
|
||||||
search?: string;
|
search?: string;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue