@extends('layouts.master')
@section('title')
{{ __('Requester Dashboard') }}
@endsection
@section('css')
@endsection
@section('content')
@component('components.breadcrumb')
@slot('li_1') {{ __('Requester') }} @endslot
@slot('title') {{ __('Dashboard') }} @endslot
@endcomponent
@php
$viewerId = (int) (Auth::id() ?? 0);
$viewerRole = (string) (Auth::user()->role ?? '');
$viewerOrganization = strtolower(trim((string) (Auth::user()->organization_name ?? '')));
$canReviewDocument = \App\Support\WorkflowPermission::canUseAdminPermission($viewerRole, \App\Support\WorkflowPermission::ADMIN_PERMISSION_REVIEW_DOCUMENT);
$canRequestDocument = \App\Support\WorkflowPermission::canUseAdminPermission($viewerRole, \App\Support\WorkflowPermission::ADMIN_PERMISSION_REQUEST_DOCUMENT);
$isSentBackByViewer = function ($request) use ($viewerId) {
$latestHistory = $request->latestHistory;
return (string) ($latestHistory?->action ?? '') === \App\Support\WorkflowPermission::ACTION_REQUEST_REVISION
&& $viewerId > 0
&& (int) ($latestHistory?->actor_user_id ?? 0) === $viewerId;
};
$isRequesterSideCorrection = function ($request) use ($viewerId) {
$latestHistory = $request->latestHistory;
$latestMeta = is_array($latestHistory?->meta) ? $latestHistory->meta : [];
$targetType = strtolower(trim((string) data_get($latestMeta, 'sent_back_target_type', '')));
$targetStepOrder = (int) data_get($latestMeta, 'sent_back_selected_target_step_order', 0);
$targetUserId = (int) data_get(
$latestMeta,
'sent_back_to_user_id',
data_get($latestMeta, 'sent_back_selected_target_user_id', 0)
);
$isRequesterTarget = in_array($targetType, ['requester', 'user'], true)
|| ($targetType === '' && $targetStepOrder <= 0 && $targetUserId === $viewerId);
return (string) ($latestHistory?->action ?? '') === \App\Support\WorkflowPermission::ACTION_REQUEST_REVISION
&& (int) ($request->user_id ?? 0) === $viewerId
&& $targetStepOrder <= 0
&& $isRequesterTarget
&& ($targetUserId === 0 || $targetUserId === $viewerId);
};
$workStatusFor = function ($request) use ($viewerRole, $viewerId, $isRequesterSideCorrection, $isSentBackByViewer) {
if ($isSentBackByViewer($request)) {
return [
'label' => 'Sent Back by You',
'badge' => \App\Support\WorkflowPermission::dashboardStatusBadgeClass('Sent Back by You'),
'title' => '',
];
}
if ($isRequesterSideCorrection($request)) {
return [
'label' => 'In Progress',
'badge' => \App\Support\WorkflowPermission::dashboardStatusBadgeClass('In Progress'),
'title' => '',
];
}
return \App\Support\WorkflowPermission::dashboardStatus($request, $viewerRole, $viewerId);
};
$requestStatusFor = function ($request) use ($viewerId) {
$status = \App\Support\WorkflowPermission::dashboardStatus($request, \App\Support\WorkflowPermission::ROLE_REQUESTER, $viewerId);
if (!in_array($status['label'], ['Sent Back to You', 'Completed', 'Rejected'], true)) {
$status['label'] = 'In Progress';
$status['badge'] = \App\Support\WorkflowPermission::dashboardStatusBadgeClass('In Progress');
$status['title'] = '';
}
return $status;
};
$personalRequests = $requests->filter(fn ($request) => (int) ($request->user_id ?? 0) === $viewerId)->values();
$workflowStepsFor = function ($request): array {
$steps = $request->workflow_steps_override;
if (!is_array($steps) || count($steps) === 0) {
$templateSteps = $request->workflowTemplate?->steps ?? [];
if (is_string($templateSteps)) {
$decoded = json_decode($templateSteps, true);
$templateSteps = is_array($decoded) ? $decoded : [];
}
$steps = is_array($templateSteps) ? $templateSteps : [];
}
return collect($steps)
->filter(fn ($step) => is_array($step))
->sortBy(fn ($step) => (int) ($step['order'] ?? 0))
->values()
->all();
};
$workflowIncludesViewerReviewStage = function ($request) use ($viewerId, $viewerRole, $viewerOrganization, $workflowStepsFor): bool {
$viewerRoleKey = \App\Support\WorkflowPermission::normalizeRole($viewerRole);
return collect($workflowStepsFor($request))->contains(function ($step) use ($viewerId, $viewerRoleKey, $viewerOrganization) {
$permissionType = strtolower(trim((string) ($step['permission_type'] ?? '')));
$stepType = strtolower(trim((string) ($step['step_type'] ?? '')));
$actorRole = \App\Support\WorkflowPermission::normalizeRole((string) ($step['actor_role'] ?? ''));
$stepOrganization = strtolower(trim((string) ($step['organization_name'] ?? $step['office_name'] ?? '')));
$assignedUserId = (int) ($step['rector_user_id'] ?? $step['assigned_user_id'] ?? 0);
$isReviewOrApprovalStage = in_array($permissionType, ['reviewer', 'approver'], true)
|| in_array($stepType, ['organization', 'office', 'vice_rector', 'approval'], true)
|| in_array($actorRole, [
\App\Support\WorkflowPermission::ROLE_RECTOR,
\App\Support\WorkflowPermission::ROLE_VICE_RECTOR,
], true);
if (!$isReviewOrApprovalStage) {
return false;
}
if ($viewerOrganization !== '' && $stepOrganization !== '' && $stepOrganization === $viewerOrganization) {
return true;
}
if ($viewerId > 0 && $assignedUserId === $viewerId) {
return true;
}
return $assignedUserId <= 0
&& $viewerRoleKey !== ''
&& $actorRole !== ''
&& $actorRole === $viewerRoleKey;
});
};
$workRequests = $canReviewDocument
? $requests->filter(function ($request) use ($isRequesterSideCorrection, $isSentBackByViewer, $workflowIncludesViewerReviewStage) {
if ($isRequesterSideCorrection($request) && !$isSentBackByViewer($request)) {
return false;
}
return $workflowIncludesViewerReviewStage($request);
})->values()
: collect();
$hasDashboardTabs = $canReviewDocument && $canRequestDocument;
$requestedDashboardTab = (string) request()->query('view', '');
$activeDashboardTab = $hasDashboardTabs
? (in_array($requestedDashboardTab, ['work', 'requests'], true) ? $requestedDashboardTab : 'work')
: ($canReviewDocument ? 'work' : 'requests');
$tableRequests = $activeDashboardTab === 'work' ? $workRequests : $personalRequests;
$dashboardStatusFor = $activeDashboardTab === 'work' ? $workStatusFor : $requestStatusFor;
$tableStatusCounts = $tableRequests
->map(fn ($request) => $dashboardStatusFor($request)['label'])
->countBy();
$tableTitle = $activeDashboardTab === 'work' ? 'Documents for Review' : 'Submitted Documents';
$emptyTableMessage = $activeDashboardTab === 'work'
? 'No work queue documents found.'
: 'No requests submitted yet.';
$rowNewUpdateLabels = [
'Needs Your Review',
'Need Your Decision',
'Returned Back',
'Sent Back to You',
'Sent Back to My Organization',
];
$rowHighlightForView = function ($request, string $view) use (
$viewerRole,
$viewerId,
$workStatusFor,
$requestStatusFor,
$rowNewUpdateLabels
): array {
$status = $view === 'work' ? $workStatusFor($request) : $requestStatusFor($request);
$baseViewerStatus = \App\Support\WorkflowPermission::dashboardStatus($request, $viewerRole, $viewerId);
$isOverdue = \App\Support\WorkflowPermission::isDashboardOverdue($request) && (
$view === 'requests'
|| in_array(
(string) ($baseViewerStatus['label'] ?? ''),
['Needs Your Review', 'Need Your Decision'],
true
)
);
$isNew = (bool) ($request->dashboard_has_unread_update ?? false)
&& in_array((string) ($status['label'] ?? ''), $rowNewUpdateLabels, true);
return [
'overdue' => $isOverdue,
'unread' => $isNew,
'highlighted' => $isOverdue || $isNew,
];
};
$workTabCount = $workRequests
->filter(fn ($request) => $rowHighlightForView($request, 'work')['highlighted'])
->count();
$requestTabCount = $personalRequests
->filter(fn ($request) => $rowHighlightForView($request, 'requests')['highlighted'])
->count();
$activeRowHighlightResolver = fn ($request) => $rowHighlightForView($request, $activeDashboardTab);
$workQueueCards = [
[
'label' => 'Needs Your Review',
'count' => (int) ($tableStatusCounts['Needs Your Review'] ?? 0),
'description' => 'Documents you can act on now',
'icon' => 'ri-file-search-line',
'color' => 'primary',
],
[
'label' => 'Sent Back to My Organization',
'count' => (int) ($tableStatusCounts['Sent Back to My Organization'] ?? 0),
'description' => 'Sent back for revision',
'icon' => 'ri-arrow-go-back-line',
'color' => 'warning',
],
[
'label' => 'Sent Back by You',
'count' => (int) ($tableStatusCounts['Sent Back by You'] ?? 0),
'description' => 'Waiting for the target to return it',
'icon' => 'ri-time-line',
'color' => 'warning',
],
[
'label' => 'Forwarded',
'count' => (int) ($tableStatusCounts['Forwarded'] ?? 0),
'description' => 'Already forwarded to the next step',
'icon' => 'ri-share-forward-line',
'color' => 'success',
],
[
'label' => 'Approved',
'count' => (int) ($tableStatusCounts['Approved'] ?? 0),
'description' => 'Approved documents',
'icon' => 'ri-check-line',
'color' => 'primary',
],
[
'label' => 'Overdue SLA',
'count' => (int) ($tableStatusCounts['Overdue SLA'] ?? 0),
'description' => 'Past SLA time',
'icon' => 'ri-alarm-warning-line',
'color' => 'danger',
],
[
'label' => 'Completed',
'count' => (int) ($tableStatusCounts['Completed'] ?? 0),
'description' => 'Completed work queue documents',
'icon' => 'ri-check-double-line',
'color' => 'success',
],
[
'label' => 'Rejected',
'count' => (int) ($tableStatusCounts['Rejected'] ?? 0),
'description' => 'Rejected work queue documents',
'icon' => 'ri-close-line',
'color' => 'danger',
],
];
$myRequestCards = [
[
'label' => 'Total Submitted',
'count' => $personalRequests->count(),
'description' => 'Documents you created',
'icon' => 'ri-file-add-line',
'color' => 'info',
],
[
'label' => 'In Progress',
'count' => (int) ($tableStatusCounts['In Progress'] ?? 0) + (int) ($tableStatusCounts['Forwarded'] ?? 0) + (int) ($tableStatusCounts['Approved'] ?? 0) + (int) ($tableStatusCounts['Needs Your Review'] ?? 0) + (int) ($tableStatusCounts['Overdue SLA'] ?? 0),
'description' => 'Still moving through workflow',
'icon' => 'ri-loader-4-line',
'color' => 'warning',
],
[
'label' => 'Sent Back to Me',
'count' => (int) ($tableStatusCounts['Sent Back to You'] ?? 0),
'description' => 'Needs your revision',
'icon' => 'ri-arrow-go-back-line',
'color' => 'warning',
],
[
'label' => 'Completed',
'count' => (int) ($tableStatusCounts['Completed'] ?? 0),
'description' => 'Finished successfully',
'icon' => 'ri-check-double-line',
'color' => 'success',
],
[
'label' => 'Rejected',
'count' => (int) ($tableStatusCounts['Rejected'] ?? 0),
'description' => 'Rejected documents',
'icon' => 'ri-close-line',
'color' => 'danger',
],
];
$workStatusFilterMap = collect($workQueueCards)
->mapWithKeys(fn ($card) => [$card['label'] => [$card['label']]])
->all();
$requestStatusFilterMap = [
'In Progress' => ['In Progress', 'Forwarded', 'Approved', 'Needs Your Review', 'Overdue SLA'],
'Sent Back to Me' => ['Sent Back to You'],
'Completed' => ['Completed'],
'Rejected' => ['Rejected'],
];
$activeStatusFilterMap = $activeDashboardTab === 'work'
? $workStatusFilterMap
: $requestStatusFilterMap;
$dashboardChartColors = ['primary', 'success', 'warning', 'info', 'danger', 'secondary'];
$dashboardChartCards = $tableRequests
->groupBy(fn ($request) => trim((string) ($request->document_type_label ?: $request->document_type ?: __('N/A'))))
->map(fn ($items, $label) => [
'label' => $label !== '' ? $label : __('N/A'),
'key' => md5(mb_strtolower((string) ($label !== '' ? $label : __('N/A')))),
'count' => $items->count(),
])
->sortByDesc('count')
->values()
->map(function ($card, $index) use ($dashboardChartColors) {
$card['color'] = $dashboardChartColors[$index % count($dashboardChartColors)];
return $card;
})
->all();
$dashboardChartMax = max(1, (int) collect($dashboardChartCards)->max('count'));
@endphp
@if($hasDashboardTabs)
@endif
@if($canReviewDocument && $activeDashboardTab === 'work')
@foreach($workQueueCards as $card)
@php
$cardColor = \App\Support\BadgeStyle::statusColor((string) ($card['label'] ?? ''), (string) ($card['color'] ?? 'primary'));
@endphp
{{ (int) $card['count'] }}
{{ __($card['description']) }}
@endforeach
@endif
@if($canRequestDocument && $activeDashboardTab === 'requests')
@foreach($myRequestCards as $card)
@php
$cardColor = \App\Support\BadgeStyle::statusColor((string) ($card['label'] ?? ''), (string) ($card['color'] ?? 'primary'));
@endphp
{{ (int) $card['count'] }}
{{ __($card['description']) }}
@endforeach
@endif
{{ __('Are you Sure ?') }}
{{ __('Are you Sure You want to Remove this Record ?') }}
@endsection
@section('script')
@endsection