Skip to content

About

Ski resort board website. server is running on "render".

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

Β 

History

16 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🎿 Ski Resorts β€” Hotel Search

A full-stack hotel search application for ski resorts, split into two packages:

  • client/ β€” React + TypeScript + Vite frontend
  • server/ β€” Node.js/TypeScript backend (Express REST API)

πŸ“‚ Repository Structure

ski-resorts/
β”œβ”€β”€ client/                 # React + TypeScript + Vite frontend
β”‚   β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ public/
β”‚   β”œβ”€β”€ package.json
β”‚   └── vite.config.ts
└── server/                 # Express + TypeScript backend
    β”œβ”€β”€ src/
    β”‚   β”œβ”€β”€ server.ts                  # Express server & initialization
    β”‚   β”œβ”€β”€ index.ts                   # Module entry point
    β”‚   β”œβ”€β”€ types/                     # TypeScript interfaces
    β”‚   β”œβ”€β”€ providers/                 # ExternalApiProvider.ts (AWS Lambda integration)
    β”‚   β”œβ”€β”€ managers/                  # HotelSearchManager.ts (core search logic)
    β”‚   β”œβ”€β”€ controllers/               # HotelSearchController.ts (request handlers)
    β”‚   β”œβ”€β”€ routes/                    # hotelRoutes.ts (API routes)
    β”‚   β”œβ”€β”€ middleware/                # validation.ts (validation & error handling)
    β”‚   β”œβ”€β”€ config/                    # configuration
    β”‚   β”œβ”€β”€ utils/                     # helper functions
    β”‚   └── data/                      # hotels.json (ski resorts reference)
    β”œβ”€β”€ dist/                          # compiled JavaScript (after build)
    β”œβ”€β”€ package.json
    └── tsconfig.json

πŸš€ Quick Start

Backend (server/)

cd server
npm install
npm run build
npm run dev        # http://localhost:9000

Frontend (client/)

cd client
npm install
npm run dev

🏨 Backend β€” Complete Implementation

Project Overview

The backend is a production-ready service for the hotel search web application. It features a scalable architecture that supports multiple API providers with intelligent aggregation, multi-group size requests, and comprehensive validation.

βœ… Core Features

  • Multi-Provider Architecture: Easy to add new API providers
  • Smart Multi-Group Aggregation: Automatically fetches larger room sizes for more options
  • Parallel Execution: All requests run simultaneously for optimal performance
  • Result Deduplication: Removes duplicates based on hotel name + capacity + price
  • Price Sorting: Results sorted by price in ascending order
  • Comprehensive Validation: Input validation with detailed error messages

βœ… Technical Implementation

  • TypeScript for type safety
  • Express.js REST API
  • Modular architecture (MVC pattern)
  • Middleware-based validation
  • Error handling and logging
  • Configuration management

πŸ“‘ API Endpoint

POST /api/hotels/search

Request:

{
  "query": {
    "ski_site": 1,                    // 1-5 (ski resort ID)
    "from_date": "03/04/2025",        // DD/MM/YYYY format
    "to_date": "03/11/2025",          // DD/MM/YYYY format
    "group_size": 4                   // 1-10 people
  }
}

Response:

{
  "success": true,
  "data": {
    "hotels": [
      {
        "id": "hotel-123",
        "name": "Hotel Name",
        "room_type": "Standard",
        "capacity": 4,
        "price": 150,
        "available_rooms": 2,
        "ski_site": 1,
        "provider": "ExternalHotelsSimulator"
      }
    ],
    "totalCount": 25,
    "query": { /* original query */ }
  }
}

Test it with curl:

curl -X POST http://localhost:9000/api/hotels/search \
  -H "Content-Type: application/json" \
  -d '{
    "query": {
      "ski_site": 1,
      "from_date": "03/04/2025",
      "to_date": "03/11/2025",
      "group_size": 2
    }
  }'

πŸ—οΈ Architecture Highlights

1. Provider Pattern

// Add new providers by implementing the interface
interface ApiProvider {
  name: string;
  search(query: SearchQuery): Promise<Hotel[]>;
}

2. Multi-Group Aggregation Flow

User searches for group_size: 2
    ↓
Manager calculates: [2, 3, 4, 5, 6, 7, 8, 9, 10]
    ↓
Sends 9 parallel requests to external API
    ↓
Aggregates all results
    ↓
Deduplicates entries
    ↓
Sorts by price
    ↓
Returns combined results

3. Error Handling

  • Invalid input β†’ 400 Bad Request
  • Server error β†’ 500 Internal Server Error
  • Provider failure β†’ Graceful recovery (returns results from other providers)

πŸ“ Validation Rules

Field Rules
ski_site Required, must be positive number
from_date Required, format: DD/MM/YYYY
to_date Required, format: DD/MM/YYYY, must be after from_date
group_size Required, must be 1-10

🎯 Performance Features

  • Parallel Requests: ~9x faster than sequential
  • Set-Based Deduplication: O(n) time complexity
  • Price Sorting: O(n log n) time complexity
  • Error Resilience: One provider failure doesn't crash search

🌐 Ski Resorts (Available Destinations)

1: Val Thorens
2: Courchevel
3: Tignes
4: La Plagne
5: Chamonix

πŸ”Œ Integration with the Frontend

The React frontend should:

  1. Send requests to POST /api/hotels/search
  2. Parse response with structure: { success, data: { hotels, totalCount, query } }
  3. Handle errors: check response status and error field
  4. Display results: map over hotels array to render UI

Example:

async function searchHotels(query) {
  const response = await fetch('/api/hotels/search', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ query })
  });

  if (!response.ok) {
    const error = await response.json();
    console.error('Search failed:', error.error);
    return;
  }

  const data = await response.json();
  displayHotels(data.data.hotels);
}

πŸ›‘οΈ Security Features

  • βœ… Input validation on all fields
  • βœ… Type-safe TypeScript implementation
  • βœ… CORS configured
  • βœ… Error messages don't expose system details
  • βœ… Middleware-based protection

🚒 Deployment

npm run build
PORT=8080 npm run start

Environment Variables

PORT=8080              # Server port
NODE_ENV=production    # Environment
DEBUG=false            # Debug logging

πŸ”§ npm Scripts (server)

npm run dev         # Start development server with hot reload
npm run build       # Compile TypeScript to JavaScript
npm run start       # Run compiled JavaScript (production)

πŸ“ˆ Future Enhancements

  • Streaming/progressive responses
  • Result caching with TTL
  • Rate limiting
  • Advanced filtering (amenities, ratings)
  • Pagination
  • Analytics and monitoring

πŸ’» Frontend β€” React + TypeScript + Vite

The client is built on Vite's minimal React + TypeScript template, providing HMR and preconfigured ESLint rules.

Two official Vite plugins are available for Fast Refresh:

Expanding the ESLint configuration

If you are developing a production application, it's recommended to enable type-aware lint rules:

  • Configure the top-level parserOptions property:
export default tseslint.config({
  languageOptions: {
    // other options...
    parserOptions: {
      project: ['./tsconfig.node.json', './tsconfig.app.json'],
      tsconfigRootDir: import.meta.dirname,
    },
  },
})
  • Replace tseslint.configs.recommended with tseslint.configs.recommendedTypeChecked or tseslint.configs.strictTypeChecked
  • Optionally add ...tseslint.configs.stylisticTypeChecked
  • Install eslint-plugin-react and update the config:
// eslint.config.js
import react from 'eslint-plugin-react'

export default tseslint.config({
  // Set the react version
  settings: { react: { version: '18.3' } },
  plugins: {
    // Add the react plugin
    react,
  },
  rules: {
    // other rules...
    // Enable its recommended rules
    ...react.configs.recommended.rules,
    ...react.configs['jsx-runtime'].rules,
  },
})

✨ What Makes This Project Great

  1. Extensible: Add new backend providers without touching existing code
  2. Performant: Parallel execution for speed
  3. Reliable: Graceful error handling and recovery
  4. Maintainable: Clean architecture, TypeScript for safety throughout client and server
  5. Production-Ready: Includes validation, error handling, and logging

About

Ski resort board website. server is running on "render".

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages