=== Circumflex Booking ===
Contributors: sutregutt
Tags: booking, appointments, scheduling, availability, calendar
Requires at least: 6.8
Tested up to: 7.0
Requires PHP: 8.3
Stable tag: 1.0.2
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Appointment booking with manual approval, flexible availability, multiple services and practitioners, and email notifications.

== Description ==

Circumflex Booking is a self-hosted appointment booking plugin for treatments,
consultations, and other scheduled services. Customers request an available
time, and authorized staff approve or reject each request manually.

= Customer booking =

* Let customers select one or more services in a single booking.
* Show a practitioner choice or "first available" when several practitioners
  qualify. The choice is hidden automatically when only one qualifies.
* Present available dates and times in accessible calendar and list views.
  Unavailable times are visually distinct and not selectable.
* Collect name, email address, phone number, and an optional practical comment.
* Reserve a requested time while the booking is pending, preventing another
  customer from taking it.
* Send customer and staff notifications for booking events and reminders.
* Give confirmed customers a private link to view the booking, request another
  time, or cancel within the configured deadline.

= Administration =

* Configure services, durations, preparation buffers, prices, booking and
  cancellation deadlines, and drag-and-drop service order.
* Configure one or more practitioners and assign the services each can provide.
* Combine recurring weekly hours with closures, extra opening dates, and manual
  blocks.
* Review and process bookings in a filterable list or calendar with
  role- and practitioner-scoped permissions.
* Configure the site identity shown in email headers, edit plain-text
  notification templates, and preview the matching responsive HTML email and
  exact plain-text alternative.
* Use WordPress privacy tools, configurable retention, local diagnostics,
  configuration transfer, and Site Health checks.

= Add the booking form anywhere =

Use the `[circumflex_booking]` shortcode, the dynamic Circumflex Booking block,
or the optional Elementor widget. Elementor, WooCommerce, and customer accounts
are not required.

All shipped functionality is available without payment or a license key.
Payments, recurring bookings, and multiple locations are outside scope. Email
uses `wp_mail()`; a separate SMTP plugin is recommended.

Booking and diagnostics stay on the site. Optional Cloudflare Turnstile is
disabled by default and disclosed below.

== Installation ==

1. Install and activate Circumflex Booking.
2. Add at least one service under Booking > Services.
3. Add a practitioner, assign services, and configure recurring hours under
   Booking > Practitioners and Booking > Availability.
4. Review deadlines, notices, retention, recipients, and email templates under
   Booking > Settings.
5. Add the `[circumflex_booking]` shortcode, Circumflex Booking block, or
   Elementor widget to a page.
6. Check Tools > Booking status, then make and process a test booking before
   opening the page to customers.

The tested and supported database baseline is MySQL 8.0 or MariaDB 10.11 and
newer. Use HTTPS and configure the site's mail or SMTP setup before accepting
real bookings.

== Frequently Asked Questions ==

= Is the booking form a separate WordPress page? =

No. Add the shortcode, Gutenberg block, or Elementor widget to any page. All
three use the same booking flow and settings.

= What happens when there is only one practitioner? =

The practitioner step is hidden when the selected services have exactly one
eligible practitioner. With several eligible practitioners, the customer can
choose one or ask for the first available.

= Are notification emails sent immediately? =

An asynchronous worker starts as soon as a message is queued. WordPress cron
remains as fallback and for retries. Inbox delivery depends on the site's
`wp_mail()` or SMTP setup.

= Why are MySQL 8.0 and MariaDB 10.11 listed? =

They match WordPress's recommended production baseline and the versions covered
by the plugin's compatibility test matrix. Older versions may work, but they
are not tested or supported. The status page reports an older version as a
warning; the database version alone does not deactivate the plugin.

= Can customers change or cancel an appointment? =

Confirmed customers can receive a private link to request a new time or cancel
before the deadline. New times require manual approval. Treat the link as a
secret access key.

= Does the plugin support payments or recurring appointments? =

No. They are outside the plugin's scope.

= Should customers enter health information in the comment field? =

Configure the warning beside the optional comment to tell customers not to
submit health or other sensitive data that is not needed for scheduling.

= What happens when the plugin is deactivated or removed? =

Deactivation and normal uninstall preserve data. Permanent deletion requires an
authorized administrator to enable and confirm the uninstall deletion option.

== Screenshots ==

1. The customer booking flow starts with one or more services.
2. Accessible calendar and list views show available and unavailable times.
3. The booking dashboard summarizes pending and upcoming work.
4. Staff can review a booking and approve or reject it with a message.
5. Weekly hours, exceptions, extra openings, and blocks control availability.
6. Notification previews show the responsive HTML email and plain-text version.

== Privacy and External Services ==

The site's database stores customer contact details, optional practical
comment, services, practitioner, appointment time, and customer-notice
snapshot. Internal notes are visible only to authorized roles.

By default, personal data is anonymized 365 days after a terminal status; the
period is configurable. Anonymization removes contact details, free text,
customer tokens, and identifying notification and audit data. Anonymous
booking facts may remain for statistics. WordPress privacy export and erasure
are supported. Erasing an active booking does not release its reserved time.

Authorized administrators can generate local diagnostics that omit personal
data, free text, tokens, secrets, IP addresses, and site URLs. Nothing is sent
to Circumflex AS.

= Cloudflare Turnstile =

[Cloudflare Turnstile](https://developers.cloudflare.com/turnstile/) is an
optional anti-spam service. It is disabled by default and requires Cloudflare
keys plus explicit administrator activation.

When enabled, the browser loads `https://challenges.cloudflare.com`. Cloudflare
processes signals including IP address, TLS fingerprint, User-Agent, site key,
and origin. WordPress sends the secret and response token to Siteverify but
does not explicitly add the visitor IP. Bookings fail closed if verification
cannot finish.

Review Cloudflare's
[Turnstile Privacy Addendum](https://www.cloudflare.com/turnstile-privacy-policy/),
[Privacy Policy](https://www.cloudflare.com/privacypolicy/), and
[Terms](https://www.cloudflare.com/policies/terms/) before enabling the service.
The site owner must reflect this processing in the site's privacy information.

== Source Code ==

Human-readable source, tests, build configuration, and release tooling
are maintained in the
[public GitLab repository](https://gitlab.slettene.com/gvar/circumflex-booking).
Generated JavaScript and CSS in `assets/build` are built from `assets/src`.

With Node.js 20.10+, PHP 8.3+, and Composer:

1. Run `composer install` in the `circumflex-booking` directory.
2. Run `npm ci`.
3. Run `npm run build`.
4. Run `npm run plugin:zip` for the deterministic production archive.

The complete quality gate is `npm run check`.

== Support ==

Use the Support tab on the WordPress.org plugin page for free-version support
after the directory listing is published. Product information is available at
[circumflex.no/circumflex-booking](https://circumflex.no/circumflex-booking/).
Do not post customer data, private booking links, credentials, or health
information in a public support topic.

== Changelog ==

= 1.0.2 =

* Address directory review findings, prepare WordPress language packs, and label the admin menu CF Booking.

= 1.0.1 =

* Clarify the supported database baseline and report older versions as a warning without deactivating the plugin.

= 1.0.0 =

* First stable customer booking, administration, notifications, privacy, and embedding release.

Older development history is available in `changelog.txt`.
