# Screens Specification

## App Shell

The new client should provide:

- Persistent top header with app name and global actions.
- Section navigation for Devices, Scripts, and Areas.
- Route-level loading, error, and empty states.
- Toast notifications.
- Confirmation dialogs.
- Reusable modal/dialog system.

Initial route:

- `/` redirects to `/areas/favorites`.

## Devices List

Route:

- `/devices`

Data:

- `GET /api/v1/devices/list`
- Per active row: `GET /api/v1/devices/id/{id}/status`

Table columns:

- Device name
- Connection status
- Live state
- IP
- Actions

Required behavior:

- Render DB list first.
- Load live state independently per device.
- Skip live status request for devices with `connection_status = lost`.
- Limit concurrent status requests.
- Show per-row loading.
- Show per-row offline/error state.
- Provide Details action.
- Provide Reboot action with confirmation or clear feedback.

## Devices Scanning

Route:

- `/devices/scanning`

Data:

- `GET /api/v1/devices/scanning/all`

Table columns:

- Device ID
- Device name
- Type
- Status
- IP
- MAC
- WiFi signal
- Actions

Required behavior:

- Show setup button only for devices in `setup` status.
- Setup flow should collect alias, name, and description.
- On successful setup, refresh list and show success toast.

### Device Setup Modal

Opened from:

- Devices Scanning screen.

Source data:

- Scanned device object from `/api/v1/devices/scanning/all`.

Read-only device fields:

- All public fields returned by `/about` after current field unification.
- Typical fields: `device_id`, `name`, `type`, `status`, `ip`, `mac`,
  `wifi_signal`, firmware/core fields.

Form fields:

- `alias` - required.
- `name` - required.
- `description` - optional textarea.

Submit endpoint:

- `POST /api/v1/devices/setup/new-device`

Payload:

```json
{
  "device_ip": "192.168.2.42",
  "alias": "kitchen_relay",
  "name": "Kitchen relay",
  "description": "Optional description"
}
```

Validation:

- Client-side required validation for `alias` and `name`.
- Server-side `failed_fields` should mark matching form fields.
- Server-side `msg` should be shown in an inline alert.

Success behavior:

- Close modal.
- Refresh current screen data.
- Show success toast.

## Scripts Actions

Route:

- `/scripts/actions`

Data:

- `GET /api/v1/scripts/actions/list`
- `POST /api/v1/scripts/actions/run`

Required behavior:

- Render scripts as action cards.
- Card shows icon, name, description, and enabled/disabled visual state.
- Clicking card content runs script.
- Details action opens script details.
- Show in-progress state per card.
- Show success/failure toast.
- Refresh after successful run if current backend behavior requires it.

## Scripts Regular

Route:

- `/scripts/regular`

Data:

- `GET /api/v1/scripts/regular/list`
- `GET /api/v1/scripts/regular/alias/{alias}/enable`
- `GET /api/v1/scripts/regular/alias/{alias}/disable`

Required behavior:

- Table with alias, name, filename/path, state, actions.
- Enable/disable button based on current state.
- Show in-progress state per button.
- Refresh after state mutation.

## Scripts Scopes

Route:

- `/scripts/scopes`

Data:

- `GET /api/v1/scripts/scopes/list`
- `GET /api/v1/scripts/scopes/name/{name}/enable`
- `GET /api/v1/scripts/scopes/name/{name}/disable`

Required behavior:

- Table with scope name, filename/path, state, actions.
- Enable/disable button based on current state.
- Show in-progress state per button.
- Refresh after state mutation.

## Areas Tree

Route:

- `/areas/tree`

Data:

- `GET /api/v1/areas/list`

Required behavior:

- Build tree from flat list using `parent_id`.
- Protect against self-reference and cycles.
- Root nodes are areas without valid parent.
- Render children collapsible by branch.
- Area row actions:
  - Actions
  - Devices
  - Details
  - Favorite toggle
- Create area button opens create modal.

## Areas Favorites

Route:

- `/areas/favorites`

Data:

- `GET /api/v1/areas/list`
- Local favorites store.

Required behavior:

- Render only favorite areas.
- Empty state when no favorites.
- Area row actions:
  - Actions
  - Devices
  - Remove from favorites

Favorite persistence:

- Current client uses local storage through `FavoritesStore`.
- New client should preserve local-only favorite behavior unless backend support is added.

## Area Devices Modal

Opened from:

- Areas tree.
- Areas favorites.

Data:

- `GET /api/v1/areas/id/{area_id}/devices`
- Device status endpoints per device.
- `GET /api/v1/devices/id/{id}/reboot`
- `GET /api/v1/areas/id/{area_id}/reboot_devices`

Required behavior:

- Table with device, connection status, live state, actions.
- Reuse the same robust state-loading behavior as Devices List.
- Reboot one device.
- Reboot all devices in the area.
- Hide reboot-all if area has no devices.
- Details action opens Device Details Modal.

## Device Details Modal

Opened from:

- Devices List.
- Area Devices Modal.

Source data:

- Device object from list or area-device response.

Displayed fields:

- All available device fields as key/value rows.
- Format `ip`, `mac`, and `device_id` as code values.
- Format `status` and `connection_status` as badges.
- Format `last_contact`, `create_at`, and `update_at` as human-readable dates.
- Render live state through the shared Device State component.

Editable fields:

- `name` through `POST /api/v1/devices/update-name`
- `description` through `POST /api/v1/devices/update-description`
- `alias` through `POST /api/v1/devices/update-alias`

Edit behavior:

- Use inline editable text controls.
- On successful edit, invalidate cached device data and refresh affected views.
- On failure, restore the original value and show an error toast.

Actions:

- Close.
- ReSetup through `POST /api/v1/devices/resetup`.
- Reboot through `GET /api/v1/devices/id/{id}/reboot`.
- Reset through `POST /api/v1/devices/reset`.
- Remove through `GET /api/v1/devices/id/{id}/remove`.

Dangerous actions:

- ReSetup, Reset, and Remove require confirmation.
- Remove should close modal, refresh current screen, and show success/error toast.

Placement:

- Include Place In Area component for device area assignment.

## Area Actions Modal

Opened from:

- Areas tree.
- Areas favorites.

Data:

- `GET /api/v1/areas/id/{area_id}/scripts`
- Script action run endpoint.

Required behavior:

- Show scripts/actions assigned to the area.
- Allow running action scripts.
- Show empty state when no scripts exist.

## Area Details Modal

Opened from:

- Areas tree.

Required behavior:

- Show area id, display name, alias, type, parent.
- Allow editing fields covered by backend endpoints.
- Allow unassigning/moving where current backend supports it.

Displayed fields:

- All available area fields as key/value rows.
- Format `alias` with link icon.
- Format `create_at` and `update_at`.
- Render unsupported `schema` as muted placeholder.

Editable fields:

- `display_name` through `POST /api/v1/areas/update-display-name`
- `alias` through `POST /api/v1/areas/update-alias`

Actions:

- Close.
- Remove through `GET /api/v1/areas/id/{area_id}/remove`.

Dangerous actions:

- Remove requires confirmation.
- On success, invalidate area data, close modal, refresh current screen, and show
  success toast.

Placement:

- Include Place In Area component for changing `parent_id`.

## Create Area Modal

Opened from:

- Areas Tree.

Form fields:

- `type` - required.
- `alias` - required.
- `display_name` - required.

Supporting data:

- `GET /api/v1/areas/types/list`

Submit endpoint:

- `POST /api/v1/areas/new-area`

Payload:

```json
{
  "type": "room",
  "alias": "office",
  "display_name": "Office"
}
```

Required behavior:

- Load area types and provide searchable/selectable type input.
- Validate all fields as non-empty.
- Mark fields listed in server `failed_fields`.
- Show server `msg` in inline alert.
- On success, close modal, invalidate areas list, refresh screen, and show toast.

## Action Script Details Modal

Opened from:

- Scripts Actions screen.
- Area Actions Modal where script details are available.

Displayed fields:

- Alias.
- Description.
- State badge.
- Filename.
- Author.
- PHP code block with syntax highlighting.

Actions:

- Close.
- Enable/disable action script through `action_enable` or `action_disable`.
- Run action script through `POST /api/v1/scripts/actions/run`.

Placement:

- If script has `area_id`, include Place In Area component with type `action`.

Success behavior:

- Enable/disable closes modal, refreshes screen, and shows toast.
- Run shows button loading state; on success, closes modal and shows toast.

## Place In Area Component

Used by:

- Device Details Modal.
- Area Details Modal.
- Action Script Details Modal.

Target types:

- `device` uses `/api/v1/devices/place-in-area` and
  `/api/v1/devices/id/{id}/unassign-from-area`.
- `area` uses `/api/v1/areas/place-in-area` and
  `/api/v1/areas/id/{id}/unassign-from-area`.
- `action` uses `/api/v1/scripts/place-in-area` and
  `/api/v1/scripts/id/{id}/unassign-from-area`.

Required behavior:

- Load areas list.
- Show current parent area display name, or `Area ID {id}` fallback.
- Hide unassign button when current parent id is `0`.
- Show searchable area selector.
- Exclude self from candidate list when target type is `area`.
- On assignment success, update current parent, invalidate areas data, refresh
  relevant views, and show success toast.
- On unassign success, set current parent to `0`, invalidate areas data, refresh
  relevant views, and show success toast.

Implementation note:

- Current client stores component state in module-level variables, so multiple
  instances can conflict. The Vue implementation must keep each Place In Area
  instance state-isolated.
