# nexdirectory (WordPress Plugin)

Community-driven events platform with moderated submissions.

## What this plugin includes

- Event custom post type with taxonomy filters
- Archive grid page with filters (search, type, mode, city, date)
- Save filter presets per user
- Map page with marker view + live filter sidebar
- Logged-in user event submission form
- Admin moderation workflow (all user submissions are `Pending`)
- Admin moderation queue with approve/reject + moderation notes
- User dashboard to view/edit/delete own events
- Account management page
- Login + sign-up page shortcode
- Event detail block appended on each event page
- RSVP + waitlist capacity handling
- Abuse reporting workflow
- Calendar export (ICS/Google/Outlook)
- Organizer directory with verification badges/history
- Recurring event generation (daily/weekly/monthly until date)
- Reminder emails for RSVP attendees before events
- Video and image gallery URLs on event profiles
- Spam controls (honeypot + rate limit)
- Strict signup validation (email format/domain DNS check + suspicious username blocking)
- Configurable email verification flow before first event submission
- Backend settings page for Google Maps + reCAPTCHA keys (`WP Admin > nexdirectory`)
- Form layout updated to sectioned workflow (General, Images, Contact, Location, Details)
- Additional taxonomies: `event_tag`, `event_price_range`
- Auto-save drafts every minute from the submit form
- Drag-and-drop image uploader with WordPress Media Library support
- Multi-date session builder for events
- Contact event holder form from single event pages (uses `wp_mail` / SMTP plugin setup)
- Listing claim workflow (claim page shortcode + admin approve/reject in moderation queue)
- Chrome extension connector with signed App Pass handshake for remote AI imports
- Admin metrics dashboard (`WP Admin > nexdirectory > Metrics`) for submissions, approvals, spam blocks, and conversion
- Capability layer (`eep_submit_events`, `eep_moderate_events`, `eep_manage_organizers`) with role mappings
- DB schema versioning via `EEP_DB_VERSION` + migration routine
- Uninstall cleanup flow with optional full data purge toggle
- Elementor widgets: all plugin shortcodes are available as individual Elementor widgets with controls
- Admin import tool for bulk event creation via JSON or CSV (`WP Admin > nexdirectory > Import Events`)
- Import flow now includes Step 2 preview + column mapping (first 5 rows) before writing posts
- Optional duplicate-skip on import (checks existing events by title + start datetime)
- Submit form timezone now uses a canonical timezone dropdown with browser auto-detect
- Single event pages now show automatic viewer-local timezone conversion text
- Map sidebar filters now include price, official-event status, and from-date filters
- Added distance filter and "Search this area" UX for map discovery
- Map pins are now fetched dynamically via REST endpoint based on visible map bounds (lighter page payload)
- Leaflet marker clustering is enabled for dense cities
- Tailwind Play CDN removed in favor of static local stylesheet (`assets/css/eep-tailwind.css`)
- Custom map pin URL setting available in admin settings
- Geocoding now goes through backend REST proxy (Nominatim User-Agent compliant)
- RSVP writes use dedicated custom table with transactional updates (`wp_eep_rsvps`) to reduce race-condition data loss
- Reminder emails are queued via `wp_schedule_single_event` batches instead of synchronous bulk sends
- Rich text editor option for event description in submit form
- Events I'm Attending dashboard shortcode for user RSVPs (`[eep_my_tickets]`)
- Organizer attendee management panel + attendee CSV export from My Events
- Calendar view shortcode (`[eep_events_calendar]`)
- Frontend uses toast notifications + loading states instead of blocking `window.alert`
- Tables in user/admin dashboards are wrapped for horizontal mobile scrolling

## Architecture (10-file cap)

To keep the plugin manageable while staying under your max-file limit, core logic is split into focused modules:

- `nexdirectory.php`: bootstrap, trait loading, hooks, activation/deactivation
- `includes/trait-eep-admin.php`: settings/admin pages + Elementor registration wiring
- `includes/trait-eep-content.php`: CPT/taxonomy registration, assets, REST endpoints, map/archive query builders
- `includes/trait-eep-utilities.php`: shared helpers, validation, import parsing/mapping, spam/verification utilities
- `includes/trait-eep-frontend.php`: shortcodes, frontend renderers, form handlers, moderation/auth flows, single-event output
- `includes/elementor-widgets.php`: Elementor widget classes/controls

## Install

1. Copy folder `nexdirectory` into `wp-content/plugins/`
2. Activate plugin in WordPress admin
3. Create these pages and add shortcodes:
   - `Events`: `[eep_events_archive]`
   - `Map`: `[eep_events_map]`
   - `Calendar`: `[eep_events_calendar]`
   - `Submit Event`: `[eep_submit_event]`
   - `My Events`: `[eep_my_events]`
   - `Events I'm Attending`: `[eep_my_tickets]`
   - `Account`: `[eep_account]`
   - `Login / Sign Up`: `[eep_auth]`
   - `User Management` (admin only): `[eep_user_management]`
   - `Moderation Queue` (admin/editor): `[eep_moderation_queue]`
   - `Organizers`: `[eep_organizers]`
   - `Claim Listing`: `[eep_claim_listing]`
4. Add menu links to these pages
5. In WP Admin, create taxonomy terms for:
   - Event Types (`event_type`)
   - Event Modes (`event_mode`)
   - Event Tags (`event_tag`)
   - Price Ranges (`event_price_range`)

## API settings

1. In WP Admin, open `nexdirectory` in the left menu.
2. Configure:
   - Google Maps API key
   - Global custom map pin URL
   - reCAPTCHA site key
   - reCAPTCHA secret key
   - Toggle: require email verification before first submission
   - Default redirect URL after login
   - Toggle + interval for submit autosave
   - Toggle for event reporting
   - Default submit form section nav visibility
   - Toggle: auto-refresh map results when panning/zooming
   - Toggle: rich text editor in submit form
   - Extension connector (enable API + App Pass + default import status)
   - Extension import owner + mark imported events claimable toggle
   - Claim notification email toggle
3. Save.

## Chrome extension companion

- Source location: `chrome-extension/event-plugin-wp-scanner`
- Load unpacked in Chrome developer mode.
- Configure in side panel:
  - Plugin Site URL
  - Extension App Pass (from plugin settings)
  - OpenAI API key + model (`gpt-5.2` default)
- Flow:
  1. Open any event webpage
  2. Click **Start Scan**
  3. Review/edit extracted fields
  4. Click **Import To WordPress**
- The extension uses signed REST calls:
  - `POST /wp-json/eep/v1/extension/ping`
  - `POST /wp-json/eep/v1/extension/import`

## Import events

1. Open `WP Admin > nexdirectory > Import Events`.
2. Upload `.json` or `.csv`.
3. Choose default status (`pending`, `draft`, `publish`) and duplicate handling.
4. Continue to Step 2 preview.
5. Map source columns to event fields and run import.
6. Metrics page tracks cumulative imported events.

Supported columns/keys:
`title,description,excerpt,start,end,timezone,venue,address,city,country,lat,lng,capacity,price,external_url,contact_email,contact_phone,contact_name,cover_image_url,official_event,recurrence,recurrence_until,video_urls,gallery_urls,sessions,event_type,event_mode,event_price_range,event_tags,status`

## Elementor integration

- Widget category: `nexdirectory`
- Widgets included:
  - Events Archive
  - Events Map
  - Events Calendar
  - Submit Event Form
  - My Events
  - Events I'm Attending
  - Account
  - Auth (Login/Signup)
  - User Management
  - Moderation Queue
  - Organizers
  - Claim Listing
- Each widget includes per-widget settings (limits/toggles/redirect/wrapper class).
- Map widget includes filter toggles (search/type/mode/tag/price/official/date/distance/list), sidebar toggle, and map height.
- All widgets include style overrides (accent color, panel background, text color, corner radius).

## Builder compatibility aliases

- For builders that prefer custom shortcode naming, aliases are registered:
  - `[nexdirectory_events_archive]`, `[nexdirectory_events_map]`, `[nexdirectory_events_calendar]`
  - `[nexdirectory_submit_event]`, `[nexdirectory_my_events]`, `[nexdirectory_my_tickets]`
  - `[nexdirectory_account]`, `[nexdirectory_auth]`, `[nexdirectory_user_management]`
  - `[nexdirectory_moderation_queue]`, `[nexdirectory_organizers]`, `[nexdirectory_claim_listing]`

## Suggested quality-of-life setup

- Enable email notifications for admins on pending posts.
- Add anti-spam (reCAPTCHA or honeypot) on auth/submission forms.
- Add image upload/gallery field for event banners.
- Add geocoding integration to auto-fill lat/lng from address.
- Configure transactional mail for account and moderation notifications.

## Test scaffolding

- PHPUnit scaffold added under `tests/phpunit/`
  - `tests/phpunit/bootstrap.php`
  - `tests/phpunit/test-rest-map-events.php`
- Playwright scaffold added under `tests/e2e/`
  - `tests/e2e/playwright.config.js`
  - `tests/e2e/smoke.spec.js`

## Notes

- Map uses Leaflet + OpenStreetMap tiles.
- Map data loads from REST endpoint (`/wp-json/eep/v1/map-events`) and updates by map bounds.
- Users can submit/edit only their own events.
- Editing an event returns it to pending review for admin verification.
- To export ICS from an event, use URL query `?eep_ics=<event_id>` (buttons are shown on single event pages).

## License

- Plugin license: **GNU General Public License v2.0 or later** (`GPL-2.0-or-later`).
- See [COPYING](COPYING) for the primary license notice.
- See [THIRD_PARTY_LICENSES.md](THIRD_PARTY_LICENSES.md) for bundled third-party licensing notes.
