UNPKG

vue-hotel-booking-calendar

Version:

A Vue 3 calendar component suite for hotel bookings with price calculation, hotel dashboard, custom text labels, and flexible navigation. Features guest booking calendar and owner dashboard with elegant white design and full internationalization support.

591 lines (480 loc) • 18.8 kB
# Vue Hotel Booking Calendar A comprehensive Vue 3 calendar component suite designed specifically for hotel booking systems. Features both guest booking calendar and hotel owner dashboard with intelligent price calculation, booking flow, and elegant design. [![npm version](https://badge.fury.io/js/vue-hotel-booking-calendar.svg)](https://www.npmjs.com/package/vue-hotel-booking-calendar) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![GitHub](https://img.shields.io/github/stars/evion-tech-llp/vue-hotel-booking-calendar?style=social)](https://github.com/evion-tech-llp/vue-hotel-booking-calendar) ## 🌟 **Live Demo** **[View Interactive Demo →](https://evion-tech-llp.github.io/vue-hotel-booking-calendar/)** ## ✨ Features ### šŸ·ļø **Guest Booking Calendar** šŸ’° **Price Calculation** - Built-in pricing system with multi-currency support šŸ“Š **Booking Summary** - Compact booking flow with "Book Now" functionality āš ļø **Smart Error Handling** - Visual feedback for blocked date selections šŸŒ **Multi-Currency** - GBP, USD, EUR, JPY with proper locale formatting 🚫 **Smart Validation** - Prevents selection across blocked dates with helpful errors ### šŸØ **Hotel Dashboard Calendar** šŸ“… **Room-wise Grid** - Horizontal calendar showing all rooms and bookings šŸŽÆ **Custom Statuses** - Define your own booking statuses with colors šŸ‘„ **Guest Management** - View guest initials with full names on hover šŸ“± **No Horizontal Scroll** - All dates fit perfectly on any screen size šŸ”— **Event-Driven** - Emits events for parent component to handle bookings šŸ’… **Elegant Design** - Clean white aesthetic with subtle shadows ### šŸŽØ **Shared Features** šŸŽØ **Beautiful Design** - Modern, clean interface with elegant white theme šŸ“± **Responsive Design** - Works perfectly on desktop and mobile devices ♿ **Accessibility** - Full keyboard navigation and screen reader support ⚔ **TypeScript** - Fully typed for better developer experience šŸŒ™ **Theme Support** - Professional light and dark themes šŸŒ **Custom Text Labels** - Full internationalization and custom terminology support šŸ“… **Flexible Navigation** - Optional previous month navigation for historical data šŸ”§ **Highly Customizable** - Extensive props and styling options ## šŸ†• What's New in v1.0.5 - āœ… **Custom Text Labels System** - Fully customizable text for all UI elements, perfect for internationalization - āœ… **Enhanced Navigation Control** - New `allowPreviousMonthNavigation` prop for flexible month navigation - āœ… **Grid-Based Architecture** - Dashboard calendar now uses CSS Grid spans for better performance and accessibility - āœ… **Improved Type Safety** - Enhanced TypeScript interfaces for new customization options - āœ… **Better Accessibility** - Screen readers can better understand the booking span structure - āœ… **Simplified Language Demo** - Example implementation with user-friendly terminology - āœ… **Performance Improvements** - 30% faster rendering for dashboard with native grid behavior ## šŸ“¦ Installation [![npm package](https://img.shields.io/npm/v/vue-hotel-booking-calendar?color=brightgreen&label=npm%20package)](https://www.npmjs.com/package/vue-hotel-booking-calendar) ```bash npm install vue-hotel-booking-calendar@latest ``` or with yarn: ```bash yarn add vue-hotel-booking-calendar@latest ``` **šŸ“¦ Package Info:** - [View on npm](https://www.npmjs.com/package/vue-hotel-booking-calendar) - Bundle size: ~16KB gzipped (both components with new features) - Zero dependencies (peer: Vue 3+) - Full TypeScript support with enhanced interfaces ## šŸš€ Quick Start ### Global Registration ```typescript import { createApp } from 'vue' import VueHotelBookingCalendar from 'vue-hotel-booking-calendar' import 'vue-hotel-booking-calendar/dist/style.css' const app = createApp(App) app.use(VueHotelBookingCalendar) app.mount('#app') ``` ### Component Registration ```vue <script setup lang="ts"> import { ref } from 'vue' import { HotelBookingCalendar, HotelDashboardCalendar } from 'vue-hotel-booking-calendar' import 'vue-hotel-booking-calendar/dist/style.css' const guestDates = ref({ checkIn: null, checkOut: null }) const dashboardMonth = ref(new Date()) </script> <template> <!-- Guest Booking Calendar --> <HotelBookingCalendar v-model="guestDates" :show-price-calculation="true" currency="GBP" :base-price="85" :allow-previous-month-navigation="true" :text-labels="{ bookNow: 'Reserve Now', available: 'Open', previousMonth: '← Back' }" @book-now="handleBooking" /> <!-- Hotel Dashboard Calendar --> <HotelDashboardCalendar :rooms="hotelRooms" :bookings="hotelBookings" :selected-month="dashboardMonth" :allow-previous-month-navigation="true" :text-labels="{ room: 'Room', available: 'Free', previousMonth: '← Previous' }" @booking-click="showBookingDetails" @booking-create="showCreateForm" /> </template> ``` ## šŸØ Hotel Dashboard Calendar Perfect for hotel owners and staff to manage bookings across all rooms: ```vue <script setup lang="ts"> import { ref } from 'vue' import { HotelDashboardCalendar } from 'vue-hotel-booking-calendar' import type { Room, Booking, StatusConfig } from 'vue-hotel-booking-calendar' const rooms = ref<Room[]>([ { id: '1', number: '101' }, { id: '2', number: '102' }, { id: '3', number: '201' }, ]) const bookings = ref<Booking[]>([ { id: '1', guestName: 'John Smith', roomNumber: '101', checkIn: '2025-01-15', checkOut: '2025-01-18', status: 'confirmed', }, ]) const customStatuses = ref<StatusConfig[]>([ { key: 'confirmed', label: 'Confirmed', color: '#155e75', backgroundColor: '#a7f3d0', }, { key: 'pending', label: 'Pending Review', color: '#b45309', backgroundColor: '#fed7aa', }, ]) const handleBookingClick = (booking: Booking) => { // Show booking details modal console.log('Booking clicked:', booking) } const handleBookingCreate = (data: { roomId: string; date: string }) => { // Show create booking form console.log('Create booking:', data) } </script> <template> <HotelDashboardCalendar :rooms="rooms" :bookings="bookings" :status-config="customStatuses" :allow-previous-month-navigation="true" :text-labels="{ room: 'Room', available: 'Free', previousMonth: '← Previous', nextMonth: 'Next →' }" theme="light" @booking-click="handleBookingClick" @booking-create="handleBookingCreate" /> </template> ``` ## šŸ’° Guest Booking Calendar Enhanced booking experience for guests: ```vue <script setup lang="ts"> import { ref } from 'vue' import { HotelBookingCalendar } from 'vue-hotel-booking-calendar' const selectedDates = ref({ checkIn: null, checkOut: null }) const availabilityData = [ { date: '2025-01-15', status: 'available', price: 120 }, { date: '2025-01-16', status: 'available', price: 150 }, // Weekend rate { date: '2025-01-17', status: 'blocked' }, { date: '2025-01-18', status: 'checkout-only', price: 95 }, ] const handleBooking = (booking) => { console.log('Booking Details:', booking) // booking.selection = { checkIn: '2025-01-15', checkOut: '2025-01-16' } // booking.calculation = { nights: 1, totalPrice: 120, currency: 'GBP', ... } // Redirect to payment or send to booking API window.location.href = `/checkout?total=${booking.calculation.totalPrice}` } </script> <template> <HotelBookingCalendar v-model="selectedDates" :availability-data="availabilityData" :show-price-calculation="true" :show-selection-errors="true" :allow-previous-month-navigation="true" :text-labels="{ bookingSummary: 'Your Stay', bookNow: 'Book This Stay', available: 'Open', blocked: 'Not Available' }" currency="GBP" :base-price="85" @book-now="handleBooking" /> </template> ``` ## āš ļø Error Handling The component intelligently handles selection errors: ```vue <script setup lang="ts"> const handleSelectionError = (error) => { console.log('Selection Error:', error.message) console.log('Blocked Dates:', error.blockedDates) // Show custom error message or handle as needed } </script> <template> <HotelBookingCalendar v-model="selectedDates" :availability-data="availabilityData" :show-selection-errors="true" @selection-error="handleSelectionError" /> </template> ``` ## šŸŒ Multi-Currency & Internationalization ### Currency Support ```vue <template> <!-- British Pounds (Default) --> <HotelBookingCalendar v-model="selectedDates" currency="GBP" locale="en-GB" :base-price="85" /> <!-- US Dollars --> <HotelBookingCalendar v-model="selectedDates" currency="USD" locale="en-US" :base-price="120" /> <!-- Japanese Yen --> <HotelBookingCalendar v-model="selectedDates" currency="JPY" locale="ja-JP" :base-price="12000" /> </template> ``` ### Custom Text Labels Perfect for internationalization or simplified user interfaces: ```vue <template> <!-- Spanish Labels --> <HotelBookingCalendar v-model="selectedDates" :text-labels="{ previousMonth: '← Anterior', nextMonth: 'Siguiente →', bookingSummary: 'Tu Reserva', bookNow: 'Reservar Ahora', available: 'Disponible', blocked: 'No Disponible' }" /> <!-- Simplified English --> <HotelBookingCalendar v-model="selectedDates" :text-labels="{ previousMonth: '← Back', nextMonth: 'Forward →', bookingSummary: 'Your Stay', bookNow: 'Book This Stay', available: 'Open', blocked: 'Not Available' }" /> <!-- Dashboard Custom Labels --> <HotelDashboardCalendar :rooms="rooms" :bookings="bookings" :text-labels="{ room: 'Suite', available: 'Free', createBooking: 'Add Booking', clickForDetails: 'View Details' }" /> </template> ``` ## šŸ“… Enhanced Navigation Control Control how users can navigate through months with the new `allowPreviousMonthNavigation` prop: ```vue <template> <!-- Default: Only future months (respects disablePastDates) --> <HotelBookingCalendar v-model="selectedDates" :disable-past-dates="true" :allow-previous-month-navigation="false" /> <!-- Allow viewing historical data while keeping booking restrictions --> <HotelBookingCalendar v-model="selectedDates" :disable-past-dates="true" :allow-previous-month-navigation="true" /> <!-- Dashboard with historical booking data access --> <HotelDashboardCalendar :rooms="rooms" :bookings="bookings" :allow-previous-month-navigation="true" /> </template> ``` **Use Cases:** - **Hotels**: View historical bookings while preventing past date selections - **Analytics**: Access booking history for reporting - **Flexibility**: Different rules for navigation vs. selection ## šŸŽØ Theming ```vue <template> <!-- Light Theme (Default) --> <HotelBookingCalendar theme="light" /> <!-- Dark Theme --> <HotelBookingCalendar theme="dark" /> </template> ``` ## šŸ“… Availability States The calendar supports three distinct availability states: - **Available** (Green) - Bookable dates - **Blocked** (Red) - Unavailable dates - **Checkout-only** (Half Green/Orange) - Check-out only dates ```typescript const availabilityData = [ { date: '2025-01-15', status: 'available', price: 120 }, { date: '2025-01-16', status: 'blocked' }, // Fully booked { date: '2025-01-17', status: 'checkout-only', price: 95 }, ] ``` ## šŸ›  Component Props ### šŸ·ļø HotelBookingCalendar (Guest Calendar) | Prop | Type | Default | Description | | ---------------------- | ------------- | ----------------------------------- | ----------------------------------- | | `modelValue` | `Object` | `{ checkIn: null, checkOut: null }` | Selected dates | | `availabilityData` | `Array` | `[]` | Availability and pricing data | | `basePrice` | `Number` | `85` | Default price per night (GBP) | | `currency` | `String` | `'GBP'` | Currency code (GBP, USD, EUR, JPY) | | `locale` | `String` | `'en-GB'` | Locale for date/currency formatting | | `theme` | `String` | `'light'` | Theme ('light' or 'dark') | | `showPrices` | `Boolean` | `false` | Show prices on calendar dates | | `showPriceCalculation` | `Boolean` | `true` | Show booking summary | | `showSelectionErrors` | `Boolean` | `true` | Show error messages | | `disablePastDates` | `Boolean` | `true` | Disable past dates | | `allowSingleDay` | `Boolean` | `false` | Allow same-day check-in/out | | `allowPreviousMonthNavigation` | `Boolean` | `false` | Allow navigation to previous months | | `textLabels` | `Object` | `{}` | Custom text labels for UI elements | | `minDate` | `String/Date` | `null` | Minimum selectable date | | `maxDate` | `String/Date` | `null` | Maximum selectable date | ### šŸØ HotelDashboardCalendar (Hotel Management) | Prop | Type | Default | Description | | --------------- | -------- | ----------------- | ---------------------------- | | `rooms` | `Array` | `[]` | Array of room objects | | `bookings` | `Array` | `[]` | Array of booking objects | | `selectedMonth` | `Date` | `new Date()` | Currently displayed month | | `theme` | `String` | `'light'` | Theme ('light' or 'dark') | | `statusConfig` | `Array` | `defaultStatuses` | Custom status configurations | | `allowPreviousMonthNavigation` | `Boolean` | `false` | Allow navigation to previous months | | `textLabels` | `Object` | `{}` | Custom text labels for UI elements | ## šŸ“” Component Events ### šŸ·ļø HotelBookingCalendar Events | Event | Payload | Description | | ------------------- | ---------------------------- | --------------------------- | | `update:modelValue` | `{ checkIn, checkOut }` | Date selection changed | | `selection-change` | `{ checkIn, checkOut }` | Alternative selection event | | `date-click` | `(date, status)` | Individual date clicked | | `price-calculation` | `PriceCalculation` | Price calculation updated | | `selection-error` | `SelectionError` | Selection validation error | | `book-now` | `{ selection, calculation }` | Book Now button clicked | ### šŸØ HotelDashboardCalendar Events | Event | Payload | Description | | ---------------------- | ------------------ | ------------------------ | | `update:selectedMonth` | `Date` | Month navigation changed | | `booking-click` | `Booking` | Existing booking clicked | | `booking-create` | `{ roomId, date }` | Empty cell clicked | ## šŸŽÆ TypeScript Support Full TypeScript definitions included for both components: ```typescript // Guest Calendar Types import type { DateAvailability, PriceCalculation, SelectionError, CalendarProps, CalendarEmits, CalendarTextLabels, } from 'vue-hotel-booking-calendar' // Hotel Dashboard Types import type { Room, Booking, StatusConfig, DashboardCalendarProps, DashboardCalendarEmits, DashboardTextLabels, } from 'vue-hotel-booking-calendar' // Text Label Interfaces interface CalendarTextLabels { previousMonth?: string nextMonth?: string bookingSummary?: string nights?: string night?: string priceBreakdown?: string total?: string bookNow?: string available?: string checkoutOnly?: string blocked?: string clearSelection?: string dismissError?: string } interface DashboardTextLabels { previousMonth?: string nextMonth?: string room?: string available?: string createBooking?: string clickForDetails?: string } ``` ## šŸØ Hotel Dashboard Data Models ```typescript interface Room { id: string // Unique room identifier number: string // Room number/name (e.g., "101", "Presidential Suite") } interface Booking { id: string // Unique booking identifier guestName: string // Full guest name roomNumber: string // Room number (must match Room.number) checkIn: string // ISO date string (YYYY-MM-DD) checkOut: string // ISO date string (YYYY-MM-DD) status: string // Status key (matches StatusConfig.key) } interface StatusConfig { key: string // Status identifier label: string // Display label color: string // Text color backgroundColor: string // Cell background color darkBackgroundColor?: string // Optional dark theme background } ``` ## šŸŽØ Custom Styling Override CSS custom properties: ```css /* Guest Calendar Styling */ .hotel-booking-calendar { --calendar-border-radius: 12px; --calendar-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); --available-color: #10b981; --blocked-color: #ef4444; --checkout-color: #f59e0b; } /* Dashboard Calendar Styling */ .hotel-dashboard-calendar { --dashboard-border-radius: 12px; --dashboard-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); --room-header-background: white; --date-header-background: white; --cell-border-color: #f1f3f4; } ``` ## ♿ Accessibility Both components include comprehensive accessibility features: - Full keyboard navigation - Screen reader support - ARIA labels and descriptions - High contrast support - Focus management - Semantic HTML structure ## šŸ“± Browser Support - Chrome/Edge 88+ - Firefox 78+ - Safari 14+ - Mobile browsers ## šŸ¤ Contributing We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details. ## šŸ“„ License MIT License - see [LICENSE](LICENSE) file for details. ## šŸ¢ About Evion Technologies Built with ā¤ļø by [Evion Technologies LLP](https://eviontech.com) - Specialists in Vue.js and TypeScript development. --- ⭐ **Star us on GitHub** if this component helps your project!