user()->can('managementtools.access') || ! auth()->user()->can('managementtools.task_report')) { abort(403, 'Unauthorized action.'); } } protected function businessId(Request $request): int { return (int) $request->session()->get('user.business_id'); } protected function adjacentUsers($users, $user_id): array { $ids = collect($users)->keys()->filter(fn ($id) => ! empty($id))->values(); if ($ids->isEmpty()) { return [null, null]; } if (empty($user_id)) { $first = User::find($ids->first()); return [$first, $first]; } $idx = $ids->search((int) $user_id); if ($idx === false) { $first = User::find($ids->first()); return [$first, $first]; } $nextId = $idx < $ids->count() - 1 ? $ids[$idx + 1] : $ids->first(); $prevId = $idx > 0 ? $ids[$idx - 1] : $ids->last(); return [User::find($nextId), User::find($prevId)]; } public function index(Request $request) { $this->authorizeAccess(); $business_id = $this->businessId($request); $users = User::forDropdown($business_id, false); $user_id = $request->input('user_id'); $start_date_input = $request->input('start_date'); $end_date_input = $request->input('end_date'); $start_gregorian = $this->mtUtil->parseInputDate($start_date_input); $end_gregorian = $this->mtUtil->parseInputDate($end_date_input); $user_tasks = collect(); $week = []; $last_week = []; $calendar_tasks = collect(); $calendar_events = collect(); $grouped_tasks = collect(); $total_minutes = 0; $day_tabs = $this->reportUtil->dayTabDates(); $dates = $day_tabs['future']; $last_dates = $day_tabs['past']; [$next_user, $previous_user] = $this->adjacentUsers($users, $user_id); if ($user_id && $start_gregorian && $end_gregorian) { $start = Carbon::parse($start_gregorian)->startOfDay(); $end = Carbon::parse($end_gregorian)->endOfDay(); $user_tasks = $this->reportUtil->tasksForUserInRange($business_id, (int) $user_id, $start, $end); $total_minutes = $this->reportUtil->sumTasksWorkMinutes($user_tasks, (int) $user_id); $grouped_tasks = $this->reportUtil->groupedTasksByTimelineDate($user_tasks, (int) $user_id); foreach ($last_dates as $date) { $last_week[] = $this->reportUtil->tasksForUserOnDate($business_id, (int) $user_id, $date); } foreach ($dates as $date) { $week[] = $this->reportUtil->tasksForUserOnDate($business_id, (int) $user_id, $date); } $calendar_start = now()->subDays(6)->startOfDay(); $calendar_end = now()->addDays(6)->endOfDay(); $calendar_tasks = $this->reportUtil->calendarTasks($business_id, (int) $user_id, $calendar_start, $calendar_end); } $calendar_events = $calendar_tasks->map(fn ($task) => [ 'title' => $task->title, 'start' => optional($task->created_at)->format('Y-m-d'), 'end' => optional($task->due_date)->format('Y-m-d'), ])->values(); return view('managementtools::task_report.index', [ 'users' => $users, 'user_id' => $user_id, 'start_date' => $this->mtUtil->formatForInput($start_gregorian ?? $start_date_input), 'end_date' => $this->mtUtil->formatForInput($end_gregorian ?? $end_date_input), 'user_tasks' => $user_tasks, 'total_minutes' => $total_minutes, 'dates' => $dates, 'last_dates' => $last_dates, 'week' => $week, 'last_week' => $last_week, 'grouped_tasks' => $grouped_tasks, 'calendar_tasks' => $calendar_tasks, 'calendar_events' => $calendar_events, 'next_user' => $next_user, 'previous_user' => $previous_user, 'current_user_name' => ! empty($user_id) ? ($users[$user_id] ?? '—') : '—', 'can_manage_scores' => auth()->user()->can('managementtools.manage_scores'), 'can_manage_tasks' => auth()->user()->can('managementtools.manage_employee_tasks'), 'statuses' => MtUserTask::statusLabels(), ]); } public function userList() { $this->authorizeAccess(); $business_id = $this->businessId(request()); $users = User::forDropdown($business_id, false); $day_tabs = $this->reportUtil->dayTabDates(); return view('managementtools::task_report.modals.user_days', [ 'users' => $users, 'dates' => $day_tabs['future'], 'business_id' => $business_id, ]); } public function changeTimeline($task_id, $user_id, $date = null) { $this->authorizeAccess(); $business_id = $this->businessId(request()); $task = MtUserTask::forBusiness($business_id)->findOrFail($task_id); $timeline = $this->reportUtil->latestTimelineForTask($business_id, (int) $user_id, (int) $task_id, $date); if (! $timeline) { $timeline = MtUserTimeLine::create([ 'business_id' => $business_id, 'user_id' => $user_id, 'user_task_id' => $task_id, 'starts_at' => $date ? Carbon::parse($date)->startOfDay()->addHours(9) : now(), 'ends_at' => $date ? Carbon::parse($date)->startOfDay()->addHours(10) : now()->addHour(), ]); } return view('managementtools::task_report.modals.change_timeline', compact('timeline', 'task', 'user_id')); } public function storeTimelineChange(Request $request) { $this->authorizeAccess(); $business_id = $this->businessId($request); $request->validate([ 'timeline_id' => 'required|integer|exists:mt_user_time_lines,id', 'starts_at' => 'required|string|max:30', 'ends_at' => 'required|string|max:30', ]); $starts_at = $this->mtUtil->parseInputDateTime($request->starts_at); $ends_at = $this->mtUtil->parseInputDateTime($request->ends_at); if (! $starts_at || ! $ends_at || Carbon::parse($ends_at)->lte(Carbon::parse($starts_at))) { return response()->json(['success' => false, 'msg' => __('managementtools::lang.something_went_wrong')]); } $timeline = MtUserTimeLine::forBusiness($business_id)->findOrFail($request->timeline_id); $timeline->update([ 'starts_at' => Carbon::parse($starts_at), 'ends_at' => Carbon::parse($ends_at), ]); return response()->json(['success' => true, 'msg' => __('managementtools::lang.timeline_updated')]); } public function taskScores($user_id, $task_id) { $this->authorizeAccess(); $business_id = $this->businessId(request()); $scores = MtUserScore::forBusiness($business_id) ->where('user_id', $user_id) ->where('task_id', $task_id) ->with(['scoreCard', 'user']) ->latest() ->get(); $cards = MtScoreCard::forBusiness($business_id)->active()->ordered()->get(); return view('managementtools::task_report.modals.task_scores', compact('scores', 'user_id', 'task_id', 'cards')); } public function storeTaskScore(Request $request, $user_id, $task_id) { if (! auth()->user()->can('managementtools.manage_scores')) { abort(403, 'Unauthorized action.'); } $business_id = $this->businessId($request); $request->validate([ 'score_card_id' => 'required|integer|exists:mt_score_cards,id', 'description' => 'nullable|string|max:1000', ]); $card = MtScoreCard::forBusiness($business_id)->findOrFail($request->score_card_id); MtUserScore::create([ 'business_id' => $business_id, 'user_id' => $user_id, 'score_card_id' => $card->id, 'score' => $card->points, 'type' => $card->points >= 0 ? '1' : '2', 'description' => $request->description, 'task_id' => $task_id, 'created_by' => auth()->id(), ]); return response()->json(['success' => true, 'msg' => __('managementtools::lang.score_record_added')]); } public function destroyTaskScore($user_id, $score_id, $task_id) { if (! auth()->user()->can('managementtools.manage_scores')) { abort(403, 'Unauthorized action.'); } $business_id = $this->businessId(request()); $score = MtUserScore::forBusiness($business_id) ->where('user_id', $user_id) ->where('task_id', $task_id) ->findOrFail($score_id); $score->delete(); return response()->json(['success' => true, 'msg' => __('managementtools::lang.score_record_deleted')]); } public function storeTimeLine(Request $request) { $this->authorizeAccess(); $business_id = $this->businessId($request); $request->validate([ 'user_id' => 'required|integer|exists:users,id', 'user_task_id' => 'nullable|integer|exists:mt_user_tasks,id', 'starts_at' => 'required|string|max:30', 'ends_at' => 'required|string|max:30', 'note' => 'nullable|string|max:500', ]); $starts_at = $this->mtUtil->parseInputDateTime($request->starts_at); $ends_at = $this->mtUtil->parseInputDateTime($request->ends_at); if (! $starts_at || ! $ends_at || Carbon::parse($ends_at)->lte(Carbon::parse($starts_at))) { return response()->json(['success' => false, 'msg' => __('managementtools::lang.something_went_wrong')]); } MtUserTimeLine::create([ 'business_id' => $business_id, 'user_id' => $request->user_id, 'user_task_id' => $request->user_task_id ?: null, 'starts_at' => Carbon::parse($starts_at), 'ends_at' => Carbon::parse($ends_at), 'note' => $request->note, ]); return response()->json(['success' => true, 'msg' => __('managementtools::lang.timeline_added')]); } public function destroyTimeLine($id) { $this->authorizeAccess(); $business_id = $this->businessId(request()); $line = MtUserTimeLine::forBusiness($business_id)->findOrFail($id); $line->delete(); return response()->json(['success' => true, 'msg' => __('managementtools::lang.timeline_deleted')]); } }