Rapport-Laravel/app/Http/Controllers/LeaderboardController.php

820 lines
34 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests\LambdaRequest;
use Maatwebsite\Excel\Facades\Excel;
use App\Exports\InvoicesExport;
class LeaderboardController extends Controller
{
public function __construct()
{
$this->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);
$item->leaderboard_roles_type_label = (($item->leaderboard_roles_type ?? 'roles') === 'team') ? 'Team' : 'Roles';
}
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'],
'leaderboard_roles_type_label' => ['title' => 'Type', '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 teamDropdownOptions(): array
{
$teams_dd = [];
foreach ([['detailing', 'dropdown'], ['detailing', 'get_all'], ['detailing', 'list']] as $call) {
[$service, $url] = $call;
$teams = $this->getlambda('get', $service, 'team', $url);
$items = [];
if (is_object($teams) && isset($teams->data->items) && is_array($teams->data->items)) {
$items = $teams->data->items;
} elseif (is_object($teams) && isset($teams->data) && is_array($teams->data)) {
$items = $teams->data;
}
foreach ($items as $team) {
$id = is_object($team) ? ($team->id ?? null) : (is_array($team) ? ($team['id'] ?? null) : null);
$name = is_object($team) ? ($team->name ?? '') : (is_array($team) ? ($team['name'] ?? '') : '');
if ($id) {
$teams_dd[$id] = $name !== '' ? $name : $id;
}
}
if (!empty($teams_dd)) {
break;
}
}
return $teams_dd;
}
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;
}
}
$teams_dd = $this->teamDropdownOptions();
$userattr_dd = $this->getUserAttributeOptions();
$managerLevels = [
'l1manager' => 'L1 Manager',
'l2manager' => 'L2 Manager',
'l3manager' => 'L3 Manager',
'l4manager' => 'L4 Manager',
];
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],
'leaderboard_roles_type' => ['title' => 'Leaderboard Type', 'type' => 'select', 'required' => true, 'values' => ['roles' => 'Roles', 'team' => 'Team']],
'leaderboard_team_ids' => ['title' => 'Teams', 'type' => 'multiselect', 'values' => $teams_dd, 'fullwidth' => true, 'required' => true, 'showIf' => ['leaderboard_roles_type' => 'team']],
'view_mode' => ['title' => 'Team View Mode', 'type' => 'select', 'required' => true, 'values' => ['versus' => 'Versus', 'podium' => 'Podium'], 'default' => 'versus', 'showIf' => ['leaderboard_roles_type' => 'team']],
'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, 'showIf' => ['leaderboard_roles_type' => 'roles']],
'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']],
'show_units_export' => ['title' => 'Show Units Export', 'type' => 'select', 'required' => true, 'values' => ['yes' => 'Yes', 'no' => 'No'], 'default' => 'yes'],
'show_user_attributes' => ['title' => 'Show User Attributes', 'type' => 'select', 'required' => true, 'values' => ['yes' => 'Yes', 'no' => 'No'], 'default' => 'no'],
'user_attributes' => ['title' => 'Include User Attributes', 'type' => 'multiselect', 'values' => $userattr_dd, 'default' => []],
'show_normal_metrics' => ['title' => 'Show Normal Metrics', 'type' => 'select', 'required' => true, 'values' => ['yes' => 'Yes', 'no' => 'No'], 'default' => 'yes'],
'show_combined_metrics' => ['title' => 'Show Combined Metrics', 'type' => 'select', 'required' => true, 'values' => ['yes' => 'Yes', 'no' => 'No'], 'default' => 'yes'],
'manager_details' => ['title' => 'Manager Details', 'type' => 'multiselect', 'values' => $managerLevels, 'default' => ['l1manager']],
'total_units_name' => ['title' => 'Total Units Name', 'type' => 'text', 'required' => false, 'default' => ''],
'bg_color' => ['title' => 'Background Color', 'type' => 'color'],
'bg_image' => ['title' => 'Background Image', 'type' => 'image'],
'icon' => ['title' => 'Icon', 'type' => 'image'],
'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', 'leaderboard_team_ids', 'manager_details'] as $field) {
if (!isset($data[$field]) || !is_array($data[$field])) {
$data[$field] = [];
}
}
if (!isset($data['leaderboard_roles_type']) || !in_array($data['leaderboard_roles_type'], ['team', 'roles'], true)) {
$data['leaderboard_roles_type'] = 'roles';
}
if ($data['leaderboard_roles_type'] === 'team') {
if (!isset($data['view_mode']) || !in_array($data['view_mode'], ['versus', 'podium'], true)) {
$data['view_mode'] = 'versus';
}
} else {
$data['leaderboard_team_ids'] = [];
$data['view_mode'] = '';
}
if (empty($data['manager_details'])) {
$data['manager_details'] = ['l1manager'];
}
foreach (['show_units_export', 'show_normal_metrics', 'show_combined_metrics'] as $flag) {
if (!isset($data[$flag]) || $data[$flag] === '') {
$data[$flag] = 'yes';
}
}
$data['total_units_name'] = trim((string) ($data['total_units_name'] ?? ''));
$data['show_user_attributes'] = ($data['show_user_attributes'] ?? 'no') === 'yes' ? 'yes' : 'no';
$data['user_attributes'] = $this->normalizeAttributeCodes($data['user_attributes'] ?? []);
if (!isset($data['bg_color']) || is_array($data['bg_color'])) {
$data['bg_color'] = '';
}
if ($request->file('bg_image')) {
$data['bg_image'] = $this->_uploadMedia($request, 'bg_image', 'leaderboard');
} else {
unset($data['bg_image']);
}
if ($request->file('icon')) {
$data['icon'] = $this->_uploadMedia($request, 'icon', 'leaderboard');
} else {
unset($data['icon']);
}
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' => [],
'leaderboard_roles_type' => 'roles',
'leaderboard_team_ids' => [],
'view_mode' => 'versus',
'manager_details' => ['l1manager'],
'show_units_export' => 'yes',
'show_user_attributes' => 'no',
'user_attributes' => [],
'show_normal_metrics' => 'yes',
'show_combined_metrics' => 'yes',
'total_units_name' => '',
'bg_color' => '',
'bg_image' => '',
'icon' => '',
];
}
if ($type == 'edit') {
foreach (['visible_roles', 'reporting_roles', 'intervals', 'metrics', 'rank_roles', 'leaderboard_team_ids', 'manager_details'] as $field) {
if (!isset($values->{$field}) || !is_array($values->{$field})) {
$values->{$field} = [];
}
}
if (!isset($values->leaderboard_roles_type) || !in_array($values->leaderboard_roles_type, ['team', 'roles'], true)) {
$values->leaderboard_roles_type = 'roles';
}
if (!isset($values->view_mode) || !in_array($values->view_mode, ['versus', 'podium'], true)) {
$values->view_mode = 'versus';
}
if (empty($values->manager_details)) {
$values->manager_details = ['l1manager'];
}
foreach (['show_units_export', 'show_normal_metrics', 'show_combined_metrics'] as $flag) {
if (!isset($values->{$flag}) || $values->{$flag} === '') {
$values->{$flag} = 'yes';
}
}
if (!isset($values->total_units_name) || $values->total_units_name === null) {
$values->total_units_name = '';
}
$values->show_user_attributes = (($values->show_user_attributes ?? 'no') === 'yes') ? 'yes' : 'no';
$values->user_attributes = $this->normalizeAttributeCodes($values->user_attributes ?? []);
if (!isset($values->bg_color)) {
$values->bg_color = '';
}
if (!isset($values->bg_image)) {
$values->bg_image = '';
}
if (!isset($values->icon)) {
$values->icon = '';
}
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']);
}
if (!empty($data['is_team'])) {
$headers = ['Rank', 'Team', 'Score'];
} else {
$headers = ['Rank', 'User', 'Employee Code', 'Designation', 'Position', 'Score'];
}
foreach ($data['metrics'] as $metric) {
$headers[] = $metric['name'];
}
$exceldata = [$headers];
foreach ($data['users'] as $index => $user) {
if (!empty($data['is_team'])) {
$row = [
$user['rank'] ?? ($index + 1),
$user['name'] ?? '',
$user['score'] ?? 0,
];
} else {
$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,
'is_team' => false,
];
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);
}
$teamRows = $this->teamRowsFromGroups($groups);
if ($this->isTeamLeaderboardView($view->team_view ?? false) || count($teamRows)) {
return $this->teamLeaderboardViewData($view, $teamRows, $request);
}
$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,
'is_team' => false,
];
}
$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,
'is_team' => false,
];
}
protected function isTeamLeaderboardView($flag): bool
{
return $flag === true || $flag === 1 || $flag === '1' || $flag === 'true' || $flag === 'yes';
}
protected function teamRowsFromGroups(array $groups): array
{
foreach ($groups as $group) {
$group = is_object($group) ? $group : (object) $group;
$rows = $group->teams ?? null;
if (is_object($rows)) {
$rows = array_values((array) $rows);
}
if (is_array($rows) && count($rows)) {
return $rows;
}
}
return [];
}
protected function teamLeaderboardViewData($view, array $teamRows, Request $request): array
{
$periods = $this->uniquePeriodOptions($view->periods ?? []);
$selectedPeriod = (string) ($request->query('period') ?: ($view->interval ?? ''));
if ($selectedPeriod === '') {
$selectedPeriod = 'all';
}
$metrics = [];
$users = [];
foreach ($teamRows as $index => $row) {
$row = is_object($row) ? $row : (object) $row;
$team = is_object($row->team ?? null) ? $row->team : (object) ($row->team ?? []);
$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;
}
}
$name = trim((string) ($team->name ?? ''));
$users[] = [
'rank' => $row->rank ?? ($index + 1),
'name' => $name !== '' ? $name : 'Team',
'avatar' => $team->icon ?? '',
'employee_code' => '',
'designation' => '',
'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' => 'Teams',
'period_label' => $periodLabel,
'periods' => $periods,
'selected_period' => $selectedPeriod,
'users' => $users,
'metrics' => $metrics,
'pills' => [],
'selected_role' => '',
'is_team' => true,
];
}
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;
}
protected function getUserAttributeOptions(): array
{
$options = [];
$userAttrs = $this->getlambda('get', 'ums', 'userattribute', 'get_all');
foreach (($userAttrs->data->items ?? []) as $attr) {
if (($attr->status ?? 'active') === 'disabled') {
continue;
}
$code = $attr->code ?? '';
if ($code === '') {
continue;
}
$options[$code] = $attr->attribute ?? $code;
}
return $options;
}
protected function normalizeAttributeCodes($raw): array
{
if (is_string($raw) && $raw !== '') {
$decoded = json_decode($raw, true);
$raw = is_array($decoded) ? $decoded : explode('#', $raw);
}
if (!is_array($raw)) {
return [];
}
$codes = [];
foreach ($raw as $code) {
if (is_object($code)) {
$code = $code->code ?? '';
}
$code = trim((string) $code);
if ($code !== '') {
$codes[] = $code;
}
}
return array_values(array_unique($codes));
}
}