=== Appointment Booking System, Scheduling & Calendar – Tiger Booking ===
Contributors: tigerelements
Tags: booking, appointment booking, appointments, booking system, booking calendar
Requires at least: 6.2
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 2.0.4
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Online booking for your website. Appointment scheduling with services, staff calendars, time slots and email confirmations. No per-booking fees.

== Description ==

Tiger Booking turns your WordPress site into a working appointment book.

Add the services you offer, set who provides them and when they work, then put a booking form on any page. Customers choose a service, a person and a time; the slot is held, the confirmation email goes out, and the appointment lands in your dashboard.

It is self-hosted. Your services, staff, customers and appointments live in your own WordPress database. There are no per-booking fees, no seat limits and no external account to sign up for.

Everything described on this page is included and fully working. There is no licence key, no trial period, no usage cap and no locked screen anywhere in this plugin.

= Nothing gets booked twice =

Two customers can be filling in the form at the same moment, and only one of them will get the slot. The other is told straight away and offered the next free time, instead of both being confirmed and you finding out afterwards. The gap you set between appointments, a person's holidays and the hours they actually work are all held to in the same way.

= What you can do =

* **Services** — what can be booked, with duration, price, buffer time and a category
* **Staff** — unlimited team members, each with their own calendar, services and holidays
* **Weekly rosters** — working hours, shifts and breaks, so bookings only land while someone is on shift
* **Locations** — assign staff to branches; the booking form asks visitors which one only when you have more than one
* **Public booking flow** — a service-then-person-then-time form that works on a page, a post or a widget area
* **Recurring appointments** — weekly or monthly series booked in one go
* **Manual bookings** — add, move, reschedule and cancel appointments from the admin
* **Walk-in queue** — serve people who arrive without an appointment
* **Customer records** — a profile per customer with their history, spend and notes
* **Customer self-service** — customers get a link in their confirmation email to view or cancel their own booking, without an account
* **Intake and consent forms** — ask your own questions at booking time, and keep the answer next to the wording the customer actually agreed to
* **Reviews** — collect customer reviews and moderate them before they appear
* **Analytics** — bookings, revenue, staff workload, busiest hours, new versus returning customers
* **Staff and customer portals** — self-service logins with per-role, per-screen permissions
* **Email confirmations** — automatic notices to you and to the customer, with a readable delivery log
* **Calendar invites** — confirmations carry an .ics attachment, so the appointment lands in the customer's own calendar app
* **Email reminders** — a reminder before the appointment, sent once per booking, and never for one already cancelled or past
* **Time zones** — times are stored and shown against your site's time zone, so someone booking from another country sees the hour they will actually turn up
* **Setup wizard** — asks what kind of business you run, then creates your booking page and thank-you page for you
* **Activity log** — who changed what, and when

= It speaks your trade =

During setup you choose what kind of business you run — Salon, Barbershop, Clinic, Therapy Practice, Personal Training, Tutoring, or plain Appointments. The admin then uses your vocabulary: a salon sees Treatments and Stylists, a clinic sees Consultations and Practitioners. Screens you have no use for are hidden rather than left to clutter the menu.

= Where the booking form goes =

Use the `[tiger_booking]` shortcode on any page, the Booking block in the block editor, or the Tiger Booking widgets if you use Elementor. Elementor is optional and is never required. Every shortcode takes `width="900px"`, `width="80%"` or `width="full"`, plus `align="wide"` and `align="full"` for block themes.

Your services also get real pages of their own, each with its price, duration and a working booking form, so a visitor can book straight from a search result. Your theme or page builder still wins if you would rather design those pages yourself.

= What is not in this plugin =

These are separate products, not locked features. This plugin contains none of their code, and nothing here is disabled, limited or waiting for a key:

* Online payments — Stripe, PayPal, Square and Razorpay checkout
* Google Calendar sync, and the Zoom / CRM / webhook integrations hub
* SMS confirmations and reminders (the email ones above are included)
* Discount codes, and the waitlist for times that are already full
* Document uploads at booking time — asking a customer to attach an ID or a form
* Other booking verticals — hotel and property, restaurant, fitness classes, hourly rentals

They belong to Tiger Booking Pro, a separate add-on that installs alongside this plugin and extends it rather than replacing it. This plugin does not check for it, does not change behaviour when it is absent, and carries no screen that asks you to buy it. If you never install the add-on, nothing described above stops working.

Learn more at https://tigerelementswp.com/tiger-booking/

== Installation ==

1. In your WordPress admin go to **Plugins → Add New**, search for **Tiger Booking**, and click **Install Now**. To install manually instead, upload the `tiger-booking` folder to `/wp-content/plugins/`.
2. Click **Activate**.
3. Open **Tiger Booking** in the admin menu. The setup asks what kind of business you run and creates a booking page and a thank-you page for you.
4. Add at least one service, then at least one staff member, and give that person some working hours under **Availability**. A service with nobody able to provide it cannot be booked.
5. Visit the booking page it created, or drop `[tiger_booking]` on a page of your own, and place a test booking.

Confirmation emails use whatever WordPress already uses to send mail. If your site does not reliably send email, install an SMTP plugin first — **Tiger Booking → Settings → General** has a status panel that tells you whether mail, the database and scheduled tasks are healthy.

== Frequently Asked Questions ==

= My confirmation emails are not arriving. What should I check? =

Switch email delivery to SMTP, under Tiger Booking → Settings → Notifications.

By default WordPress hands mail to your server's own `mail()` function, and on a great many hosts that is either blocked outright or sends from an address that fails SPF/DKIM checks — so the message is discarded or filed as spam by the receiving side. Your server still reports the handoff as successful, which is why the delivery log can show every message as sent while nothing reaches the inbox. That is also why the statistics on that screen say "accepted" rather than "delivered": WordPress cannot know what happened after the handoff, and saying otherwise would be a guess.

Sending through SMTP — your own mailbox provider, or SendGrid, Mailgun, Amazon SES and similar — removes that uncertainty, because the message is authenticated by the service that owns the sending domain. Fill in the host, port and credentials, then use "Send test email" on the same screen to confirm before relying on it.

If you set a From address, use one on your own domain. A From address at a free provider (gmail.com and the like) will fail authentication when sent from your server, regardless of which delivery method you choose.

= Does it need Elementor, or any other page builder? =

No. Tiger Booking works on its own through the `[tiger_booking]` shortcode and a block for the block editor. If Elementor happens to be active, matching Elementor widgets are registered automatically — but nothing requires it.

= Where is my booking data stored? =

In your own WordPress database, in the plugin's own tables. It is not sent anywhere, and there are no per-booking fees.

= Can customers pay when they book? =

Not with this plugin — it contains no payment gateway code at all. Bookings are confirmed by you or by email, and you take payment however you already do: on arrival, by invoice, or with a separate payments plugin. Online checkout is part of a separate product.

= Is anything here limited, trial-based or waiting for a licence key? =

No. There is no licence check, no trial, no cap on services, staff or bookings, and no screen anywhere that asks you to upgrade. Every feature listed on this page is complete in this plugin.

= Can two people book the same slot? =

No. Availability is re-checked inside the write, per staff member and per resource, at the moment the booking is saved — not only when the calendar was drawn. If someone takes the slot while another person is filling in the form, the second person is told the time has gone and asked to choose another.

= Can staff manage their own calendar without a WordPress admin account? =

Yes. The staff portal is a separate self-service login with its own per-role permissions, screen by screen and action by action. It gives no access to WordPress admin.

= Does it send anything to a third party? =

No. Your bookings never leave your server, and the plugin contacts no third party under any setting. Its typefaces are bundled inside the plugin rather than fetched from a font host. See **External services** below.

= How do I remove everything when I uninstall? =

Tick **Delete all data on uninstall** under **Tiger Booking → Tools** before you delete the plugin. Without that box ticked, deleting the plugin leaves your bookings in place so you can reinstall safely.

= Is it translation ready? =

Yes. The plugin's text domain is `tiger-booking` and it loads translations from wordpress.org language packs automatically.

== External services ==

This plugin uses no external services.

Tiger Booking is entirely self-hosted. Your services, staff, customers and bookings are stored in your own WordPress database and never leave your server. The plugin makes no outbound request to any third party, under any setting.

The booking widget uses typefaces bundled inside the plugin, so no font is fetched from a remote host. No third party is contacted. The plugin sends no analytics, no telemetry and no usage data anywhere, and it does not phone home. The sample content installed by the demo seeder ships with its own artwork inside the plugin, so no image is fetched from a remote host either.

== Screenshots ==

1. Choosing a time — the visitor picks a service and a member of staff, then a day and a free slot.
2. Bookings — every appointment in one list, with status filters and a calendar view.
3. Services — what can be booked, with price, duration and buffer time.
4. Staff — unlimited team members, each with their own calendar and portal login.
5. Availability — weekly working hours, shifts, breaks and days off, per person.
6. Analytics — bookings, revenue and staff workload across everything you offer.
7. The staff portal sign-in — your team log in here, not through WordPress admin, and each role sees only the screens you allow.
8. Confirming — the visitor checks what they are booking and leaves their details.

== Source code ==

The admin screens and the public booking form are a React application, so what
runs in your browser is compiled. Nothing here is obfuscated, and you do not
have to ask anyone for the source: **the readable source ships inside this
plugin**, in `src/`, next to the compiled output in `tiger-dist/`.

To rebuild it, from the plugin directory:

`npm install`
`npm run build`

That regenerates `tiger-dist/` from `src/`. The JavaScript it produces is
identical, file for file, to what ships. The stylesheet can differ by a small
number of unused utility classes, because Tailwind generates CSS by scanning
the files present on disk — it is the same stylesheet, not a different one.

* Build tools: [Vite](https://vitejs.dev/) and [Tailwind CSS](https://tailwindcss.com/),
  both free software. The exact versions are pinned in the bundled
  `package.json` and `package-lock.json`.
* `src/` contains the source for everything this plugin does. Code for the paid
  add-on is not included, because none of it runs here either.
* The two bundled typefaces, Inter and Space Grotesk, are under the SIL Open
  Font License 1.1; the license text ships in `LICENSE-FONTS.txt`, and every
  other bundled dependency is listed in `LICENSE-THIRD-PARTY.txt`.
* No code is downloaded or executed from a remote server, at any point.

== Changelog ==

= 2.0.4 =
* Solo practitioner & mentor setup: individual business owners can now configure their practitioner name, role, email and phone directly during setup and in Appointment Settings, with a clean switch between Personal (Solo) and Institution (Team) modes.
* Fixed: fresh installations no longer seed hardcoded placeholder staff (Alex Thompson, Sarah Chen) into the database, and existing sites receive an automatic database cleanup utility to purge legacy placeholder records.
* Universal host email delivery: resolved default PHP mailer delivery failures across shared hosts (Hostinger, GoDaddy, Bluehost, SiteGround) by preventing envelope sender (-f) flag rejections on unauthenticated mail, while maintaining full support for authenticated SMTP.
* Fixed: a customer email could be redirected away from the customer. The "Send To" control was offered on customer templates as well as business alerts, and setting a custom address there sent every customer's confirmation to that one mailbox instead — the customer received nothing, and one inbox collected everyone's booking details. Customer mail now always goes to the person who booked, a stored address from before this release can no longer redirect anything, and the screen no longer implies it was ever a choice.
* Fixed: the operator's cancellation alert was written to the customer. The business received "Hi <customer name>, your booking has been cancelled", subject and all. Business alerts now have their own wording and carry the customer's email and phone so you can reach them.
* Every email is rebuilt on the layout email clients actually support. The previous markup used CSS flexbox and grid, which Outlook on Windows ignores completely — the header row, the three-column summary and the two-column details all collapsed into a stack there while looking correct in Gmail and Apple Mail. Emails are now built with tables, carry a proper inbox preview line, and declare their colours for dark mode.
* Your own templates are no longer sent unstyled. A custom template used to go out as a bare fragment with no wrapper, no logo and no branding, so writing your own copy made the email look worse than leaving it alone. Custom wording now sits inside the same layout as everything else.
* New: choose between the built-in template and your own, per notification. The built-in one is shown as a live preview so you can see exactly what your customers receive, and switching to your own keeps that draft when you switch back. A "Start from the built-in template" button copies the real HTML into the editor for anyone who wants to edit it directly.
* Fixed: the business logo never appeared in emails, because the sending code looked for the wrong setting. It now reads the logo you set under Settings → General, and is never cropped — in emails and in the settings screen alike.
* New placeholders: {{clientEmail}}, {{clientPhone}}, {{duration}} and {{status}}. Each was already available in the booking data and simply never offered.
* Built-in emails now include payment details, the meeting link and a link to view or change the booking — each shown only when it applies. A free service gets no total, a cancelled booking gets neither link, and the self-service link never appears on the business's copy.
* Booking notes are included in the built-in emails when the customer wrote any.
* Fixed: "Go to the dashboard" at the end of setup did nothing on a new site. The button rebuilt the same address it was already on, which the browser treats as no navigation at all, so the page never reloaded. It only ever failed on fresh installs, which is where it matters most.
* Fixed: the switch controls were drawn a fraction off centre — the knob sat 3px from the top and 1px from the bottom.
* Fixed: the step row in the Bento Grid booking layout was left-aligned while the content below it was centred.
* A new site no longer has a thank-you page created for it automatically. Creating one silently turned on the redirect that takes customers away from their confirmation screen, reference number and all. It is still one click away under Settings → Pages.
* Booking pages the plugin creates now carry width="full", so the widget fills the column your theme gives it instead of sitting in a narrow strip. Pages you already made are untouched.
* "Seed demo data" now asks for confirmation, like the Clear button beside it always has. It writes services, staff, customers and bookings into a live site, and a single unguarded click next to an informational panel was too easy to hit by accident.
* Added guidance for when email does not arrive: most shared hosts either block the server's own mail or send it from an address that fails authentication, and the server reports success either way. The Notifications screen now says so and points at SMTP.

= 2.0.3 =
* Fixed: booking alerts to the operator went to a placeholder address. The plugin shipped `admin@tigerbooking.com` as the default administrator email, so any site that saved its settings without editing that field sent every booking alert to a domain that does not exist — silently, because the mail server accepts the handoff either way. The field now starts empty and falls back to your WordPress administrator address, and the old placeholder is treated as unset so existing sites are repaired on update.
* The "New Booking Alerts" template is now actually used. Its subject, its body and the address you set under Send To drive the operator's email; previously nothing on the server read any of it and a fixed copy of the booking invoice was sent instead. A site with no template of its own keeps receiving exactly what it received before.
* Fixed: the placeholder picker offered 21 tokens when only 13 could be filled. The other eight — including five hotel fields shown on sites with no hotel module — were inserted in good faith and then silently removed on send, so "Your room: {{roomName}}" arrived as "Your room: ".
* Fixed: {{location}} inserted the booking's time zone rather than an address. It is now offered honestly as {{timezone}}.
* Fixed: the operator's copy of a booking email was never recorded in the email log, so a missing booking alert left no trace and the delivery panel still showed a clean 100%.
* Fixed: settings could be saved with the previous value. Editing a field and clicking Save in the same moment stored what was there before the edit, and sometimes the button was still disabled so the click did nothing at all.
* Fixed: saving one screen of settings could erase settings belonging to another. A save now merges with what is stored instead of replacing the whole record, so a key the browser did not send is left alone rather than deleted.
* Fixed: checkboxes and radio buttons were invisible. They were still there and still clickable, but nothing was drawn — including the consent boxes on the public booking form and the whole role-permissions grid.
* Fixed: number, date and time fields had no border or background, so values floated with no field around them.
* Fixed: buttons inside dialogs showed the plain arrow instead of the hand cursor.
* Fixed: the WordPress admin menu could scroll away and leave an empty dark column beside long screens.
* Fixed: the settings menu now stays in view while a long tab scrolls, and the open tab survives a page reload.
* Fixed: "&" appeared as "&amp;" in several headings.
* Fixed: the appointment settings screen announced itself as "Dashboard".
* Save buttons now wait for the write to finish, show a spinner while it runs, and report a failure instead of a false success. Dialogs stay open if the save fails, with your values still in them.
* Email statistics now say "accepted" rather than "delivered". WordPress can only report that your server took the message for sending; it never learns whether it arrived, bounced or was filed as spam.
* A day the business is closed is now marked as closed in the booking calendar, in both layouts, instead of looking the same as an ordinary day — and the stepped calendar no longer lets a closed day be selected at all.
* Fixed: choosing a status from a booking's row menu did nothing. The menu closed and the booking was left as it was. The menu is drawn outside the table so it cannot be clipped, and the code that closed it on an outside click ran before the click ever reached the button underneath — so the button was never pressed. Only "Download Invoice" appeared to work, because a link does not need the page's help to open.
* Fixed: the row menu offered statuses a booking could not move to. Picking one — "Pending" on a confirmed booking, for example — was refused by the server and quietly undone, which is indistinguishable from a broken button. Impossible moves are now shown as unavailable, with the reason on hover, and a refusal that does happen says why instead of silently reverting.
* Fixed: the row menu could close the instant it opened. Pressing the button focuses it, and focusing a control inside a scrolling area can make the browser nudge the area — which the menu read as "the page moved" and shut itself. This is what made the problem come and go with no pattern to it.
* Changing a booking's status now emails the people it affects. Cancelling tells the customer and alerts you; confirming sends the confirmation; completing sends the thank-you. These four switches have always been on the Notifications screen and none of them were connected to anything, so turning them on sent nothing. They use your own templates where you have written them, and a plain built-in message where you have not.
* Fixed: clicking a notification did nothing. A notice about a booking now opens that booking. Older notices, and notices about a recurring series, have no single booking behind them — those now open the bookings list narrowed to the customer named in the message, rather than going nowhere.
* Each notification can now be marked read or unread on its own, from anywhere in the admin, instead of only being marked read by opening it.
* Fixed: the notification panel listed the oldest notice first, so the thing that had just happened was the one you had to scroll to find.
* Fixed: a notification about a booking that has since been deleted now says so, instead of opening nothing.
* The bookings table's last column is now labelled "Actions" rather than left blank.

= 2.0.2 =
* New product artwork: the plugin icon, the directory banners and the mark shown in the admin header, the block editor and the staff portal are now the finished Tiger Booking logo.
* The plugins list row now links straight to the settings screen, for users who can reach it.

= 2.0.1 =
* Every JSON request body is now sanitised at a single boundary before it reaches any handler, and each storage column is sanitised again with the function that fits it.
* Admin notices are limited to this plugin's own screens, are dismissible, and are fully translatable; the inline scripts they used to print are now an enqueued file.
* CSV import accepts only the columns a module declares; unknown headers are discarded.
* Fixed a database error on sites without the hotel module that could break the booking importer's response.
* Booking actions that only read or re-send are now icons, so the detail footer no longer overflows when translated.

= Earlier releases =

Versions before 2.0.1 were distributed outside the WordPress.org directory and are not listed here. Everything they introduced is part of this plugin and is described under **What you can do** above.

== Upgrade Notice ==

= 2.0.4 =
Solo practitioner & mentor setup with direct owner profile controls, zero placeholder data on clean installs, automated database cleanup utility, universal default PHP mailer compatibility across all web hosting environments, Outlook-compatible email templates, and setup wizard navigation fixes. Recommended for every site.

= 2.0.3 =
Changing a booking's status from its row menu did nothing, and the four notification switches for confirmations, cancellations and follow-ups were never connected to anything. Booking alerts to the operator also went to a placeholder address that shipped as the default. Also fixes settings that saved the previous value or overwrote other settings, and restores checkboxes and number fields that were drawn invisible. Recommended for every site.

= 2.0.2 =
Artwork only. The plugin icon and the mark shown inside the admin screens and the staff portal have been replaced with the finished logo. No functional change.

= 2.0.1 =
Security hardening: every request body is now sanitised at a single boundary, and each stored field again at the point it is written. Admin notices are confined to this plugin's own screens. Nothing you have set up changes.
