createAchievementPost($user, "follower_{$milestone}", [ 'milestone' => $milestone, 'message' => "🎉 Just reached {$milestone} followers! Thank you all!", ]); break; } } } /** * Check if an artwork's view count crosses a milestone. */ public function maybeArtworkViewMilestone(User $user, int $artworkId, int $newViewCount): void { foreach (self::VIEW_MILESTONES as $milestone) { if ($newViewCount === $milestone) { $this->createAchievementPost($user, "artwork_{$milestone}_views", [ 'artwork_id' => $artworkId, 'milestone' => $milestone, 'message' => "🎨 One of my artworks just hit {$milestone} views!", ], $artworkId); break; } } } /** * Create an achievement post for receiving an award. */ public function awardReceived(User $user, string $awardName, ?int $artworkId = null): void { $this->createAchievementPost($user, 'award_received', [ 'award_name' => $awardName, 'artwork_id' => $artworkId, 'message' => "🏆 Just received the \"{$awardName}\" award!", ], $artworkId); } // ───────────────────────────────────────────────────────────────────────── private function createAchievementPost( User $user, string $achievementType, array $meta, ?int $artworkId = null, ): void { // Deduplicate: don't create the same achievement post twice $exists = Post::where('user_id', $user->id) ->where('type', Post::TYPE_ACHIEVEMENT) ->whereJsonContains('meta->achievement_type', $achievementType) ->exists(); if ($exists) { return; } DB::transaction(function () use ($user, $achievementType, $meta, $artworkId) { $post = Post::create([ 'user_id' => $user->id, 'type' => Post::TYPE_ACHIEVEMENT, 'visibility' => Post::VISIBILITY_PUBLIC, 'body' => $meta['message'] ?? null, 'status' => Post::STATUS_PUBLISHED, 'meta' => array_merge($meta, ['achievement_type' => $achievementType]), ]); if ($artworkId) { PostTarget::create([ 'post_id' => $post->id, 'target_type' => 'artwork', 'target_id' => $artworkId, ]); } }); Log::info("PostAchievementService: created '{$achievementType}' post for user #{$user->id}"); } }