UNPKG

bookingjs

Version:

A framework-agnostic JavaScript library for managing rink bookings, availability, and scheduling

434 lines (330 loc) 10.8 kB
# 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