# Admin Chrome & Content-List View Affordances

> **Status (2026-05-17):** ✅ Implemented.
>
> **What it covers:** Three related changes to make it easier for an admin to bounce between admin and public surfaces:
>
> 1. A **View** button on every row of every Content admin DataTable, opening that record's public view page in a new tab.
> 2. A **"View Front Website"** button in the admin topbar, replacing the previously-dead search box.
> 3. A reusable **user avatar partial** (`_user_avatar.blade.php`) that shows `users.image` when set, else a 2-letter initials badge (Rahul Agrawal → "RA"). Sidebar no longer carries its own user dropdown — Change Password + Log out remain in the topbar avatar menu only.

---

## Why this exists

Admin lists give a row count and the structural columns (title, year, category, etc.) but no preview of how the entry renders on the public site. Without a quick way to jump to the rendered output, admins had to manually construct URLs like `/user/view/<type>/<id>` or guess the type slug.

The public route `Route::get('/view/{type}/{id}', …)->name('user.item.view')` (in `routes/web.php`) is gated by `auth` middleware only — it does not require a separate "user" role — so an admin who is already logged in can hit it directly. No extra route or middleware change was needed.

---

## Type-slug mapping

The slugs must match the `switch ($type)` in `UserController@viewItem` (around line 1370 of `app/Http/Controllers/User/UserController.php`).

| Admin module | Controller slug used | Public URL pattern |
|---|---|---|
| Articles          | `article`            | `/user/view/article/{id}` |
| Circulars         | `circular`           | `/user/view/circular/{id}` |
| Amendments        | `amendment`          | `/user/view/amendment/{id}` |
| Samasyas          | `samasya_samadhan`   | `/user/view/samasya_samadhan/{id}` |
| Research Articles | `research_article`   | `/user/view/research_article/{id}` |
| Journals          | `judgement`          | `/user/view/judgement/{id}` |

Two slugs are easy to get wrong if you copy-paste:

- **Samasyas** uses `samasya_samadhan` (with the `_samadhan` suffix), not just `samasya`.
- **Journals** uses `judgement` (the user-facing label), not `journal`. This is the same Journals/Judgements terminology split documented in `journals-admin-plan.md` §1.

---

## Implementation pattern

In each Content controller's `getDataTable()`, the action-cell builder gained one new variable just before the existing Edit + Delete buttons:

```php
$viewUrl = route('user.item.view', ['type' => '<slug>', 'id' => $item->id]);
$viewBtn = '<a href="' . $viewUrl . '" target="_blank" rel="noopener" '
         . 'class="btn btn-sm btn-outline-info" title="View public page">'
         . '<i class="fas fa-eye"></i></a>';
```

And the row's action cell:

```php
$viewBtn . ' ' . $editBtn . ' ' . $delBtn,
```

The existing Edit button picked up an extra `ms-1` class so the three buttons space evenly.

### Why `target="_blank" rel="noopener"`

- `target="_blank"` keeps the admin list intact while the rendered page opens in a new tab — admins typically want to bounce between admin and public quickly.
- `rel="noopener"` blocks the opened tab from accessing `window.opener` (the standard "reverse tabnabbing" mitigation). Cheap habit; always pair with `target="_blank"`.

---

## Files changed

### Per-row View button (controllers)

All under `app/Http/Controllers/Admin/`:

- `ArticleController.php`
- `CircularController.php`
- `AmendmentController.php`
- `SamasyaController.php`
- `ResearchArticleController.php`
- `JournalController.php`

No model, view, route, or migration changes were needed for the per-row buttons.

### Topbar & sidebar chrome (partials)

- **`resources/views/admin/partials/topbar.blade.php`** — removed the previously-dead search input/button (the input had no submit handler and no backend endpoint); replaced with a "**View Front Website**" link button that opens `route('welcome')` in a new tab. Same `target="_blank" rel="noopener"` defensive pair used by the per-row View buttons. The button uses a scoped `.btn-view-front` class (inline `<style>` block at the top of the partial) — pill shape, **solid primary fill** (`var(--bs-primary, #3b7ddd)` — no gradient), soft shadow, +1px lift on hover. Hidden below the `sm` Bootstrap breakpoint so it doesn't crowd the mobile nav. The avatar `<img>` was also swapped for the new `_user_avatar` partial (36px).
- **`resources/views/admin/partials/sidebar.blade.php`** — removed the duplicate user dropdown (Change Password / Log out already lived in the topbar avatar menu). The sidebar user block is now just the avatar + plain-text name + plain-text "Super Admin" subtitle. Avatar uses `_user_avatar` (40px).
- **`resources/views/admin/partials/_user_avatar.blade.php`** *(new)* — reusable avatar block. Renders `<img src="{{ asset($user->image) }}">` when `$user->image` is non-empty; otherwise renders a circular initials badge (first letter of up to 2 whitespace-separated words in `$user->name`, uppercased — `mb_substr`/`mb_strtoupper` so non-ASCII names are safe). Accepts `$user`, `$size`, `$classes` overrides; defaults to the auth user / 40px / no extra classes. Background colour is AdminKit's `#3b7ddd`.

---

## Verification

| Check | Result |
|---|---|
| `php -l` on all 6 modified controllers | No syntax errors. |
| Slug verification against `UserController@viewItem` switch | All 6 match. |
| Topbar Blade compile + render | OK; no `placeholder="Search…"` left in output; `"View Front Website"` text present. |
| `_user_avatar` partial — 4 case test (no-image RA/A/RK; with-image renders `<img>`) | All 4 cases pass. |

**Not verified — needs browser session:**

- Clicking the per-row View button on each Content list opens the correct public page in a new tab.
- Topbar "View Front Website" button opens `/` in a new tab.
- Sidebar / topbar avatars show "SA" initials for the seeded super admin (no `users.image` set).
- The public view pages render for an admin session (the `auth` middleware should accept any logged-in user).

---

## Cross-references

The per-module plan docs that cover the admin lists where this button now appears:

- `circulars-admin-plan.md`
- `amendments-admin-plan.md`
- `samasyas-admin-plan.md`
- `research-articles-admin-plan.md`
- `journals-admin-plan.md`
- (Articles is documented in the master `backendwork.md`.)

Each of those has a one-line reference pointing back to this doc, so future readers find the type-slug mapping in one place.
