random = $random; $this->rows = max(1, $rows); $cfg = timebank_config('calls.welcome_carousel', []); $this->guestPhotoBlur = (int) timebank_config('calls.guest_photo_blur_px', 0); $this->guestPhotoContrast = (int) timebank_config('calls.guest_photo_contrast', 100); $this->guestPhotoSaturate = (int) timebank_config('calls.guest_photo_saturate', 100); $this->guestPhotoBrightness = (int) timebank_config('calls.guest_photo_brightness', 100); $locale = App::getLocale(); $this->showScore = (bool) ($cfg['show_score'] ?? false) || (getActiveProfileType() === 'Admin' && (bool) ($cfg['show_score_for_admins'] ?? true)); // is_public always hardcoded — this is a guest page $query = Call::with([ 'tag.contexts.category.translations', 'tag.contexts.category.ancestors.translations', 'translations', 'location.city.translations', 'location.country.translations', 'callable.locations.city.translations', 'callable.locations.division.translations', 'callable.locations.country.translations', 'callable.loveReactant.reactionCounters', 'loveReactant.reactionCounters', ]) ->where('is_public', true) ->where('is_paused', false) ->where('is_suppressed', false) ->whereNull('deleted_at') ->where(fn ($q) => $q->whereNull('till')->orWhere('till', '>=', now())); $limit = $this->rows * 2; $poolSize = $limit * max(1, (int) ($cfg['pool_multiplier'] ?? 5)); $scorer = new CallCarouselScorer($cfg, null, null, null); $calls = $query->limit($poolSize)->get(); $this->calls = $calls->map(function (Call $call) use ($locale, $scorer) { $translation = $call->translations->firstWhere('locale', $locale) ?? $call->translations->first(); $tag = $call->tag; $tagContext = $tag?->contexts->first(); $tagCategory = $tagContext?->category; $tagColor = $tagCategory?->relatedColor ?? 'gray'; $tagName = $tag?->translation?->name ?? $tag?->name; $locationStr = null; if ($call->location) { $loc = $call->location; $parts = []; if ($loc->city) { $cityName = optional($loc->city->translations->first())->name; if ($cityName) $parts[] = $cityName; } if ($loc->country) { if ($loc->country->code === 'XX') { $parts[] = __('Location not specified'); } elseif ($loc->country->code) { $parts[] = strtoupper($loc->country->code); } } $locationStr = $parts ? implode(', ', $parts) : null; } $tagCategories = []; if ($tagCategory) { $ancestors = $tagCategory->ancestorsAndSelf()->get()->reverse(); foreach ($ancestors as $cat) { $catName = $cat->translations->firstWhere('locale', $locale)?->name ?? $cat->translations->first()?->name ?? ''; if ($catName) { $tagCategories[] = [ 'name' => $catName, 'color' => $cat->relatedColor ?? 'gray', ]; } } } $score = $scorer->score($call); if ($this->random) { $score *= (random_int(85, 115) / 100); } return [ 'id' => $call->id, 'model' => Call::class, 'title' => $tagName ?? '', 'excerpt' => $translation?->content ?? '', 'photo' => $call->callable?->profile_photo_url ?? '', 'location' => $locationStr, 'tag_color' => $tagColor, 'tag_categories' => $tagCategories, 'callable_name' => $call->callable?->name ?? '', 'callable_location' => ProfileCalls::buildCallableLocation($call->callable), 'till' => $call->till, 'expiry_badge_text' => ProfileCalls::buildExpiryBadgeText($call->till), 'like_count' => $call->loveReactant?->reactionCounters ->firstWhere('reaction_type_id', 3)?->count ?? 0, 'score' => $score, ]; }) ->sortByDesc('score') ->take($limit) ->values() ->toArray(); } public function render() { return view('livewire.main-page.call-card-half'); } }