@extends('layouts.dashboard')
@section('content')
@php
use App\Models\Order;
/**
* Admin → Users → one account. A read-only drill-down whose lower panel adapts
* to the user's role. Built entirely from shared dashboard components
* (.qm-card / kpi-card / .qm-table / role_pill) — no bespoke markup.
*
* @var array $user the account row (password/PIN hashes already stripped by the controller)
* @var array $panel role-scoped data assembled in UserController::show()
* @var bool $pinSet whether this account carries a screen-lock PIN
* @var array $activity the platform audit trail for what THIS account did
* @var array $statusHistory what admins have done TO this account, and who did it
* @var array $activityPager pager for the audit trail
* @var array $historyPager pager for the account history
*
* Every table here is a page of its own set, not a fixed excerpt: each carries its own
* pager key so resizing or paging one panel leaves the others exactly where they were.
*/
$role = (string) $user['role'];
$status = (string) $user['status'];
$statusPill = ['active' => 'qm-pill-green', 'pending' => 'qm-pill-amber', 'suspended' => 'qm-pill-red'][$status] ?? 'qm-pill-grey';
$payPill = ['paid' => 'qm-pill-green', 'unpaid' => 'qm-pill-grey', 'refunded' => 'qm-pill-red'];
$pinSet = $pinSet ?? false;
$activity = $activity ?? [];
$statusHistory = $statusHistory ?? [];
$activityPager = $activityPager ?? [];
$historyPager = $historyPager ?? [];
// The roles that belong to one restaurant, read from the roles table so a role created
// on the Roles screen behaves like a shipped one on this page too. The driver is a staff
// role now, so staffSlugs() already covers it (was staff + driver via teamSlugs).
$staffRoles = \App\Models\Role::staffSlugs();
$isSelf = (int) $user['id'] === (int) \App\Support\Auth::id();
@endphp
@php /* .qm-d2: the dashboard density standard (app.css §35) */
@endphp
@php /* The account's identity wears the same hero the restaurant profile
wears: brand-wash band (avatar, name, pills — support levers on the
right) over the facts as one measured stat band. */
@endphp
@php /* Same detail-header language as the restaurant page: divided fact rail
closing on a solid call to action. Users carry no cover image. */
@endphp
{!! brandmark_html($user['avatar'] ?? null, (string) $user['name'], 'lg', 'qm-brandmark--round') !!}
{{ $user['name'] }}
{!! role_pill($role) !!}
{{ status_label('user', $status) }}
@php /* Support levers. Suspend/activate gates the account; the other two are the
recovery actions a support agent reaches for without touching the password:
end every session the account holds, and clear a forgotten screen-lock PIN. */
@endphp
@php // Support impersonation. Offered only for accounts that can actually be
// adopted: never another super admin, never yourself, never a suspended
// account (Auth::impersonate() refuses all three server-side too).
@endphp
@if (!$isSelf && in_array($role, $staffRoles, true) && $pinSet)
@endif
@if (!$isSelf)
@endif
@if ($role !== 'super_admin' && !$isSelf)
@endif
- {{ t_raw('common.email') }}
- {{ $user['email'] }}
- {{ t_raw('common.phone') }}
- {!! or_dash($user['phone'] ?? null) !!}
- {{ t_raw('admin.userdetail.member_since') }}
- {!! fmt_day($user['created_at']) !!}
- {{ t_raw('admin.userdetail.last_updated') }}
- {!! fmt_day($user['updated_at']) !!}
@php /* The one thing an admin comes here to DO closes the rail, exactly as
"Open vendor dashboard" closes the restaurant header's. */
@endphp
@if (!$isSelf && $role !== 'super_admin' && $status === 'active')
@endif
@php
// -------- Role-specific panel --------
$renderRestaurantCard = static function (?array $rest): string {
if (!$rest) {
return '
' . t('admin.userdetail.no_restaurant') . '
';
}
$statusMap = ['approved' => 'qm-pill-green', 'pending' => 'qm-pill-amber', 'suspended' => 'qm-pill-red'];
ob_start();
@endphp
{{ t_raw('admin.userdetail.restaurant') }}
{!! restaurant_logo_html($rest, 'md', 'qm-brandmark--round') !!}
{{ $rest['name'] }}
@if (!empty($rest['city'])){{ $rest['city'] }}@endif
@php return (string) ob_get_clean();
};
@endphp
@if ($role === 'vendor')
@partial('kpi-card', ['accent' => 'blue', 'icon' => 'fa-receipt', 'label' => t_raw('admin.userdetail.kpi_orders'), 'value' => number_format((int) ($panel['orders_c'] ?? 0))])
@partial('kpi-card', ['accent' => 'green', 'icon' => 'fa-money-bill-wave', 'label' => t_raw('admin.userdetail.kpi_revenue'), 'value' => money($panel['collected'] ?? 0)])
{!! $renderRestaurantCard($panel['restaurant'] ?? null) !!}
@php // Floor staff (driver excluded — its richer delivery panel is the `driver` branch below,
// which isStaff() would otherwise shadow now that the rider is a staff role).
@endphp
@elseif (\App\Models\Role::worksVendorDashboard($role))
{{ t_raw('admin.userdetail.access_pin') }}
{!! !empty($panel['pin_set']) ? t('admin.userdetail.pin_set') : t('admin.userdetail.pin_unset') !!}
{!! $renderRestaurantCard($panel['restaurant'] ?? null) !!}
@elseif ($role === 'customer')
@partial('kpi-card', ['accent' => 'blue', 'icon' => 'fa-receipt', 'label' => t_raw('admin.userdetail.kpi_orders'), 'value' => number_format((int) ($panel['orders_c'] ?? 0))])
@partial('kpi-card', ['accent' => 'green', 'icon' => 'fa-wallet', 'label' => t_raw('admin.userdetail.kpi_spent'), 'value' => money($panel['spent'] ?? 0)])
@partial('kpi-card', ['accent' => 'amber', 'icon' => 'fa-star', 'label' => t_raw('admin.userdetail.kpi_reviews'), 'value' => number_format((int) ($panel['reviews_c'] ?? 0))])
{{ t_raw('admin.userdetail.recent_orders') }}
| {{ t_raw('admin.dashboard.col_order') }} | {{ t_raw('common.status') }} | {{ t_raw('admin.orders.col_payment') }} | {{ t_raw('admin.orders.col_total') }} | {{ t_raw('admin.orders.col_placed') }} |
@if (!empty($panel['orders']))
@foreach ($panel['orders'] as $o)
| {{ $o['order_number'] }} |
{{ Order::statusLabel((string) $o['status']) }} |
{{ t_raw('status.payment.' . $o['payment_status']) }} |
{{ money($o['total']) }} |
{!! fmt_datetime($o['placed_at']) !!} |
@endforeach
@else
@partial('table-empty', ['colspan' => 5, 'icon' => 'fa-receipt', 'msg' => t('admin.userdetail.no_orders')])
@endif
@partial('table-toolbar', ['pager' => $panel['orders_pager'] ?? []])
{{ t_raw('admin.userdetail.recent_reviews') }}
| {{ t_raw('admin.userdetail.col_restaurant') }} | {{ t_raw('common.rating') }} | {{ t_raw('common.status') }} | {{ t_raw('admin.reviews.col_posted') }} |
@if (!empty($panel['reviews']))
@foreach ($panel['reviews'] as $rv)
| {{ $rv['restaurant_name'] ?? t_raw('admin.reviews.deleted_restaurant') }} |
{!! rating_stars_html((float) (int) $rv['rating']) !!} |
{{ status_label('review', (string) $rv['status']) }} |
{!! fmt_day($rv['created_at']) !!} |
@endforeach
@else
@partial('table-empty', ['colspan' => 4, 'icon' => 'fa-star', 'msg' => t('admin.userdetail.no_reviews')])
@endif
@partial('table-toolbar', ['pager' => $panel['reviews_pager'] ?? []])
@elseif ($role === 'driver')
@partial('kpi-card', ['accent' => 'blue', 'icon' => 'fa-motorcycle', 'label' => t_raw('admin.userdetail.kpi_assigned'), 'value' => number_format((int) ($panel['assigned'] ?? 0))])
@partial('kpi-card', ['accent' => 'green', 'icon' => 'fa-check-circle', 'label' => t_raw('admin.userdetail.kpi_delivered'), 'value' => number_format((int) ($panel['delivered'] ?? 0))])
{{ t_raw('admin.userdetail.access_pin') }}
{!! !empty($panel['pin_set']) ? t('admin.userdetail.pin_set') : t('admin.userdetail.pin_unset') !!}
{!! $renderRestaurantCard($panel['restaurant'] ?? null) !!}
{{ t_raw('admin.userdetail.recent_deliveries') }}
| {{ t_raw('admin.dashboard.col_order') }} | {{ t_raw('admin.userdetail.col_restaurant') }} | {{ t_raw('common.status') }} | {{ t_raw('admin.orders.col_total') }} | {{ t_raw('admin.orders.col_placed') }} |
@if (!empty($panel['orders']))
@foreach ($panel['orders'] as $o)
| {{ $o['order_number'] }} |
{!! or_dash($o['restaurant_name'] ?? null) !!} |
{{ Order::statusLabel((string) $o['status']) }} |
{{ money($o['total']) }} |
{!! fmt_datetime($o['placed_at']) !!} |
@endforeach
@else
@partial('table-empty', ['colspan' => 5, 'icon' => 'fa-motorcycle', 'msg' => t('admin.userdetail.no_orders')])
@endif
@partial('table-toolbar', ['pager' => $panel['orders_pager'] ?? []])
@endif
@php /* Two halves of the same question a support agent opens a record to answer:
what this account has been doing, and what has been done to it. */
@endphp
| {{ t_raw('admin.restaurantdetail.col_action') }} | {{ t_raw('common.description') }} | {{ t_raw('admin.userdetail.col_ip') }} | {{ t_raw('common.when') }} |
@if ($activity)
@foreach ($activity as $a)
| {{ activity_label((string) $a['action']) }} |
{!! or_dash($a['detail'] ?? null) !!} |
{!! or_dash($a['ip'] ?? null) !!} |
{{ time_ago($a['created_at']) }} |
@endforeach
@else
@partial('table-empty', ['colspan' => 4, 'icon' => 'fa-clipboard-list', 'msg' => t('admin.userdetail.no_activity')])
@endif
@partial('table-toolbar', ['pager' => $activityPager])
{{ t_raw('admin.userdetail.sec_account_history') }}
| {{ t_raw('admin.restaurantdetail.col_action') }} | {{ t_raw('admin.userdetail.col_change') }} | {{ t_raw('admin.restaurantdetail.col_by') }} | {{ t_raw('common.description') }} | {{ t_raw('common.when') }} |
@if ($statusHistory)
@foreach ($statusHistory as $h)
| {{ activity_label((string) $h['action']) }} |
@php // Only a genuine status transition has a before and after to show.
@endphp
@if (!empty($h['new_status']))
{!! or_dash($h['old_status'] ?? null) !!} → {{ (string) $h['new_status'] }}
@else{!! dash() !!}@endif
|
@if (!empty($h['changed_by_name']))
{!! brandmark_html($h['changed_by_avatar'] ?? null, (string) $h['changed_by_name'], 'sm', 'qm-brandmark--round') !!}
{{ $h['changed_by_name'] }}
@else{!! dash() !!}@endif
|
{!! or_dash($h['detail'] ?? null) !!} |
{{ time_ago($h['created_at']) }} |
@endforeach
@else
@partial('table-empty', ['colspan' => 5, 'icon' => 'fa-user-shield', 'msg' => t('admin.userdetail.no_account_history')])
@endif
@partial('table-toolbar', ['pager' => $historyPager])
@php /* /.qm-d2 */
@endphp
@endsection