Files
ladill-link/resources/views/links/show.blade.php
T
isaacclad 32a174c826
Deploy Ladill Link / deploy (push) Successful in 2m26s
Simplify destination helper copy on the link detail page.
2026-07-16 20:16:27 +00:00

152 lines
9.4 KiB
PHP

<x-user-layout>
<x-slot name="title">{{ $link->label ?: $link->slug }}</x-slot>
<div class="mx-auto max-w-6xl space-y-6">
<div class="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
<div>
<div class="flex flex-wrap items-center gap-2">
<h1 class="text-2xl font-semibold text-slate-900">{{ $link->label ?: $link->slug }}</h1>
</div>
<div class="mt-1 flex flex-wrap items-center gap-2">
<a href="{{ $link->publicUrl() }}" target="_blank" rel="noopener"
class="inline-flex items-center gap-1 text-emerald-600 hover:text-emerald-700">
{{ $link->publicUrl() }}
<svg class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25" /></svg>
</a>
<x-copy-button :text="$link->publicUrl()" label="Copy" class="text-xs font-medium text-slate-500 hover:text-emerald-700" />
</div>
<p class="mt-2 max-w-xl text-sm text-slate-500">
You can change the destination anytime.
</p>
</div>
@if ($link->is_managed_here)
<form method="POST" action="{{ route('user.links.destroy', $link) }}" onsubmit="return confirm('Delete this link?')">
@csrf @method('DELETE')
<button type="submit" class="text-sm text-red-600 hover:text-red-700">Delete</button>
</form>
@elseif ($link->manage_url)
<a href="{{ $link->manage_url }}" target="_blank" rel="noopener"
class="inline-flex items-center rounded-lg border border-slate-200 px-3 py-1.5 text-sm font-medium text-slate-700 hover:bg-slate-50">
Manage in {{ $link->sourceAppLabel() }}
</a>
@endif
</div>
@if (! $link->is_managed_here)
<div class="rounded-xl border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-900">
This {{ \App\Models\ShortLink::publicHost() }} slug was created in {{ $link->sourceAppLabel() }}. Edit the destination there the short link stays the same and updates automatically.
</div>
@endif
@if ($link->is_managed_here)
<form method="POST" action="{{ route('user.links.update', $link) }}" class="space-y-4 rounded-xl border border-emerald-200 bg-white p-6 shadow-sm">
@csrf @method('PATCH')
<div>
<h2 class="text-base font-semibold text-slate-900">Destination</h2>
<p class="mt-0.5 text-sm text-slate-500">
Change where <span class="font-medium text-emerald-700">{{ $link->publicUrl() }}</span> sends people.
Printed cards, QR codes, and old shares keep working.
</p>
</div>
<div>
<label for="destination_url" class="block text-sm font-medium text-slate-700">Destination URL</label>
<input type="url" name="destination_url" id="destination_url" value="{{ old('destination_url', $link->destination_url) }}" required
placeholder="https://example.com/new-page"
class="mt-1 block w-full rounded-lg border-slate-300 shadow-sm focus:border-emerald-500 focus:ring-emerald-500">
@error('destination_url')<p class="mt-1 text-sm text-red-600">{{ $message }}</p>@enderror
@error('link')<p class="mt-1 text-sm text-red-600">{{ $message }}</p>@enderror
</div>
<div>
<label for="label" class="block text-sm font-medium text-slate-700">Label <span class="font-normal text-slate-400">(optional)</span></label>
<input type="text" name="label" id="label" value="{{ old('label', $link->label) }}"
class="mt-1 block w-full rounded-lg border-slate-300 shadow-sm focus:border-emerald-500 focus:ring-emerald-500">
</div>
<label class="flex items-center gap-2 text-sm text-slate-700">
<input type="hidden" name="is_active" value="0">
<input type="checkbox" name="is_active" value="1" @checked(old('is_active', $link->is_active))
class="rounded border-slate-300 text-emerald-600 focus:ring-emerald-500">
Link is active
</label>
<button type="submit" class="btn-primary">Update destination</button>
</form>
@else
<div class="rounded-xl border border-slate-200 bg-white p-6">
<h2 class="text-base font-semibold text-slate-900">Destination</h2>
<p class="mt-1 break-all text-sm text-slate-600">{{ $link->destination_url }}</p>
</div>
@endif
<div class="space-y-5">
<h2 class="text-base font-semibold text-slate-900">Analytics</h2>
<div class="grid grid-cols-2 gap-4 sm:grid-cols-4">
<div class="rounded-xl border border-slate-200 bg-white p-4">
<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-4">
<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-4">
<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-4">
<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>
<div class="rounded-xl border border-slate-200 bg-white p-6">
<h3 class="text-sm font-semibold text-slate-900">Clicks last 30 days</h3>
@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 sm:grid-cols-2 lg:grid-cols-4">
@include('links.partials.analytics-breakdown', ['title' => 'Devices', 'rows' => $devices, 'empty' => 'No clicks yet'])
@include('links.partials.analytics-breakdown', ['title' => 'Browsers', 'rows' => $browsers, 'empty' => 'No clicks yet'])
@include('links.partials.analytics-breakdown', ['title' => 'Platforms', 'rows' => $platforms, 'empty' => 'No clicks yet'])
@include('links.partials.analytics-breakdown', ['title' => 'Countries', 'rows' => $countries, 'empty' => 'No location data yet'])
</div>
<div class="grid gap-4 lg:grid-cols-2">
@include('links.partials.analytics-breakdown', ['title' => 'Top referrers', 'rows' => $referrers, 'empty' => 'No referrer data yet'])
<div class="rounded-xl border border-slate-200 bg-white">
<div class="border-b border-slate-100 px-5 py-4">
<h3 class="text-sm font-semibold text-slate-900">Recent clicks</h3>
</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="truncate text-slate-700">{{ $click->contextLabel() }}</p>
@if ($click->is_unique)
<p class="text-xs text-emerald-600">Unique visit</p>
@endif
</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>
</div>
</div>
</x-user-layout>