338 lines
11 KiB
TypeScript
338 lines
11 KiB
TypeScript
import { Injectable } from '@nestjs/common';
|
||
import { CatalogItemDto } from './dto/catalog-item.dto';
|
||
import { CatalogParamsDto } from './dto/catalog-params.dto';
|
||
import { CatalogResponseDto } from './dto/catalog-response.dto';
|
||
import { MainPageCatalogResponseDto } from './dto/main-page-catalog-response.dto';
|
||
|
||
@Injectable()
|
||
export class CatalogService {
|
||
private catalogItems: CatalogItemDto[] = [
|
||
{
|
||
id: 1,
|
||
name: 'Azimut 55',
|
||
length: 16.7,
|
||
speed: 32,
|
||
minCost: 85000,
|
||
mainImageUrl: '/api/uploads/1765727362318-238005198.jpg',
|
||
galleryUrls: [
|
||
'/api/uploads/1765727362318-238005198.jpg',
|
||
'/api/uploads/1765727637471-474231444.webp',
|
||
'/api/uploads/1765727743466-187581713.webp',
|
||
'/api/uploads/1765727819793-158598111.webp',
|
||
'/api/uploads/1765727903961-559930753.webp',
|
||
'/api/uploads/1765727928577-55944164.webp',
|
||
'/api/uploads/1765727948691-389175954.webp',
|
||
'/api/uploads/1765727961591-243584836.webp',
|
||
'/api/uploads/1765727992064-37229339.webp',
|
||
],
|
||
hasQuickRent: true,
|
||
isFeatured: true,
|
||
},
|
||
{
|
||
id: 2,
|
||
name: 'Sunseeker Manhattan 52',
|
||
length: 15.8,
|
||
speed: 34,
|
||
minCost: 92000,
|
||
mainImageUrl: '/api/uploads/1765728068963-634185622.webp',
|
||
galleryUrls: [
|
||
'/api/uploads/1765728068963-634185622.webp',
|
||
'/api/uploads/1765727637471-474231444.webp',
|
||
'/api/uploads/1765727743466-187581713.webp',
|
||
'/api/uploads/1765727819793-158598111.webp',
|
||
'/api/uploads/1765727903961-559930753.webp',
|
||
'/api/uploads/1765727928577-55944164.webp',
|
||
'/api/uploads/1765727948691-389175954.webp',
|
||
'/api/uploads/1765727961591-243584836.webp',
|
||
'/api/uploads/1765727992064-37229339.webp',
|
||
],
|
||
hasQuickRent: false,
|
||
isFeatured: false,
|
||
topText: '🔥 Лучшее предложение',
|
||
},
|
||
{
|
||
id: 3,
|
||
name: 'Princess V55',
|
||
length: 16.7,
|
||
speed: 33,
|
||
minCost: 78000,
|
||
mainImageUrl: '/api/uploads/1765728152179-305707681.webp',
|
||
galleryUrls: [
|
||
'/api/uploads/1765728152179-305707681.webp',
|
||
'/api/uploads/1765727637471-474231444.webp',
|
||
'/api/uploads/1765727743466-187581713.webp',
|
||
'/api/uploads/1765727819793-158598111.webp',
|
||
'/api/uploads/1765727903961-559930753.webp',
|
||
'/api/uploads/1765727928577-55944164.webp',
|
||
'/api/uploads/1765727948691-389175954.webp',
|
||
'/api/uploads/1765727961591-243584836.webp',
|
||
'/api/uploads/1765727992064-37229339.webp',
|
||
],
|
||
hasQuickRent: true,
|
||
isFeatured: false,
|
||
topText: '🍷 Идеальна для заката с бокалом вина',
|
||
},
|
||
{
|
||
id: 4,
|
||
name: 'Ferretti 500',
|
||
length: 15.2,
|
||
speed: 31,
|
||
minCost: 68000,
|
||
mainImageUrl: '/api/uploads/1765728169750-667674217.webp',
|
||
galleryUrls: [
|
||
'/api/uploads/1765728169750-667674217.webp',
|
||
'/api/uploads/1765727637471-474231444.webp',
|
||
'/api/uploads/1765727743466-187581713.webp',
|
||
'/api/uploads/1765727819793-158598111.webp',
|
||
'/api/uploads/1765727903961-559930753.webp',
|
||
'/api/uploads/1765727928577-55944164.webp',
|
||
'/api/uploads/1765727948691-389175954.webp',
|
||
'/api/uploads/1765727961591-243584836.webp',
|
||
'/api/uploads/1765727992064-37229339.webp',
|
||
],
|
||
hasQuickRent: true,
|
||
isFeatured: false,
|
||
topText: '⏳ Часто бронируется - успей',
|
||
},
|
||
{
|
||
id: 5,
|
||
name: 'Sea Ray 510 Sundancer',
|
||
length: 15.5,
|
||
speed: 35,
|
||
minCost: 72000,
|
||
mainImageUrl: '/api/uploads/1765728190017-763752836.webp',
|
||
galleryUrls: [
|
||
'/api/uploads/1765728190017-763752836.webp',
|
||
'/api/uploads/1765727637471-474231444.webp',
|
||
'/api/uploads/1765727743466-187581713.webp',
|
||
'/api/uploads/1765727819793-158598111.webp',
|
||
'/api/uploads/1765727903961-559930753.webp',
|
||
'/api/uploads/1765727928577-55944164.webp',
|
||
'/api/uploads/1765727948691-389175954.webp',
|
||
'/api/uploads/1765727961591-243584836.webp',
|
||
'/api/uploads/1765727992064-37229339.webp',
|
||
],
|
||
hasQuickRent: false,
|
||
isFeatured: false,
|
||
},
|
||
{
|
||
id: 6,
|
||
name: 'Bavaria SR41',
|
||
length: 12.5,
|
||
speed: 28,
|
||
minCost: 45000,
|
||
mainImageUrl: '/api/uploads/1765728208376-854378188.webp',
|
||
galleryUrls: [
|
||
'/api/uploads/1765728208376-854378188.webp',
|
||
'/api/uploads/1765727637471-474231444.webp',
|
||
'/api/uploads/1765727743466-187581713.webp',
|
||
'/api/uploads/1765727819793-158598111.webp',
|
||
'/api/uploads/1765727903961-559930753.webp',
|
||
'/api/uploads/1765727928577-55944164.webp',
|
||
'/api/uploads/1765727948691-389175954.webp',
|
||
'/api/uploads/1765727961591-243584836.webp',
|
||
'/api/uploads/1765727992064-37229339.webp',
|
||
],
|
||
hasQuickRent: true,
|
||
isFeatured: false,
|
||
},
|
||
{
|
||
id: 7,
|
||
name: 'Jeanneau Merry Fisher 895',
|
||
length: 8.9,
|
||
speed: 25,
|
||
minCost: 32000,
|
||
mainImageUrl: '/api/uploads/1765728227998-695635756.webp',
|
||
galleryUrls: [
|
||
'/api/uploads/1765728227998-695635756.webp',
|
||
'/api/uploads/1765727637471-474231444.webp',
|
||
'/api/uploads/1765727743466-187581713.webp',
|
||
'/api/uploads/1765727819793-158598111.webp',
|
||
'/api/uploads/1765727903961-559930753.webp',
|
||
'/api/uploads/1765727928577-55944164.webp',
|
||
'/api/uploads/1765727948691-389175954.webp',
|
||
'/api/uploads/1765727961591-243584836.webp',
|
||
'/api/uploads/1765727992064-37229339.webp',
|
||
],
|
||
hasQuickRent: true,
|
||
isFeatured: false,
|
||
},
|
||
{
|
||
id: 8,
|
||
name: 'Beneteau Swift Trawler 41',
|
||
length: 12.5,
|
||
speed: 22,
|
||
minCost: 55000,
|
||
mainImageUrl: '/api/uploads/1765728068963-634185622.webp',
|
||
galleryUrls: [
|
||
'/api/uploads/1765728068963-634185622.webp',
|
||
'/api/uploads/1765727637471-474231444.webp',
|
||
'/api/uploads/1765727743466-187581713.webp',
|
||
'/api/uploads/1765727819793-158598111.webp',
|
||
'/api/uploads/1765727903961-559930753.webp',
|
||
'/api/uploads/1765727928577-55944164.webp',
|
||
'/api/uploads/1765727948691-389175954.webp',
|
||
'/api/uploads/1765727961591-243584836.webp',
|
||
'/api/uploads/1765727992064-37229339.webp',
|
||
],
|
||
hasQuickRent: false,
|
||
isFeatured: false,
|
||
},
|
||
{
|
||
id: 9,
|
||
name: 'Lagoon 450',
|
||
length: 13.5,
|
||
speed: 20,
|
||
minCost: 65000,
|
||
mainImageUrl: '/api/uploads/1765728152179-305707681.webp',
|
||
galleryUrls: [
|
||
'/api/uploads/1765728152179-305707681.webp',
|
||
'/api/uploads/1765727637471-474231444.webp',
|
||
'/api/uploads/1765727743466-187581713.webp',
|
||
'/api/uploads/1765727819793-158598111.webp',
|
||
'/api/uploads/1765727903961-559930753.webp',
|
||
'/api/uploads/1765727928577-55944164.webp',
|
||
'/api/uploads/1765727948691-389175954.webp',
|
||
'/api/uploads/1765727961591-243584836.webp',
|
||
'/api/uploads/1765727992064-37229339.webp',
|
||
],
|
||
hasQuickRent: true,
|
||
isFeatured: false,
|
||
},
|
||
{
|
||
id: 10,
|
||
name: 'Fountaine Pajot Lucia 40',
|
||
length: 11.7,
|
||
speed: 18,
|
||
minCost: 58000,
|
||
mainImageUrl: '/api/uploads/1765728169750-667674217.webp',
|
||
galleryUrls: [
|
||
'/api/uploads/1765728169750-667674217.webp',
|
||
'/api/uploads/1765727637471-474231444.webp',
|
||
'/api/uploads/1765727743466-187581713.webp',
|
||
'/api/uploads/1765727819793-158598111.webp',
|
||
'/api/uploads/1765727903961-559930753.webp',
|
||
'/api/uploads/1765727928577-55944164.webp',
|
||
'/api/uploads/1765727948691-389175954.webp',
|
||
'/api/uploads/1765727961591-243584836.webp',
|
||
'/api/uploads/1765727992064-37229339.webp',
|
||
],
|
||
hasQuickRent: true,
|
||
isFeatured: false,
|
||
},
|
||
{
|
||
id: 11,
|
||
name: 'Dufour 460',
|
||
length: 14.1,
|
||
speed: 26,
|
||
minCost: 62000,
|
||
mainImageUrl: '/api/uploads/1765728190017-763752836.webp',
|
||
galleryUrls: [
|
||
'/api/uploads/1765728190017-763752836.webp',
|
||
'/api/uploads/1765727637471-474231444.webp',
|
||
'/api/uploads/1765727743466-187581713.webp',
|
||
'/api/uploads/1765727819793-158598111.webp',
|
||
'/api/uploads/1765727903961-559930753.webp',
|
||
'/api/uploads/1765727928577-55944164.webp',
|
||
'/api/uploads/1765727948691-389175954.webp',
|
||
'/api/uploads/1765727961591-243584836.webp',
|
||
'/api/uploads/1765727992064-37229339.webp',
|
||
],
|
||
hasQuickRent: false,
|
||
isFeatured: false,
|
||
},
|
||
{
|
||
id: 12,
|
||
name: 'Grand Banks 60',
|
||
length: 18.3,
|
||
speed: 24,
|
||
minCost: 125000,
|
||
mainImageUrl: '/api/uploads/1765728208376-854378188.webp',
|
||
galleryUrls: [
|
||
'/api/uploads/1765728208376-854378188.webp',
|
||
'/api/uploads/1765727637471-474231444.webp',
|
||
'/api/uploads/1765727743466-187581713.webp',
|
||
'/api/uploads/1765727819793-158598111.webp',
|
||
'/api/uploads/1765727903961-559930753.webp',
|
||
'/api/uploads/1765727928577-55944164.webp',
|
||
'/api/uploads/1765727948691-389175954.webp',
|
||
'/api/uploads/1765727961591-243584836.webp',
|
||
'/api/uploads/1765727992064-37229339.webp',
|
||
],
|
||
hasQuickRent: true,
|
||
isFeatured: false,
|
||
},
|
||
];
|
||
|
||
async getMainPageCatalog(): Promise<MainPageCatalogResponseDto | null> {
|
||
const clonedCatalog = [...this.catalogItems];
|
||
const filteredCatalog = clonedCatalog.filter(
|
||
({ isFeatured }) => !isFeatured,
|
||
);
|
||
|
||
const featuredYacthIndex = clonedCatalog.findIndex(
|
||
(item) => item.isFeatured === true,
|
||
);
|
||
|
||
if (featuredYacthIndex !== -1) {
|
||
return {
|
||
featuredYacht: clonedCatalog[featuredYacthIndex],
|
||
restYachts: filteredCatalog.slice(0, 6),
|
||
};
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
async getCatalog(params?: CatalogParamsDto): Promise<CatalogResponseDto> {
|
||
let filteredItems = [...this.catalogItems];
|
||
|
||
if (params?.search) {
|
||
const searchTerm = params.search.toLowerCase();
|
||
|
||
filteredItems = filteredItems.filter((item) =>
|
||
item.name.toLowerCase().includes(searchTerm),
|
||
);
|
||
}
|
||
|
||
if (params?.filter?.price) {
|
||
const { minvalue, maxvalue } = params.filter.price;
|
||
|
||
filteredItems = filteredItems.filter((item) => {
|
||
if (minvalue !== undefined && item.minCost < minvalue) return false;
|
||
if (maxvalue !== undefined && item.minCost > maxvalue) return false;
|
||
return true;
|
||
});
|
||
}
|
||
|
||
if (params?.sort?.field) {
|
||
const { field, direction = 'asc' } = params.sort;
|
||
|
||
filteredItems.sort((a, b) => {
|
||
let valueA = a[field];
|
||
let valueB = b[field];
|
||
|
||
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;
|
||
});
|
||
}
|
||
|
||
return {
|
||
items: filteredItems,
|
||
total: filteredItems.length,
|
||
filters: params?.filter,
|
||
sort: params?.sort,
|
||
search: params?.search,
|
||
};
|
||
}
|
||
|
||
async getAllCatalogItems(): Promise<CatalogItemDto[]> {
|
||
return this.catalogItems;
|
||
}
|
||
}
|