From 01b8dd1930d5f9c72079271a5e4f5c30054cd5bc Mon Sep 17 00:00:00 2001 From: Micha Date: Sun, 18 Jan 2026 18:58:57 +0100 Subject: [PATCH] fixed post count --- app/Http/Controllers/AuthController.php | 49 +++++++++++----------- resources/js/components/PortalTopicRow.jsx | 4 +- resources/js/pages/Home.jsx | 41 ++++++++++++++++++ 3 files changed, 69 insertions(+), 25 deletions(-) diff --git a/app/Http/Controllers/AuthController.php b/app/Http/Controllers/AuthController.php index dadb599..938f622 100644 --- a/app/Http/Controllers/AuthController.php +++ b/app/Http/Controllers/AuthController.php @@ -22,17 +22,18 @@ class AuthController extends Controller public function register(Request $request, CreateNewUser $creator): JsonResponse { $input = [ - 'name' => $request->input('name') ?? $request->input('username'), - 'email' => $request->input('email'), - 'password' => $request->input('password') ?? $request->input('plainPassword'), - 'password_confirmation' => $request->input('password_confirmation') ?? $request->input('plainPassword'), + 'name' => $request->input(key: 'name') ?? $request->input(key: 'username'), + 'email' => $request->input(key: 'email'), + 'password' => $request->input(key: 'password') ?? $request->input(key: 'plainPassword'), + 'password_confirmation' => $request->input(key: 'password_confirmation') + ?? $request->input(key: 'plainPassword'), ]; - $user = $creator->create($input); + $user = $creator->create(input: $input); $user->sendEmailVerificationNotification(); - return response()->json([ + return response()->json(data: [ 'user_id' => $user->id, 'email' => $user->email, 'message' => 'Verification email sent.', @@ -41,46 +42,46 @@ class AuthController extends Controller public function login(Request $request): JsonResponse { - $request->merge([ - 'login' => $request->input('login', $request->input('email')), + $request->merge(input: [ + 'login' => $request->input(key: 'login', default: $request->input(key: 'email')), ]); - $request->validate([ + $request->validate(rules: [ 'login' => ['required', 'string'], 'password' => ['required', 'string'], ]); - $login = trim((string) $request->input('login')); - $loginNormalized = Str::lower($login); + $login = trim(string: (string) $request->input(key: 'login')); + $loginNormalized = Str::lower(value: $login); $userQuery = User::query(); - if (filter_var($login, FILTER_VALIDATE_EMAIL)) { - $userQuery->whereRaw('lower(email) = ?', [$loginNormalized]); + if (filter_var(value: $login, filter: FILTER_VALIDATE_EMAIL)) { + $userQuery->whereRaw(sql: 'lower(email) = ?', bindings: [$loginNormalized]); } else { - $userQuery->where('name_canonical', $loginNormalized); + $userQuery->where(column: 'name_canonical', operator: $loginNormalized); } $user = $userQuery->first(); - if (!$user || !Hash::check($request->input('password'), $user->password)) { - throw ValidationException::withMessages([ + if (!$user || !Hash::check(value: $request->input(key: 'password'), hashedValue: $user->password)) { + throw ValidationException::withMessages(messages: [ 'login' => ['Invalid credentials.'], ]); } if (!$user->hasVerifiedEmail()) { - return response()->json([ + return response()->json(data : [ 'message' => 'Email not verified.', - ], 403); + ], status: 403); } - $token = $user->createToken('api')->plainTextToken; + $token = $user->createToken(name: 'api')->plainTextToken; - return response()->json([ + return response()->json(data: [ 'token' => $token, 'user_id' => $user->id, 'email' => $user->email, - 'roles' => $user->roles()->pluck('name')->values(), + 'roles' => $user->roles()->pluck(column: 'name')->values(), ]); } @@ -88,13 +89,13 @@ class AuthController extends Controller { $user = User::findOrFail($id); - if (!hash_equals($hash, sha1($user->getEmailForVerification()))) { - abort(403); + if (!hash_equals(known_string: $hash, user_string: sha1(string: $user->getEmailForVerification()))) { + abort(code: 403); } if (!$user->hasVerifiedEmail()) { $user->markEmailAsVerified(); - event(new Verified($user)); + event(new Verified(user: $user)); } return redirect('/login'); diff --git a/resources/js/components/PortalTopicRow.jsx b/resources/js/components/PortalTopicRow.jsx index b0f21b4..563b9c8 100644 --- a/resources/js/components/PortalTopicRow.jsx +++ b/resources/js/components/PortalTopicRow.jsx @@ -28,6 +28,8 @@ export default function PortalTopicRow({ thread, forumName, forumId, showForum = return `${day}.${month}.${year} ${hours}:${minutes}:${seconds}` } + const repliesCount = Math.max((thread.posts_count ?? 0) - 1, 0) + return (
@@ -72,7 +74,7 @@ export default function PortalTopicRow({ thread, forumName, forumId, showForum =
-
{thread.posts_count ?? 0}
+
{repliesCount}
{thread.views_count ?? 0}
diff --git a/resources/js/pages/Home.jsx b/resources/js/pages/Home.jsx index 7b5181d..7997115 100644 --- a/resources/js/pages/Home.jsx +++ b/resources/js/pages/Home.jsx @@ -91,7 +91,48 @@ export default function Home() { nodes.forEach((node) => sortNodes(node.children)) } + const aggregateNodes = (node) => { + if (!node.children?.length) { + return { + threads: node.threads_count ?? 0, + views: node.views_count ?? 0, + posts: node.posts_count ?? 0, + last: node.last_post_at ? { at: node.last_post_at, node } : null, + } + } + + let threads = node.threads_count ?? 0 + let views = node.views_count ?? 0 + let posts = node.posts_count ?? 0 + let last = node.last_post_at ? { at: node.last_post_at, node } : null + + node.children.forEach((child) => { + const agg = aggregateNodes(child) + threads += agg.threads + views += agg.views + posts += agg.posts + if (agg.last && (!last || agg.last.at > last.at)) { + last = agg.last + } + }) + + node.threads_count = threads + node.views_count = views + node.posts_count = posts + if (last) { + const source = last.node + node.last_post_at = source.last_post_at + node.last_post_user_id = source.last_post_user_id + node.last_post_user_name = source.last_post_user_name + node.last_post_user_rank_color = source.last_post_user_rank_color + node.last_post_user_group_color = source.last_post_user_group_color + } + + return { threads, views, posts, last } + } + sortNodes(roots) + roots.forEach((root) => aggregateNodes(root)) return roots }, [forums])