HEX
Server: LiteSpeed
System: Linux s1049.use1.mysecurecloudhost.com 4.18.0-477.27.2.lve.el8.x86_64 #1 SMP Wed Oct 11 12:32:56 UTC 2023 x86_64
User: xedaptot (3356)
PHP: 8.3.31
Disabled: NONE
Upload Files
File: /home/xedaptot/ai.naniguide.com/app/Http/Controllers/Refactor/SearchController.php
<?php

namespace App\Http\Controllers\Refactor;

use App\Http\Controllers\Controller;
use App\Library\Cache\AppCache;
use Illuminate\Http\Request;

class SearchController extends Controller
{
    /**
     * Unified power search endpoint — returns JSON for all searchable entities.
     */
    public function search(Request $request)
    {
        $customer = $request->user()->customer;
        $keyword = trim($request->keyword ?? '');
        $limit = 5;

        $categories = [];

        if ($keyword !== '') {
            // Campaigns — rich info
            $campaigns = $customer->local()->campaigns()
                ->search($keyword)
                ->orderBy('campaigns.updated_at', 'desc')
                ->paginate($limit);

            if ($campaigns->total() > 0) {
                $categories[] = [
                    'key' => 'campaigns',
                    'label' => trans('refactor/search.section.campaigns'),
                    'icon' => 'campaign',
                    'total' => $campaigns->total(),
                    'items' => $campaigns->map(function ($c) {
                        $statusColors = [
                            'new' => 'default', 'draft' => 'default', 'queuing' => 'blue',
                            'queued' => 'blue', 'sending' => 'orange', 'done' => 'green',
                            'paused' => 'orange', 'error' => 'red',
                        ];
                        $statusLabel = $c->status === 'done' ? 'Sent' : ucfirst($c->status);
                        if ($c->isError()) {
                            $statusLabel = 'Error';
                        } elseif ($c->isPaused()) {
                            $statusLabel = 'Paused';
                        }

                        $openRate = AppCache::for($c)->read('UniqOpenRate', 0);
                        $clickRate = AppCache::for($c)->read('ClickedRate', 0);
                        $subCount = AppCache::for($c)->read('SubscriberCount', 0);
                        $deliveredCount = AppCache::for($c)->read('DeliveredCount', 0);

                        return [
                            'type' => 'campaign',
                            'title' => $c->name,
                            'subtitle' => $c->subject ?: '',
                            'url' => route('refactor.campaigns.overview', $c->uid),
                            'icon' => 'campaign',
                            'badge' => [
                                'label' => $statusLabel,
                                'color' => $statusColors[$c->status] ?? 'default',
                            ],
                            'meta' => [
                                'recipients' => number_format($subCount),
                                'delivered' => number_format($deliveredCount),
                                'open_rate' => $openRate ? round($openRate * 100, 1) . '%' : '—',
                                'click_rate' => $clickRate ? round($clickRate * 100, 1) . '%' : '—',
                                'date' => $c->run_at ? $c->run_at->format('M j, Y') : ($c->created_at ? $c->created_at->format('M j, Y') : ''),
                            ],
                        ];
                    })->values()->toArray(),
                ];
            }

            // Mail Lists
            $lists = $customer->local()->mailLists()
                ->search($keyword)
                ->orderBy('mail_lists.updated_at', 'desc')
                ->paginate($limit);

            if ($lists->total() > 0) {
                $categories[] = [
                    'key' => 'lists',
                    'label' => trans('refactor/search.section.lists'),
                    'icon' => 'list',
                    'total' => $lists->total(),
                    'items' => $lists->map(function ($l) {
                        return [
                            'type' => 'list',
                            'title' => $l->name,
                            'subtitle' => '',
                            'url' => route('refactor.lists.overview', $l->uid),
                            'icon' => 'list',
                            'meta' => [
                                'subscribers' => number_format(AppCache::for($l)->read('SubscriberCount', 0)),
                                'created' => $l->created_at ? $l->created_at->format('M j, Y') : '',
                            ],
                        ];
                    })->values()->toArray(),
                ];
            }

            // Subscribers (cross-list)
            $subscribers = $customer->local()->subscribers()
                ->search($keyword)
                ->orderBy('subscribers.updated_at', 'desc')
                ->paginate($limit);

            if ($subscribers->total() > 0) {
                $categories[] = [
                    'key' => 'subscribers',
                    'label' => trans('refactor/search.section.subscribers'),
                    'icon' => 'person',
                    'total' => $subscribers->total(),
                    'items' => $subscribers->map(function ($s) {
                        $statusColors = [
                            'subscribed' => 'green', 'unsubscribed' => 'default',
                            'unconfirmed' => 'orange', 'spam-reported' => 'red',
                            'blacklisted' => 'red',
                        ];

                        return [
                            'type' => 'subscriber',
                            'title' => $s->email,
                            'subtitle' => $s->getFullName() ?: '',
                            'url' => route('refactor.lists.subscriber_edit', [$s->mailList->uid, $s->id]),
                            'icon' => 'person',
                            'badge' => [
                                'label' => ucfirst($s->status),
                                'color' => $statusColors[$s->status] ?? 'default',
                            ],
                            'avatar' => [
                                'initials' => strtoupper(substr($s->email, 0, 1)),
                                'color' => (ord(strtoupper(substr($s->email, 0, 1))) % 8) + 1,
                            ],
                            'meta' => [
                                'list' => $s->mailList->name,
                                'date' => $s->created_at ? $s->created_at->format('M j, Y') : '',
                            ],
                        ];
                    })->values()->toArray(),
                ];
            }

            // Email Templates — with preview/edit actions
            $templates = $customer->customerEmailTemplates()
                ->whereHas('template', function ($q) use ($keyword) {
                    $q->where('templates.name', 'like', '%' . $keyword . '%');
                })
                ->with('template')
                ->orderBy('updated_at', 'desc')
                ->paginate($limit);

            if ($templates->total() > 0) {
                $categories[] = [
                    'key' => 'templates',
                    'label' => trans('refactor/search.section.templates'),
                    'icon' => 'web',
                    'total' => $templates->total(),
                    'items' => $templates->map(function ($cet) {
                        $t = $cet->template;
                        $categories = $t->categories ? $t->categories->pluck('name')->implode(', ') : '';

                        return [
                            'type' => 'template',
                            'title' => $t->name,
                            'subtitle' => '',
                            'url' => route('refactor.templates.preview', $t->uid),
                            'icon' => 'web',
                            'thumb' => $t->getThumbUrl(),
                            'meta' => [
                                'category' => $categories ?: '',
                                'created' => $t->created_at ? $t->created_at->format('M j, Y') : '',
                                'updated' => $t->updated_at ? $t->updated_at->format('M j, Y') : '',
                            ],
                            'actions' => [
                                ['label' => 'Preview', 'url' => route('refactor.templates.preview', $t->uid), 'icon' => 'visibility'],
                            ],
                        ];
                    })->values()->toArray(),
                ];
            }

            // Automations
            $automations = $customer->local()->automation2s()
                ->search($keyword)
                ->orderBy('automation2s.updated_at', 'desc')
                ->paginate($limit);

            if ($automations->total() > 0) {
                $categories[] = [
                    'key' => 'automations',
                    'label' => trans('refactor/search.section.automations'),
                    'icon' => 'bolt',
                    'total' => $automations->total(),
                    'items' => $automations->map(function ($a) {
                        $statusColors = ['active' => 'green', 'inactive' => 'default'];

                        return [
                            'type' => 'automation',
                            'title' => $a->name,
                            'subtitle' => '',
                            'url' => route('refactor.automations.index'),
                            'icon' => 'bolt',
                            'badge' => [
                                'label' => ucfirst($a->status),
                                'color' => $statusColors[$a->status] ?? 'default',
                            ],
                            'meta' => [
                                'created' => $a->created_at ? $a->created_at->format('M j, Y') : '',
                            ],
                        ];
                    })->values()->toArray(),
                ];
            }

            // Forms — with thumbnail from template
            $forms = $customer->local()->forms()
                ->search($keyword)
                ->with('template', 'mailList')
                ->orderBy('forms.updated_at', 'desc')
                ->paginate($limit);

            if ($forms->total() > 0) {
                $categories[] = [
                    'key' => 'forms',
                    'label' => trans('refactor/search.section.forms'),
                    'icon' => 'dynamic_form',
                    'total' => $forms->total(),
                    'items' => $forms->map(function ($f) {
                        $statusColors = ['published' => 'green', 'draft' => 'default'];
                        $thumb = $f->template ? $f->template->getThumbUrl() : null;

                        return [
                            'type' => 'form',
                            'title' => $f->name,
                            'subtitle' => $f->mailList ? $f->mailList->name : '',
                            'url' => route('refactor.forms.index'),
                            'icon' => 'dynamic_form',
                            'badge' => [
                                'label' => ucfirst($f->status),
                                'color' => $statusColors[$f->status] ?? 'default',
                            ],
                            'thumb' => $thumb,
                            'thumb_ratio' => 'landscape', // 5:3 for forms
                            'actions' => $f->status === 'published' ? [
                                ['label' => 'Preview', 'url' => route('refactor.forms.preview', $f->uid), 'icon' => 'visibility'],
                            ] : [],
                        ];
                    })->values()->toArray(),
                ];
            }

            // Segments (cross-list search)
            $segments = collect();
            $customer->local()->mailLists()->each(function ($list) use ($keyword, &$segments) {
                $list->segments()
                    ->where('segments.name', 'like', '%' . $keyword . '%')
                    ->take(5)
                    ->get()
                    ->each(function ($seg) use (&$segments, $list) {
                        $seg->_list = $list; // attach list for reference
                        $segments->push($seg);
                    });
            });
            $segments = $segments->take($limit);

            if ($segments->count() > 0) {
                $categories[] = [
                    'key' => 'segments',
                    'label' => trans('refactor/search.section.segments'),
                    'icon' => 'filter_alt',
                    'total' => $segments->count(),
                    'items' => $segments->map(function ($seg) {
                        $list = $seg->_list ?? $seg->mailList;

                        return [
                            'type' => 'segment',
                            'title' => $seg->name,
                            'subtitle' => $list ? $list->name : '',
                            'url' => route('refactor.lists.segment_edit', [$list->uid, $seg->uid]),
                            'icon' => 'filter_alt',
                            'meta' => [
                                'subscribers' => number_format(AppCache::for($seg)->read('SubscriberCount', 0)),
                                'match' => $seg->matching === 'all' ? 'Match ALL' : 'Match ANY',
                            ],
                        ];
                    })->values()->toArray(),
                ];
            }
        }

        return response()->json([
            'categories' => $categories,
        ]);
    }

    /**
     * Get customer pages for client-side instant search.
     */
    public static function getPages()
    {
        return [
            // Core
            ['title' => trans('refactor/search.page.dashboard'), 'description' => trans('refactor/search.desc.dashboard'), 'url' => route('refactor.dashboard'), 'icon' => 'dashboard', 'keywords' => 'home overview statistics stats summary report chart'],
            ['title' => trans('refactor/search.page.campaigns'), 'description' => trans('refactor/search.desc.campaigns'), 'url' => route('refactor.campaigns.index'), 'icon' => 'campaign', 'keywords' => 'email send broadcast newsletter bulk ab test schedule'],
            ['title' => trans('refactor/search.page.lists'), 'description' => trans('refactor/search.desc.lists'), 'url' => route('refactor.lists.index'), 'icon' => 'list', 'keywords' => 'mailing audience contacts subscribers list manage import export segment field'],
            ['title' => trans('refactor/search.page.templates'), 'description' => trans('refactor/search.desc.templates'), 'url' => route('refactor.templates.index'), 'icon' => 'web', 'keywords' => 'email design layout builder html drag drop gallery'],
            ['title' => trans('refactor/search.page.automations'), 'description' => trans('refactor/search.desc.automations'), 'url' => route('refactor.automations.index'), 'icon' => 'bolt', 'keywords' => 'workflow trigger autoresponder drip sequence welcome series'],
            ['title' => trans('refactor/search.page.forms'), 'description' => trans('refactor/search.desc.forms'), 'url' => route('refactor.forms.index'), 'icon' => 'dynamic_form', 'keywords' => 'signup embed popup subscribe opt-in landing widget'],
            ['title' => trans('refactor/search.page.funnels'), 'description' => trans('refactor/search.desc.funnels'), 'url' => route('refactor.funnels.index'), 'icon' => 'filter_alt', 'keywords' => 'funnel conversion flow pipeline page builder'],

            // Sending infrastructure
            ['title' => trans('refactor/search.page.sending_servers'), 'description' => trans('refactor/search.desc.sending_servers'), 'url' => route('refactor.sending.servers'), 'icon' => 'dns', 'keywords' => 'smtp server amazon ses sendgrid mailgun sparkpost elastic postmark gmail oauth'],
            ['title' => trans('refactor/search.page.sending_domains'), 'description' => trans('refactor/search.desc.sending_domains'), 'url' => route('refactor.sending.domains'), 'icon' => 'domain', 'keywords' => 'domain dkim spf authentication dns record mx'],
            ['title' => trans('refactor/search.page.tracking_domains'), 'description' => trans('refactor/search.desc.tracking_domains'), 'url' => route('refactor.sending.tracking_domains'), 'icon' => 'track_changes', 'keywords' => 'tracking click open custom domain cname https ssl'],
            ['title' => trans('refactor/search.page.verified_senders'), 'description' => trans('refactor/search.desc.verified_senders'), 'url' => route('refactor.sending.senders'), 'icon' => 'verified', 'keywords' => 'sender identity from address email verified verify'],
            ['title' => trans('refactor/search.page.blacklist'), 'description' => trans('refactor/search.desc.blacklist'), 'url' => route('refactor.sending.blacklist'), 'icon' => 'block', 'keywords' => 'block suppress unsubscribe exclude ban'],
            ['title' => trans('refactor/search.page.email_verification'), 'description' => trans('refactor/search.desc.email_verification'), 'url' => route('refactor.sending.verification_servers'), 'icon' => 'mark_email_read', 'keywords' => 'verify clean validate hygiene bounce list cleaning'],

            // Integrations
            ['title' => trans('refactor/search.page.websites'), 'description' => trans('refactor/search.desc.websites'), 'url' => route('refactor.websites.index'), 'icon' => 'language', 'keywords' => 'integration site connect website embed tracking pixel'],

            // Account settings (enriched keywords for discoverability)
            ['title' => trans('refactor/search.page.account') . ' > ' . trans('refactor/search.page.profile'), 'description' => trans('refactor/search.desc.profile'), 'url' => route('refactor.account.profile'), 'icon' => 'person', 'keywords' => 'name email password change avatar photo image upload timezone language locale first last profile settings account'],
            ['title' => trans('refactor/search.page.account') . ' > ' . trans('refactor/search.page.contact'), 'description' => trans('refactor/search.desc.contact'), 'url' => route('refactor.account.contact'), 'icon' => 'contact_mail', 'keywords' => 'contact information company address phone country city state zip'],
            ['title' => trans('refactor/search.page.account') . ' > ' . trans('refactor/search.page.billing'), 'description' => trans('refactor/search.desc.billing'), 'url' => route('refactor.account.billing'), 'icon' => 'receipt_long', 'keywords' => 'payment invoice billing address credit card receipt history tax vat'],
            ['title' => trans('refactor/search.page.account') . ' > ' . trans('refactor/search.page.subscription'), 'description' => trans('refactor/search.desc.subscription'), 'url' => route('refactor.account.subscription'), 'icon' => 'card_membership', 'keywords' => 'plan upgrade cancel renew downgrade pricing trial subscription quota limit usage'],
            ['title' => trans('refactor/search.page.account') . ' > ' . trans('refactor/search.page.quota'), 'description' => trans('refactor/search.desc.quota'), 'url' => route('refactor.account.quota'), 'icon' => 'data_usage', 'keywords' => 'quota usage limit sending credits subscribers remaining plan allocation'],
            ['title' => trans('refactor/search.page.account') . ' > ' . trans('refactor/search.page.users'), 'description' => trans('refactor/search.desc.users'), 'url' => route('refactor.account.users'), 'icon' => 'group', 'keywords' => 'team user member invite colleague share access multi-user'],
            ['title' => trans('refactor/search.page.account') . ' > ' . trans('refactor/search.page.2fa'), 'description' => trans('refactor/search.desc.2fa'), 'url' => route('refactor.account.2fa'), 'icon' => 'security', 'keywords' => 'two factor 2fa authentication google authenticator security otp totp'],
            ['title' => trans('refactor/search.page.account') . ' > ' . trans('refactor/search.page.api'), 'description' => trans('refactor/search.desc.api'), 'url' => route('refactor.account.api'), 'icon' => 'api', 'keywords' => 'api key token integration rest webhook developer renew regenerate'],
            ['title' => trans('refactor/search.page.activity_log'), 'description' => trans('refactor/search.desc.activity_log'), 'url' => route('refactor.account.logs'), 'icon' => 'history', 'keywords' => 'log activity recent audit trail history event'],
        ];
    }

    /**
     * Get customer quick actions for client-side instant search.
     */
    public static function getActions()
    {
        return [
            ['title' => trans('refactor/search.action.create_campaign'), 'description' => trans('refactor/search.action_desc.create_campaign'), 'url' => route('refactor.campaigns.select_type'), 'icon' => 'add_circle'],
            ['title' => trans('refactor/search.action.create_list'), 'description' => trans('refactor/search.action_desc.create_list'), 'url' => route('refactor.lists.create'), 'icon' => 'add_circle'],
            ['title' => trans('refactor/search.action.create_template'), 'description' => trans('refactor/search.action_desc.create_template'), 'url' => route('refactor.templates.gallery'), 'icon' => 'add_circle'],
            ['title' => trans('refactor/search.action.create_automation'), 'description' => trans('refactor/search.action_desc.create_automation'), 'url' => route('refactor.automations.create'), 'icon' => 'add_circle'],
            ['title' => trans('refactor/search.action.create_form'), 'description' => trans('refactor/search.action_desc.create_form'), 'url' => route('refactor.forms.create'), 'icon' => 'add_circle'],
            ['title' => trans('refactor/search.action.go_dashboard'), 'description' => trans('refactor/search.action_desc.go_dashboard'), 'url' => route('refactor.dashboard'), 'icon' => 'home'],
            ['title' => trans('refactor/search.action.account_settings'), 'description' => trans('refactor/search.action_desc.account_settings'), 'url' => route('refactor.account.profile'), 'icon' => 'settings'],
            ['title' => trans('refactor/search.action.toggle_theme'), 'description' => trans('refactor/search.action_desc.toggle_theme'), 'url' => '#toggle-theme', 'icon' => 'dark_mode'],
        ];
    }
}