# 14 — System review 1: admin, website and doctor dashboard fixes

Source: `notes/sysytem_review1.md` (admin items 1–15, website items 1–11, doctor dashboard items 1–2).
Item numbers below keep the note's numbering (A = admin, W = website, D = doctor dashboard).

Status: **plan confirmed 2026-09-28** (D1, D3, D4, D8 answered by the user; the rest use the recommended option).

Build progress (2026-09-29): Tracks A–E done (tasks 1–28, one commit each). Notes:
- Task 22 (Google logo on testimonials) shipped with task 14; task 23 (blog card category) already existed;
  task 25 (specialty image) already existed in the form — no change.
- Extra fixes found on the way: gallery form could never save, several upload paths (banner, city, feedback)
  never displayed, empty countries table blocked cities (Egypt added), site used toastr it never loaded,
  RTL `.position-center` / search popup offsets, ImageProcessing now writes through the images disk.
- Done after that (2026-09-29): E2 server-side clinic lists (doctors, patients, staff, bookings, follow-ups);
  E3 medicine delivery orders; clinic sidebar rebuild; Track F reports (doctor account, clinic/branch profit,
  revenue, statistics, CSV export); Track H doctor visit page + bookings calendar; Track I offer subscriptions
  linked to the logged-in account (task 36) and paid online on the placeholder gateway (task 37:
  `site_offer_subscriptions.payment_status` pending_payment → paid / failed, admin payment column + filter,
  paid subscriptions in the revenue report).
- Fixed on the way: website login/register redirected to a removed `profile` route (500 after login).
- Known failing tests (not from this round): the old storefront tests (cart, wishlist, checkout, profile)
  whose pages were removed in the site rebuild, and `dashboard_route_loads_for_authorized_admin`.
- **Plan 14 complete.** Next: plan 15 (light CRM, D8).

---

## 1. What exists today (checked in the code, 2026-09-28)

| Item | Page / code | Finding |
|---|---|---|
| A1 users list | `Admin\Users\UsersController@index` | Already a yajra server-side table. Role column reads the old `admins.group_name → roles` link (`Admin::role()`), not the Spatie role, so it is often empty or wrong |
| A2 users create | `users/create.blade.php` | Role select lists `App\Models\Roles::all()` and prints `title`. **All 4 roles have `title = null`**, so the options are blank. Super Admin is listed. No JsValidator, no test |
| A3 permissions | `PermissionsController@index` → `permissions.blade.php:268` | Loads all **417** permissions and renders one edit modal per row. **17 permissions have `title = null`** → `$title['en']` crashes |
| A4 main data video | `site_data.video` column **already exists** | Not in the Main Data form, not shown on the home page |
| A5 blog | `Admin\Site\BlogController` | Server-side table exists. `site_blogs` has **no status column**. Show page exists (`details-new`) |
| A6 banner | `admin/banner` → `Site\BannerController` → `site_banners` | **The website does not read `site_banners`**; it reads `clinic_banners` (managed at `admin/clinic/banners`). Two banner menus in the sidebar |
| A6 statistics | `site_statistics` (`number`, `title`) | No icon column. Shown on the About page |
| A6 feedback, gallery, polices, city | `Admin\Site\*`, `Admin\settings\CityController` | Server-side tables exist; forms have no JsValidator; details open as separate pages, not modals |
| A7 settings links | sidebar lines 420 / 428 | Links to `core.settings.index` and `core.settings.manage.index` |
| A8 specialty image | `specialties/partials/form.blade.php`, `SpecialtyService` | **`photo` and `icon` uploads already exist** (`photo_path`, `icon_path`). The gap is on the website (W4) |
| A9 doctor details | `Admin\Clinic\DoctorController` | **No show page** (index/create/edit/schedule only). `clinic_bookings.doctor_share_amount` exists for the money tab. Ratings in `clinic_reviews.doctor_rating` |
| A10 patient details | `patients/show.blade.php` (179 lines) | Single page, no tabs |
| A11 CRM | — | Nothing exists. Lead sources we already store: `site_contacts`, `site_offer_subscriptions`, service requests, patients without bookings |
| A12 notifications | `Admin\System\NotificationController` | Paginated Blade list; mark-read is a `PATCH` form with a full page reload |
| A14 reports | `admin/clinic/reports` → `ClinicReportService::getReport()` | One report page. `clinic_bookings` has `price`, `doctor_share_amount`, `center_share_amount`, `type` (`visit`/`online`/`followup`) |
| A15 sidebar | `dashboard/admin/layouts/main-sidebar.blade.php` (926 lines) | Keenicons font is bundled but lacks some names (`ki-hospital`, `ki-stethoscope`, `ki-profile-user`), see plan 13 |
| W1 sweetalert | `web_site/partials/alerts.blade.php` | Bootstrap alerts + a hidden toast span; no SweetAlert on the site |
| W2 offer payment | `BookingPaymentService` | Gateways are **simulated hosted-redirect placeholders** (no real gateway call yet) |
| W5 doctor card | `partials/doctor-card.blade.php` | Card already prints branch and rating, but the home page's "Our Doctors" query loads only `specialty` (no `clinics.branch`, no reviews), so they stay hidden |
| W6 offer price | `clinic_offers` | Only `discount_type` + `discount_value`; **no original price** to show "old price" |
| W7 feedback | `site_feedbacks` (`image`, `name`, `jop_title`, `feedback`) | No source field |
| W8 blog category | `SiteBlog` with `category` is already eager-loaded on home | Card partial does not print it |
| W9–W10 search | header popup form → `clinic.search?q=` | Popup styles are LTR-only; search only searches doctors |
| W11 background | `public/assets_web/img/bg-shape-2.jpg` exists | "Why Choose" section has no background div |
| D1 visit page | `doctor/visits/show.blade.php` | Shows part of the booking; attachments and history not all shown |
| D2 calendar | `doctor/dashboard.blade.php` (96 lines) | FullCalendar is bundled at `assets/plugins/custom/fullcalendar/` |

Existing patterns to reuse: yajra `DataTables::of()` (UsersController, Site controllers), `JsValidator::formRequest()`
(clinic create/edit views), `show_load/{id}` routes already exist for banner/statistics/feedback/gallery/polices
(reuse them for the modal content), `ClinicBranchScope` for branch-scoped admins.

---

## 2. Tracks and tasks (one commit per task)

### Track A — bugs and quick fixes (do first)

1. **A3 permissions page crash** — null-safe titles (`$title['en'] ?? $x->name`) and a migration that fills the
   17 empty titles (en from the permission name, ar from the same labels used by the seeder).
2. **W5 doctor card** — eager-load `clinics.branch` and the average rating in the home "Our Doctors" query; show
   the rating even when it is 0 as "new" (see D10).
3. **A7 sidebar** — remove the two Settings links. Routes stay (other screens and tests use them).
4. **W9 search box in Arabic** — RTL styles for the popup search (input direction, close button and icon sides).
5. **W11 "Why Choose" background** — add the `bg-box-shape2` div with `bg-shape-2.jpg`.

### Track B — user management

6. **A1 users table** — role column from Spatie roles (`$admin->roles`), server-side search/sort on name, email,
   role, branch, status; role filter above the table.
7. **A2 users create/edit** — rebuild the form (two-column card like the clinic forms), JsValidator on
   `AdminStoreRequest`/`AdminUpdateRequest`, role select shows Spatie roles with a readable label
   (`title` → fallback to a translated name), **Super Admin hidden** and also rejected in the request.
   Fill `roles.title` (ar/en) with a migration.
8. **A3 permissions page rebuild** — server-side table (name, title, group, guard, roles count) + one shared
   edit modal loaded by AJAX instead of 417 inline modals.
9. **Tests** — `tests/Feature/Admin/UserManagementTest.php`: list JSON has role, create page lists roles without
   Super Admin, posting Super Admin is refused, create/update succeed, permissions page loads with a null title.

### Track C — website content admin

10. **A4 main data video** — upload field (mp4/webm, size limit) + optional YouTube URL (see D6), preview, delete.
11. **A5 blog** — migration `site_blogs.is_active` (default true); table columns: image, title, category,
    status badge with an AJAX toggle, date; create/edit rebuilt with JsValidator; details page reviewed.
    Website shows active blogs only.
12. **A6 banner** — rebuild `admin/banner` (`site_banners`): server-side table, create/edit with JsValidator,
    details modal, active toggle, sort order. Switch the website hero (`Site\MainController@home`) to read
    active `site_banners` ordered by `sort_order`. `admin/clinic/banners` stays for the **mobile app** (the API's
    `HomeService::banners()` reads `clinic_banners`) and is relabelled "بنرات التطبيق" in the sidebar.
13. **A6 statistics** — migration `site_statistics.icon` (see D5), form + JsValidator, details modal; icon shown
    on the website.
14. **A6 feedback** — migration `site_feedbacks.source` (`manual`/`google`) + optional `rating` (see D7), form +
    JsValidator, details modal.
15. **A6 gallery** — form + JsValidator, details modal (images grid).
16. **A6 polices** — form + JsValidator (details already exist).
17. **A6 city** — form + JsValidator.

A shared piece first: `dashboard/admin/partials/_details_modal.blade.php` + a small JS helper that loads a
`show_load` URL into the modal, so tasks 12–15 only supply the inner view.

### Track D — website

18. **W1 SweetAlert** — show `session('success')`/`session('error')` and validation errors through SweetAlert2
    on every site form (layout-level, one include). Check the bundle exists in `assets_web`; add it if not.
19. **W3 about video** — home About section plays the uploaded video (or YouTube embed) when set, image otherwise.
20. **W4 specialty images** — "Our Doctors" tabs show each specialty's icon/photo.
21. **W6 offer card prices** — old price struck through + new price (depends on D3).
22. **W7 feedback card** — Google logo on cards whose source is `google`.
23. **W8 blog card** — category badge when set.
24. **W10 search** — one search page with tabs for doctors, specialties, services, offers and blogs
    (name/title in both languages), keeps the current doctor filters.

### Track E — clinic admin screens

25. **A8 specialty image** — already in the form; only check the preview on edit and the website use (task 20).
26. **A9 doctor details page** — new `doctors/{doctor}` route + view with tabs: main data, clinics & schedule,
    ratings (average + list of reviews), bookings (server-side table, visit/followup), online bookings, account
    (period filter; per booking: price, doctor share, center share; totals).
27. **A10 patient details rebuild** — tabs: main data, medical profile (history/allergies), bookings, visits and
    medical records, attachments, payments, offer subscriptions, reviews.
28. **A12 notifications** — server-side table, mark one / mark all read via AJAX (JSON response), table reloads,
    bell counter updates.

### Track E2 — server-side clinic lists (added 2026-09-29)

28a. **Doctors** list (`admin/clinic/doctors`) — server-side table, search, specialty/status/branch filters.
28b. **Patients** list (`admin/clinic/patients`).
28c. **Staff** list (`admin/clinic/staff`).
28d. **Bookings** list (`admin/clinic/bookings`) — keeps the existing status and `?date=` filters.
28e. **Follow-ups** list (`admin/clinic/followups`).

All keep branch scoping and the current permissions.

### Track E3 — medicine delivery orders (added 2026-09-29)

28f. **طلبات صرف الدواء** — staff enter a request after a visit (patient, optional visit, prescription photo
     and/or text, delivery phone/address defaulting to the patient's), then complete it: status
     جاري / تم التحضير / تم التسليم and amounts, total = net medicine cost + center % of it + delivery cost.
     Decisions (user, 2026-09-29): staff-only entry (no website/app form), center share is a percentage.
     Table `clinic_medicine_orders` (branch scoped), permissions `clinic.medicine_orders.*`.

### Track F — sidebar (A15)

29. **Clinic sidebar rebuild** — group the clinic flow into sections (Dashboard · Bookings & Followups ·
    Patients · Doctors & Schedules · Clinics, Specialties, Pricing · Offers & Subscriptions · Reviews · Reports
    · Website content), keenicons duotone per item (names checked against the bundled font), accordion groups
    that open on the active page, count badges (pending bookings, new offer subscriptions, unread contacts),
    permission-gated like today. Move the site-content links under one "Website" group.

### Track G — reports (A14)

New "Reports" group in the sidebar, each report a page with filters, totals, table, Excel/print.

30. **Doctor account** — doctor + date range → all bookings of every type, price, doctor share, center share,
    totals per type.
31. **Clinic / branch profit** — branch + clinic + date range → revenue, doctor shares, center share (profit),
    by clinic and by doctor.
32. **Revenue** — branch/clinic + range → revenue by booking type and offer subscriptions (subscriptions only
    once they have a paid amount, see D4).
33. **Management statistics** — one page with a period filter and cards + charts: bookings, payments and revenue,
    clinic and doctor performance, ratings and comments, completed vs cancelled, online video consultations,
    patient inquiries (site contacts + chat) and replies, clinic activity.

Revenue definition stays the one agreed in plan 13: `sum(price)` of `confirmed` + `completed` bookings.
All reports respect branch scoping and `clinic.reports.view`.

### Track H — doctor dashboard

34. **D1 visit page** — show every booking field, patient profile and medical history, previous visits, booking
    attachments and patient attachments (download/preview), payment status.
35. **D2 calendar on home** — FullCalendar (month/week/day) fed by a JSON endpoint of the doctor's bookings,
    colored by status, click opens the visit page.

### Track I — offer subscription with payment (W2, after D4)

36. Logged-in users: subscription form pre-filled from their account and linked to `user_id`.
37. Payment step through the same placeholder gateway flow bookings use (real gateway later), subscription
    status `pending_payment` → `paid`; admin list shows payment status.

### Track J — CRM (A11)

Separate plan (`15-crm-plan.md`) once D8 is answered; not built in this round.

---

## 3. Decisions to confirm

| # | Question | Recommended |
|---|---|---|
| D1 | Two banner admins: `admin/banner` (`site_banners`, not used by the website) and `admin/clinic/banners` (used) | **Chosen: site banners.** Rebuild `admin/banner` and point the website at `site_banners`; clinic banners remain the mobile app's banners |
| D2 | Who can see/assign Super Admin in the user form | Hidden for everyone and refused by the request; Super Admin accounts are managed by seeder/DB only |
| D3 | Offer "old price" source | **Chosen:** new column `clinic_offers.original_price`; new price = original − discount |
| D4 | Offer payment (W2) | **Chosen:** build the flow on the placeholder gateway now (same as bookings), real gateway later |
| D5 | Statistics icon | Image upload (SVG/PNG), like specialty icons |
| D6 | About video | Upload file **or** YouTube link (whichever is set) |
| D7 | "Image of Google" on feedback | `source` field; Google logo shown on Google reviews only |
| D8 | CRM scope | **Chosen:** light CRM: leads from contacts / offer subscriptions / service requests, pipeline status, assignee, notes and follow-up dates, convert to patient + booking. Separate plan |
| D9 | Order of work | Tracks A → B → C → D → E → F → G → H → I, one commit per task |
| D10 | Doctor with no reviews on the card | Show "جديد" instead of hiding the rating |
