# ISP360 UI Shell Pattern

**Version:** 1.0  
**Date:** 2026-06-13  

Companion: [UI_SPECIFICATIONS.md](UI_SPECIFICATIONS.md) | [RBAC_SPEC.md](RBAC_SPEC.md) | [WIREGUARD_SPEC.md](WIREGUARD_SPEC.md)

---

## 1. Purpose

ISP360 adopts the **same structural approach** used in the legacy Prodigy ENT `index.php`, `login.php`, and `logout.php` pages — but replaces the hospital design language and MySQLi/hospital schema with:

- **ISP360 design tokens** (`assets/css/isp360-theme.css` + `tenant_themes`)
- **PDO** database access (`includes/db.php`)
- **ISP360 schema** (`users`, `sessions`, `login_history`, `vw_tenant_dashboard_metrics`, etc.)
- **RBAC** from [RBAC_SPEC.md](RBAC_SPEC.md)

Every new admin page (including WireGuard VPN pages in Phase 7) follows this shell.

---

## 2. Page Types

| Type | Examples | Layout |
|------|----------|--------|
| **Public auth** | `login.php`, `logout.php`, `forgot_password.php` | `layouts/main.php` + split auth card |
| **Redirect handler** | `index.php`, `login_process.php` | No HTML — logic only |
| **Authenticated app** | `dashboard.php`, `vpn_servers.php`, `customers.php` | `layouts/app-start.php` … `app-end.php` |
| **AJAX** | `ajax/get_vpn_servers.php` | JSON only, no layouts |

---

## 3. Authenticated Page Template

Same pattern as legacy `index.php`: PHP logic at top, optional AJAX early-exit, then layout includes.

```php
<?php
ob_start();
require_once __DIR__ . '/includes/config.php';
require_once __DIR__ . '/includes/db.php';
require_once __DIR__ . '/includes/auth.php';
require_once __DIR__ . '/includes/tenant.php';

requireLogin();
require_permission('vpn.view');          // module permission
$tenant_id = require_tenant_context();   // tenant-scoped data

// AJAX block — exit before HTML (see dashboard.php)
if (isset($_GET['ajax'])) { /* ... */ }

$page_title = 'VPN Servers';
include __DIR__ . '/layouts/app-start.php';
?>

<!-- Page content: KPI cards, DataTables, forms -->

<?php include __DIR__ . '/layouts/app-end.php'; ?>
```

---

## 4. Auth Page Template

Same split-panel card pattern as legacy `login.php` / `logout.php`:

```php
<?php
require_once __DIR__ . '/includes/config.php';
require_once __DIR__ . '/includes/auth.php';
if (isLoggedIn()) redirect('dashboard.php');
?>
<?php include __DIR__ . '/layouts/main.php'; ?>
<head>
    <?php includeFileWithVariables(__DIR__ . '/layouts/title-meta.php', ['title' => 'Sign In — ISP360']); ?>
    <?php include __DIR__ . '/layouts/head-css.php'; ?>
</head>
<body>
<div class="auth-page-wrapper">...</div>
<?php include __DIR__ . '/layouts/vendor-scripts.php'; ?>
</body>
</html>
```

---

## 5. File Map

| File | Role |
|------|------|
| `includes/config.php` | App constants, session bootstrap |
| `includes/db.php` | PDO `$pdo` connection |
| `includes/auth.php` | `permission_check()`, `requireLogin()`, session helpers |
| `includes/tenant.php` | `tenant_context()`, `tenant_theme()` |
| `includes/menu_config.php` | Sidebar menu (permission-filtered) |
| `includes/functions.php` | `includeFileWithVariables()`, `e()`, flash helpers |
| `assets/css/isp360-theme.css` | Design system (replaces Prodigy teal/green) |
| `layouts/app-start.php` | Opens app shell: sidebar, topbar, content wrapper |
| `layouts/app-end.php` | Closes content, footer, scripts |
| `layouts/main.php` | Opens `<!DOCTYPE html>` for auth pages |
| `layouts/menu.php` | Sidebar navigation |
| `layouts/theme-vars.php` | Tenant CSS variable overrides |

---

## 6. Design Language

### Legacy (Prodigy ENT) → ISP360

| Element | Legacy | ISP360 |
|---------|--------|--------|
| Primary brand | Medical teal `#0d9488` / green `#2d7a2d` | Network blue `#2563eb` |
| Secondary | Medical teal accents | Indigo `#4f46e5` |
| Auth layout | Split card, green gradient | Split card, blue gradient |
| Dashboard KPIs | Patients, consultations, labs | Customers, routers, revenue, sessions |
| DB driver | MySQLi `$conn` | PDO `$pdo` |
| Activity log | `activity_log` | `login_history`, `audit_logs` |
| Dashboard file | `index.php` (hospital) | `dashboard.php` |

### Tenant Branding

Active admin theme loaded from `tenant_themes` where `theme_type = 'admin'`:

- `primary_color`, `secondary_color`, `accent_color` → CSS variables in `layouts/theme-vars.php`
- `logo_url` → sidebar brand image

---

## 7. Dashboard Pattern (from index.php)

`dashboard.php` preserves the legacy admin dashboard structure:

1. **Session-cached metrics** (120s TTL) — avoids repeated heavy queries
2. **Early AJAX exit** — `?ajax=charts` returns JSON before any HTML
3. **KPI card grid** — Bootstrap row/col with `.kpi-card` components
4. **Chart.js lazy load** — deferred CDN script, poll until loaded
5. **Greeting header** — time-based salutation + user first name

Queries use ISP360 views/tables:

- `vw_tenant_dashboard_metrics` for tenant KPIs
- `payments`, `pppoe_sessions`, `hotspot_sessions` for charts
- `vpn_peer_status` for VPN online count (when `vpn.view` granted)

---

## 8. Login Flow (from login.php)

| Step | Legacy | ISP360 |
|------|--------|--------|
| Form | `login.php` POST inline | `login.php` → `login_process.php` |
| Auth query | Hospital `users` + `user_roles` | `users` + `user_roles` + `roles` |
| Failure log | `activity_log` | `login_history` |
| Success log | `activity_log` | `login_history` + `sessions` |
| Permissions | Role-based pages | `$_SESSION['permissions']` array |
| Redirect | Role-specific hospital dashboards | `dashboard.php` |

---

## 9. Menu & RBAC

Sidebar rendered from `includes/menu_config.php`, filtered by `getFilteredMenu()`:

- Each item has optional `permission` key
- VPN section (Phase 7): dropdown with Servers, Peers, Tunnels, Logs
- Super Admin bypasses all `permission_check()` calls

---

## 10. Implementation Checklist

- [x] `includes/config.php`, `db.php`, `auth.php`, `tenant.php`
- [x] `layouts/` shell (app + auth)
- [x] `assets/css/isp360-theme.css`
- [x] `index.php` redirect
- [x] `login.php`, `login_process.php`, `logout.php`
- [x] `dashboard.php` with ISP360 KPIs + Chart.js AJAX
- [x] `includes/menu_config.php` with VPN entries
- [ ] Remaining 160+ root pages (implementation waves)
- [ ] `portal_*` pages with `layouts/portal-*.php` variant

---

## 11. Adding a New Page (e.g. vpn_servers.php)

1. Copy authenticated template from Section 3
2. Set `$page_title` and `require_permission()` for module
3. Use `$pdo->prepare()` with `tenant_id = ?` on all queries
4. Reuse `.kpi-card`, `.chart-card`, DataTables from theme
5. Add AJAX endpoint under `ajax/` with matching permission
6. Register in `menu_config.php` if sidebar link needed

See [WIREGUARD_SPEC.md](WIREGUARD_SPEC.md) Section 9 for VPN-specific page and AJAX mapping.
