Expand Link app with analytics, settings, and custom domains.
Deploy Ladill Link / deploy (push) Successful in 37s
Deploy Ladill Link / deploy (push) Successful in 37s
Add Bitly-style branded domain support via Ladill Domains SSL API, account analytics dashboard, settings page with default domain picker, and fix SSO/dashboard issues from QR Plus template leftovers. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
@props(['title' => 'Dashboard'])
|
||||
@php
|
||||
$mobileFullScreenPage = false;
|
||||
@endphp
|
||||
@@ -8,7 +9,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
@include('partials.favicon')
|
||||
<title>{{ $title ?? 'Dashboard' }} - Ladill Link</title>
|
||||
<title>{{ $title }} - Ladill Link</title>
|
||||
<link rel="preconnect" href="https://fonts.bunny.net">
|
||||
<link href="https://fonts.bunny.net/css?family=figtree:400,500,600&display=swap" rel="stylesheet" />
|
||||
@vite(['resources/css/app.css', 'resources/js/app.js'])
|
||||
@@ -239,7 +240,7 @@ document.addEventListener('alpine:init', () => {
|
||||
});
|
||||
|
||||
</script>
|
||||
@include('partials.afia')
|
||||
|
||||
@include('partials.sso-keepalive')
|
||||
@include('partials.confirm-prompt')
|
||||
</body>
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
<x-user-layout>
|
||||
<x-slot name="title">Analytics</x-slot>
|
||||
<div class="mx-auto max-w-6xl space-y-6">
|
||||
<div>
|
||||
<h1 class="text-2xl font-semibold text-slate-900">Analytics</h1>
|
||||
<p class="mt-1 text-sm text-slate-500">Click activity across all your short links.</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-2 gap-4 sm:grid-cols-5">
|
||||
<div class="rounded-xl border border-slate-200 bg-white p-5">
|
||||
<p class="text-2xl font-bold text-slate-900">{{ number_format($summary['total_clicks']) }}</p>
|
||||
<p class="mt-0.5 text-xs text-slate-500">Total clicks</p>
|
||||
</div>
|
||||
<div class="rounded-xl border border-slate-200 bg-white p-5">
|
||||
<p class="text-2xl font-bold text-slate-900">{{ number_format($summary['unique_clicks']) }}</p>
|
||||
<p class="mt-0.5 text-xs text-slate-500">Unique clicks</p>
|
||||
</div>
|
||||
<div class="rounded-xl border border-slate-200 bg-white p-5">
|
||||
<p class="text-2xl font-bold text-slate-900">{{ number_format($summary['clicks_7d']) }}</p>
|
||||
<p class="mt-0.5 text-xs text-slate-500">Last 7 days</p>
|
||||
</div>
|
||||
<div class="rounded-xl border border-slate-200 bg-white p-5">
|
||||
<p class="text-2xl font-bold text-slate-900">{{ number_format($summary['clicks_30d']) }}</p>
|
||||
<p class="mt-0.5 text-xs text-slate-500">Last 30 days</p>
|
||||
</div>
|
||||
<div class="rounded-xl border border-slate-200 bg-white p-5">
|
||||
<p class="text-2xl font-bold text-emerald-700">{{ number_format($summary['links_total']) }}</p>
|
||||
<p class="mt-0.5 text-xs text-slate-500">Links created</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="rounded-xl border border-slate-200 bg-white p-6">
|
||||
<h2 class="text-sm font-semibold text-slate-900">Clicks — last 30 days</h2>
|
||||
@php $maxDaily = max(1, $dailyClicks->max('total')); @endphp
|
||||
<div class="mt-5 flex h-28 items-end gap-px">
|
||||
@foreach($dailyClicks as $day)
|
||||
<div class="group relative flex flex-1 flex-col items-center justify-end" title="{{ $day->date }}: {{ $day->total }}">
|
||||
<div class="w-full rounded-t-sm bg-emerald-400/70 transition-colors group-hover:bg-emerald-600"
|
||||
style="height: {{ max(2, ($day->total / $maxDaily) * 100) }}%"></div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid gap-4 lg:grid-cols-2">
|
||||
<div class="rounded-xl border border-slate-200 bg-white p-5">
|
||||
<h2 class="text-sm font-semibold text-slate-900">Top links</h2>
|
||||
<ul class="mt-4 space-y-2.5">
|
||||
@forelse($topLinks as $row)
|
||||
<li class="flex items-center justify-between gap-3 text-sm">
|
||||
<a href="{{ $row['url'] }}" class="truncate text-slate-600 hover:text-emerald-700">{{ $row['label'] }}</a>
|
||||
<span class="shrink-0 font-semibold text-slate-900">{{ number_format($row['total']) }}</span>
|
||||
</li>
|
||||
@empty
|
||||
<li class="text-sm text-slate-400">No clicks yet</li>
|
||||
@endforelse
|
||||
</ul>
|
||||
</div>
|
||||
<div class="rounded-xl border border-slate-200 bg-white p-5">
|
||||
<h2 class="text-sm font-semibold text-slate-900">Top referrers</h2>
|
||||
<ul class="mt-4 space-y-2.5">
|
||||
@forelse($referrers as $row)
|
||||
<li class="flex items-center justify-between gap-3 text-sm">
|
||||
<span class="truncate text-slate-600">{{ $row['label'] }}</span>
|
||||
<span class="shrink-0 font-semibold text-slate-900">{{ number_format($row['total']) }}</span>
|
||||
</li>
|
||||
@empty
|
||||
<li class="text-sm text-slate-400">No referrer data yet</li>
|
||||
@endforelse
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="rounded-xl border border-slate-200 bg-white">
|
||||
<div class="border-b border-slate-100 px-5 py-4">
|
||||
<h2 class="font-semibold text-slate-900">Recent clicks</h2>
|
||||
</div>
|
||||
<ul class="divide-y divide-slate-100">
|
||||
@forelse($recentClicks as $click)
|
||||
<li class="flex items-center justify-between gap-4 px-5 py-3 text-sm">
|
||||
<div class="min-w-0">
|
||||
<p class="font-medium text-slate-900">{{ $click->shortLink?->label ?: $click->shortLink?->slug }}</p>
|
||||
<p class="truncate text-xs text-slate-500">{{ $click->referer ?: 'Direct / unknown' }}</p>
|
||||
</div>
|
||||
<time class="shrink-0 text-xs text-slate-400">{{ $click->clicked_at->diffForHumans() }}</time>
|
||||
</li>
|
||||
@empty
|
||||
<li class="px-5 py-8 text-center text-sm text-slate-400">No clicks recorded yet.</li>
|
||||
@endforelse
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</x-user-layout>
|
||||
@@ -1,4 +1,5 @@
|
||||
<x-layouts.user :title="'Create Link'">
|
||||
<x-user-layout>
|
||||
<x-slot name="title">Create Link</x-slot>
|
||||
<div class="mx-auto max-w-xl space-y-6">
|
||||
<div>
|
||||
<h1 class="text-2xl font-semibold text-slate-900">Create short link</h1>
|
||||
@@ -50,4 +51,4 @@
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</x-layouts.user>
|
||||
</x-user-layout>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<x-layouts.user :title="'Dashboard'">
|
||||
<x-user-layout>
|
||||
<x-slot name="title">Dashboard</x-slot>
|
||||
<div class="mx-auto max-w-5xl space-y-6">
|
||||
<div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
|
||||
<div>
|
||||
@@ -47,4 +48,4 @@
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</x-layouts.user>
|
||||
</x-user-layout>
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
<x-user-layout>
|
||||
<x-slot name="title">Custom Domains</x-slot>
|
||||
<div class="mx-auto max-w-4xl space-y-6">
|
||||
<div>
|
||||
<h1 class="text-2xl font-semibold text-slate-900">Custom Domains</h1>
|
||||
<p class="mt-1 text-sm text-slate-500">Use your own domain for short links — like Bitly branded domains. Point DNS to Ladill, we handle SSL.</p>
|
||||
</div>
|
||||
|
||||
@unless($enabled)
|
||||
<div class="rounded-xl border border-amber-200 bg-amber-50 p-4 text-sm text-amber-900">
|
||||
Custom domains are not configured on this environment yet. Contact support to enable the Domains API key.
|
||||
</div>
|
||||
@endunless
|
||||
|
||||
@if($enabled)
|
||||
<div class="rounded-xl border border-slate-200 bg-white p-6">
|
||||
<h2 class="font-semibold text-slate-900">Connect a domain</h2>
|
||||
<p class="mt-1 text-sm text-slate-500">Example: <span class="font-medium">go.yourbrand.com</span> → short links like <span class="font-medium">go.yourbrand.com/summer-sale</span></p>
|
||||
<form method="POST" action="{{ route('link.domains.store') }}" class="mt-5 space-y-4">
|
||||
@csrf
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-slate-700">Domain</label>
|
||||
<input type="text" name="host" value="{{ old('host') }}" placeholder="go.yourbrand.com"
|
||||
class="mt-1 w-full rounded-lg border-slate-200 text-sm" required>
|
||||
@error('host')<p class="mt-1 text-xs text-red-600">{{ $message }}</p>@enderror
|
||||
</div>
|
||||
<label class="flex items-center gap-2 text-sm text-slate-600">
|
||||
<input type="checkbox" name="include_www" value="1" checked class="rounded border-slate-300 text-emerald-600">
|
||||
Include www subdomain in certificate
|
||||
</label>
|
||||
<label class="flex items-center gap-2 text-sm text-slate-600">
|
||||
<input type="checkbox" name="make_default" value="1" class="rounded border-slate-300 text-emerald-600">
|
||||
Make default domain for new links
|
||||
</label>
|
||||
<p class="text-xs text-slate-500">Add an <strong>A record</strong> for your domain pointing to <code class="rounded bg-slate-100 px-1">{{ $serverIp }}</code>, then click Verify.</p>
|
||||
<button type="submit" class="rounded-lg bg-emerald-600 px-4 py-2 text-sm font-semibold text-white hover:bg-emerald-700">Add domain</button>
|
||||
</form>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="rounded-xl border border-slate-200 bg-white">
|
||||
<div class="border-b border-slate-100 px-5 py-4">
|
||||
<h2 class="font-semibold text-slate-900">Your domains</h2>
|
||||
</div>
|
||||
@if($domains->isEmpty())
|
||||
<p class="px-5 py-8 text-center text-sm text-slate-400">No custom domains yet. Your links use <span class="font-medium text-emerald-700">{{ $publicDomain }}</span> by default.</p>
|
||||
@else
|
||||
<ul class="divide-y divide-slate-100">
|
||||
@foreach($domains as $domain)
|
||||
<li class="px-5 py-4">
|
||||
<div class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
|
||||
<div>
|
||||
<p class="font-medium text-slate-900">{{ $domain->host }}</p>
|
||||
<p class="mt-1 text-xs text-slate-500">
|
||||
DNS: {{ $domain->dns_verified_at ? 'verified' : 'pending' }} ·
|
||||
SSL: {{ $domain->ssl_status }} ·
|
||||
@if($domain->is_default)<span class="font-medium text-emerald-700">Default</span>@endif
|
||||
</p>
|
||||
@if($domain->last_error)
|
||||
<p class="mt-1 text-xs text-red-600">{{ $domain->last_error }}</p>
|
||||
@endif
|
||||
</div>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
@if($enabled && $domain->ssl_status !== 'active')
|
||||
<form method="POST" action="{{ route('link.domains.verify', $domain) }}">
|
||||
@csrf
|
||||
<button class="rounded-lg border border-slate-200 px-3 py-1.5 text-xs font-medium text-slate-700 hover:bg-slate-50">Verify DNS</button>
|
||||
</form>
|
||||
@endif
|
||||
@if($domain->isLive() && ! $domain->is_default)
|
||||
<form method="POST" action="{{ route('link.domains.default', $domain) }}">
|
||||
@csrf
|
||||
<button class="rounded-lg border border-emerald-200 px-3 py-1.5 text-xs font-medium text-emerald-700 hover:bg-emerald-50">Make default</button>
|
||||
</form>
|
||||
@endif
|
||||
<form method="POST" action="{{ route('link.domains.destroy', $domain) }}" onsubmit="return confirm('Remove this domain?')">
|
||||
@csrf @method('DELETE')
|
||||
<button class="rounded-lg border border-red-200 px-3 py-1.5 text-xs font-medium text-red-700 hover:bg-red-50">Remove</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<p class="text-sm text-slate-500">
|
||||
Domains also appear in <a href="{{ ladill_domains_url() }}" class="font-medium text-emerald-700 hover:underline">Ladill Domains</a> once connected.
|
||||
</p>
|
||||
</div>
|
||||
</x-user-layout>
|
||||
@@ -1,4 +1,5 @@
|
||||
<x-layouts.user :title="'My Links'">
|
||||
<x-user-layout>
|
||||
<x-slot name="title">My Links</x-slot>
|
||||
<div class="mx-auto max-w-5xl space-y-6">
|
||||
<div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
|
||||
<div>
|
||||
@@ -52,4 +53,4 @@
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</x-layouts.user>
|
||||
</x-user-layout>
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
<x-user-layout>
|
||||
<x-slot name="title">Settings</x-slot>
|
||||
<div class="mx-auto max-w-3xl space-y-6">
|
||||
<div>
|
||||
<h1 class="text-2xl font-semibold text-slate-900">Settings</h1>
|
||||
<p class="mt-1 text-sm text-slate-500">Manage your Ladill Link preferences.</p>
|
||||
</div>
|
||||
|
||||
<div class="rounded-xl border border-slate-200 bg-white p-6">
|
||||
<h2 class="font-semibold text-slate-900">Default short-link domain</h2>
|
||||
<p class="mt-1 text-sm text-slate-500">Choose which domain new links are shown on. Custom domains must be verified first.</p>
|
||||
<form method="POST" action="{{ route('link.settings.default-domain') }}" class="mt-4 space-y-3">
|
||||
@csrf @method('PUT')
|
||||
<label class="flex items-center gap-3 rounded-lg border border-slate-200 px-4 py-3">
|
||||
<input type="radio" name="domain" value="platform" @checked(! $defaultDomain) class="text-emerald-600">
|
||||
<span class="text-sm text-slate-700"><span class="font-medium">{{ $publicDomain }}</span> — Ladill default</span>
|
||||
</label>
|
||||
@foreach($customDomains->where('status', 'active')->where('ssl_status', 'active') as $domain)
|
||||
<label class="flex items-center gap-3 rounded-lg border border-slate-200 px-4 py-3">
|
||||
<input type="radio" name="domain" value="{{ $domain->id }}" @checked($defaultDomain?->id === $domain->id) class="text-emerald-600">
|
||||
<span class="text-sm text-slate-700"><span class="font-medium">{{ $domain->host }}</span> — custom domain</span>
|
||||
</label>
|
||||
@endforeach
|
||||
<button type="submit" class="rounded-lg bg-emerald-600 px-4 py-2 text-sm font-semibold text-white hover:bg-emerald-700">Save</button>
|
||||
</form>
|
||||
<p class="mt-3 text-xs text-slate-500">
|
||||
<a href="{{ route('link.domains.index') }}" class="font-medium text-emerald-700 hover:underline">Manage custom domains →</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="rounded-xl border border-slate-200 bg-white p-6">
|
||||
<h2 class="font-semibold text-slate-900">Billing</h2>
|
||||
<p class="mt-1 text-sm text-slate-500">GHS {{ number_format($pricePerLink, 2) }} per link created. Charged to your Ladill wallet.</p>
|
||||
<div class="mt-4 flex flex-wrap gap-3">
|
||||
<a href="{{ route('account.wallet') }}" class="rounded-lg border border-slate-200 px-4 py-2 text-sm font-medium text-slate-700 hover:bg-slate-50">Wallet</a>
|
||||
<a href="{{ route('account.billing') }}" class="rounded-lg border border-slate-200 px-4 py-2 text-sm font-medium text-slate-700 hover:bg-slate-50">Billing history</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="rounded-xl border border-slate-200 bg-white p-6">
|
||||
<h2 class="font-semibold text-slate-900">Ladill Account</h2>
|
||||
<p class="mt-1 text-sm text-slate-500">Profile, security, and platform settings live on your Ladill account.</p>
|
||||
<a href="{{ ladill_account_url('account-settings') }}" class="mt-4 inline-flex rounded-lg border border-slate-200 px-4 py-2 text-sm font-medium text-slate-700 hover:bg-slate-50">
|
||||
Open account settings
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</x-user-layout>
|
||||
@@ -1,4 +1,5 @@
|
||||
<x-layouts.user :title="$link->label ?: $link->slug">
|
||||
<x-user-layout>
|
||||
<x-slot name="title">{{ $link->label ?: $link->slug }}</x-slot>
|
||||
<div class="mx-auto max-w-3xl space-y-6">
|
||||
<div class="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
|
||||
<div>
|
||||
@@ -55,4 +56,4 @@
|
||||
<button type="submit" class="rounded-lg bg-emerald-600 px-4 py-2 text-sm font-semibold text-white hover:bg-emerald-700">Save changes</button>
|
||||
</form>
|
||||
</div>
|
||||
</x-layouts.user>
|
||||
</x-user-layout>
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
'icon' => '<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 12 11.2 3.05c.44-.44 1.15-.44 1.59 0L21.75 12M4.5 9.75v10.5a.75.75 0 0 0 .75.75H9.75v-6a.75.75 0 0 1 .75-.75h3a.75.75 0 0 1 .75.75v6h4.5a.75.75 0 0 0 .75-.75V9.75" />'],
|
||||
['name' => 'My Links', 'route' => route('user.links.index'), 'active' => request()->routeIs('user.links.*'),
|
||||
'icon' => '<path stroke-linecap="round" stroke-linejoin="round" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622 1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244" />'],
|
||||
['name' => 'Analytics', 'route' => route('link.analytics.index'), 'active' => request()->routeIs('link.analytics.*'),
|
||||
'icon' => '<path stroke-linecap="round" stroke-linejoin="round" d="M3 13.125C3 12.504 3.504 12 4.125 12h2.25c.621 0 1.125.504 1.125 1.125v6.75C7.5 20.496 6.996 21 6.375 21h-2.25A1.125 1.125 0 0 1 3 19.875v-6.75ZM9.75 8.625c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125v11.25c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V8.625ZM16.5 4.125c0-.621.504-1.125 1.125-1.125h2.25C20.496 3 21 3.504 21 4.125v15.75c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V4.125Z" />'],
|
||||
['name' => 'Custom Domains', 'route' => route('link.domains.index'), 'active' => request()->routeIs('link.domains.*'),
|
||||
'icon' => '<path stroke-linecap="round" stroke-linejoin="round" d="M12 21a9.004 9.004 0 0 0 8.716-6.747M12 21a9.004 9.004 0 0 1-8.716-6.747M12 21c2.485 0 4.5-4.03 4.5-9S14.485 3 12 3m0 18c-2.485 0-4.5-4.03-4.5-9S9.515 3 12 3m0 0a8.997 8.997 0 0 1 7.843 4.582M12 3a8.997 8.997 0 0 0-7.843 4.582m15.686 0A11.953 11.953 0 0 1 12 10.5c-2.998 0-5.74-1.1-7.843-2.918m15.686 0A8.959 8.959 0 0 1 21 12c0 .778-.099 1.533-.284 2.253m0 0A17.919 17.919 0 0 1 12 16.5a17.92 17.92 0 0 1-8.716-2.247m0 0A8.966 8.966 0 0 1 3 12c0-1.264.26-2.467.732-3.553" />'],
|
||||
];
|
||||
@endphp
|
||||
<nav class="flex-1 space-y-0.5 overflow-y-auto px-3 py-4">
|
||||
@@ -20,4 +24,14 @@
|
||||
</a>
|
||||
@endforeach
|
||||
</nav>
|
||||
|
||||
<div class="shrink-0 border-t border-slate-100 px-3 py-3">
|
||||
<a href="{{ route('link.settings') }}"
|
||||
class="group flex items-center gap-3 rounded-lg px-3 py-2 text-[13px] transition {{ request()->routeIs('link.settings*') ? 'bg-emerald-50 text-emerald-700 font-semibold' : 'text-slate-600 hover:bg-slate-50 hover:text-slate-900' }}">
|
||||
<svg class="h-[18px] w-[18px] shrink-0 {{ request()->routeIs('link.settings*') ? 'text-emerald-600' : 'text-slate-400' }}" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.325.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 0 1 1.37.49l1.296 2.247a1.125 1.125 0 0 1-.26 1.431l-1.003.827c-.293.241-.438.613-.43.992a7.723 7.723 0 0 1 0 .255c-.008.378.137.75.43.991l1.004.827c.424.35.534.955.26 1.43l-1.298 2.247a1.125 1.125 0 0 1-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.47 6.47 0 0 1-.22.128c-.331.183-.581.495-.644.869l-.213 1.281c-.09.543-.56.94-1.11.94h-2.594c-.55 0-1.019-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 0 1-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 0 1-1.369-.49l-1.297-2.247a1.125 1.125 0 0 1 .26-1.431l1.004-.827c.292-.241.437-.613.43-.992a6.932 6.932 0 0 1 0-.255c.007-.378-.138-.75-.43-.991l-1.004-.827a1.125 1.125 0 0 1-.26-1.43l1.297-2.247a1.125 1.125 0 0 1 1.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.086.22-.128.332-.183.582-.495.644-.869l.214-1.281Z" /><path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
|
||||
</svg>
|
||||
<span class="flex-1 truncate">Settings</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
</button>
|
||||
@include('partials.mobile-topbar-title')
|
||||
<div class="relative hidden min-w-0 flex-1 max-w-md lg:block"
|
||||
x-data="topbarSearch({ searchUrl: @js(route('qr.search')) })"
|
||||
x-data="topbarSearch({ searchUrl: @js(route('user.links.index')) })"
|
||||
@click.outside="open = false"
|
||||
@keydown.escape.window="open = false">
|
||||
<div class="relative">
|
||||
@@ -26,7 +26,7 @@
|
||||
@keydown.arrow-down.prevent="moveDown()"
|
||||
@keydown.arrow-up.prevent="moveUp()"
|
||||
@keydown.enter.prevent="go()"
|
||||
placeholder="Search QR codes…"
|
||||
placeholder="Search links…"
|
||||
class="w-full rounded-xl border border-slate-200 bg-slate-50 py-2 pl-9 pr-10 text-sm text-slate-700 placeholder-slate-400 transition focus:border-indigo-300 focus:bg-white focus:ring-2 focus:ring-indigo-100 focus:outline-none">
|
||||
<kbd class="pointer-events-none absolute right-3 top-1/2 hidden -translate-y-1/2 rounded-md border border-slate-200 bg-white px-1.5 py-0.5 text-[10px] font-medium text-slate-400 sm:inline-block">/</kbd>
|
||||
</div>
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
@include('partials.search-screen', [
|
||||
'query' => $query,
|
||||
'results' => $results,
|
||||
'backUrl' => route('qr.dashboard'),
|
||||
'searchUrl' => route('qr.search'),
|
||||
'backUrl' => route('link.dashboard'),
|
||||
'searchUrl' => route('user.links.index'),
|
||||
'heading' => 'Find QR codes',
|
||||
'placeholder' => 'Search QR codes, short codes, URLs…',
|
||||
'emptyHint' => 'Use at least 2 characters to search labels, short codes, or destinations.',
|
||||
|
||||
Reference in New Issue
Block a user