middleware('auth'); $this->_service = 'reports'; $this->_module = 'roles_leaderboard'; $this->_viewname = 'leaderboard'; $this->_title = 'Leaderboard'; $this->_base_url = '/leaderboard'; } public function list(Request $request) { $response = LambdaRequest::signedrequest('get', $this->_service, $this->_module.'/get_all'); if (isset($response->statusCode) && $response->statusCode == 401) { return redirect('/unauthorised'); } $items = isset($response->data->items) ? $response->data->items : []; $roleMap = $this->getRoleNameMap(); foreach ($items as &$item) { if (!empty($item->validity_start)) { $item->validity_start = date('m/d/Y', strtotime($item->validity_start)); } if (!empty($item->validity_end)) { $item->validity_end = date('m/d/Y', strtotime($item->validity_end)); } if (!isset($item->sort_order) || $item->sort_order === null || $item->sort_order === '') { $item->sort_order = 0; } $item->visible_roles_label = $this->formatAssignedRoles($item->visible_roles ?? [], $roleMap); } unset($item); $fields = $this->get_list_fields(); return $this->view('list')->with([ 'title' => $this->_title, 'fields' => $fields, 'base_url' => $this->_base_url, 'items' => $items, 'buttons' => $this->get_list_buttons() ]); } protected function get_list_fields() { return [ 'actions' => ['title' => 'Actions', 'buttons' => ['edit', 'delete']], 'name' => ['title' => 'Name', 'type' => 'text'], 'sort_order' => ['title' => 'Sort Order', 'type' => 'number'], 'visible_roles_label' => ['title' => 'Visible Roles', 'type' => 'text'], 'validity_start' => ['title' => 'Validity start', 'type' => 'text'], 'validity_end' => ['title' => 'Validity end', 'type' => 'text'], 'status' => ['title' => 'Status', 'type' => 'select'], ]; } protected function get_list_buttons() { return [ ['title' => 'Add New', 'link' => $this->_base_url.'/addnew'], ]; } protected function get_form_fields($type, $values) { $metrics = $this->getlambda('get', 'metric', 'metric', 'get_all'); $metrics_dd = []; if (isset($metrics->data->items) && is_array($metrics->data->items)) { foreach ($metrics->data->items as $metric) { $metrics_dd[$metric->id] = $metric->name; } } $roles = $this->getlambda('get', 'ums', 'roles', 'dropdown'); $roles_dd = []; if (isset($roles->data->items) && is_array($roles->data->items)) { foreach ($roles->data->items as $role) { $roles_dd[$role->id] = $role->name; } } return [ 'id' => ['title' => '', 'type' => 'hidden'], 'name' => ['title' => 'Name', 'type' => 'text', 'required' => true], 'sort_order' => ['title' => 'Sort Order', 'type' => 'number', 'required' => true], 'validity_start' => ['title' => 'Validity start', 'type' => 'date', 'required' => true], 'validity_end' => ['title' => 'Validity end', 'type' => 'date', 'required' => true], 'visible_roles' => ['title' => 'Visible Roles', 'type' => 'multiselect', 'values' => $roles_dd, 'required' => true], 'reporting_roles' => ['title' => 'Reporting Roles', 'type' => 'multiselect', 'values' => $roles_dd, 'required' => true], 'rank_roles' => ['title' => 'Rank Roles', 'type' => 'rank_roles', 'roles' => $roles_dd, 'required' => true, 'fullwidth' => true], 'metrics' => ['title' => 'Choose Metric', 'type' => 'mapping', 'required' => true, 'metrics' => $metrics_dd, 'fullwidth' => true], 'combined_metrics' => ['title' => 'Combined Metrics (if any)', 'type' => 'combined_metrics', 'fullwidth' => true], 'intervals' => ['title' => 'Intervals', 'type' => 'multiselect', 'required' => true, 'values' => [ 'yearlycy' => 'Calender Year', 'yearlyfy' => 'Financial Year', 'monthly' => 'Monthly', 'weekly' => 'Weekly', 'daily' => 'Daily', ]], 'default_interval' => ['title' => 'Default Interval', 'type' => 'select', 'values' => [ '' => 'Overall / All', 'all' => 'Overall', 'month-0' => 'This Month', 'month-1' => 'Last Month', 'month-3' => 'Last 3 Months', 'month-6' => 'Last 6 Months', 'month-12' => 'Last 12 Months', 'day-0' => 'Today', 'day-1' => 'Yesterday', 'day-7' => 'Last 7 Days', 'day-30' => 'Last 30 Days', 'week-0' => 'This week', 'week-1' => 'Last week', 'yearfy-0' => 'This Financial Year', 'yearfy-1' => 'Last Financial Year', 'yearcy-0' => 'This Calender Year', 'yearcy-1' => 'Last Calender Year', ]], 'show_positions' => ['title' => 'Show Positions', 'type' => 'select', 'required' => true, 'values' => ['yes' => 'Yes', 'no' => 'No']], 'show_positions_type' => ['title' => 'Show Positions Type', 'type' => 'select', 'required' => true, 'values' => ['all' => 'All', 'loggedin' => 'Logged In']], 'status' => ['title' => 'Status', 'type' => 'select', 'required' => true, 'values' => ['active' => 'Active', 'disabled' => 'Disabled']], ]; } protected function _beforesave($type, $request) { $data = $request->except('_token'); $data['sort_order'] = isset($data['sort_order']) && $data['sort_order'] !== '' ? (int) $data['sort_order'] : 0; $metrics = []; if (isset($data['metric']) && is_array($data['metric'])) { foreach ($data['metric'] as $k => $metric) { if ($metric === '' || $metric === null) { continue; } $metrics[] = [ 'metric' => $metric, 'display' => $data['display_unit'][$k] ?? '', 'sort_order' => isset($data['metric_sort_order'][$k]) && $data['metric_sort_order'][$k] !== '' ? (int) $data['metric_sort_order'][$k] : 0, 'weight' => isset($data['weight'][$k]) && $data['weight'][$k] !== '' ? (string) $data['weight'][$k] : '1', ]; } } $data['metrics'] = $metrics; $rankRoles = []; if (isset($data['rank_roles']['title']) && is_array($data['rank_roles']['title'])) { foreach ($data['rank_roles']['title'] as $i => $title) { $role = $data['rank_roles']['role'][$i] ?? ''; if ($title === '' && $role === '') { continue; } $rankRoles[] = [ 'title' => $title, 'role' => $role, 'limit' => isset($data['rank_roles']['limit'][$i]) && $data['rank_roles']['limit'][$i] !== '' ? (int) $data['rank_roles']['limit'][$i] : 10, 'sort_order' => isset($data['rank_roles']['sort_order'][$i]) && $data['rank_roles']['sort_order'][$i] !== '' ? (int) $data['rank_roles']['sort_order'][$i] : 0, ]; } } $data['rank_roles'] = $rankRoles; $combined_metrics = []; if (isset($data['combined_metrics']) && is_array($data['combined_metrics']) && !empty($data['combined_metrics']['type'])) { foreach ($data['combined_metrics']['type'] as $i => $v) { if ($v === '' || $v === null) { continue; } $combined_metrics[] = [ 'type' => $v, 'title' => $data['combined_metrics']['title'][$i] ?? '', 'fields' => isset($data['combined_metrics']['fields'][$i]) ? $data['combined_metrics']['fields'][$i] : [], 'list_view' => isset($data['combined_metrics']['list_view'][$i]) ? $data['combined_metrics']['list_view'][$i] : 'yes', ]; } } $data['combined_metrics'] = json_encode($combined_metrics); foreach (['visible_roles', 'reporting_roles', 'intervals'] as $field) { if (!isset($data[$field]) || !is_array($data[$field])) { $data[$field] = []; } } if (!isset($data['default_interval'])) { $data['default_interval'] = ''; } if (array_key_exists('id', $data) && ($data['id'] === null || $data['id'] === '')) { unset($data['id']); } unset($data['metric'], $data['display_unit'], $data['metric_sort_order'], $data['weight']); return $data; } protected function _beforeform($type, $values) { if ($type === 'new') { return (object) [ 'sort_order' => 0, 'show_positions' => 'no', 'show_positions_type' => 'all', 'status' => 'active', 'default_interval' => '', 'combined_metrics' => '[]', 'metrics' => [], 'rank_roles' => [], 'visible_roles' => [], 'reporting_roles' => [], 'intervals' => [], ]; } if ($type == 'edit') { foreach (['visible_roles', 'reporting_roles', 'intervals', 'metrics', 'rank_roles'] as $field) { if (!isset($values->{$field}) || !is_array($values->{$field})) { $values->{$field} = []; } } if (!isset($values->combined_metrics) || $values->combined_metrics === '') { $values->combined_metrics = '[]'; } elseif (is_array($values->combined_metrics)) { $values->combined_metrics = json_encode($values->combined_metrics); } if (!isset($values->sort_order) || $values->sort_order === null || $values->sort_order === '') { $values->sort_order = 0; } if (isset($values->show_positions)) { $values->show_positions = strtolower((string) $values->show_positions); } if (!isset($values->show_positions_type) || $values->show_positions_type === '') { $values->show_positions_type = 'all'; } if (!isset($values->default_interval)) { $values->default_interval = ''; } if (!empty($values->metrics)) { usort($values->metrics, function ($a, $b) { $aOrder = (int) (is_object($a) ? ($a->sort_order ?? 0) : ($a['sort_order'] ?? 0)); $bOrder = (int) (is_object($b) ? ($b->sort_order ?? 0) : ($b['sort_order'] ?? 0)); return $aOrder <=> $bOrder; }); } if (!empty($values->rank_roles)) { usort($values->rank_roles, function ($a, $b) { $aOrder = (int) (is_object($a) ? ($a->sort_order ?? 0) : ($a['sort_order'] ?? 0)); $bOrder = (int) (is_object($b) ? ($b->sort_order ?? 0) : ($b['sort_order'] ?? 0)); return $aOrder <=> $bOrder; }); } if (!empty($values->validity_start)) { $values->validity_start = date('m/d/Y', strtotime($values->validity_start) + 19800); } if (!empty($values->validity_end)) { $values->validity_end = date('m/d/Y', strtotime($values->validity_end) + 19800); } } return $values; } public function dashboard(Request $request) { $data = $this->roleLeaderboardViewData($request); $data['exportUrl'] = url('/leaderboard/export') . '?' . http_build_query($request->query()); return view('leaderboard.dashboard', $data); } public function export(Request $request) { $data = $this->roleLeaderboardViewData($request); if (!empty($data['error'])) { return redirect('/leaderboard/dashboard?' . http_build_query($request->query())) ->withError($data['error']); } $headers = ['Rank', 'User', 'Employee Code', 'Designation', 'Position', 'Score']; foreach ($data['metrics'] as $metric) { $headers[] = $metric['name']; } $exceldata = [$headers]; foreach ($data['users'] as $index => $user) { $row = [ $user['rank'] ?? ($index + 1), $user['name'] ?? '', $user['employee_code'] ?? '', $user['designation'] ?? '', $user['position_name'] ?? '', $user['score'] ?? 0, ]; foreach ($data['metrics'] as $metric) { $row[] = $user['metric_values'][$metric['id']] ?? ''; } $exceldata[] = $row; } $filename = preg_replace('/[^A-Za-z0-9_\-]+/', '-', (string) ($data['title'] ?: 'leaderboard')); $filename = trim($filename, '-') ?: 'leaderboard'; return Excel::download(new InvoicesExport($exceldata), $filename . '.xlsx'); } protected function roleLeaderboardViewData(Request $request): array { $id = trim((string) $request->query('id', '')); $roleId = trim((string) $request->query('role', '')); $empty = [ 'error' => '', 'title' => 'Leaderboard', 'subtitle' => '', 'period_label' => '', 'periods' => [], 'selected_period' => (string) $request->query('period', ''), 'users' => [], 'metrics' => [], 'pills' => [], 'selected_role' => $roleId, ]; if ($id === '') { $empty['error'] = 'Leaderboard is required.'; return $empty; } $params = ['id' => $id]; if ($request->query('period')) { $params['period'] = $request->query('period'); } $response = LambdaRequest::signedrequest('get', $this->_service, $this->_module . '/dashboard', $params, 120); if (!is_object($response) || ($response->statusCode ?? 0) != 200 || !isset($response->data)) { $empty['error'] = is_object($response) ? ($response->message ?? 'Unable to load leaderboard.') : 'Unable to load leaderboard.'; $empty['pills'] = $this->roleLeaderboardPills($id, $roleId, [], $request->query('period')); return $empty; } $view = $response->data->view ?? (object) []; $groups = $response->data->leaderboard ?? []; if (is_object($groups)) { $groups = array_values((array) $groups); } $selected = null; foreach ($groups as $group) { $group = is_object($group) ? $group : (object) $group; $roleConfig = is_object($group->role ?? null) ? $group->role : (object) ($group->role ?? []); $currentRoleId = (string) ($roleConfig->role ?? ($roleConfig->id ?? '')); if ($roleId === '' || $currentRoleId === $roleId) { $selected = $group; $roleId = $currentRoleId; break; } } $pills = $this->roleLeaderboardPills($id, $roleId, $groups, $request->query('period')); $periods = $this->uniquePeriodOptions($view->periods ?? []); $selectedPeriod = (string) ($request->query('period') ?: ($view->interval ?? '')); if ($selectedPeriod === '') { $selectedPeriod = 'all'; } if (!$selected) { return [ 'error' => 'No data found for this role.', 'title' => $view->name ?? 'Leaderboard', 'subtitle' => '', 'period_label' => '', 'periods' => $periods, 'selected_period' => $selectedPeriod, 'users' => [], 'metrics' => [], 'pills' => $pills, 'selected_role' => $roleId, ]; } $roleConfig = is_object($selected->role ?? null) ? $selected->role : (object) []; $limit = (int) ($roleConfig->limit ?? 0); $roleTitle = trim((string) ($roleConfig->title ?? '')); if ($roleTitle === '') { $roleTitle = 'Role'; } $subtitle = preg_match('/^\s*top\s+\d+/i', $roleTitle) ? $roleTitle : ('Top ' . ($limit > 0 ? $limit : count((array) ($selected->users ?? []))) . ' ' . $roleTitle); $rows = $selected->users ?? []; if (is_object($rows)) { $rows = array_values((array) $rows); } if ($limit > 0) { $rows = array_slice($rows, 0, $limit); } $metrics = []; $users = []; foreach ($rows as $index => $row) { $row = is_object($row) ? $row : (object) $row; $info = is_object($row->user ?? null) ? $row->user : (object) []; $metricValues = []; $rowMetrics = $row->metrics ?? []; if (is_object($rowMetrics)) { $rowMetrics = array_values((array) $rowMetrics); } if (is_array($rowMetrics)) { foreach ($rowMetrics as $metric) { $metric = is_object($metric) ? $metric : (object) $metric; $metricId = $metric->metric ?? ($metric->title ?? ('m' . count($metrics))); $metricName = $metric->name ?? ($metric->display ?? ($metric->title ?? $metricId)); if ($index === 0) { $metrics[] = ['id' => $metricId, 'name' => $metricName]; } $metricValues[$metricId] = $metric->value ?? 0; } } $users[] = [ 'rank' => $row->rank ?? ($index + 1), 'name' => $info->name ?? '', 'avatar' => $info->avatar ?? '', 'employee_code' => $info->employee_code ?? '', 'designation' => $info->designation ?? '', 'position_name' => $info->position_name ?? '', 'score' => $row->score ?? 0, 'metric_values' => $metricValues, ]; } $periodLabel = trim(($view->firstDay ?? '') . (($view->firstDay ?? '') && ($view->lastDay ?? '') ? ' – ' : '') . ($view->lastDay ?? '')); return [ 'error' => '', 'title' => $view->name ?? 'Leaderboard', 'subtitle' => $subtitle, 'period_label' => $periodLabel, 'periods' => $periods, 'selected_period' => $selectedPeriod, 'users' => $users, 'metrics' => $metrics, 'pills' => $pills, 'selected_role' => $roleId, ]; } protected function uniquePeriodOptions($periods): array { if (is_object($periods)) { $periods = array_values((array) $periods); } if (!is_array($periods)) { return []; } $out = []; $seen = []; foreach ($periods as $period) { $period = is_object($period) ? $period : (object) $period; $value = (string) ($period->value ?? ''); if ($value === '' || isset($seen[$value])) { continue; } $seen[$value] = true; $out[] = $period; } return $out; } protected function roleLeaderboardPills($leaderboardId, $selectedRoleId, array $groups, $period = null): array { $rankRoles = []; $one = LambdaRequest::signedrequest('get', $this->_service, $this->_module . '/get_one', ['id' => $leaderboardId]); if (is_object($one) && ($one->statusCode ?? 0) == 200) { $item = $one->data->item ?? null; $configured = $item->rank_roles ?? []; if (is_object($configured)) { $configured = array_values((array) $configured); } if (is_array($configured)) { usort($configured, function ($a, $b) { $a = is_object($a) ? $a : (object) $a; $b = is_object($b) ? $b : (object) $b; return ((int) ($a->sort_order ?? 0)) <=> ((int) ($b->sort_order ?? 0)); }); $rankRoles = $configured; } } if (!count($rankRoles)) { foreach ($groups as $group) { $group = is_object($group) ? $group : (object) $group; $rankRoles[] = is_object($group->role ?? null) ? $group->role : (object) []; } } $pills = []; foreach ($rankRoles as $index => $rankRole) { $rankRole = is_object($rankRole) ? $rankRole : (object) $rankRole; $roleId = (string) ($rankRole->role ?? ($rankRole->id ?? '')); $limit = (int) ($rankRole->limit ?? 10); if ($limit < 1) { $limit = 10; } $title = trim((string) ($rankRole->title ?? '')); if ($title === '') { $title = 'Role'; } $label = preg_match('/^\s*top\s+\d+/i', $title) ? $title : ('Top ' . $limit . ' ' . $title); $query = ['id' => $leaderboardId, 'role' => $roleId]; if ($period) { $query['period'] = $period; } $pills[] = [ 'label' => $label, 'url' => url('/leaderboard/dashboard') . '?' . http_build_query($query), 'active' => $selectedRoleId !== '' ? $roleId === (string) $selectedRoleId : $index === 0, ]; } return $pills; } }