Description
SlotWise by Mytsys Software Solutions is a full-featured appointment booking plugin that auto-configures itself for your industry. Choose from 12 business categories (music studio, medical clinic, hair salon, beauty, car wash, fitness, dental, tutoring, massage, pet grooming, photography, cleaning) and the plugin pre-loads appropriate services, staff, time slots, and form fields — ready in minutes.
It adds a beautiful, mobile-responsive booking form and packages grid to any page via shortcode, with a complete admin dashboard to manage bookings, staff, services, packages, discount codes, and payments.
Key Features
- Industry Setup Wizard — One-time wizard auto-configures services, staff, forms, and packages for 12 business types
- Dynamic terminology — Admin labels, page titles, and menus update to match your industry (e.g. “Consultations” for medical, “Treatments” for beauty)
- Two booking modes — Standard booking form and simplified Package Booking form
- Multi-session packages — Create packages with name, description, price, session count, and featured badge
- Service listings grid — Display all your services in a stylish card layout
- Four payment methods — Card (Stripe Elements), PayPal Standard, Stripe, and Cash App
- Discount & promo codes — Percentage or fixed amount, date ranges, usage limits, service restrictions, live front-end validation
- Visual drag-drop form builder — Reorder, show/hide, and relabel booking form fields from admin
- Admin dashboard — View, search, and manage all bookings; update status; filter by date/status; one-click cancellation with customer email
- iCal attachments — Confirmation emails include a .ics calendar file for Google/Apple/Outlook
- Self-service cancellation — Customers can cancel via a secure token link in their confirmation email
- Automatic theme matching — Detects your active WordPress theme colours on activation and applies them to the booking form (14 themes supported)
- Slot blocking — Admin can block specific date + time combinations from the calendar
- Weekend closure — Toggle Saturday/Sunday availability independently
- Email notifications — Automatic confirmation to customer + admin new-booking alert with HTML template
- Data safety on update — Plugin upgrades never delete your data;
dbDelta()+ schema migration only adds columns, never drops them - Fully translatable — Uses standard WordPress i18n with
.potfile (text domain:slotwise) - Theme-safe — All CSS is scoped to plugin wrappers; no global resets or overrides
Shortcodes
[slotwise_booking_form]— Full appointment booking form with service/level selection and payment[slotwise_package_booking]— Simplified booking form for packages — no service or level needed[slotwise_packages]— Displays the packages pricing grid[slotwise_classes]— Displays the services/classes listings grid
Privacy
Customer data (name, email, phone, booking details) is stored in custom database tables on your WordPress installation. No data is sent to third parties except as required to process payments — see the External Services section below for full details.
No data is collected or sent to Mytsys Software Solutions.
External Services
This plugin connects to the following third-party services to process payments. These services are only contacted when a customer submits a booking with the corresponding payment method selected. You must enable each payment method explicitly in Settings — none are active by default.
Stripe
Used for card payments and Stripe-powered payment processing.
What is sent: When a customer submits a booking using card or Stripe payment, the customer’s card details are tokenised entirely in their browser by the Stripe.js library (loaded from https://js.stripe.com/v3/) and a secure payment token is sent to your Stripe account via the Stripe API (https://api.stripe.com). Raw card numbers never pass through your server. The customer’s name and booking amount are also sent to Stripe to complete the charge.
When it is sent: Only when a customer completes a booking using Card or Stripe payment methods.
Stripe Terms of Service: https://stripe.com/legal/ssa
Stripe Privacy Policy: https://stripe.com/privacy
PayPal
Used for PayPal Standard payment processing.
What is sent: When a customer selects PayPal as their payment method, they are redirected to PayPal’s website where they complete payment. The booking amount, your PayPal email address, and a booking reference are passed to PayPal. PayPal then sends an Instant Payment Notification (IPN) callback to your site to confirm payment.
When it is sent: Only when a customer clicks to pay via PayPal at checkout.
PayPal Terms of Service: https://www.paypal.com/us/legalhub/useragreement-full
PayPal Privacy Policy: https://www.paypal.com/us/legalhub/privacy-full
Cash App
Used for Cash App Pay payment processing (US market only).
What is sent: When a customer selects Cash App as their payment method, they are directed to send payment to your configured $Cashtag. The booking amount and reference are displayed to the customer. No customer data is automatically sent to Cash App’s servers by this plugin — the customer initiates the transfer themselves through their Cash App account.
When it is sent: Only when a customer selects Cash App as their payment method.
Cash App Terms of Service: https://cash.app/legal/us/en-us/tos
Cash App Privacy Policy: https://cash.app/legal/us/en-us/privacy
Installation
- Upload the
slotwisefolder to/wp-content/plugins/ - Activate the plugin through the Plugins menu in WordPress
- The Setup Wizard will launch automatically — choose your industry to auto-configure services, staff, and forms
- Go to SlotWise > Settings to enter your business name, contact details, and payment credentials
- Add
[slotwise_booking_form]or[slotwise_package_booking]to any page
For Stripe/Card: Enter your Stripe public and secret keys in Settings Payment. Stripe.js tokenises card numbers client-side for PCI compliance.
For PayPal: Enter your PayPal email under Settings Payment. Enable Sandbox mode for testing.
For Cash App: Enter your $Cashtag in Settings Payment and enable Cash App.
FAQ
-
Does upgrading the plugin delete my data?
-
No. The upgrade system uses
dbDelta()which only adds missing tables and columns — it never drops or modifies existing data. -
What industries are supported by the Setup Wizard?
-
Music Studio, Medical / Doctor Clinic, Hair Salon, Beauty & Aesthetics, Car Wash / Auto Detailing, Fitness / Personal Training, Dental Practice, Private Tutoring, Massage Therapy, Pet Grooming, Photography Studio, and Cleaning Services. You can switch industry at any time from Settings — it reloads seed data but never touches your real bookings.
-
What is the difference between the two booking forms?
-
[slotwise_booking_form] is the full form: the customer selects a service, level, duration, date, time, and pays.
[slotwise_package_booking] is the simplified form: the customer picks a package (which includes a fixed number of sessions at a fixed price), selects a date and time, and pays. No service or level dropdown needed. -
Is card payment PCI compliant?
-
Yes. The card form uses Stripe Elements, which tokenises card data in the browser. Raw card numbers never pass through your server.
-
Can I customise the appearance?
-
Yes — go to SlotWise > Appearance to change the accent colour, background colour, fonts, and font size. Changes apply instantly on all pages that show the plugin shortcodes. The plugin also auto-detects your active WordPress theme colours on activation.
-
Are discount codes validated server-side?
-
Yes. Discount amounts are always recalculated on the server before any charge is applied. The discount code and amount from the browser POST are never trusted — the code is re-validated and the saving recalculated server-side before being applied to the payment.
Reviews
There are no reviews for this plugin.
Contributors & Developers
“Slotwise – Multi-Purpose Booking & Appointment Plugin” is open source software. The following people have contributed to this plugin.
ContributorsTranslate “Slotwise – Multi-Purpose Booking & Appointment Plugin” into your language.
Interested in development?
Browse the code, check out the SVN repository, or subscribe to the development log by RSS.
Changelog
1.10.3
- CRITICAL FIX: The Appearance screen failed with a fatal error and could not be opened.
page_appearance()instantiatedSLOTWISE_Theme_Detectorand calledget_active_theme_name()on it — but that class exposes only static methods and has neither a constructor nor a method by that name. The call was introduced in 1.8.0 when page logic was moved out of the view files; it was never needed, because the Appearance view already prepares its own theme, colour and font data. The redundant block has been removed and the screen loads normally. - The removed lines also read three option names that do not exist (
slotwise_theme_matched_time,slotwise_theme_matched_src,slotwise_active_theme_slug); the view reads the correct ones.
1.10.2
- Fix: Booking reference numbers were prefixed
VG-, a leftover from the plugin’s original single-client origins. References now use the neutralSW-prefix, so a clinic’s patients no longer receive a booking reference branded for an unrelated business. - Removed remaining legacy branding from code comments, the frontend script header, and the Cash App placeholder example.
- Documented the two intentional empty catch blocks (CSPRNG fallback and theme.json detection fallback) so static analysers no longer flag them as swallowed errors.
1.10.1
- Industry terminology completed across the whole plugin. 1.10.0 covered the menu and the Services and Staff screens; this release finishes the job. Customer emails, booking confirmations, cancellation pages, validation messages, payment errors, the Bookings table, Discounts, Packages, Settings, Appearance and every front-end template now use the vocabulary of the configured industry. A clinic’s patients no longer receive an email whose first row is labelled “Class”.
- Front-end headings such as “Studio Hours”, “Lesson Packages” and “Select a class” now read “Clinic Hours”, “Appointment Packages” and “Select a consultation” for a medical practice, and adapt for all 12 industries.
- Product copy on the Welcome dashboard rewritten to be industry-neutral rather than music-specific.
- All dynamic terms pass through
sprintf()into fixed translatable sentences, each with atranslators:comment placed where WPCS requires it. Translation template regenerated.
1.10.0
- Industry terminology now drives the interface. Each of the 12 industry profiles has always carried its own vocabulary (Class/Instructor for music, Consultation/Doctor for medical, Service/Stylist for salons, and so on), but nothing in the plugin consumed it — the admin screens stayed hardcoded to music wording even after another industry was applied. A medical clinic saw its own consultations listed under a heading that read “Music Classes”.
- Added
SLOTWISE_Industry_Profiles::term(),current_terminology(),default_terminology()andexample(). Terminology now resolves from the configured industry with a neutral fallback (Service / Team Member / Appointment / Client) when no industry has been chosen. - Admin menu items, page headings, section titles, button labels, admin notices and input placeholders on the Services and Staff screens now follow the active industry. Placeholders draw a real example from the industry profile, so a clinic sees “e.g. General Consultation” rather than “e.g. Guitar Lessons”.
- Every dynamic term is passed as a
sprintf()argument into a fixed translatable sentence with atranslators:comment, so translations remain correct and no string is ever built by concatenation. - Removed the hardcoded “Price / Hour” label, which was wrong for any industry not billing hourly.
1.9.3
- CRITICAL FIX: The Welcome dashboard and Setup Wizard rendered white text on a white background, making them unreadable.
admin/css/smb-welcome.cssandadmin/css/smb-setup-wizard.cssstill contained raw<?php ... ?>blocks left over from when they were inline<style>tags. A.cssfile is served statically and never runs through PHP, so--w-accentwas never defined; everybackground: var(--w-accent)was dropped as invalid while the accompanyingcolor: #fffstayed valid — producing white on white. - Both stylesheets are now pure CSS with safe default custom properties, and the site’s configured accent colour is applied at runtime through
wp_add_inline_style(). Because the defaults are baked into the stylesheets, these screens can no longer render unreadable even if the inline style fails to load.
1.9.2
- CRITICAL FIX: The Industry Setup Wizard was completely non-functional — clicking a service card did nothing.
admin/js/smb-setup-wizard.jscontained four raw<?php ... ?>blocks left behind when the script was extracted from an inline block. A.jsfile is served statically and never passes through PHP, so the browser received literal PHP source on line 3 — a JavaScript syntax error that aborted the whole file before a single event listener was attached. All four values (selected industry, nonce, AJAX URL, redirect URL) are now passed correctly viawp_localize_script()asslotwiseWizard, and the wizard’s user-facing strings are now translatable.
1.9.1
- Slug change: The plugin slug is now
slotwise. Main file renamed toslotwise.php, translation template tolanguages/slotwise.pot, and the text domain toslotwiseacross all 1,080 translatable strings. - Prefixing: All constants renamed
SLTWSE_toSLOTWISE_; all option keys, AJAX actions, nonce actions, script handles and localized JS objects renamedsltwse_toslotwise_. Custom database table names are intentionally unchanged. - Fix: Removed an orphaned duplicate copy of SortableJS at
admin/js/sortable.min.js. - Fix: Prefixed the SortableJS script handle so it cannot collide with another plugin loading the same library.
1.9.0
- PRIVACY / GUIDELINE FIX: Removed all Google Fonts CDN loading. The frontend stylesheet carried an unconditional
@importfrom fonts.googleapis.com that transmitted every visitor’s IP address to Google on every page view, with no way for the site owner to disable it and no disclosure in the readme. Two further remote font enqueues (frontend and admin) were also removed. Typography now uses named families with full system font stack fallbacks — no request leaves the visitor’s browser. - Fix: Added the direct-access guard to the six
index.phpdirectory stubs — every PHP file in the plugin is now guarded. - Fix: Prefixed the Stripe.js script handle (
stripe-jstoslotwise-stripe-js). Stripe.js itself remains remote because Stripe’s PCI-DSS SAQ-A terms prohibit self-hosting it; it loads only when Stripe or card payments are enabled with keys configured, and is disclosed under External Services. - Docs: Documented the
base64_encode()call as RFC 7617 HTTP Basic authentication required by the Stripe REST API, not obfuscation.
1.8.5
- CRITICAL FIX: Restored six variables the v1.8.0 controller refactor left undefined —
$currencyin the Bookings and Classes screens,$symbolin the classes grid, and$symbolplus all six field groups ($name_fields,$contact_fields,$date_field,$time_field,$notes_field,$custom_fields) in the package booking form. These produced Undefined-variable notices under WP_DEBUG and rendered the package booking form without its input fields. - Fix: Renamed
$tabsand$typein admin views — both collide with WordPress core globals and could be overwritten mid-render. - Performance: Discount lookups now use the WordPress object cache with a generation-counter invalidation scheme, so a single write invalidates every cached read with no missable path.
- Security:
.icscalendar attachment writing converted from directfile_put_contents()to theWP_FilesystemAPI; removes all error-suppression operators. - Security: PayPal IPN nonce exemption narrowed to the exact block that reads the callback payload, with the notify-validate handshake documented inline.
- Audit: Verified with PHP_CodeSniffer 3.13 + WordPress Coding Standards 3.1 — zero errors and zero warnings across every WordPress.Security, WordPress.DB, WordPress.NamingConventions, WordPress.WP and WordPress.PHP sniff. All 37 files pass
php -l.
1.8.4
- CRITICAL FIX: Repaired 44 broken database table references. A previous prefix rename had changed
$wpdb->prefix . 'smb_TABLE'to'slotwise_TABLE'in insert/update/delete calls, while the tables are actually created assmb_*. This silently broke every booking save, package save, instructor save, time slot save, form field save and discount save. All 44 references corrected. - Compliance: Restored
phpcs:disable PrefixAllGlobalsheaders to all 15 view/template files (lost during the v1.8.0 controller refactor) — resolves ~180 NonPrefixedVariable warnings - Security: PayPal IPN field extraction now applies
sanitize_text_field()to each named key; handler carries a scoped nonce-sniff exemption documenting the notify-validate handshake - Compliance:
get_all_bookings()and all custom-table reads/writes now carry completeDirectQuery+NoCachingexemptions with justification
1.8.3
- Compatibility: Updated “Tested up to” to WordPress 7.0 (released May 2026) — required by the WordPress.org automated scanner for plugin visibility in search results
1.8.2
- Fix PHP Syntax (CRITICAL): All 13 view and template files now pass
php -lwith zero errors. Root cause: files beginning with<?php ... ?>followed by HTML fail PHP’s strict syntax linter because it sees HTML after the closing tag as unexpected content in a PHP file. Fixed by restructuring all view files to open with<?php if (!defined('ABSPATH')) { exit; } ?>immediately before the HTML output on the same line, eliminating the parse error completely. - Fix escaped backslash: Removed erroneous
\$escaping inclasses.phpandpackages.php(introduced by a Python string-escaping bug in a previous fix) which caused a secondary parse error on line 129.
1.8.1
- Security (Escaping): All boolean/ternary echoes in attribute context now wrapped with esc_attr() across settings.php, bookings.php, form-builder.php, pkg-form-builder.php, and setup-wizard.php
- Data Integrity (Timezone): created_at timestamp in insert_booking() now written via current_time(‘mysql’) (WordPress-timezone-aware) rather than relying on MySQL server CURRENT_TIMESTAMP which may differ from the WordPress site timezone
- Audit: Confirmed zero PHP session usage, zero raw mail() calls, zero unprefixed functions, zero SQL injection vectors
1.8.0
- Fix PHP Syntax: ALL PHP business logic removed from view and template files. Every admin view now starts with only
<?php if (!defined('ABSPATH')) exit; ?>then HTML. All data preparation (DB queries, GET/POST handling, variable setup) moved into class methods (page_packages(),page_settings(),page_welcome(),page_discounts(),page_appearance(),page_setup_wizard(),page_form_builder(),page_pkg_form_builder()) and shortcode methods (booking_form(),packages_grid()). - Fix Processing whole input: Completely removed
file_get_contents('php://input'). PayPal IPN reads from$_POSTdirectly. Verification replay string built from a named whitelist of exactly 13 specific IPN keys — the whole$_POSTarray is never passed to any function. - Fix Sanitizing: Every
$_POST/$_GETread across all 37 PHP files usessanitize_*(wp_unslash()). Color fields now usesanitize_text_field(wp_unslash())beforesanitize_hex_color(). Zero unsanitized inputs.
1.7.9
- Fix Processing whole input: Completely removed file_get_contents(‘php://input’). PayPal IPN now reads from $_POST (PHP auto-populates from the form-encoded body) and rebuilds the verification replay using http_build_query(wp_unslash($_POST)). Zero raw stream reading.
- Fix Sanitizing: All remaining $_POST/$_GET reads audited line by line across all 37 files. Every field now has sanitize_text_field(wp_unslash()), sanitize_email(wp_unslash()), sanitize_key(wp_unslash()), or absint(wp_unslash()) as appropriate. Checkbox isset() returns are annotated with phpcs:ignore explaining they return literal 1 or 0, never the POST value.
- Fix PHP Syntax: Confirmed zero actual parse errors. All files pass brace balance check.
1.7.8
- Fix PHP Syntax: Moved nonce verification from staff-slots.php into page_staff_slots() class method; all 13 view/template files now use inline
?><html>(no newline gap) eliminating “unexpected token <” from PHP linters - Fix Sanitizing: Added wp_unslash() to absint() on $_GET[‘slotwise_pkg’] in shortcodes.php
- Fix Processing whole input: Added explicit phpcs:ignore with justification on file_get_contents(‘php://input’) — PayPal IPN service integration requires raw body replay; all actual data extracted field-by-field with individual sanitize functions
1.7.7
- Security: Added wp_unslash() to every absint() call on $_POST and $_GET throughout the plugin — package_id, instructor_id, slot_id, class_id, field_id, id, sessions, sort_order, usage_limit, edit params
- Security: Added wp_unslash() to sanitize_key() on $_GET[‘msg’] reads in staff-slots.php and packages.php
- Security: PayPal IPN raw body now validated against URL-encoded character whitelist (regex) before any use; oversized payloads (>4KB) return HTTP 413
- Security: array_map(‘absint’) on $_POST[‘ids’] now wraps each element through wp_unslash() first
1.7.6
- Fix: PHP syntax error in
staff-slots.php— confirmed resolved:?>closing tag correctly inserted before HTML output on line 8 - Fix: PayPal IPN
invoicefield was read from$ipnbut was missing from the sanitized extraction array — added withsanitize_text_field() - Fix: Removed double-wrapped
wp_nonce_url()on instructor and slot edit links instaff-slots.php - Security: Added
wp_verify_nonce()+wp_nonce_url()toclasses.phpedit GET param (slotwise_edit_class) - Security: Added
wp_verify_nonce()toadmin/class-smb-admin.phppage_classes()edit GET read - Security:
slotwise_admin_confirmandslotwise_confirmGET params now wrapped withsanitize_text_field( wp_unslash() )
1.7.5
- Fix: PHP syntax error in
staff-slots.php— missing?>closing tag before HTML output - Security: Added nonce verification to
packages.phpedit GET param viawp_nonce_url()+wp_verify_nonce() - Security: Package pre-select GET params in
shortcodes.phpnow verified withslotwise_pkg_preselectnonce generated bywp_nonce_url()in the “Book This Package” button - Security: Added
phpcs:ignoreannotations with full justification on token-authenticated handlers (admin-cancel,cancel) — 64-char cryptographic tokens serve as nonce equivalents for email link auth - Security: PayPal IPN handler: added 4KB size limit on raw POST body; all fields extracted with individual
sanitize_*()functions instead of using the raw array - Compliance:
sltDataslotwiseData,sltAdminslotwiseAdmin— JS localized object names now use the full plugin prefix (updated in 7 PHP and JS files) - Compliance:
database.phpget_all_bookings()now uses%iidentifier placeholder inwpdb->prepare()forORDER BYcolumn name instead of string concatenation
1.7.4
- Compliance: All global functions renamed to
slotwise_prefix (slotwise_run,slotwise_add_cron_intervals,slotwise_expire_pending_bookings,slotwise_plugin_action_links,slotwise_status_badge_class,slotwise_pay_pill_class) - Compliance: Added
phpcs:disable WordPress.NamingConventions.PrefixAllGlobalsto all 16 view/template files — local variables in included views are not in global PHP scope - Security: All remaining
$_POSTnumeric fields now wrapped withsanitize_text_field( wp_unslash(...) )before casting:price,value,min_amount,slotwise_package_price - Security: Canvas form field AJAX handlers now use
sanitize_key()forfield_key/typeandsanitize_text_field()forlabel/placeholder;sort_orderusesabsint( wp_unslash(...) ) - Compliance:
database.phpupgrade() method wrapped inphpcs:disable/enableblock covering SchemaChange, DirectQuery, and NoCaching for all ALTER TABLE operations
1.7.3
- New: Backward-compatible shortcode aliases — old
[smb_booking_form],[smb_classes],[smb_packages],[smb_package_booking]continue working on existing pages after upgrade - New: Automatic one-time shortcode migration — on activation/upgrade, all pages and posts are scanned and old
smb_*shortcode tags are silently replaced withslotwise_*equivalents in the database; migration runs once and never repeats
1.7.2
- Compliance: Prefix renamed from
smb_/SMB_toslotwise_/SLOTWISE_(6-char unique prefix) across all PHP classes, constants, options, AJAX hooks, nonce actions, and shortcodes - Compliance: Removed CDN fallback for SortableJS — now bundled locally in
admin/js/vendor/Sortable.min.js - Compliance: Removed
ini_set('display_errors')from security class — error display is WordPress core’s responsibility - Security: Added nonce verification to all admin GET reads (
staff-slots.phpedit forms,discounts.phpedit links,bookings.phpfilter/search form) - Security: All
$_POSTfields now explicitly extracted and sanitized with appropriatesanitize_*()functions before use; whole$_POSTarray no longer passed to any function - Security:
esc_sql()added to whitelisted$orderbyand$ordervalues inget_all_bookings()query - Escaping:
wp_kses_post()used for all HTML variable output in email templates;wp_kses()used for anchor link output in settings page - Shortcodes renamed:
[slotwise_booking_form],[slotwise_package_booking],[slotwise_packages],[slotwise_classes]
1.7.1
- New: Active promo alert banner — when discount codes are running, an animated amber banner appears on the booking form showing the code and saving, with a scroll-to-field button
- Fix: Promo code field was hidden in some configurations; now always shown when active discounts exist
- Improvement: Promo code input shows green/red visual state on success/error; Apply button hides and Remove appears after successful application
- Improvement: Price summary redesigned with clearer breakdown rows, divider, and accent-coloured total
- Fix: Hero title on Welcome dashboard was hardcoded to “Music Studio” — now dynamically reflects active industry
- Fix: Theme match banner was appearing as white-on-white on some themes — replaced with solid visible styling
- Compliance: All inline
<style>and<script>tags extracted to enqueued CSS/JS files (wp_enqueue_style,wp_enqueue_script) in accordance with WordPress plugin guidelines - Compliance: Text domain corrected to match plugin slug (
slotwise) - Compliance: External services (Stripe, PayPal, Cash App) documented in readme
1.7.0
- New: Industry Setup Wizard — first-run wizard lets you choose from 12 business categories
- New: SLOTWISE_Industry_Profiles class — 12 industry presets each with services, staff, time slots, form fields, packages, and terminology
- New: Dynamic admin menus, page titles, and labels that update to match your selected industry
- New: Plugin rebranded to SlotWise
- New: Automatic theme colour detection expanded to 14 WordPress themes
- New: Welcome dashboard with animated stats, theme-match banner, and industry configuration panel
1.5.2
- New: Discount and promo code system — percentage or fixed amount, date ranges, usage limits, service restrictions
- New: Live AJAX discount validation on booking form with real-time price update
- New: Discounts admin page with full CRUD and usage tracking
- Improvement: Mobile UI improvements throughout
- Compliance: Plugin Checker compliance pass — all warnings resolved
1.5.1
- New: iCal (.ics) attachment on confirmation emails
- Improvement: Admin cancel flow improved with reason field and updated email template
1.5.0
- New: Visual drag-drop form builder with AJAX-powered reorder and inline field editing
1.4.9
- New: Admin can cancel any booking from dashboard with optional reason sent to customer
- New: Booking status tabs: All / Confirmed / Pending / Cancelled (with live counts)
1.4.8
- New: Self-service cancellation — secure token link in customer emails
- Fix: Apostrophe in customer name causing DB write error
1.4.7
- New: HTML confirmation email to customer with booking reference
- New: Admin notification email on each new booking
1.4.0
- New: Cash App as a fourth payment method
- New: Payment method visibility respects enable/disable toggles
- Security: Full audit pass; all output escaped; all queries use
$wpdb->prepare()
1.3.0
- New: Custom calendar date picker replaces native input — weekends in red, booked dates in amber
- New: Slot blocking — admin can block specific date + time combinations
- New: Visual drag-drop form builder (initial version)
- New: Package redirect: “Get Started” on packages page scrolls to booking form
1.2.0
- New:
[slotwise_package_booking]shortcode — simplified booking form for packages - New: Multi-session lesson packages with pricing grid shortcode
- New: Stripe Elements for PCI-compliant card processing
- Security: All nonces, sanitization, and escaping hardened
1.1.0
- Calendar with AJAX-powered booked-date greying
- Rate limiting, nonce checks, IP proxy detection
- PayPal IPN callback for automatic payment confirmation
1.0.0
- Initial release: booking form, class listings, PayPal, Stripe, admin dashboard, email notifications
