bookingjs
Version:
A framework-agnostic JavaScript library for managing rink bookings, availability, and scheduling
434 lines (330 loc) • 10.8 kB
Markdown
# 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