# FormBuilder Pro — Project Goals & Architecture

> **Single-tenant, self-hosted PHP/MySQL application** built for Namecheap shared hosting.  
> Sell as a packaged ZIP on CodeCanyon / Gumroad. No framework. No Docker required.

---

## What It Is

FormBuilder Pro is a three-module web application that can be deployed as a single ZIP on any PHP 7.4+ / MySQL shared host. It is intentionally single-tenant (one installation = one business), keeping the architecture simple and the codebase sellable to non-technical buyers.

The three modules are independently functional but share a single database, auth layer, and Stripe configuration.

---

## Module 1 — Form Builder

**Goal:** Let a business owner create custom web forms without code and collect submissions.

| Feature | Status |
|---|---|
| Drag-and-drop form builder (11 field types) | ✅ Done |
| Public form embed / direct link | ✅ Done |
| Per-form password protection | ✅ Done |
| Submission inbox with PDF export | ✅ Done |
| Email notifications (admin + submitter) | ✅ Done |
| File upload fields | ✅ Done |
| E-signature field | ✅ Done |
| Conditional logic | ✅ Done |
| Multi-step forms | ✅ Done |
| Webhooks (Zapier/Make) | ✅ Done |
| Stripe payment field | ✅ Done |

**Key files:** `admin/builder.php`, `form.php`, `api/index.php`, `lib.php`  
**DB tables:** `fb_forms`, `fb_form_fields`, `fb_submissions`, `fb_submission_files`

---

## Module 2 — Appointment Booking

**Goal:** Let members (or walk-in customers) book time slots with providers, with Stripe membership plans gating access.

| Feature | Status |
|---|---|
| Services CRUD (name, duration, color, restricted flag) | ✅ Done |
| Providers CRUD (name, branch, email, timezone) | ✅ Done |
| Provider working hours per day-of-week | ✅ Done |
| Provider breaks (date-specific) | ✅ Done |
| Slot availability engine with race-condition protection | ✅ Done |
| Membership-gated booking flow (6-step wizard) | ✅ Done |
| Walk-in booking for unrestricted services (`is_restricted=0`) | ✅ Fixed |
| Waitlist with admin notify | ✅ Done |
| Promo codes (percent / fixed) | ✅ Done |
| Booking confirmation emails (customer + provider) | ✅ Done |
| 24h and 1h reminder emails (cron-triggered) | ✅ Done |
| Customer cancel from dashboard | ✅ Done |
| Customer reschedule from dashboard | ✅ Fixed |
| Ratings / reviews (1–5 stars, admin moderation) | ✅ Done |
| Membership freeze / unfreeze (admin) | ✅ Done |
| Stripe Checkout for plan purchase | ✅ Done |
| Stripe webhook → activate membership | ✅ Done |
| Admin appointment CRUD (status, notes) | ✅ Done |
| Admin stats dashboard (today, week, top services) | ✅ Done |

**Key files:** `book.php`, `plans.php`, `checkout.php`, `api/booking.php`, `lib/BookingEngine.php`, `lib/StripeBooking.php`, `admin/booking.php`, `admin/booking-plans.php`, `admin/booking-providers.php`, `admin/booking-services.php`, `customer/dashboard.php`, `cron.php`

**DB tables (all prefixed `bk_`):**

```
bk_services          — service catalogue
bk_providers         — staff / instructors
bk_provider_services — which providers offer which services (+ capacity_per_slot)
bk_provider_hours    — weekly schedule per provider
bk_provider_breaks   — date-specific breaks
bk_plans             — membership plans (name, price, duration_days)
bk_plan_services     — which services a plan unlocks
bk_customers         — customer records (linked to bk_users)
bk_users             — customer auth accounts (email, password_hash)
bk_memberships       — active/expired memberships per customer
bk_appointments      — bookings (ref, status, datetime, reminder flags)
bk_waitlist          — customers waiting for a slot
bk_promo_codes       — discount codes (percent / fixed, per-plan or global)
bk_ratings           — post-appointment star ratings
```

---

## Module 3 — Membership / Auth

**Goal:** Customer accounts so people can log in, view their bookings, cancel, and reschedule.

| Feature | Status |
|---|---|
| Customer register / login / logout | ✅ Done |
| Email verification | ✅ Done |
| Password reset (email token) | ✅ Done |
| Google OAuth login | ✅ Done |
| Customer dashboard (upcoming + past appointments) | ✅ Done |
| Profile edit (name, phone) | ✅ Done |
| Cancel appointment | ✅ Done |
| Reschedule appointment | ✅ Fixed |
| Post-appointment star ratings | ✅ Done |

**Key files:** `login.php`, `register.php`, `verify-email.php`, `reset-password.php`, `forgot-password.php`, `customer/dashboard.php`, `api/auth.php`, `api/auth-google.php`

---

## Architecture Decisions

### Why no framework?
Target buyers install on Namecheap shared hosting. Composer is available but Laravel/Symfony are not. Flat PHP keeps the deployment a 5-minute FTP upload + setup wizard.

### Why single-tenant?
Multi-tenancy requires `tenant_id` on every table, a license server, and a SaaS billing layer. All of that adds months of work before a first sale. The current architecture is designed so `tenant_id` can be added as a migration later, after real customer demand for a hosted version is proven.

### Request flow

```
Browser → .htaccess → index.php router
  → Auth middleware (session check)
    → API handler (api/index.php or api/booking.php or api/auth.php)
      → BookingEngine / StripeBooking (lib/)
        → PDO queries (lib.php db())
          → JSON response
```

### Booking flow (membership-gated)
```
Step 1: Email → check-membership API
Step 2: Select service (from unlocked_services)
Step 3: Select provider (filtered by service)
Step 4: Pick date (calendar)
Step 5: Pick time slot (availability engine)
Step 6: Confirm → POST /api/booking/appointments
        → race-condition check inside transaction
        → confirmation email (customer + provider)
```

### Booking flow (walk-in, is_restricted=0)
```
Step 1: Email → no membership found → check unrestricted services
Step 2: Select unrestricted service
Steps 3-6: Same as above
POST /api/booking/appointments → skips membership check when service.is_restricted=0
```

---

## Stripe Configuration

All keys stored in `config.php` as PHP constants. Test and live key pairs supported simultaneously. Mode toggled via `STRIPE_MODE` (`test` | `live`).

```
STRIPE_MODE
STRIPE_TEST_PUBLISHABLE_KEY / STRIPE_LIVE_PUBLISHABLE_KEY
STRIPE_TEST_SECRET_KEY      / STRIPE_LIVE_SECRET_KEY
STRIPE_TEST_WEBHOOK_SECRET  / STRIPE_LIVE_WEBHOOK_SECRET
STRIPE_PUBLISHABLE_KEY      ← active key (mirrors test or live based on mode)
STRIPE_SECRET_KEY           ← active key
STRIPE_WEBHOOK_SECRET       ← active key
STRIPE_CURRENCY             (default: usd)
```

Webhook endpoint: `POST /api/booking/stripe/webhook`  
On `checkout.session.completed` → activates membership for the customer.

---

## Reminder Cron

Reminder emails are not sent in real-time. They are sent by a cron job that hits `cron.php`.

**Namecheap cPanel cron setup:**
```
*/30 * * * *  curl -s "https://yourdomain.com/formbuilder/cron.php?key=YOUR_CRON_SECRET" > /dev/null
```

Set `CRON_SECRET` in `config.php`. The script sends:
- 24h reminders for appointments starting in 23–25 hours
- 1h reminders for appointments starting in 55–65 minutes

---

## Deployment Checklist

1. Upload ZIP contents to `public_html/formbuilder/`
2. Set `data/` folder permissions to `755`
3. Run `setup.php` (creates DB tables, writes `config.php`, deletes itself)
4. Log in to `admin.php`
5. Create at least one Service, one Provider, and assign working hours
6. Create at least one Plan and link it to services
7. Set up Stripe keys in Admin → Stripe Settings
8. Set up cron job for reminders
9. Delete `setup.php` if not auto-deleted

---

## Roadmap (post-first-sale)

| Priority | Feature | Justification |
|---|---|---|
| High | Google Calendar sync for providers | Most requested feature in competing products |
| High | iCal / .ics download for customers | Standard expectation |
| Medium | SMS reminders (Twilio) | Higher open rate than email |
| Medium | Recurring appointments | Needed for gym/class use cases |
| Medium | Group bookings (multi-customer per slot UI) | Capacity > 1 already supported in DB |
| Low | Multi-language JSON files | Only needed for non-English markets |
| Low | White-label (logo, colors per install) | CodeCanyon extended licence feature |
| Future | Multi-tenant SaaS layer | Only after proven single-tenant demand |
