Files
Kol-Manager/app/Http/Controllers/SearchController.php

144 lines
5.4 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Http\Controllers;
use App\Models\Client;
use App\Models\ContentBrief;
use App\Models\Event;
use App\Models\Invoice;
use App\Models\RateCard;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
class SearchController extends Controller
{
public function index(Request $request): View
{
$q = trim($request->get('q', ''));
$results = $q ? $this->search($q) : [];
return view('search.index', compact('q', 'results'));
}
/** Quick AJAX endpoint — returns grouped results for the dropdown */
public function quick(Request $request): JsonResponse
{
$q = trim($request->get('q', ''));
if (strlen($q) < 2) {
return response()->json([]);
}
return response()->json($this->search($q, limit: 5));
}
private function search(string $q, int $limit = 20): array
{
$groups = [];
$like = "%{$q}%";
// ── Clients ──────────────────────────────────────────────
$clients = Client::where('name', 'LIKE', $like)
->orWhere('email', 'LIKE', $like)
->orWhere('company', 'LIKE', $like)
->orWhere('ig_handle', 'LIKE', $like)
->orWhere('tiktok_handle', 'LIKE', $like)
->limit($limit)->get();
if ($clients->isNotEmpty()) {
$groups[] = [
'type' => 'clients',
'label' => '👥 Clients',
'items' => $clients->map(fn ($c) => [
'icon' => '👥',
'title' => $c->name,
'subtitle' => collect([$c->company, $c->email])->filter()->implode(' · '),
'url' => route('clients.show', $c),
])->values()->all(),
];
}
// ── Events ───────────────────────────────────────────────
$events = Event::with('client')
->where('title', 'LIKE', $like)
->orWhere('description', 'LIKE', $like)
->orWhere('location', 'LIKE', $like)
->limit($limit)->get();
if ($events->isNotEmpty()) {
$groups[] = [
'type' => 'events',
'label' => '📅 Events',
'items' => $events->map(fn ($e) => [
'icon' => '📅',
'title' => $e->title,
'subtitle' => $e->start_time->format('d M Y') . ($e->client ? ' · ' . $e->client->name : ''),
'url' => route('schedule.index'),
])->values()->all(),
];
}
// ── Invoices ─────────────────────────────────────────────
$invoices = Invoice::with('client')
->where('invoice_number', 'LIKE', $like)
->orWhere('title', 'LIKE', $like)
->limit($limit)->get();
if ($invoices->isNotEmpty()) {
$groups[] = [
'type' => 'invoices',
'label' => '🧾 Invoices',
'items' => $invoices->map(fn ($i) => [
'icon' => '🧾',
'title' => $i->invoice_number . ($i->title ? ' — ' . $i->title : ''),
'subtitle' => ($i->client?->name ?? '') . ' · ' . ($i->formatted_total ?? ''),
'url' => route('invoices.show', $i),
])->values()->all(),
];
}
// ── Content Briefs ───────────────────────────────────────
$content = ContentBrief::with('client')
->where('title', 'LIKE', $like)
->orWhere('description', 'LIKE', $like)
->orWhere('platform', 'LIKE', $like)
->limit($limit)->get();
if ($content->isNotEmpty()) {
$groups[] = [
'type' => 'content',
'label' => '🎬 Content',
'items' => $content->map(fn ($c) => [
'icon' => $c->platform_icon ?? '🎬',
'title' => $c->title,
'subtitle' => ucfirst($c->platform) . ($c->client ? ' · ' . $c->client->name : ''),
'url' => route('content.show', $c),
])->values()->all(),
];
}
// ── Rate Cards ───────────────────────────────────────────
$rateCards = RateCard::where('service_name', 'LIKE', $like)
->orWhere('description', 'LIKE', $like)
->limit($limit)->get();
if ($rateCards->isNotEmpty()) {
$groups[] = [
'type' => 'rate-cards',
'label' => '💰 Rate Cards',
'items' => $rateCards->map(fn ($r) => [
'icon' => '💰',
'title' => $r->service_name,
'subtitle' => $r->description ?? '',
'url' => route('rate-cards.edit', $r),
])->values()->all(),
];
}
return $groups;
}
}