# Calendar Events and Meeting Links

This module provides CRUD APIs for managing calendar events and associated meeting URLs.

Times are stored in UTC. When retrieving events the API converts `start_time` and
`end_time` to the user's preferred timezone stored in `user_settings` with the
setting name `timezone`. Clients may further convert these timestamps to the
browser timezone if needed.

## Database Schema

### `calendar_events`
- `id` INT AUTO_INCREMENT PRIMARY KEY
- `title` VARCHAR required
- `description` TEXT nullable
- `start_time` DATETIME required
- `end_time` DATETIME nullable
- `location` VARCHAR nullable
- `recurrence_rule` VARCHAR nullable
- `recurrence_end` DATETIME nullable
  - When omitted the event recurs indefinitely. The end date is inclusive.
- `parent_event_id` INT nullable
- `category_id` INT optional category reference
- `created_at` DATETIME nullable
- `updatedAt` TIMESTAMP auto updated
- `isDeleted` TINYINT default 0

### `meeting_links`
- `id` INT AUTO_INCREMENT PRIMARY KEY
- `event_id` INT references `calendar_events.id` (no FK constraint)
- `url` VARCHAR required
- `created_at` DATETIME nullable
- `updatedAt` TIMESTAMP auto updated
- `isDeleted` TINYINT default 0

### `calendar_accounts`
- `id` INT AUTO_INCREMENT PRIMARY KEY
- `user_id` INT owner of the tokens
- `provider` VARCHAR calendar service name
- `access_token` TEXT
- `refresh_token` TEXT
- `token_expires` DATETIME
- `created_at` DATETIME
- `updatedAt` TIMESTAMP auto updated

### `calendar_availability`
- `id` INT AUTO_INCREMENT PRIMARY KEY
- `user_id` INT employee the entry belongs to
- `start_time` DATETIME start of the busy block
- `end_time` DATETIME end of the busy block
- `type` ENUM('meeting','vacation')
- `updatedAt` TIMESTAMP auto updated
- `isDeleted` TINYINT default 0

### `calendar_event_permissions`
- `id` INT AUTO_INCREMENT PRIMARY KEY
- `event_id` INT event the permission applies to
- `user_id` INT user with access
- `role` ENUM('viewer','editor','admin')
- `updatedAt` TIMESTAMP auto updated
- `isDeleted` TINYINT default 0

### `calendar_event_documents`
- `id` INT AUTO_INCREMENT PRIMARY KEY
- `event_id` INT calendar event
- `document_id` INT document linked
- `uploaded_by` INT user who attached the file
- `updatedAt` TIMESTAMP auto updated
- `isDeleted` TINYINT default 0

### `calendar_categories`
- `id` INT AUTO_INCREMENT PRIMARY KEY
- `name` VARCHAR category label
- `color` VARCHAR optional display color
- `updatedAt` TIMESTAMP auto updated
- `isDeleted` TINYINT default 0

### `push_subscriptions`
- `id` INT AUTO_INCREMENT PRIMARY KEY
- `user_id` INT owner of the token
- `endpoint` TEXT push endpoint
- `p256dh` VARCHAR user key
- `auth` VARCHAR auth secret
- `browser` VARCHAR user agent
- `updatedAt` TIMESTAMP auto updated
- `isDeleted` TINYINT default 0

## API Routes

Listing and editing events requires the **Super Admin** or **Admin** role or an
entry in `calendar_event_permissions` granting `viewer`, `editor` or `admin`
rights for that event.

### Calendar Events
- `GET /api/calendar_events` – list events
- `GET /api/calendar_events/{id}` – fetch a single event
- `POST /api/calendar_events` – create a new event
- `PUT /api/calendar_events/{id}` – update an event
- `DELETE /api/calendar_events/{id}` – remove an event
- `POST /api/calendar_events/attachDocument/{id}` – attach a document to an event

Pass a `category_id` query parameter to `GET /api/calendar_events` to retrieve only events in a specific category. The calendar UI includes a dropdown that sends this parameter automatically.

### Meetings
- `GET /api/meetings` – list meeting links
- `GET /api/meetings/{id}` – fetch a single meeting link
- `POST /api/meetings` – create a meeting link
- `PUT /api/meetings/{id}` – update a meeting link
- `DELETE /api/meetings/{id}` – delete a meeting link

### Calendar Accounts
These endpoints allow a user to manage OAuth tokens used by the calendar
services. Tokens are stored in `calendar_accounts` and are looked up when
creating events.

- `GET /api/calendar_accounts` – list connected accounts for the current user
- `POST /api/calendar_accounts` – add a new account (provider and tokens)
- `DELETE /api/calendar_accounts/{id}` – remove an account


### Calendar Availability
- `GET /api/calendar_availability` – list availability entries
- `GET /api/calendar_availability/{id}` – fetch a single entry
- `POST /api/calendar_availability` – create a new entry
- `PUT /api/calendar_availability/{id}` – update an entry
- `DELETE /api/calendar_availability/{id}` – delete an entry

### Calendar Permissions
- `GET /api/calendar_permissions` – list permission records
- `GET /api/calendar_permissions/{id}` – fetch a permission record
- `POST /api/calendar_permissions` – grant a role on an event
- `PUT /api/calendar_permissions/{id}` – change the role
- `DELETE /api/calendar_permissions/{id}` – revoke the permission

## Request Example

Create a one-time event and specify a category:

```bash
curl -X POST -b cookie.txt \
  -H 'Content-Type: application/json' \
  -d '{"title":"Board Meeting","start_time":"2024-07-01 10:00","end_time":"2024-07-01 11:00","category_id":2}' \
  http://localhost/api/calendar_events
```

Create a weekly recurring event with a category:

```bash
curl -X POST -b cookie.txt \
  -H 'Content-Type: application/json' \
  -d '{"title":"Standup","start_time":"2024-07-01 09:00","end_time":"2024-07-01 09:15", "category_id":1,
       "recurrence_rule":"FREQ=WEEKLY","recurrence_end":"2024-08-01"}' \
  http://localhost/api/calendar_events
```

Create a recurring event with no end date:

```bash
curl -X POST -b cookie.txt \
  -H 'Content-Type: application/json' \
  -d '{"title":"Daily Report","start_time":"2024-07-01 07:00","recurrence_rule":"FREQ=DAILY"}' \
  http://localhost/api/calendar_events
```

Grant editor access to another user:

```bash
curl -X POST -b cookie.txt \
  -H 'Content-Type: application/json' \
  -d '{"event_id":1,"user_id":5,"role":"editor"}' \
  http://localhost/api/calendar_permissions
```

## Document Attachments

Upload a new file:

```bash
curl -X POST -b cookie.txt \
  -F document=@file.pdf \
  http://localhost/api/calendar_events/attachDocument/1
```

Link an existing document:

```bash
curl -X POST -b cookie.txt \
  -H 'Content-Type: application/json' \
  -d '{"document_id":42}' \
  http://localhost/api/calendar_events/attachDocument/1
```


## Browser Push Setup

1. Include `public/js/pushNotifications.js` on `Dashboard.php`.
2. Call `PushNotifications.init(<VAPID Public Key>)` after DOM ready.
3. The script registers `/sw.js` service worker and posts the browser subscription to `/api/push/subscribe`.
4. `EventNotificationService` sends push alerts using stored subscriptions.
