- Enhanced globals.css with comprehensive animation system - Added advanced map marker animations (GPS, parking) - Improved button and filter animations with hover effects - Added new UI components: BookingModal, ParkingDetails, WheelPicker - Reorganized project structure with better documentation - Added optimization scripts and improved development workflow - Updated deployment guides and technical documentation - Enhanced mobile responsiveness and accessibility support
17 KiB
17 KiB
🏗️ Smart Parking Finder - System Architecture Documentation
📋 Table of Contents
- System Overview
- Architecture Patterns
- Technology Stack
- Data Structure & Schema
- System Design
- API Documentation
- Database Design
- Security & Performance
🎯 System Overview
Project Description
Smart Parking Finder is a real-time parking management system that helps users find available parking spots in urban areas. The system provides interactive mapping, route optimization, and real-time availability tracking.
Core Features
- 🗺️ Interactive map with OpenStreetMap integration
- 🔍 Real-time parking spot search
- 🧭 GPS-based navigation and routing
- 📱 Responsive web application
- 🔄 Real-time data synchronization
- 📊 Analytics and reporting
System Goals
- Performance: Sub-second response times for searches
- Scalability: Support 10,000+ concurrent users
- Reliability: 99.9% uptime availability
- Usability: Intuitive interface for all user types
🏛️ Architecture Patterns
1. Microservices Architecture
┌─────────────────────────────────────────────────────────────┐
│ Client Layer │
├─────────────────────────────────────────────────────────────┤
│ Next.js Frontend (React 18 + TypeScript + Tailwind CSS) │
└─────────────────────────────────────────────────────────────┘
│
┌─────────┴─────────┐
│ API Gateway │
│ (NestJS Router) │
└─────────┬─────────┘
│
┌─────────────────────┼─────────────────────┐
│ │ │
┌───────▼───────┐ ┌─────────▼─────────┐ ┌───────▼───────┐
│ Auth Service │ │ Parking Service │ │Routing Service│
│ (JWT) │ │ (CRUD + Search) │ │ (Valhalla) │
└───────────────┘ └───────────────────┘ └───────────────┘
│ │ │
└─────────────────────┼─────────────────────┘
│
┌─────────▼─────────┐
│ Data Layer │
│ PostgreSQL + Redis│
└───────────────────┘
2. Layered Architecture
- Presentation Layer: Next.js React Components
- Business Logic Layer: NestJS Services & Controllers
- Data Access Layer: TypeORM Repositories
- Database Layer: PostgreSQL with Redis Cache
3. Event-Driven Architecture
- Real-time updates using WebSocket connections
- Event sourcing for parking availability changes
- Message queuing for background tasks
🛠️ Technology Stack
Frontend Stack
{
"framework": "Next.js 14",
"runtime": "React 18",
"language": "TypeScript 5.x",
"styling": "Tailwind CSS 3.x",
"mapping": "React Leaflet + OpenStreetMap",
"state": "React Query (TanStack Query)",
"forms": "React Hook Form",
"testing": "Jest + React Testing Library"
}
Backend Stack
{
"framework": "NestJS 10",
"runtime": "Node.js 18+",
"language": "TypeScript 5.x",
"database": "PostgreSQL 15",
"cache": "Redis 7",
"orm": "TypeORM",
"authentication": "JWT + Passport",
"validation": "Class Validator",
"documentation": "Swagger/OpenAPI",
"testing": "Jest + Supertest"
}
Infrastructure Stack
{
"containerization": "Docker + Docker Compose",
"routing": "Valhalla Routing Engine",
"mapping": "OpenStreetMap Data",
"monitoring": "Health Check Endpoints",
"logging": "Winston Logger",
"process": "PM2 Process Manager"
}
📊 Data Structure & Schema
1. Database Schema
Users Table
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
full_name VARCHAR(255) NOT NULL,
phone VARCHAR(20),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
is_active BOOLEAN DEFAULT true,
role user_role DEFAULT 'customer'
);
CREATE TYPE user_role AS ENUM ('customer', 'operator', 'admin');
Parking Lots Table
CREATE TABLE parking_lots (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255) NOT NULL,
address TEXT NOT NULL,
latitude DECIMAL(10,8) NOT NULL,
longitude DECIMAL(11,8) NOT NULL,
total_spots INTEGER NOT NULL DEFAULT 0,
available_spots INTEGER NOT NULL DEFAULT 0,
price_per_hour DECIMAL(10,2) NOT NULL,
operating_hours JSONB,
amenities TEXT[],
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
is_active BOOLEAN DEFAULT true
);
-- Spatial index for location-based queries
CREATE INDEX idx_parking_lots_location ON parking_lots USING GIST (
ll_to_earth(latitude, longitude)
);
Parking Spots Table
CREATE TABLE parking_spots (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
parking_lot_id UUID REFERENCES parking_lots(id) ON DELETE CASCADE,
spot_number VARCHAR(20) NOT NULL,
spot_type spot_type DEFAULT 'regular',
is_occupied BOOLEAN DEFAULT false,
is_reserved BOOLEAN DEFAULT false,
last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(parking_lot_id, spot_number)
);
CREATE TYPE spot_type AS ENUM ('regular', 'disabled', 'electric', 'compact');
Reservations Table
CREATE TABLE reservations (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
parking_spot_id UUID REFERENCES parking_spots(id) ON DELETE CASCADE,
start_time TIMESTAMP NOT NULL,
end_time TIMESTAMP NOT NULL,
total_cost DECIMAL(10,2) NOT NULL,
status reservation_status DEFAULT 'pending',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TYPE reservation_status AS ENUM ('pending', 'confirmed', 'active', 'completed', 'cancelled');
2. API Data Models
Parking Lot Response Model
interface ParkingLot {
id: string;
name: string;
address: string;
coordinates: {
latitude: number;
longitude: number;
};
availability: {
totalSpots: number;
availableSpots: number;
occupancyRate: number;
};
pricing: {
hourlyRate: number;
currency: string;
discounts?: Discount[];
};
operatingHours: {
[day: string]: {
open: string;
close: string;
is24Hours: boolean;
};
};
amenities: string[];
distance?: number;
estimatedWalkTime?: number;
metadata: {
createdAt: string;
updatedAt: string;
isActive: boolean;
};
}
Search Request Model
interface ParkingSearchRequest {
location: {
latitude: number;
longitude: number;
};
radius: number; // in meters
filters?: {
maxPrice?: number;
amenities?: string[];
spotTypes?: SpotType[];
availableOnly?: boolean;
};
sorting?: {
field: 'distance' | 'price' | 'availability';
order: 'asc' | 'desc';
};
pagination?: {
page: number;
limit: number;
};
}
Route Response Model
interface RouteResponse {
route: {
distance: number; // in meters
duration: number; // in seconds
coordinates: [number, number][]; // [lng, lat] pairs
};
instructions: RouteInstruction[];
summary: {
totalDistance: string;
totalTime: string;
estimatedCost: number;
};
}
interface RouteInstruction {
text: string;
distance: number;
time: number;
sign: number;
interval: [number, number];
}
🎨 System Design
1. Frontend Architecture
Component Hierarchy
App (layout.tsx)
├── Header
├── LocationDetector
├── MapView
│ ├── LeafletMap
│ ├── ParkingMarkers
│ ├── RouteLayer
│ └── LocationMarker
├── ParkingList
│ ├── ParkingCard
│ └── PaginationControls
├── BookingModal
├── TransportationSelector
└── GPSSimulator (dev only)
State Management
// Global State Structure
interface AppState {
user: {
profile: UserProfile | null;
authentication: AuthState;
preferences: UserPreferences;
};
location: {
current: Coordinates | null;
permissions: LocationPermission;
tracking: boolean;
};
parking: {
searchResults: ParkingLot[];
selectedLot: ParkingLot | null;
filters: SearchFilters;
loading: boolean;
error: string | null;
};
routing: {
currentRoute: RouteResponse | null;
isCalculating: boolean;
transportMode: TransportMode;
};
ui: {
mapCenter: Coordinates;
mapZoom: number;
sidebarOpen: boolean;
modalState: ModalState;
};
}
2. Backend Architecture
Service Layer Design
// Parking Service Architecture
@Injectable()
export class ParkingService {
constructor(
private readonly parkingRepository: ParkingRepository,
private readonly cacheService: CacheService,
private readonly geoService: GeoService
) {}
async findNearbyParking(searchDto: ParkingSearchDto): Promise<ParkingLot[]> {
// 1. Check cache first
const cacheKey = this.generateCacheKey(searchDto);
const cached = await this.cacheService.get(cacheKey);
if (cached) return cached;
// 2. Perform spatial query
const results = await this.parkingRepository.findWithinRadius({
latitude: searchDto.latitude,
longitude: searchDto.longitude,
radius: searchDto.radius
});
// 3. Apply filters and sorting
const filtered = this.applyFilters(results, searchDto.filters);
const sorted = this.applySorting(filtered, searchDto.sorting);
// 4. Cache results
await this.cacheService.set(cacheKey, sorted, 300); // 5 min cache
return sorted;
}
}
Repository Pattern
@EntityRepository(ParkingLot)
export class ParkingRepository extends Repository<ParkingLot> {
async findWithinRadius(params: SpatialQueryParams): Promise<ParkingLot[]> {
return this.createQueryBuilder('parking')
.select()
.addSelect(`
(6371 * acos(
cos(radians(:lat)) * cos(radians(latitude)) *
cos(radians(longitude) - radians(:lng)) +
sin(radians(:lat)) * sin(radians(latitude))
)) AS distance
`)
.where(`
(6371 * acos(
cos(radians(:lat)) * cos(radians(latitude)) *
cos(radians(longitude) - radians(:lng)) +
sin(radians(:lat)) * sin(radians(latitude))
)) <= :radius
`)
.andWhere('is_active = true')
.setParameters({
lat: params.latitude,
lng: params.longitude,
radius: params.radius / 1000 // Convert to km
})
.orderBy('distance', 'ASC')
.getMany();
}
}
3. Real-time Updates
WebSocket Integration
// WebSocket Gateway for real-time updates
@WebSocketGateway({
cors: { origin: '*' },
transports: ['websocket', 'polling']
})
export class ParkingGateway implements OnGatewayConnection, OnGatewayDisconnect {
@WebSocketServer() server: Server;
async handleConnection(client: Socket) {
// Subscribe client to location-based updates
const { latitude, longitude, radius } = client.handshake.query;
const room = this.generateLocationRoom(latitude, longitude, radius);
client.join(room);
}
@SubscribeMessage('parkingUpdate')
async handleParkingUpdate(client: Socket, data: ParkingUpdateDto) {
// Broadcast to relevant clients
const affectedRooms = this.getAffectedRooms(data.location);
affectedRooms.forEach(room => {
this.server.to(room).emit('parkingAvailabilityChanged', {
parkingLotId: data.parkingLotId,
availableSpots: data.availableSpots,
timestamp: new Date().toISOString()
});
});
}
}
🔗 API Documentation
Authentication Endpoints
POST /api/auth/login
POST /api/auth/register
POST /api/auth/refresh
DELETE /api/auth/logout
GET /api/auth/profile
PUT /api/auth/profile
Parking Endpoints
GET /api/parking/search
GET /api/parking/:id
POST /api/parking/:id/reserve
GET /api/parking/reservations
PUT /api/parking/reservations/:id
DELETE /api/parking/reservations/:id
Routing Endpoints
POST /api/routing/calculate
GET /api/routing/modes
POST /api/routing/optimize
Health & Monitoring
GET /api/health
GET /api/health/database
GET /api/health/cache
GET /api/metrics
🗄️ Database Design
Indexing Strategy
-- Spatial indexes for location queries
CREATE INDEX idx_parking_lots_location ON parking_lots
USING GIST (ll_to_earth(latitude, longitude));
-- Compound indexes for filtering
CREATE INDEX idx_parking_lots_active_price ON parking_lots (is_active, price_per_hour);
CREATE INDEX idx_parking_spots_lot_available ON parking_spots (parking_lot_id, is_occupied);
-- Time-based indexes for reservations
CREATE INDEX idx_reservations_time_range ON reservations (start_time, end_time);
CREATE INDEX idx_reservations_user_status ON reservations (user_id, status, created_at);
Data Partitioning
-- Partition reservations by month for better performance
CREATE TABLE reservations_2024_01 PARTITION OF reservations
FOR VALUES FROM ('2024-01-01') TO ('2024-02-01');
-- Automated partition management
CREATE OR REPLACE FUNCTION create_monthly_partition()
RETURNS void AS $$
DECLARE
start_date date;
end_date date;
table_name text;
BEGIN
start_date := date_trunc('month', CURRENT_DATE + interval '1 month');
end_date := start_date + interval '1 month';
table_name := 'reservations_' || to_char(start_date, 'YYYY_MM');
EXECUTE format('CREATE TABLE %I PARTITION OF reservations
FOR VALUES FROM (%L) TO (%L)',
table_name, start_date, end_date);
END;
$$ LANGUAGE plpgsql;
🔒 Security & Performance
Security Measures
- Authentication: JWT with refresh tokens
- Authorization: Role-based access control (RBAC)
- Input Validation: DTO validation with class-validator
- SQL Injection: Protected by TypeORM parameterized queries
- Rate Limiting: API rate limiting per user/IP
- CORS: Configured for specific origins
- HTTPS: TLS encryption in production
Performance Optimizations
- Caching: Redis for frequently accessed data
- Database: Optimized indexes and query planning
- CDN: Static asset delivery optimization
- Compression: Gzip compression for API responses
- Lazy Loading: Component and route-based code splitting
- Pagination: Efficient pagination for large datasets
- Connection Pooling: Database connection optimization
Monitoring & Logging
// Health Check Implementation
@Controller('health')
export class HealthController {
constructor(
private readonly healthCheckService: HealthCheckService,
private readonly databaseHealthIndicator: TypeOrmHealthIndicator,
private readonly redisHealthIndicator: RedisHealthIndicator
) {}
@Get()
@HealthCheck()
check() {
return this.healthCheckService.check([
() => this.databaseHealthIndicator.pingCheck('database'),
() => this.redisHealthIndicator.checkHealth('redis'),
() => this.checkExternalServices()
]);
}
}
📈 Scalability Considerations
Horizontal Scaling
- Load Balancing: Multiple application instances
- Database Sharding: Geographic or user-based sharding
- Microservices: Independent service scaling
- CDN Integration: Global content distribution
Vertical Scaling
- Database Optimization: Query optimization and indexing
- Memory Management: Efficient caching strategies
- CPU Optimization: Algorithmic improvements
- Storage Optimization: Data archiving and compression
Future Enhancements
- Machine Learning: Predictive parking availability
- Mobile Apps: Native iOS/Android applications
- Payment Integration: Online payment processing
- IoT Integration: Smart parking sensor integration
- Multi-language: Internationalization support
Last Updated: August 3, 2025 Version: 1.0.0