diff --git a/app/Livewire/Modals/CreateLink.php b/app/Livewire/Modals/CreateLink.php index 656f089..ad7e7e0 100644 --- a/app/Livewire/Modals/CreateLink.php +++ b/app/Livewire/Modals/CreateLink.php @@ -74,12 +74,19 @@ class CreateLink extends ModalComponent public function suggestSlugs(): void { - if (! $this->targetUrl) { + if (! filter_var($this->targetUrl, FILTER_VALIDATE_URL)) { + $this->dispatch('toast', message: 'Bitte zuerst eine gültige URL eingeben', type: 'warning'); + return; } $this->aiLoading = true; - $this->slugSuggestions = app(SlugSuggester::class)->suggest($this->targetUrl); - $this->aiLoading = false; + try { + $this->slugSuggestions = app(SlugSuggester::class)->suggest($this->targetUrl); + } catch (\Exception $e) { + $this->dispatch('toast', message: 'AI-Fehler: '.$e->getMessage(), type: 'error'); + } finally { + $this->aiLoading = false; + } } public function pickSuggestion(string $slug): void diff --git a/app/Livewire/Modals/UtmBuilder.php b/app/Livewire/Modals/UtmBuilder.php index 0380404..7621611 100644 --- a/app/Livewire/Modals/UtmBuilder.php +++ b/app/Livewire/Modals/UtmBuilder.php @@ -6,8 +6,11 @@ use Illuminate\View\View; use Livewire\Attributes\Computed; use LivewireUI\Modal\ModalComponent; +/** @property-read string $fullUrl */ class UtmBuilder extends ModalComponent { + public string $workspaceUlid = ''; + public string $baseUrl = ''; public string $utmSource = ''; @@ -22,6 +25,11 @@ class UtmBuilder extends ModalComponent public bool $copied = false; + public function mount(string $workspaceUlid = ''): void + { + $this->workspaceUlid = $workspaceUlid; + } + #[Computed] public function fullUrl(): string { @@ -55,11 +63,15 @@ class UtmBuilder extends ModalComponent public function createLink(): void { $url = $this->fullUrl; + $wsUlid = $this->workspaceUlid; + if (! $wsUlid) { + $ws = current_workspace(); + $wsUlid = $ws !== null ? $ws->ulid : ''; + } $this->closeModal(); - $ws = current_workspace(); - if ($ws) { + if ($wsUlid) { $this->dispatch('openModal', component: 'modals.create-link', arguments: [ - 'workspaceUlid' => $ws->ulid, + 'workspaceUlid' => $wsUlid, 'prefillUrl' => $url, ]); } diff --git a/app/Livewire/Pages/Ai/Anomalies.php b/app/Livewire/Pages/Ai/Anomalies.php index 07d457b..df78851 100644 --- a/app/Livewire/Pages/Ai/Anomalies.php +++ b/app/Livewire/Pages/Ai/Anomalies.php @@ -4,6 +4,7 @@ namespace App\Livewire\Pages\Ai; use App\Domains\Ai\Services\AiService; use App\Domains\Link\Models\Link; +use App\Domains\Workspace\Models\Workspace; use Illuminate\View\View; use Livewire\Component; @@ -13,9 +14,16 @@ class Anomalies extends Component public bool $loading = false; + public int $workspaceId = 0; + + public function mount(): void + { + $this->workspaceId = require_workspace()->id; + } + public function detect(): void { - $workspace = require_workspace(); + $workspace = Workspace::findOrFail($this->workspaceId); $this->loading = true; $links = Link::where('workspace_id', $workspace->id) diff --git a/app/Livewire/Pages/Ai/Insights.php b/app/Livewire/Pages/Ai/Insights.php index b3407ec..23b80f8 100644 --- a/app/Livewire/Pages/Ai/Insights.php +++ b/app/Livewire/Pages/Ai/Insights.php @@ -4,6 +4,7 @@ namespace App\Livewire\Pages\Ai; use App\Domains\Ai\Services\AiService; use App\Domains\Link\Models\Link; +use App\Domains\Workspace\Models\Workspace; use Illuminate\View\View; use Livewire\Component; @@ -13,9 +14,16 @@ class Insights extends Component public bool $loading = false; + public int $workspaceId = 0; + + public function mount(): void + { + $this->workspaceId = require_workspace()->id; + } + public function generate(): void { - $workspace = require_workspace(); + $workspace = Workspace::findOrFail($this->workspaceId); $this->loading = true; $topLinks = Link::where('workspace_id', $workspace->id) diff --git a/app/Livewire/Pages/Analytics/Index.php b/app/Livewire/Pages/Analytics/Index.php index b8cc98e..b980069 100644 --- a/app/Livewire/Pages/Analytics/Index.php +++ b/app/Livewire/Pages/Analytics/Index.php @@ -46,6 +46,13 @@ class Index extends Component $this->range = in_array($range, ['24h', '7d', '30d', '90d']) ? $range : '7d'; } + public function clearFilters(): void + { + $this->country = ''; + $this->device = ''; + $this->linkId = ''; + } + private function rangeStart(): Carbon { return match ($this->range) { diff --git a/app/Livewire/Pages/Settings/Index.php b/app/Livewire/Pages/Settings/Index.php index 4f6fe87..7c1ca36 100644 --- a/app/Livewire/Pages/Settings/Index.php +++ b/app/Livewire/Pages/Settings/Index.php @@ -2,6 +2,7 @@ namespace App\Livewire\Pages\Settings; +use App\Domains\Workspace\Models\Workspace; use Illuminate\View\View; use Livewire\Component; @@ -28,7 +29,7 @@ class Index extends Component 'workspaceSlug' => 'nullable|string|max:50|alpha_dash', ]); - $ws = \App\Domains\Workspace\Models\Workspace::findOrFail($this->workspaceId); + $ws = Workspace::findOrFail($this->workspaceId); $ws->update([ 'name' => $this->workspaceName, 'slug' => $this->workspaceSlug ?: $ws->slug, diff --git a/resources/css/app.css b/resources/css/app.css index 53df06d..4bc9323 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -46,7 +46,7 @@ --color-b1: rgb(255 255 255 / 8%); --color-b2: rgb(255 255 255 / 14%); --color-t1: #f0f0f5; - --color-t2: #8888a0; + --color-t2: #b8b8d0; --color-t3: #44445a; /* Accent — purple-pink gradient, consistent across both themes */ diff --git a/resources/views/components/sidebar.blade.php b/resources/views/components/sidebar.blade.php index 30acf33..35b77a0 100644 --- a/resources/views/components/sidebar.blade.php +++ b/resources/views/components/sidebar.blade.php @@ -184,12 +184,13 @@ wire:navigate data-nav-link="{{ $item['route'] }}" :title="$store.sidebar.collapsed ? '{{ $item['label'] }}' : ''" - class="flex items-center gap-3 px-3 py-2 rounded-lg text-sm transition-colors group + :class="$store.sidebar.collapsed ? 'justify-center px-2 gap-0' : 'gap-3 px-3'" + class="flex items-center py-2 rounded-lg text-sm transition-colors group {{ $isActive ? 'bg-blue/10 text-blue' : 'text-t2 hover:text-t1 hover:bg-s2' }}" > - + @if($item['icon'] === 'dashboard') diff --git a/resources/views/components/topbar.blade.php b/resources/views/components/topbar.blade.php index c3d687c..fc15be8 100644 --- a/resources/views/components/topbar.blade.php +++ b/resources/views/components/topbar.blade.php @@ -7,7 +7,7 @@ } @endphp -
+
diff --git a/resources/views/layouts/nimuli-app.blade.php b/resources/views/layouts/nimuli-app.blade.php index 3dee09d..d9b9ff3 100644 --- a/resources/views/layouts/nimuli-app.blade.php +++ b/resources/views/layouts/nimuli-app.blade.php @@ -33,7 +33,7 @@ :root { --c-bg: #0a0a0f; --c-s1: #111117; --c-s2: #16161e; --c-b1: rgba(255,255,255,0.08); --c-accent: #7c3aed; - --c-t1: #f0f0f5; --c-t2: #8888a0; + --c-t1: #f0f0f5; --c-t2: #b8b8d0; } [data-theme="light"] { --c-bg: #ffffff; --c-s1: #ffffff; --c-s2: #f9fafb; @@ -114,7 +114,7 @@
@persist('topbar') @@ -160,6 +160,12 @@ el.classList.toggle('text-t2', !isActive); el.classList.toggle('hover:text-t1', !isActive); el.classList.toggle('hover:bg-s2', !isActive); + // Also update icon span — sidebar is persisted so server classes stay stale + var icon = el.querySelector('span.flex-shrink-0'); + if (icon) { + icon.classList.toggle('text-blue', isActive); + icon.classList.toggle('text-t3', !isActive); + } }); } document.addEventListener('DOMContentLoaded', updateActiveNav); diff --git a/resources/views/livewire/modals/create-link.blade.php b/resources/views/livewire/modals/create-link.blade.php index 49606d6..ff9e12f 100644 --- a/resources/views/livewire/modals/create-link.blade.php +++ b/resources/views/livewire/modals/create-link.blade.php @@ -15,7 +15,7 @@ @endforeach diff --git a/resources/views/livewire/pages/analytics/index.blade.php b/resources/views/livewire/pages/analytics/index.blade.php index 57569c4..fb9fff3 100644 --- a/resources/views/livewire/pages/analytics/index.blade.php +++ b/resources/views/livewire/pages/analytics/index.blade.php @@ -47,7 +47,7 @@ @if($country || $device || $linkId) - - - + {{-- Actions + Clicks badge (badge always rightmost) --}} + +
+ {{-- Hover-revealed actions --}} +
+ + + + +
+ {{-- Clicks badge — always visible, rightmost --}} + + {{ number_format($link->clicks_count ?? 0) }} +
@empty - +