# BookingJS

A framework-agnostic JavaScript library for managing rink bookings, availability, and scheduling. Built following the LeagueJS architecture pattern, BookingJS provides a class-based approach for direct manipulation of booking data with full TypeScript support and cross-environment compatibility.

## Features

- **Framework Agnostic**: Works with React, Vue, Angular, and vanilla JavaScript
- **TypeScript Support**: Full type definitions included
- **Dual Module Support**: ES Modules and CommonJS builds
- **Real-time Availability**: Advanced availability checking and conflict resolution
- **Audit Logging**: Complete audit trail for all booking operations
- **Data Retention**: Configurable cleanup policies for long-term data management
- **Extensible Architecture**: Easy to extend with custom booking types and validation rules

## Installation

```bash
npm install bookingjs
```

## Quick Start

### ES Modules
```javascript
import { BookingSystem, Green, Rink, BookingType } from 'bookingjs';

// Create a booking system for your club
const bookingSystem = new BookingSystem({
  club: 'your-club-id'
});

// Create a green with rinks
const green = new Green({
  name: 'Main Green',
  location: '123 Bowling St, Your City',
  facilities: ['Changing Rooms', 'Car Park', 'Clubhouse']
});

// Add rinks to the green (up to 12 per green)
for (let i = 1; i <= 6; i++) {
  green.addRink(new Rink({ number: i }));
}

// Add the green to the booking system
bookingSystem.addGreen(green);

// Create a booking
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
tomorrow.setHours(10, 0, 0, 0);

const booking = bookingSystem.createBooking({
  memberId: 'member-123',
  rinkId: green.rinks[0]._id,
  bookingTypeId: 'regular',
  date: tomorrow,
  start: new Date(tomorrow),
  end: new Date(tomorrow.getTime() + 2 * 60 * 60 * 1000), // 2 hours
  notes: 'Team practice session'
}, 'member-123');

console.log('Booking created:', booking._id);
```

### CommonJS
```javascript
const { BookingSystem, Green, Rink } = require('bookingjs');

// Same usage as above
```

## Core Classes

### BookingSystem

The main class that orchestrates all booking operations.

```javascript
const bookingSystem = new BookingSystem({
  club: 'your-club-id',
  settings: {
    bookingRules: {
      maxAdvanceBookingDays: 30,
      minAdvanceBookingHours: 2,
      maxBookingDuration: 180, // minutes
      minBookingDuration: 60,
      allowConcurrentBookings: false,
      requireApproval: false
    }
  }
});

// Create bookings
const booking = bookingSystem.createBooking(bookingData, memberId);

// Modify bookings
bookingSystem.modifyBooking(bookingId, updates, memberId);

// Cancel bookings
bookingSystem.cancelBooking(bookingId, memberId);

// Check availability
const availability = bookingSystem.getAvailability(rinkId, date, duration);

// Get member bookings
const memberBookings = bookingSystem.getMemberBookings(memberId);

// Get system statistics
const stats = bookingSystem.getSystemStats();
```

### Green

Represents a bowling green containing multiple rinks.

```javascript
const green = new Green({
  name: 'Championship Green',
  location: 'North Field',
  facilities: ['Scoreboard', 'Seating', 'Lighting'],
  allowedBookingTypes: ['regular', 'tournament'] // Optional restrictions
});

// Add rinks
green.addRink(new Rink({ number: 1 }));

// Get available rinks for a time period
const availableRinks = green.getAvailableRinks(
  date, 
  startTime, 
  endTime, 
  existingBookings, 
  bookingTypeId
);

// Get utilization statistics
const stats = green.getUtilizationStats(allBookings, startDate, endDate);
```

### Rink

Represents an individual bookable rink within a green.

```javascript
const rink = new Rink({
  number: 1,
  allowedBookingTypes: ['regular', 'maintenance'] // Optional restrictions
});

// Check availability
const isAvailable = rink.isAvailable(date, start, end, existingBookings);

// Validate a booking
rink.validateBooking(bookingTypeId, date, start, end, existingBookings);
```

### Booking

Represents a booking reservation.

```javascript
const booking = new Booking({
  memberId: 'member-123',
  rinkId: 'rink-456',
  bookingTypeId: 'regular',
  date: new Date('2024-03-15'),
  start: new Date('2024-03-15T10:00:00'),
  end: new Date('2024-03-15T12:00:00'),
  participants: ['member-123', 'member-456'],
  notes: 'Weekly team practice'
});

// Update booking status
booking.updateStatus('confirmed');

// Add/remove participants
booking.addParticipant('member-789');
booking.removeParticipant('member-456');

// Check booking state
const isActive = booking.isActive();
const canModify = booking.canModify();
const duration = booking.getDuration(); // returns minutes
```

### BookingType

Defines types of bookings with visual styling and priorities.

```javascript
const bookingType = new BookingType({
  name: 'Tournament',
  backgroundColor: '#9C27B0',
  foregroundColor: '#FFFFFF',
  description: 'Tournament or competition booking',
  priority: 5
});

// Update booking type
bookingType.update({
  priority: 10,
  description: 'High priority tournament booking'
});

// Get default booking types
const defaults = BookingType.getDefaults();
// Returns: Regular, Maintenance, Tournament types
```

## Advanced Features

### Availability Checking

```javascript
// Get available time slots for a specific rink
const availability = bookingSystem.getAvailability(rinkId, date, durationMinutes);

// Check if a specific time slot is available
import { isTimeSlotAvailable } from 'bookingjs';
const isAvailable = isTimeSlotAvailable(start, end, existingBookings);

// Find next available slot
import { getNextAvailableSlot } from 'bookingjs';
const nextSlot = getNextAvailableSlot(
  afterTime, 
  duration, 
  existingBookings, 
  workingHours
);
```

### Member Preferences

```javascript
// Set member preferences
bookingSystem.setMemberPreferences('member-123', {
  preferredGreen: greenId,
  preferredBookingType: 'regular',
  preferredDuration: 120,
  reminderEnabled: true
});

// Get member preferences
const preferences = bookingSystem.getMemberPreferences('member-123');
```

### Audit Logging

```javascript
// Get audit log with filters
const auditLog = bookingSystem.getAuditLog({
  start: new Date('2024-01-01'),
  end: new Date('2024-01-31'),
  memberId: 'member-123',
  entityType: 'booking',
  action: 'create'
});

// Each audit entry contains:
// - action: 'create', 'update', 'delete', 'cancel'
// - entityType: 'booking', 'green', 'rink', 'bookingType'
// - memberId: who performed the action
// - timestamp: when it happened
// - oldValues/newValues: what changed
```

### Data Cleanup

```javascript
// Manual cleanup
const removedBookings = bookingSystem.clearOldBookings(cutoffDate, memberId);
const removedAuditEntries = bookingSystem.purgeAuditLog(cutoffDate, memberId);

// Automatic cleanup based on retention settings
const cleanupSummary = bookingSystem.cleanupSystem(memberId);
```

### Persistence

```javascript
// Serialize to JSON
const jsonData = bookingSystem.toJSON();

// Restore from JSON
const restoredSystem = BookingSystem.fromJSON(jsonData);

// All classes support JSON serialization
const greenJson = green.toJSON();
const restoredGreen = Green.fromJSON(greenJson);
```

## Error Handling

BookingJS provides specific error types for different scenarios:

```javascript
import { 
  BookingConflictError,
  InvalidTimeSlotError,
  MemberPermissionError,
  ValidationError,
  BookingTypeNotAllowedError
} from 'bookingjs';

try {
  bookingSystem.createBooking(bookingData, memberId);
} catch (error) {
  if (error instanceof BookingConflictError) {
    console.log('Booking conflicts with:', error.conflictingBooking);
  } else if (error instanceof ValidationError) {
    console.log('Validation failed for field:', error.field);
  }
  // Handle other error types...
}
```

## Configuration

### Booking Rules

```javascript
const settings = {
  bookingRules: {
    maxAdvanceBookingDays: 30,    // How far ahead bookings can be made
    minAdvanceBookingHours: 2,    // Minimum notice required
    maxBookingDuration: 180,      // Maximum booking length (minutes)
    minBookingDuration: 60,       // Minimum booking length (minutes)
    allowConcurrentBookings: false, // Allow overlapping bookings
    requireApproval: false        // Require admin approval
  }
};
```

### Data Retention

```javascript
const settings = {
  dataRetention: {
    bookingRetentionDays: 365,     // Keep bookings for 1 year
    auditLogRetentionDays: 1095,   // Keep audit logs for 3 years
    autoCleanupEnabled: true,      // Enable automatic cleanup
    cleanupIntervalDays: 30        // Run cleanup every 30 days
  }
};
```

## TypeScript Support

BookingJS includes comprehensive TypeScript definitions:

```typescript
import { BookingSystem, Booking, Green, BookingType } from 'bookingjs';

interface BookingData {
  memberId: string;
  rinkId: string;
  bookingTypeId: string;
  date: Date;
  start: Date;
  end: Date;
  notes?: string;
}

const system: BookingSystem = new BookingSystem({ club: 'my-club' });
const booking: Booking = system.createBooking(bookingData, memberId);
```

## Testing

Run the test suite:

```bash
npm test
```

Run tests with coverage:

```bash
npm run test:coverage
```

## Development

### Building

```bash
npm run build
```

This generates:
- `dist/index.js` - ES Module build
- `dist/index.cjs` - CommonJS build  
- `dist/index.d.ts` - TypeScript declarations

### Development Mode

```bash
npm run dev
```

Runs Rollup in watch mode for development.

## Browser Compatibility

- Modern browsers with ES2020 support
- Node.js 14+
- Supports both ES Modules and CommonJS

## License

MIT License - see LICENSE file for details.

## Contributing

1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests for new functionality
5. Run the test suite
6. Submit a pull request

## Support

For issues and questions:
- Repository Issues: [Create an issue](https://helixteamhub.cloud/lovebowlscouk/projects/leaguejs/repositories/git/bookingJS/issues)
- Documentation: See the `/docs` folder for detailed API documentation

## Related Projects

- [LeagueJS](https://helixteamhub.cloud/lovebowlscouk/projects/leaguejs) - Sports league management library

---

Built with ❤️ for the bowling community 