input('month', Carbon::now()->format('Y-m')); $user = Auth::user(); $administrations = $this->userService->getDashboard($user, $selectedMonth); $stats = $this->userService->getPersonalStats($user, $selectedMonth); $receivedRanking = $this->userService->getRankingList('received', $selectedMonth, $user); $sentRanking = $this->userService->getRankingList('sent', $selectedMonth, $user); $dashboardData = new DashboardDataDto( administrations: $administrations, selectedMonth: $selectedMonth, user: $user, receivedRankers: $receivedRanking['rankers'], receivedCurrentUserRankItem: $receivedRanking['currentUserRankItem'], sentRankers: $sentRanking['rankers'], sentCurrentUserRankItem: $sentRanking['currentUserRankItem'], receivedCount: (int) $stats['receivedCount'], sentCount: (int) $stats['sentCount'], currentRank: (int) $stats['currentRank'] ); return view('user.dashboard', $dashboardData->toArray()); } /** * Show the form to send thank cards. */ public function sendThankcards(): View { $users = $this->userService->getOtherActiveUsers(Auth::user()); return view('user.send', compact('users')); } public function storeThankcards(SendThankCardRequest $request): JsonResponse { try { $this->userService->sendThankcards( Auth::user(), (string) $request->input('receiver'), (int) $request->input('amount') ); } catch (ThankCardException $e) { return response()->json(['success' => false, 'message' => $e->getMessage()], 422); } $receiverUser = \App\Models\User::where('msnv', $request->input('receiver'))->first(); // Send ChatOps notification from backend to avoid CORS issues $chatOpsUrl = config('constants.CHATOPS_API_URL'); $chatOpsToken = config('constants.CHATOPS_API_TOKEN'); if ($chatOpsUrl && $chatOpsToken && $receiverUser) { try { \Illuminate\Support\Facades\Http::timeout(5)->post($chatOpsUrl, [ 'message' => "💌 Bạn nhận được một Thank Card mới!\nNhanh chân đến khu vực nhận thư để nhận ngay nhé!", 'userEmail' => $receiverUser->mail, 'token' => $chatOpsToken, ]); } catch (\Exception $e) { \Illuminate\Support\Facades\Log::error('ChatOps API failed: ' . $e->getMessage()); } } return response()->json([ 'success' => true, 'message' => __('messages.thank_card_send_success'), 'receiver_email' => $receiverUser ? $receiverUser->mail : '', ]); } // New page: list of ThankCards received by the current user public function receivedCards(Request $request): View { $selectedMonth = $request->input('month', Carbon::now()->format('Y-m')); $user = Auth::user(); $data = $this->userService->getReceivedPageData($user, $selectedMonth); return view('user.received', $data); } // New page: list of ThankCards sent by the current user public function sentCards(Request $request): View { $selectedMonth = $request->input('month', Carbon::now()->format('Y-m')); $user = Auth::user(); $data = $this->userService->getSentPageData($user, $selectedMonth); return view('user.sent', $data); } // New page: ranking (both received and sent) with tabs public function ranking(Request $request): View { $selectedMonth = $request->input('month', Carbon::now()->format('Y-m')); $user = Auth::user(); $receivedRanking = $this->userService->getRankingList('received', $selectedMonth, $user); $sentRanking = $this->userService->getRankingList('sent', $selectedMonth, $user); return view('user.ranking', [ 'selectedMonth' => $selectedMonth, 'receivedRankers' => $receivedRanking['rankers'], 'receivedCurrentUserRankItem' => $receivedRanking['currentUserRankItem'], 'sentRankers' => $sentRanking['rankers'], 'sentCurrentUserRankItem' => $sentRanking['currentUserRankItem'], ]); } /** * Show the change password form. */ public function changePasswordForm(): View { return view('user.change_password'); } /** * Handle user password change. */ public function updatePassword(UpdatePasswordRequest $request): RedirectResponse { $user = Auth::user(); $this->userService->updatePassword($user, $request->input('password')); $route = $user->role == config('constants.ROLE_ADMIN') ? 'admin.dashboard' : 'user.dashboard'; return redirect()->route($route)->with('success', __('messages.password_change_success')); } /** * Show the edit profile page (avatar & password). */ public function editProfile(): View { return view('user.edit'); } /** * Handle avatar upload and optional password change. */ public function updateProfile(UpdateProfileRequest $request): RedirectResponse { $user = Auth::user(); $this->userService->updateProfile( $user, $request->validated(), $request->file('avatar') ); return redirect()->route('user.edit')->with('success', 'Cập nhật hồ sơ thành công'); } }