import { Injectable } from '@nestjs/common'; import { UsersService } from '../users/users.service'; import { ReservationsService } from '../reservations/reservations.service'; import { ReviewsService } from '../reviews/reviews.service'; import { CatalogItemShortDto, CatalogItemLongDto, } 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 { constructor( private readonly usersService: UsersService, private readonly reservationsService: ReservationsService, private readonly reviewsService: ReviewsService, ) {} private catalogItems: CatalogItemLongDto[] = [ { id: 1, name: 'Азимут 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, year: 2022, comfortCapacity: 8, maxCapacity: 12, width: 4.8, cabinsCount: 3, matherial: 'Стеклопластик', power: 1200, description: 'Роскошная моторная яхта Азимут 55 - это воплощение итальянского стиля и российского качества. Идеально подходит для прогулок по Финскому заливу, корпоративных мероприятий и романтических свиданий. На борту: три комфортабельные каюты, просторный салон с панорамным остеклением, полностью оборудованная кухня и две ванные комнаты. Максимальная скорость 32 узла позволяет быстро добраться до самых живописных мест Карельского перешейка.', owner: null as any, reviews: [], reservations: [], }, { id: 2, name: 'Сансикер Манхэттен 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: '🔥 Лучшее предложение', year: 2023, comfortCapacity: 6, maxCapacity: 10, width: 4.5, cabinsCount: 3, matherial: 'Стеклопластик', power: 1400, description: 'Британский шик и русская душа в одной яхте! Сансикер Манхэттен 52 - выбор настоящих ценителей морских путешествий. Просторный кокпит с мягкими диванами, бар на 8 персон, система мультимедиа премиум-класса. Идеальна для празднования дня рождения на воде или деловой встречи с партнерами. Отличная маневренность позволяет заходить в марины Санкт-Петербурга и Кронштадта.', owner: null as any, reviews: [], reservations: [], }, { id: 3, name: 'Принцесс 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: '🍷 Идеальна для заката с бокалом вина', year: 2021, comfortCapacity: 8, maxCapacity: 12, width: 4.7, cabinsCount: 4, matherial: 'Стеклопластик', power: 1100, description: 'Принцесс V55 - королева российских вод! Эта яхта создана для тех, кто ценит комфорт и элегантность. Четыре уютные каюты с кондиционером, гальюн с душем, полностью оборудованная камбузная зона. Особенность - огромный платц с гидравлическим трапом для купания в Ладожском озере. Отличный выбор для семейного отдыха или рыбалки с друзьями.', owner: null as any, reviews: [], reservations: [], }, { id: 4, name: 'Ферретти 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: '⏳ Часто бронируется - успей', year: 2020, comfortCapacity: 6, maxCapacity: 8, width: 4.3, cabinsCount: 3, matherial: 'Стеклопластик', power: 900, description: 'Итальянская страсть в русской стихии! Ферретти 500 сочетает в себе средиземноморский шарм и надежность для суровых условий Балтики. Просторный салон с панорамными окнами, обеденная зона на 6 человек, современная навигационная система. Идеально подходит для фотосессий на фоне разводных мостов Петербурга или романтического ужина под звуки волн.', owner: null as any, reviews: [], reservations: [], }, { id: 5, name: 'Си Рей 510 Сандансер', 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, year: 2023, comfortCapacity: 8, maxCapacity: 10, width: 4.6, cabinsCount: 3, matherial: 'Стеклопластик', power: 1300, description: 'Американская мощь для русского моря! Си Рей 510 Сандансер - самая быстрая яхта в нашем флоте. Развивает скорость до 35 узлов, что позволяет за день обогнуть весь Финский залив. Три комфортабельные каюты, система стабилизации на стоянке, мощная аудиосистема с сабвуфером. Отличный выбор для любителей острых ощущений и скоростных прогулок.', owner: null as any, reviews: [], reservations: [], }, { id: 6, name: 'Бавария 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, year: 2019, comfortCapacity: 6, maxCapacity: 8, width: 3.9, cabinsCount: 2, matherial: 'Стеклопластик', power: 320, description: 'Немецкое качество для русского характера! Бавария SR41 - надежная и экономичная яхта для спокойных прогулок по Ладоге. Две уютные каюты, просторный кокпит с тентом от дождя, лебедка для подъема парусов. Идеальный выбор для начинающих яхтсменов или семейного отдыха с детьми. Расход топлива всего 15 литров в час!', owner: null as any, reviews: [], reservations: [], }, { id: 7, name: 'Жанно Мери Фишер 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, year: 2022, comfortCapacity: 4, maxCapacity: 6, width: 3.0, cabinsCount: 1, matherial: 'Стеклопластик', power: 250, description: 'Французская элегантность для русского простора! Жанно Мери Фишер 895 - компактная, но вместительная яхта для рыбалки и пикников. Одна просторная каюта, открытый кокпит, столик для барбекю. Отлично подходит для выездов на природу, ночевки в бухтах или обучения детей управлению яхтой. Самый экономичный вариант в нашем флоте!', owner: null as any, reviews: [], reservations: [], }, { id: 8, name: 'Бенето Свифт Троулер 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, year: 2021, comfortCapacity: 6, maxCapacity: 8, width: 4.2, cabinsCount: 2, matherial: 'Стеклопластик', power: 425, description: 'Французский траулер для русского севера! Бенето Свифт Троулер 41 создан для длительных путешествий по Белому морю. Экономичный дизельный двигатель, большой запас топлива, система опреснения воды. Две комфортабельные каюты с подогревом пола. Идеальный выбор для экспедиций или многодневных круизов по северным островам.', owner: null as any, reviews: [], reservations: [], }, { id: 9, name: 'Лагун 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, year: 2020, comfortCapacity: 8, maxCapacity: 10, width: 7.8, cabinsCount: 4, matherial: 'Стеклопластик', power: 90, description: 'Французский катамаран для русского размаха! Лагун 450 - невероятно устойчивая и просторная яхта. Четыре отдельные каюты с санузлами, огромный салон-трансформер, две кухни. Идеально подходит для больших компаний, свадебных церемоний на воде или длительных круизов всей семьей. Не кренится даже в шторм!', owner: null as any, reviews: [], reservations: [], }, { id: 10, name: 'Фонтен Пажо Люсия 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, year: 2023, comfortCapacity: 8, maxCapacity: 10, width: 7.1, cabinsCount: 4, matherial: 'Стеклопластик', power: 80, description: 'Французский катамаран класса люкс! Фонтен Пажо Люсия 40 - это плавающий пятизвездочный отель. Четыре каюты-люкс с джакузи, салон с камином, профессиональная кухня с шеф-поваром. Система стабилизации на якоре, гидромассажный бассейн на палубе. Выбор настоящих ценителей роскоши и комфорта на воде.', owner: null as any, reviews: [], reservations: [], }, { id: 11, name: 'Дюфур 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, year: 2022, comfortCapacity: 8, maxCapacity: 10, width: 4.5, cabinsCount: 3, matherial: 'Стеклопластик', power: 380, description: 'Французская парусная яхта для русского ветра! Дюфур 460 - мечта любого яхтсмена. Три просторные каюты, кокпит с мягкими сиденьями, современное парусное вооружение. Идеально сбалансированная, легко управляется даже новичками. Отличный выбор для регат, обучения парусному спорту или романтических круизов под парусами.', owner: null as any, reviews: [], reservations: [], }, { id: 12, name: 'Гранд Бэнкс 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, year: 2023, comfortCapacity: 6, maxCapacity: 8, width: 5.2, cabinsCount: 3, matherial: 'Стеклопластик', power: 1600, description: 'Американская легенда для русского океана! Гранд Бэнкс 60 - экспедиционная яхта для самых смелых путешествий. Три каюты-люкс, салон с библиотекой, зимний сад, сауна. Автономность плавания - 30 дней! Способна пересечь Баренцево море и дойти до Шпицбергена. Выбор для настоящих морских волков и исследователей Арктики.', owner: null as any, reviews: [], reservations: [], }, ]; private toShortDto(item: CatalogItemLongDto): CatalogItemShortDto { const { id, name, length, speed, minCost, mainImageUrl, galleryUrls, hasQuickRent, isFeatured, topText, } = item; return { id, name, length, speed, minCost, mainImageUrl, galleryUrls, hasQuickRent, isFeatured, topText, }; } async getCatalogItemById(id: number): Promise { const item = this.catalogItems.find((item) => item.id === id); if (!item) return null; const ownerId = [1, 2][(id - 1) % 2]; const owner = await this.usersService.findById(ownerId); if (owner) { item.owner = owner; } item.reviews = this.reviewsService.getReviewsByYachtId(id); item.reservations = this.reservationsService.getReservationsByYachtId(id); return item; } async getMainPageCatalog(): Promise { const clonedCatalog = [...this.catalogItems]; const filteredCatalog = clonedCatalog.filter( ({ isFeatured }) => !isFeatured, ); const featuredYachtIndex = clonedCatalog.findIndex( (item) => item.isFeatured === true, ); if (featuredYachtIndex !== -1) { const minCost = Math.min( ...filteredCatalog.map((item) => item.minCost || Infinity), ); const mappedRestYachts = filteredCatalog.slice(0, 6).map((item) => ({ ...this.toShortDto(item), isBestOffer: item.minCost === minCost, })); return { featuredYacht: this.toShortDto(clonedCatalog[featuredYachtIndex]), restYachts: mappedRestYachts, }; } return null; } async getCatalog(params?: CatalogParamsDto): Promise { let filteredItems = this.catalogItems.map((item) => this.toShortDto(item)); 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 { return this.catalogItems.map((item) => this.toShortDto(item)); } }