+
{revision.features?.slice(0, 3).map((feature, index) => (
{feature}
))}
{revision.features && revision.features.length > 3 && (
-
+
+{revision.features.length - 3} more
)}
diff --git a/src/app/results/results.module.css b/src/app/results/results.module.css
index f13d758..b1b13a4 100644
--- a/src/app/results/results.module.css
+++ b/src/app/results/results.module.css
@@ -1,12 +1,8 @@
-.resultsContainer {
+/* Results page specific styles */
+.container {
min-height: 100vh;
+ background: linear-gradient(135deg, var(--background), rgba(8, 61, 119, 0.05));
padding: 2rem;
- background-color: #f9fafb;
-}
-
-.contentContainer {
- max-width: 80rem;
- margin: 0 auto;
}
.header {
@@ -14,26 +10,38 @@
justify-content: space-between;
align-items: center;
margin-bottom: 2rem;
+ max-width: 1200px;
+ margin: 0 auto 2rem;
}
-.resultsTitle {
- font-size: 1.875rem;
- font-weight: bold;
+.title {
+ font-size: 2.5rem;
+ font-weight: 700;
+ color: var(--color-charcoal);
}
.backButton {
- background-color: #3b82f6;
+ background-color: var(--color-yale-blue);
color: white;
- padding: 0.5rem 1rem;
- border-radius: 0.375rem;
- transition: background-color 0.2s;
+ padding: 0.6rem 1.2rem;
+ border-radius: 25px;
+ text-decoration: none;
+ font-weight: 600;
+ transition: all 0.2s ease;
+ display: inline-flex;
+ align-items: center;
}
.backButton:hover {
- background-color: #2563eb;
+ background-color: var(--color-charcoal);
}
-.loadingContainer {
+.content {
+ max-width: 1200px;
+ margin: 0 auto;
+}
+
+.loader {
display: flex;
justify-content: center;
align-items: center;
@@ -41,11 +49,11 @@
}
.spinner {
- border-radius: 50%;
width: 3rem;
height: 3rem;
- border: 0.25rem solid rgba(59, 130, 246, 0.1);
- border-top-color: #3b82f6;
+ border: 0.25rem solid rgba(8, 61, 119, 0.1);
+ border-top: 0.25rem solid var(--color-yale-blue);
+ border-radius: 50%;
animation: spin 1s linear infinite;
}
@@ -54,56 +62,64 @@
100% { transform: rotate(360deg); }
}
-.errorContainer {
- background-color: #fee2e2;
- border: 1px solid #f87171;
- color: #b91c1c;
- padding: 0.75rem 1rem;
- border-radius: 0.375rem;
-}
-
-.emptyResultsContainer {
- background-color: white;
- padding: 2rem;
+.errorMessage {
+ background-color: #fde8e8;
+ border: 1px solid #f8b4b4;
+ color: #9b1c1c;
+ padding: 1rem;
border-radius: 0.5rem;
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
text-align: center;
}
-.emptyResultsTitle {
+.noResults {
+ background-color: white;
+ padding: 2rem;
+ border-radius: 0.5rem;
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
+ text-align: center;
+}
+
+.emptyResults {
+ text-align: center;
+ padding: 2rem 0;
+}
+
+.noResultsTitle {
font-size: 1.5rem;
font-weight: 600;
margin-bottom: 1rem;
+ color: var(--color-charcoal);
}
-.emptyResultsMessage {
- color: #6b7280;
-}
-
-.resultsSection {
- margin-bottom: 2rem;
+.noResultsText {
+ color: #4b5563;
}
.sectionTitle {
- font-size: 1.5rem;
+ font-size: 1.8rem;
font-weight: 600;
- margin-bottom: 1rem;
+ margin-bottom: 1.5rem;
+ color: var(--color-charcoal);
}
-.cardsGrid {
+.sectionContent {
+ margin-bottom: 2.5rem;
+}
+
+.grid {
display: grid;
grid-template-columns: repeat(1, 1fr);
gap: 1.5rem;
}
@media (min-width: 768px) {
- .cardsGrid {
+ .grid {
grid-template-columns: repeat(2, 1fr);
}
}
@media (min-width: 1024px) {
- .cardsGrid {
+ .grid {
grid-template-columns: repeat(3, 1fr);
}
}
@@ -111,23 +127,29 @@
.card {
background-color: white;
border-radius: 0.5rem;
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
overflow: hidden;
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
}
-.cardImageContainer {
- height: 12rem;
- background-color: #e5e7eb;
- position: relative;
+.card:hover {
+ transform: translateY(-4px);
+ box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
}
.cardImage {
+ height: 12rem;
+ background-color: #f3f4f6;
+ position: relative;
+}
+
+.image {
width: 100%;
height: 100%;
object-fit: cover;
}
-.noImageContainer {
+.noImage {
display: flex;
align-items: center;
justify-content: center;
@@ -148,17 +170,18 @@
.cardTitle {
font-size: 1.25rem;
- font-weight: bold;
+ font-weight: 700;
+ color: var(--color-charcoal);
}
.brandName {
font-size: 0.875rem;
font-weight: 500;
- color: #3b82f6;
+ color: var(--color-yale-blue);
}
.cardDescription {
- color: #6b7280;
+ color: #4b5563;
font-size: 0.875rem;
margin-bottom: 0.5rem;
}
@@ -174,9 +197,14 @@
background-color: #f3f4f6;
padding: 0.25rem 0.5rem;
border-radius: 0.25rem;
+ color: #4b5563;
}
-.specsGrid {
+.years {
+ color: #4b5563;
+}
+
+.specGrid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 0.5rem;
@@ -186,16 +214,17 @@
.specLabel {
font-weight: 500;
+ color: var(--color-charcoal);
}
-.featuresList {
+.tagContainer {
display: flex;
flex-wrap: wrap;
gap: 0.25rem;
margin-top: 0.5rem;
}
-.featureTag {
+.tag {
background-color: #dbeafe;
color: #1e40af;
font-size: 0.75rem;
@@ -203,7 +232,7 @@
border-radius: 0.25rem;
}
-.moreFeatures {
+.tagCount {
font-size: 0.75rem;
color: #6b7280;
}
\ No newline at end of file
diff --git a/src/backend/models/Brand.ts b/src/backend/models/Brand.ts
index 6f1906c..ab80a9a 100644
--- a/src/backend/models/Brand.ts
+++ b/src/backend/models/Brand.ts
@@ -1,7 +1,9 @@
import { CarModel } from './CarModel';
+import { ObjectId } from 'mongodb';
export interface Brand {
- id: string;
+ _id?: ObjectId;
+ id?: string;
name: string;
logo: string;
description: string;
@@ -9,5 +11,4 @@ export interface Brand {
headquarters: string;
website: string;
carModels?: CarModel[];
-}
-
+}
\ No newline at end of file
diff --git a/src/backend/models/CarModel.ts b/src/backend/models/CarModel.ts
index fc014d4..533305c 100644
--- a/src/backend/models/CarModel.ts
+++ b/src/backend/models/CarModel.ts
@@ -1,14 +1,16 @@
import { Brand } from './Brand';
import { CarRevision } from './CarRevision';
+import { ObjectId } from 'mongodb';
export interface CarModel {
- id: string;
+ _id?: ObjectId;
+ id?: string;
name: string;
- brand: Brand;
productionStartYear: number;
productionEndYear?: number;
category?: string;
description?: string;
image?: string;
revisions?: CarRevision[];
+ brandId?: ObjectId;
}
\ No newline at end of file
diff --git a/src/backend/models/CarRevision.ts b/src/backend/models/CarRevision.ts
index d50c7db..1e9fdfa 100644
--- a/src/backend/models/CarRevision.ts
+++ b/src/backend/models/CarRevision.ts
@@ -1,4 +1,5 @@
import { CarModel } from './CarModel';
+import { ObjectId } from 'mongodb';
export interface Dimensions {
length: number;
@@ -8,9 +9,9 @@ export interface Dimensions {
}
export interface CarRevision {
- id: string;
+ _id?: ObjectId;
+ id?: string;
name: string;
- baseModel: CarModel;
releaseYear: number;
engineTypes: string[];
horsePower: number;
@@ -22,4 +23,5 @@ export interface CarRevision {
weight: number;
features: string[];
images: string[];
+ modelId?: ObjectId;
}
\ No newline at end of file
diff --git a/src/backend/repositories/CarRepository.ts b/src/backend/repositories/CarRepository.ts
index 177de87..7d54dbc 100644
--- a/src/backend/repositories/CarRepository.ts
+++ b/src/backend/repositories/CarRepository.ts
@@ -1,512 +1,540 @@
import { Brand, CarModel, CarRevision } from '../models';
+import { MongoClient, Db, Collection, ObjectId } from 'mongodb';
-// Dummy brands
-const brands: Brand[] = [
- {
- id: '1',
- name: 'Tesla',
- logo: 'https://example.com/tesla-logo.png',
- description: 'American electric vehicle and clean energy company',
- foundedYear: 2003,
- headquarters: 'Palo Alto, California, United States',
- website: 'https://www.tesla.com',
- },
- {
- id: '2',
- name: 'BMW',
- logo: 'https://example.com/bmw-logo.png',
- description: 'German luxury automobile and motorcycle manufacturer',
- foundedYear: 1916,
- headquarters: 'Munich, Germany',
- website: 'https://www.bmw.com',
- },
- {
- id: '3',
- name: 'Toyota',
- logo: 'https://example.com/toyota-logo.png',
- description: 'Japanese multinational automotive manufacturer',
- foundedYear: 1937,
- headquarters: 'Toyota City, Japan',
- website: 'https://www.toyota.com',
- },
- {
- id: '4',
- name: 'Audi',
- logo: 'https://example.com/audi-logo.png',
- description: 'German luxury automobile manufacturer',
- foundedYear: 1909,
- headquarters: 'Ingolstadt, Germany',
- website: 'https://www.audi.com',
- },
- {
- id: '5',
- name: 'Mercedes-Benz',
- logo: 'https://example.com/mercedes-logo.png',
- description: 'German global automobile marque and a division of Daimler AG',
- foundedYear: 1926,
- headquarters: 'Stuttgart, Germany',
- website: 'https://www.mercedes-benz.com',
- },
-];
-
-// Dummy car models (without revisions yet)
-const carModels: CarModel[] = [
- {
- id: '1',
- name: 'Model S',
- brand: brands[0], // Tesla
- productionStartYear: 2012,
- category: 'Sedan',
- description: 'All-electric five-door liftback sedan',
- image: 'https://example.com/tesla-model-s.jpg',
- },
- {
- id: '2',
- name: 'Model 3',
- brand: brands[0], // Tesla
- productionStartYear: 2017,
- category: 'Sedan',
- description: 'All-electric four-door sedan',
- image: 'https://example.com/tesla-model-3.jpg',
- },
- {
- id: '3',
- name: '3 Series',
- brand: brands[1], // BMW
- productionStartYear: 1975,
- category: 'Sedan',
- description: 'Compact executive car',
- image: 'https://example.com/bmw-3-series.jpg',
- },
- {
- id: '4',
- name: 'X5',
- brand: brands[1], // BMW
- productionStartYear: 1999,
- category: 'SUV',
- description: 'Mid-size luxury SUV',
- image: 'https://example.com/bmw-x5.jpg',
- },
- {
- id: '5',
- name: 'Camry',
- brand: brands[2], // Toyota
- productionStartYear: 1982,
- category: 'Sedan',
- description: 'Mid-size car',
- image: 'https://example.com/toyota-camry.jpg',
- },
- {
- id: '6',
- name: 'Prius',
- brand: brands[2], // Toyota
- productionStartYear: 1997,
- category: 'Hatchback',
- description: 'Hybrid electric mid-size car',
- image: 'https://example.com/toyota-prius.jpg',
- },
- {
- id: '7',
- name: 'A4',
- brand: brands[3], // Audi
- productionStartYear: 1994,
- category: 'Sedan',
- description: 'Compact executive car',
- image: 'https://example.com/audi-a4.jpg',
- },
- {
- id: '8',
- name: 'Q7',
- brand: brands[3], // Audi
- productionStartYear: 2005,
- category: 'SUV',
- description: 'Full-size luxury crossover SUV',
- image: 'https://example.com/audi-q7.jpg',
- },
- {
- id: '9',
- name: 'C-Class',
- brand: brands[4], // Mercedes-Benz
- productionStartYear: 1993,
- category: 'Sedan',
- description: 'Compact executive car',
- image: 'https://example.com/mercedes-c-class.jpg',
- },
- {
- id: '10',
- name: 'GLE',
- brand: brands[4], // Mercedes-Benz
- productionStartYear: 2015,
- category: 'SUV',
- description: 'Mid-size luxury crossover SUV',
- image: 'https://example.com/mercedes-gle.jpg',
- },
-];
-
-// Dummy car revisions
-const carRevisions: CarRevision[] = [
- {
- id: '1',
- name: 'Model S Long Range Plus',
- baseModel: carModels[0], // Tesla Model S
- releaseYear: 2020,
- engineTypes: ['Electric'],
- horsePower: 670,
- torque: 850,
- topSpeed: 250,
- acceleration0To100: 3.1,
- fuelConsumption: 0,
- dimensions: {
- length: 4970,
- width: 1964,
- height: 1445,
- wheelbase: 2960,
- },
- weight: 2250,
- features: ['Autopilot', 'Premium Interior', 'All-Wheel Drive'],
- images: ['https://example.com/tesla-model-s-2020-1.jpg', 'https://example.com/tesla-model-s-2020-2.jpg'],
- },
- {
- id: '2',
- name: 'Model S Plaid',
- baseModel: carModels[0], // Tesla Model S
- releaseYear: 2021,
- engineTypes: ['Electric'],
- horsePower: 1020,
- torque: 1050,
- topSpeed: 322,
- acceleration0To100: 2.1,
- fuelConsumption: 0,
- dimensions: {
- length: 4970,
- width: 1964,
- height: 1445,
- wheelbase: 2960,
- },
- weight: 2300,
- features: ['Enhanced Autopilot', 'Yoke Steering', 'All-Wheel Drive', 'New Interior Design'],
- images: ['https://example.com/tesla-model-s-plaid-1.jpg', 'https://example.com/tesla-model-s-plaid-2.jpg'],
- },
- {
- id: '3',
- name: 'Model 3 Standard Range Plus',
- baseModel: carModels[1], // Tesla Model 3
- releaseYear: 2021,
- engineTypes: ['Electric'],
- horsePower: 283,
- torque: 450,
- topSpeed: 225,
- acceleration0To100: 5.6,
- fuelConsumption: 0,
- dimensions: {
- length: 4694,
- width: 1849,
- height: 1443,
- wheelbase: 2875,
- },
- weight: 1750,
- features: ['Basic Autopilot', 'Standard Interior', 'Rear-Wheel Drive'],
- images: ['https://example.com/tesla-model-3-standard-1.jpg', 'https://example.com/tesla-model-3-standard-2.jpg'],
- },
- {
- id: '4',
- name: '330i Sedan',
- baseModel: carModels[2], // BMW 3 Series
- releaseYear: 2021,
- engineTypes: ['Gasoline'],
- horsePower: 255,
- torque: 400,
- topSpeed: 209,
- acceleration0To100: 5.6,
- fuelConsumption: 7.1,
- dimensions: {
- length: 4709,
- width: 1827,
- height: 1435,
- wheelbase: 2851,
- },
- weight: 1620,
- features: ['LED Headlights', 'iDrive Infotainment System', 'Leather Seats'],
- images: ['https://example.com/bmw-330i-1.jpg', 'https://example.com/bmw-330i-2.jpg'],
- },
- {
- id: '5',
- name: 'M340i Sedan',
- baseModel: carModels[2], // BMW 3 Series
- releaseYear: 2021,
- engineTypes: ['Gasoline'],
- horsePower: 382,
- torque: 500,
- topSpeed: 250,
- acceleration0To100: 4.4,
- fuelConsumption: 8.0,
- dimensions: {
- length: 4709,
- width: 1827,
- height: 1435,
- wheelbase: 2851,
- },
- weight: 1670,
- features: ['M Sport Differential', 'M Sport Brakes', 'Adaptive M Suspension'],
- images: ['https://example.com/bmw-m340i-1.jpg', 'https://example.com/bmw-m340i-2.jpg'],
- },
- {
- id: '6',
- name: 'X5 xDrive40i',
- baseModel: carModels[3], // BMW X5
- releaseYear: 2021,
- engineTypes: ['Gasoline'],
- horsePower: 335,
- torque: 450,
- topSpeed: 243,
- acceleration0To100: 5.5,
- fuelConsumption: 9.2,
- dimensions: {
- length: 4922,
- width: 2004,
- height: 1745,
- wheelbase: 2975,
- },
- weight: 2260,
- features: ['Panoramic Roof', 'Head-Up Display', 'Gesture Control'],
- images: ['https://example.com/bmw-x5-xdrive40i-1.jpg', 'https://example.com/bmw-x5-xdrive40i-2.jpg'],
- },
- {
- id: '7',
- name: 'Camry LE',
- baseModel: carModels[4], // Toyota Camry
- releaseYear: 2021,
- engineTypes: ['Gasoline'],
- horsePower: 203,
- torque: 250,
- topSpeed: 210,
- acceleration0To100: 8.1,
- fuelConsumption: 7.6,
- dimensions: {
- length: 4880,
- width: 1840,
- height: 1445,
- wheelbase: 2825,
- },
- weight: 1580,
- features: ['Toyota Safety Sense', 'Apple CarPlay', 'Android Auto'],
- images: ['https://example.com/toyota-camry-le-1.jpg', 'https://example.com/toyota-camry-le-2.jpg'],
- },
- {
- id: '8',
- name: 'Camry Hybrid',
- baseModel: carModels[4], // Toyota Camry
- releaseYear: 2021,
- engineTypes: ['Hybrid'],
- horsePower: 208,
- torque: 220,
- topSpeed: 180,
- acceleration0To100: 7.8,
- fuelConsumption: 4.2,
- dimensions: {
- length: 4880,
- width: 1840,
- height: 1445,
- wheelbase: 2825,
- },
- weight: 1680,
- features: ['Regenerative Braking', 'EV Mode', 'Energy Monitor'],
- images: ['https://example.com/toyota-camry-hybrid-1.jpg', 'https://example.com/toyota-camry-hybrid-2.jpg'],
- },
- {
- id: '9',
- name: 'Prius Prime',
- baseModel: carModels[5], // Toyota Prius
- releaseYear: 2021,
- engineTypes: ['Plug-in Hybrid'],
- horsePower: 121,
- torque: 142,
- topSpeed: 165,
- acceleration0To100: 10.5,
- fuelConsumption: 1.8,
- dimensions: {
- length: 4645,
- width: 1760,
- height: 1470,
- wheelbase: 2700,
- },
- weight: 1530,
- features: ['Electric Range of 40 km', 'Touch-sensitive controls', 'Quad-LED projector headlights'],
- images: ['https://example.com/toyota-prius-prime-1.jpg', 'https://example.com/toyota-prius-prime-2.jpg'],
- },
- {
- id: '10',
- name: 'A4 Prestige',
- baseModel: carModels[6], // Audi A4
- releaseYear: 2021,
- engineTypes: ['Gasoline'],
- horsePower: 261,
- torque: 370,
- topSpeed: 210,
- acceleration0To100: 5.5,
- fuelConsumption: 7.5,
- dimensions: {
- length: 4762,
- width: 1847,
- height: 1435,
- wheelbase: 2820,
- },
- weight: 1640,
- features: ['Audi Virtual Cockpit', 'Bang & Olufsen Sound System', 'Adaptive Cruise Control'],
- images: ['https://example.com/audi-a4-prestige-1.jpg', 'https://example.com/audi-a4-prestige-2.jpg'],
- },
-];
-
-// Connect revisions to models
-const connectRevisionsToModels = () => {
- // Tesla Model S revisions
- carModels[0].revisions = [carRevisions[0], carRevisions[1]];
-
- // Tesla Model 3 revisions
- carModels[1].revisions = [carRevisions[2]];
-
- // BMW 3 Series revisions
- carModels[2].revisions = [carRevisions[3], carRevisions[4]];
-
- // BMW X5 revisions
- carModels[3].revisions = [carRevisions[5]];
-
- // Toyota Camry revisions
- carModels[4].revisions = [carRevisions[6], carRevisions[7]];
-
- // Toyota Prius revisions
- carModels[5].revisions = [carRevisions[8]];
-
- // Audi A4 revisions
- carModels[6].revisions = [carRevisions[9]];
-};
-
-// Connect car models to brands
-const connectModelsToBrands = () => {
- // Tesla models
- brands[0].carModels = [carModels[0], carModels[1]];
-
- // BMW models
- brands[1].carModels = [carModels[2], carModels[3]];
-
- // Toyota models
- brands[2].carModels = [carModels[4], carModels[5]];
-
- // Audi models
- brands[3].carModels = [carModels[6], carModels[7]];
-
- // Mercedes models
- brands[4].carModels = [carModels[8], carModels[9]];
-};
-
-// Initialize connections
-connectRevisionsToModels();
-connectModelsToBrands();
-
-// Car Repository Service
export class CarRepository {
+ private client: MongoClient;
+ private db: Db | null = null;
+ private brandsCollection: Collection | null = null;
+ private carModelsCollection: Collection | null = null;
+ private carRevisionsCollection: Collection | null = null;
+
+ constructor(private mongoUrl: string = process.env.MONGODB_URI || 'mongodb://localhost:27017/evwiki') {
+ this.client = new MongoClient(this.mongoUrl);
+ }
+
+ /**
+ * Initialize the database connection
+ */
+ async connect(): Promise {
+ if (!this.db) {
+ await this.client.connect();
+ this.db = this.client.db();
+ this.brandsCollection = this.db.collection('brands');
+ this.carModelsCollection = this.db.collection('carModels');
+ this.carRevisionsCollection = this.db.collection('carRevisions');
+
+ // Check if data exists, if not initialize with default data
+ const brandsCount = await this.brandsCollection.countDocuments();
+ if (brandsCount === 0) {
+ await this.initializeDefaultData();
+ }
+ }
+ }
+
+ /**
+ * Close the database connection
+ */
+ async disconnect(): Promise {
+ if (this.client) {
+ await this.client.close();
+ this.db = null;
+ this.brandsCollection = null;
+ this.carModelsCollection = null;
+ this.carRevisionsCollection = null;
+ }
+ }
+
+ /**
+ * Initialize the database with default data if empty
+ */
+ private async initializeDefaultData(): Promise {
+ if (!this.db || !this.brandsCollection || !this.carModelsCollection || !this.carRevisionsCollection) {
+ throw new Error('Database not initialized');
+ }
+
+ // Insert default brands
+ await this.brandsCollection.insertMany([
+ {
+ name: 'Tesla',
+ logo: 'https://example.com/tesla-logo.png',
+ description: 'American electric vehicle and clean energy company',
+ foundedYear: 2003,
+ headquarters: 'Palo Alto, California, United States',
+ website: 'https://www.tesla.com',
+ },
+ {
+ name: 'BMW',
+ logo: 'https://example.com/bmw-logo.png',
+ description: 'German luxury automobile and motorcycle manufacturer',
+ foundedYear: 1916,
+ headquarters: 'Munich, Germany',
+ website: 'https://www.bmw.com',
+ },
+ {
+ name: 'Toyota',
+ logo: 'https://example.com/toyota-logo.png',
+ description: 'Japanese multinational automotive manufacturer',
+ foundedYear: 1937,
+ headquarters: 'Toyota City, Japan',
+ website: 'https://www.toyota.com',
+ },
+ {
+ name: 'Audi',
+ logo: 'https://example.com/audi-logo.png',
+ description: 'German luxury automobile manufacturer',
+ foundedYear: 1909,
+ headquarters: 'Ingolstadt, Germany',
+ website: 'https://www.audi.com',
+ },
+ {
+ name: 'Mercedes-Benz',
+ logo: 'https://example.com/mercedes-logo.png',
+ description: 'German global automobile marque and a division of Daimler AG',
+ foundedYear: 1926,
+ headquarters: 'Stuttgart, Germany',
+ website: 'https://www.mercedes-benz.com',
+ },
+ ]);
+
+ // Get the inserted brands to connect them with models later
+ const brands = await this.brandsCollection.find().toArray();
+
+ // Insert default car models
+ await this.carModelsCollection.insertMany([
+ {
+ name: 'Model S',
+ productionStartYear: 2012,
+ category: 'Sedan',
+ description: 'All-electric five-door liftback sedan',
+ image: 'https://example.com/tesla-model-s.jpg',
+ brandId: brands[0]._id,
+ },
+ {
+ name: 'Model 3',
+ productionStartYear: 2017,
+ category: 'Sedan',
+ description: 'All-electric four-door sedan',
+ image: 'https://example.com/tesla-model-3.jpg',
+ brandId: brands[0]._id,
+ },
+ {
+ name: '3 Series',
+ productionStartYear: 1975,
+ category: 'Sedan',
+ description: 'Compact executive car',
+ image: 'https://example.com/bmw-3-series.jpg',
+ brandId: brands[1]._id,
+ },
+ {
+ name: 'X5',
+ productionStartYear: 1999,
+ category: 'SUV',
+ description: 'Mid-size luxury SUV',
+ image: 'https://example.com/bmw-x5.jpg',
+ brandId: brands[1]._id,
+ },
+ {
+ name: 'Camry',
+ productionStartYear: 1982,
+ category: 'Sedan',
+ description: 'Mid-size car',
+ image: 'https://example.com/toyota-camry.jpg',
+ brandId: brands[2]._id,
+ },
+ {
+ name: 'Prius',
+ productionStartYear: 1997,
+ category: 'Hatchback',
+ description: 'Hybrid electric mid-size car',
+ image: 'https://example.com/toyota-prius.jpg',
+ brandId: brands[2]._id,
+ },
+ {
+ name: 'A4',
+ productionStartYear: 1994,
+ category: 'Sedan',
+ description: 'Compact executive car',
+ image: 'https://example.com/audi-a4.jpg',
+ brandId: brands[3]._id,
+ },
+ {
+ name: 'Q7',
+ productionStartYear: 2005,
+ category: 'SUV',
+ description: 'Full-size luxury crossover SUV',
+ image: 'https://example.com/audi-q7.jpg',
+ brandId: brands[3]._id,
+ },
+ {
+ name: 'C-Class',
+ productionStartYear: 1993,
+ category: 'Sedan',
+ description: 'Compact executive car',
+ image: 'https://example.com/mercedes-c-class.jpg',
+ brandId: brands[4]._id,
+ },
+ {
+ name: 'GLE',
+ productionStartYear: 2015,
+ category: 'SUV',
+ description: 'Mid-size luxury crossover SUV',
+ image: 'https://example.com/mercedes-gle.jpg',
+ brandId: brands[4]._id,
+ },
+ ]);
+
+ // Get the inserted models to connect them with revisions
+ const models = await this.carModelsCollection.find().toArray();
+
+ // Find models by name for easy reference
+ const findModelByName = (name: string) => models.find(model => model.name === name);
+
+ // Insert default car revisions
+ await this.carRevisionsCollection.insertMany([
+ {
+ name: 'Model S Long Range Plus',
+ releaseYear: 2020,
+ engineTypes: ['Electric'],
+ horsePower: 670,
+ torque: 850,
+ topSpeed: 250,
+ acceleration0To100: 3.1,
+ fuelConsumption: 0,
+ dimensions: {
+ length: 4970,
+ width: 1964,
+ height: 1445,
+ wheelbase: 2960,
+ },
+ weight: 2250,
+ features: ['Autopilot', 'Premium Interior', 'All-Wheel Drive'],
+ images: ['https://example.com/tesla-model-s-2020-1.jpg', 'https://example.com/tesla-model-s-2020-2.jpg'],
+ modelId: findModelByName('Model S')?._id,
+ },
+ {
+ name: 'Model S Plaid',
+ releaseYear: 2021,
+ engineTypes: ['Electric'],
+ horsePower: 1020,
+ torque: 1050,
+ topSpeed: 322,
+ acceleration0To100: 2.1,
+ fuelConsumption: 0,
+ dimensions: {
+ length: 4970,
+ width: 1964,
+ height: 1445,
+ wheelbase: 2960,
+ },
+ weight: 2300,
+ features: ['Enhanced Autopilot', 'Yoke Steering', 'All-Wheel Drive', 'New Interior Design'],
+ images: ['https://example.com/tesla-model-s-plaid-1.jpg', 'https://example.com/tesla-model-s-plaid-2.jpg'],
+ modelId: findModelByName('Model S')?._id,
+ },
+ {
+ name: 'Model 3 Standard Range Plus',
+ releaseYear: 2021,
+ engineTypes: ['Electric'],
+ horsePower: 283,
+ torque: 450,
+ topSpeed: 225,
+ acceleration0To100: 5.6,
+ fuelConsumption: 0,
+ dimensions: {
+ length: 4694,
+ width: 1849,
+ height: 1443,
+ wheelbase: 2875,
+ },
+ weight: 1750,
+ features: ['Basic Autopilot', 'Standard Interior', 'Rear-Wheel Drive'],
+ images: ['https://example.com/tesla-model-3-standard-1.jpg', 'https://example.com/tesla-model-3-standard-2.jpg'],
+ modelId: findModelByName('Model 3')?._id,
+ },
+ {
+ name: '330i Sedan',
+ releaseYear: 2021,
+ engineTypes: ['Gasoline'],
+ horsePower: 255,
+ torque: 400,
+ topSpeed: 209,
+ acceleration0To100: 5.6,
+ fuelConsumption: 7.1,
+ dimensions: {
+ length: 4709,
+ width: 1827,
+ height: 1435,
+ wheelbase: 2851,
+ },
+ weight: 1620,
+ features: ['LED Headlights', 'iDrive Infotainment System', 'Leather Seats'],
+ images: ['https://example.com/bmw-330i-1.jpg', 'https://example.com/bmw-330i-2.jpg'],
+ modelId: findModelByName('3 Series')?._id,
+ },
+ {
+ name: 'M340i Sedan',
+ releaseYear: 2021,
+ engineTypes: ['Gasoline'],
+ horsePower: 382,
+ torque: 500,
+ topSpeed: 250,
+ acceleration0To100: 4.4,
+ fuelConsumption: 8.0,
+ dimensions: {
+ length: 4709,
+ width: 1827,
+ height: 1435,
+ wheelbase: 2851,
+ },
+ weight: 1670,
+ features: ['M Sport Differential', 'M Sport Brakes', 'Adaptive M Suspension'],
+ images: ['https://example.com/bmw-m340i-1.jpg', 'https://example.com/bmw-m340i-2.jpg'],
+ modelId: findModelByName('3 Series')?._id,
+ },
+ {
+ name: 'X5 xDrive40i',
+ releaseYear: 2021,
+ engineTypes: ['Gasoline'],
+ horsePower: 335,
+ torque: 450,
+ topSpeed: 243,
+ acceleration0To100: 5.5,
+ fuelConsumption: 9.2,
+ dimensions: {
+ length: 4922,
+ width: 2004,
+ height: 1745,
+ wheelbase: 2975,
+ },
+ weight: 2260,
+ features: ['Panoramic Roof', 'Head-Up Display', 'Gesture Control'],
+ images: ['https://example.com/bmw-x5-xdrive40i-1.jpg', 'https://example.com/bmw-x5-xdrive40i-2.jpg'],
+ modelId: findModelByName('X5')?._id,
+ },
+ {
+ name: 'Camry LE',
+ releaseYear: 2021,
+ engineTypes: ['Gasoline'],
+ horsePower: 203,
+ torque: 250,
+ topSpeed: 210,
+ acceleration0To100: 8.1,
+ fuelConsumption: 7.6,
+ dimensions: {
+ length: 4880,
+ width: 1840,
+ height: 1445,
+ wheelbase: 2825,
+ },
+ weight: 1580,
+ features: ['Toyota Safety Sense', 'Apple CarPlay', 'Android Auto'],
+ images: ['https://example.com/toyota-camry-le-1.jpg', 'https://example.com/toyota-camry-le-2.jpg'],
+ modelId: findModelByName('Camry')?._id,
+ },
+ {
+ name: 'Camry Hybrid',
+ releaseYear: 2021,
+ engineTypes: ['Hybrid'],
+ horsePower: 208,
+ torque: 220,
+ topSpeed: 180,
+ acceleration0To100: 7.8,
+ fuelConsumption: 4.2,
+ dimensions: {
+ length: 4880,
+ width: 1840,
+ height: 1445,
+ wheelbase: 2825,
+ },
+ weight: 1680,
+ features: ['Regenerative Braking', 'EV Mode', 'Energy Monitor'],
+ images: ['https://example.com/toyota-camry-hybrid-1.jpg', 'https://example.com/toyota-camry-hybrid-2.jpg'],
+ modelId: findModelByName('Camry')?._id,
+ },
+ {
+ name: 'Prius Prime',
+ releaseYear: 2021,
+ engineTypes: ['Plug-in Hybrid'],
+ horsePower: 121,
+ torque: 142,
+ topSpeed: 165,
+ acceleration0To100: 10.5,
+ fuelConsumption: 1.8,
+ dimensions: {
+ length: 4645,
+ width: 1760,
+ height: 1470,
+ wheelbase: 2700,
+ },
+ weight: 1530,
+ features: ['Electric Range of 40 km', 'Touch-sensitive controls', 'Quad-LED projector headlights'],
+ images: ['https://example.com/toyota-prius-prime-1.jpg', 'https://example.com/toyota-prius-prime-2.jpg'],
+ modelId: findModelByName('Prius')?._id,
+ },
+ {
+ name: 'A4 Prestige',
+ releaseYear: 2021,
+ engineTypes: ['Gasoline'],
+ horsePower: 261,
+ torque: 370,
+ topSpeed: 210,
+ acceleration0To100: 5.5,
+ fuelConsumption: 7.5,
+ dimensions: {
+ length: 4762,
+ width: 1847,
+ height: 1435,
+ wheelbase: 2820,
+ },
+ weight: 1640,
+ features: ['Audi Virtual Cockpit', 'Bang & Olufsen Sound System', 'Adaptive Cruise Control'],
+ images: ['https://example.com/audi-a4-prestige-1.jpg', 'https://example.com/audi-a4-prestige-2.jpg'],
+ modelId: findModelByName('A4')?._id,
+ },
+ ]);
+ }
+
/**
* Get all brands
*/
- getAllBrands(): Promise {
- return Promise.resolve(brands);
+ async getAllBrands(): Promise {
+ await this.connect();
+ if (!this.brandsCollection) throw new Error('Database not initialized');
+
+ return this.brandsCollection.find().toArray();
}
/**
* Get brand by ID
*/
- getBrandById(id: string): Promise {
- const brand = brands.find(brand => brand.id === id);
- return Promise.resolve(brand || null);
+ async getBrandById(id: string): Promise {
+ await this.connect();
+ if (!this.brandsCollection) throw new Error('Database not initialized');
+
+ return this.brandsCollection.findOne({ _id: new ObjectId(id) });
}
/**
* Get all car models
*/
- getAllCarModels(): Promise {
- return Promise.resolve(carModels);
+ async getAllCarModels(): Promise {
+ await this.connect();
+ if (!this.carModelsCollection) throw new Error('Database not initialized');
+
+ return this.carModelsCollection.find().toArray();
}
/**
* Get car models by brand ID
*/
- getCarModelsByBrandId(brandId: string): Promise {
- const brand = brands.find(brand => brand.id === brandId);
- return Promise.resolve(brand?.carModels || []);
+ async getCarModelsByBrandId(brandId: string): Promise {
+ await this.connect();
+ if (!this.carModelsCollection) throw new Error('Database not initialized');
+
+ return this.carModelsCollection.find({ brandId: new ObjectId(brandId) }).toArray();
}
/**
* Get car model by ID
*/
- getCarModelById(id: string): Promise {
- const carModel = carModels.find(model => model.id === id);
- return Promise.resolve(carModel || null);
+ async getCarModelById(id: string): Promise {
+ await this.connect();
+ if (!this.carModelsCollection) throw new Error('Database not initialized');
+
+ return this.carModelsCollection.findOne({ _id: new ObjectId(id) });
}
/**
* Get all car revisions
*/
- getAllCarRevisions(): Promise {
- return Promise.resolve(carRevisions);
+ async getAllCarRevisions(): Promise {
+ await this.connect();
+ if (!this.carRevisionsCollection) throw new Error('Database not initialized');
+
+ return this.carRevisionsCollection.find().toArray();
}
/**
* Get car revisions by model ID
*/
- getCarRevisionsByModelId(modelId: string): Promise {
- const carModel = carModels.find(model => model.id === modelId);
- return Promise.resolve(carModel?.revisions || []);
+ async getCarRevisionsByModelId(modelId: string): Promise {
+ await this.connect();
+ if (!this.carRevisionsCollection) throw new Error('Database not initialized');
+
+ return this.carRevisionsCollection.find({ modelId: new ObjectId(modelId) }).toArray();
}
/**
* Get car revision by ID
*/
- getCarRevisionById(id: string): Promise {
- const carRevision = carRevisions.find(revision => revision.id === id);
- return Promise.resolve(carRevision || null);
+ async getCarRevisionById(id: string): Promise {
+ await this.connect();
+ if (!this.carRevisionsCollection) throw new Error('Database not initialized');
+
+ return this.carRevisionsCollection.findOne({ _id: new ObjectId(id) });
}
/**
* Search cars by name (searches both models and revisions)
*/
- searchCarsByName(name: string): Promise<{ models: CarModel[], revisions: CarRevision[] }> {
+ async searchCarsByName(name: string): Promise<{ models: CarModel[], revisions: CarRevision[], brands: Brand[] }> {
+ await this.connect();
+ if (!this.brandsCollection || !this.carModelsCollection || !this.carRevisionsCollection) {
+ throw new Error('Database not initialized');
+ }
+
const lowercaseName = name.toLowerCase();
- const matchingModels = carModels.filter(model =>
- model.name.toLowerCase().includes(lowercaseName)
- );
+ const matchingModels = await this.carModelsCollection.find({
+ name: { $regex: new RegExp(lowercaseName, 'i') }
+ }).toArray();
- const matchingRevisions = carRevisions.filter(revision =>
- revision.name.toLowerCase().includes(lowercaseName)
- );
-
- return Promise.resolve({
+ const matchingRevisions = await this.carRevisionsCollection.find({
+ name: { $regex: new RegExp(lowercaseName, 'i') }
+ }).toArray();
+
+ const matchingBrands = await this.brandsCollection.find({
+ name: { $regex: new RegExp(lowercaseName, 'i') }
+ }).toArray();
+
+ return {
models: matchingModels,
- revisions: matchingRevisions
- });
+ revisions: matchingRevisions,
+ brands: matchingBrands
+ };
}
/**
* Get cars by category
*/
- getCarsByCategory(category: string): Promise {
- const matchingModels = carModels.filter(model =>
- model.category?.toLowerCase() === category.toLowerCase()
- );
+ async getCarsByCategory(category: string): Promise {
+ await this.connect();
+ if (!this.carModelsCollection) throw new Error('Database not initialized');
- return Promise.resolve(matchingModels);
+ return this.carModelsCollection.find({
+ category: { $regex: new RegExp(`^${category}$`, 'i') }
+ }).toArray();
}
/**
* Get cars by year range
*/
- getCarsByYearRange(startYear: number, endYear: number): Promise {
- const matchingModels = carModels.filter(model => {
- const startYearMatch = !model.productionStartYear || model.productionStartYear <= endYear;
- const endYearMatch = !model.productionEndYear || model.productionEndYear >= startYear;
- return startYearMatch && endYearMatch;
- });
+ async getCarsByYearRange(startYear: number, endYear: number): Promise {
+ await this.connect();
+ if (!this.carModelsCollection) throw new Error('Database not initialized');
- return Promise.resolve(matchingModels);
+ return this.carModelsCollection.find({
+ $or: [
+ { productionStartYear: { $lte: endYear, $gte: startYear } },
+ {
+ productionStartYear: { $lte: endYear },
+ productionEndYear: { $gte: startYear }
+ },
+ {
+ productionStartYear: { $lte: endYear },
+ productionEndYear: { $exists: false }
+ }
+ ]
+ }).toArray();
}
}
\ No newline at end of file