Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 31 additions & 45 deletions app/Livewire/Header.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use App\Enums\UserRole;
use App\Models\Project;
use Livewire\Component;
use Livewire\Attributes\On;
use Filament\Actions\Action;
use App\Rules\ProfanityCheck;
use App\Settings\GeneralSettings;
Expand Down Expand Up @@ -44,29 +45,23 @@ public function mount()
->get();
}

public function render()
#[On('create-item-from-search')]
public function openSubmitItemWithQuery(string $query): void
{
return view('livewire.header');
// Mount the submit item action with the query as an argument
$this->mountAction('submitItem', ['prefilledTitle' => $query]);
}

public function searchItemAction(): Action
#[On('open-submit-item-modal')]
public function openSubmitItemModal(): void
{
return Action::make('searchItem')
->link()
->color('gray')
->label(function () {
return view('components.search-button-label');
})
->icon('heroicon-o-magnifying-glass')
->extraAttributes(['class' => '!px-3 !py-1.5 rounded-lg text-white hover:text-white hover:bg-white/10 focus:ring-white/20 [&_svg]:text-white'])
->modalWidth('4xl')
->modalFooterActions([
Action::make('👀')->hidden()
])
->modalHeading($this->getRandomFunnyPlaceholder())
->modalIcon('heroicon-o-magnifying-glass')
->modalAlignment(Alignment::Left)
->modalContent(view('modals.search'));
// Mount the submit item action without pre-filled data
$this->mountAction('submitItem');
}

public function render()
{
return view('livewire.header');
}

public function submitItemAction(): Action
Expand Down Expand Up @@ -101,8 +96,23 @@ public function submitItemAction(): Action
->modalIcon('heroicon-o-plus-circle')
->modalWidth('3xl')
->modalSubmitActionLabel('Confirm')
->fillForm(function () {
return $this->currentProjectId ? ['project_id' => $this->currentProjectId] : [];
->mountUsing(function ($form, array $arguments) {
// Fill the form with prefilled data if available
$data = [];

// Add project_id if currentProjectId is set
if ($this->currentProjectId) {
$data['project_id'] = $this->currentProjectId;
}

// Add prefilled title if provided from search
if ($prefilledTitle = $arguments['prefilledTitle'] ?? null) {
$data['title'] = $prefilledTitle;
// Also set similar items for the prefilled title
$this->setSimilarItems($prefilledTitle);
}

$form->fill($data);
})
->schema(function () {
$inputs = [];
Expand Down Expand Up @@ -215,28 +225,4 @@ public function setSimilarItems($state): void
return $query;
})->get(['title', 'slug']) : collect([]);
}

protected function getRandomFunnyPlaceholder(): string
{
$placeholders = [
"Type here to find your lost keys... or your sanity",
"Searching for Wi-Fi signals and lost socks",
"Type something brilliant or your cat will judge you",
"Looking for answers, memes, and cat videos",
"Search for unicorns, we might find one",
"Finding a needle in a digital haystack",
"Type your thoughts, we'll pretend to understand",
"Searching for dinosaurs in the digital age",
"Lost in the web? We've got a virtual map",
"Hunting for pixels and easter eggs",
"Type something epic or order pizza, your choice",
"Lost in the code? We'll be your debugger",
"Looking for a shortcut to success",
"Searching for the meaning of life... or cute cat videos"
];

shuffle($placeholders);

return $placeholders[0];
}
}
117 changes: 117 additions & 0 deletions app/Livewire/SpotlightSearch.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
<?php

namespace App\Livewire;

use App\Models\Item;
use App\Models\Project;
use Illuminate\Support\Collection;
use Livewire\Attributes\On;
use Livewire\Component;

class SpotlightSearch extends Component
{
public string $query = '';
public bool $isOpen = false;
public array $items = [];
public array $projects = [];
public int $totalResults = 0;

#[On('open-spotlight')]
public function open(): void
{
$this->isOpen = true;
$this->query = '';
$this->items = [];
$this->projects = [];
$this->totalResults = 0;

// Dispatch browser event for Alpine.js
$this->dispatch('spotlight-opened');
}

public function close(): void
{
$this->isOpen = false;
$this->query = '';
$this->items = [];
$this->projects = [];
$this->totalResults = 0;
}

public function updatedQuery(): void
{
if (empty(trim($this->query))) {
$this->items = [];
$this->projects = [];
$this->totalResults = 0;
return;
}

$this->searchItems();
$this->searchProjects();
$this->totalResults = count($this->items) + count($this->projects);
}

protected function searchItems(): void
{
$query = Item::query()
->visibleForCurrentUser()
->with(['project', 'board', 'user'])
->where(function ($q) {
$q->where('title', 'like', '%' . $this->query . '%')
->orWhere('content', 'like', '%' . $this->query . '%');
})
->orderByDesc('created_at')
->limit(8);

$this->items = $query->get()->map(function (Item $item) {
return [
'id' => $item->id,
'title' => $item->title,
'slug' => $item->slug,
'project_title' => $item->project?->title,
'board_title' => $item->board?->title,
'votes_count' => $item->total_votes ?? 0,
'created_at' => $item->created_at?->diffForHumans(),
'url' => route('items.show', $item),
];
})->toArray();
}

protected function searchProjects(): void
{
$query = Project::query()
->visibleForCurrentUser()
->with(['boards'])
->where(function ($q) {
$q->where('title', 'like', '%' . $this->query . '%')
->orWhere('description', 'like', '%' . $this->query . '%');
})
->orderBy('title')
->limit(8);

$this->projects = $query->get()->map(function (Project $project) {
return [
'id' => $project->id,
'title' => $project->title,
'slug' => $project->slug,
'description' => $project->description,
'icon' => $project->icon,
'boards_count' => $project->boards->count(),
'url' => route('projects.show', $project),
];
})->toArray();
}

public function createNewItem(): void
{
$query = $this->query;
$this->close();
$this->dispatch('create-item-from-search', query: $query);
}

public function render()
{
return view('livewire.spotlight-search');
}
}
23 changes: 23 additions & 0 deletions lang/en/spotlight.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

return [
'search' => 'Search',
'search_button' => 'Search',
'create-item' => [
'name' => 'Create item',
'description' => 'Create an item',
Expand All @@ -18,4 +19,26 @@
'name' => 'Logout',
'description' => 'Logout out of your account',
],

// Search Interface
'search_placeholder' => 'Search items and projects...',
'section_items' => 'Items',
'section_projects' => 'Projects',
'section_actions' => 'Actions',
'quick_actions' => 'Quick Actions',
'create_new_item' => 'Create new item',
'create_new_item_desc' => 'Create a new roadmap item',
'profile_title' => 'Profile',
'profile_desc' => 'View and edit your profile',
'activity' => 'Activity',
'activity_desc' => 'View recent activity and updates',
'admin_panel' => 'Admin Panel',
'admin_panel_desc' => 'Manage your roadmap settings',
'no_results' => 'No results found for',
'initial_message' => 'Search for items and projects',
'keyboard_hint' => 'Use arrow keys to navigate',
'keyboard_navigate' => 'to navigate',
'keyboard_open' => 'to open',
'results_count' => ':count result|:count results',
'board' => 'board|boards',
];
23 changes: 23 additions & 0 deletions lang/nl/spotlight.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

return [
'search' => 'Zoeken',
'search_button' => 'Zoeken',
'create-item' => [
'name' => 'Item aanmaken',
'description' => 'Maak een item aan',
Expand All @@ -18,4 +19,26 @@
'name' => 'Uitloggen',
'description' => 'Log jezelf uit',
],

// Search Interface
'search_placeholder' => 'Zoek items en projecten...',
'section_items' => 'Items',
'section_projects' => 'Projecten',
'section_actions' => 'Acties',
'quick_actions' => 'Snelle Acties',
'create_new_item' => 'Nieuw item aanmaken',
'create_new_item_desc' => 'Maak een nieuw roadmap item aan',
'profile_title' => 'Profiel',
'profile_desc' => 'Bekijk en bewerk je profiel',
'activity' => 'Activiteit',
'activity_desc' => 'Bekijk recente activiteit en updates',
'admin_panel' => 'Beheerpaneel',
'admin_panel_desc' => 'Beheer je roadmap instellingen',
'no_results' => 'Geen resultaten gevonden voor',
'initial_message' => 'Zoek op items en projecten',
'keyboard_hint' => 'Gebruik de pijltjestoetsen om te navigeren',
'keyboard_navigate' => 'om te navigeren',
'keyboard_open' => 'om te openen',
'results_count' => ':count resultaat|:count resultaten',
'board' => 'board|boards',
];
39 changes: 39 additions & 0 deletions resources/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,42 @@
.fi-ta {
@apply w-full;
}

/* Spotlight Search Styles */
.spotlight-container {
box-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);
}

@media (prefers-color-scheme: dark) {
.spotlight-container {
box-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.5);
}
}

/* Custom scrollbar for spotlight results */
.spotlight-container .max-h-\[60vh\]::-webkit-scrollbar {
width: 8px;
}

.spotlight-container .max-h-\[60vh\]::-webkit-scrollbar-track {
background: transparent;
}

.spotlight-container .max-h-\[60vh\]::-webkit-scrollbar-thumb {
background: rgba(156, 163, 175, 0.3);
border-radius: 4px;
}

.spotlight-container .max-h-\[60vh\]::-webkit-scrollbar-thumb:hover {
background: rgba(156, 163, 175, 0.5);
}

@media (prefers-color-scheme: dark) {
.spotlight-container .max-h-\[60vh\]::-webkit-scrollbar-thumb {
background: rgba(75, 85, 99, 0.5);
}

.spotlight-container .max-h-\[60vh\]::-webkit-scrollbar-thumb:hover {
background: rgba(75, 85, 99, 0.7);
}
}
1 change: 1 addition & 0 deletions resources/views/components/app.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ function updateTheme() {
@livewireScriptConfig
@filamentScripts
@livewire('notifications')
@livewire('spotlight-search')

@stack('javascript')
<x-impersonate::banner/>
Expand Down
6 changes: 0 additions & 6 deletions resources/views/components/search-button-label.blade.php

This file was deleted.

Loading
Loading