fix(ui): proper 3/4-arc spinner centered in button, honest AI prompt
- Button: wire:loading.remove on label (DOM removal, no z-index fight) spinner span is normal flex child — button's own flex centers it SVG: track circle opacity 25% + 3/4 arc via stroke-dasharray 42.4/56.6, stroke-linecap round, rotated -90deg so arc starts at top - AI prompt: explicitly flags sparse data (<3 links or <10 clicks), requires every claim reference a specific slug, forbids generic padding Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>main
parent
8cd46398c0
commit
add7957430
|
|
@ -54,21 +54,19 @@ class Insights extends Component
|
||||||
$summary = $topLinks->map(fn ($l) => "- {$l->slug} ({$l->clicks_count} clicks) → {$l->target_url}")->implode("\n");
|
$summary = $topLinks->map(fn ($l) => "- {$l->slug} ({$l->clicks_count} clicks) → {$l->target_url}")->implode("\n");
|
||||||
|
|
||||||
$prompt = <<<PROMPT
|
$prompt = <<<PROMPT
|
||||||
You are a link performance analyst for a URL shortener platform. Respond in {$language}.
|
You are a link performance analyst for a URL shortener. Respond in {$language}.
|
||||||
|
|
||||||
Workspace: {$workspace->name}
|
Workspace: {$workspace->name}
|
||||||
Total links analysed: {$linkCount} | Total clicks: {$totalClicks}
|
Links analysed: {$linkCount} | Total clicks: {$totalClicks}
|
||||||
|
|
||||||
Top links:
|
Data:
|
||||||
{$summary}
|
{$summary}
|
||||||
|
|
||||||
Provide 3–4 short, specific insights:
|
Rules:
|
||||||
- Which link types or destinations perform best and why
|
- If fewer than 3 links or fewer than 10 total clicks exist, say so upfront and explain that reliable patterns need more data. Give 1–2 observations possible from the limited data, then stop.
|
||||||
- Patterns across target domains (e.g. social, docs, pricing pages)
|
- Otherwise give 3–4 insights: best-performing destination types, domain patterns, what underperforming links share, one concrete next action.
|
||||||
- What the low-click links have in common and how to improve them
|
- Every claim must reference a specific slug or URL from the data above.
|
||||||
- One concrete next action for this workspace
|
- No generic marketing advice. No padding. Plain language, no excessive formatting.
|
||||||
|
|
||||||
No generic marketing advice. Base every insight on the data above. Be direct, no fluff.
|
|
||||||
PROMPT;
|
PROMPT;
|
||||||
|
|
||||||
$result = app(AiService::class)->complete($prompt);
|
$result = app(AiService::class)->complete($prompt);
|
||||||
|
|
|
||||||
|
|
@ -21,14 +21,16 @@ $cls = $base . ' ' . ($variants[$variant] ?? $variants['primary']);
|
||||||
{{ $attributes->merge(['type' => $type, 'class' => $cls]) }}
|
{{ $attributes->merge(['type' => $type, 'class' => $cls]) }}
|
||||||
@if($action) wire:loading.attr="disabled" wire:target="{{ $action }}" @endif
|
@if($action) wire:loading.attr="disabled" wire:target="{{ $action }}" @endif
|
||||||
>
|
>
|
||||||
<span @if($action) wire:loading.class="opacity-40" wire:target="{{ $action }}" @endif class="flex items-center gap-2">
|
<span @if($action) wire:loading.remove wire:target="{{ $action }}" @endif class="flex items-center gap-2">
|
||||||
{{ $slot->isNotEmpty() ? $slot : $label }}
|
{{ $slot->isNotEmpty() ? $slot : $label }}
|
||||||
</span>
|
</span>
|
||||||
@if($action)
|
@if($action)
|
||||||
<span wire:loading wire:target="{{ $action }}" class="absolute inset-0 flex items-center justify-center rounded-lg bg-inherit">
|
<span wire:loading wire:target="{{ $action }}" class="flex items-center justify-center">
|
||||||
<svg class="animate-spin h-5 w-5 flex-shrink-0" viewBox="0 0 24 24" fill="none">
|
<svg class="animate-spin w-5 h-5 flex-shrink-0" viewBox="0 0 24 24" fill="none">
|
||||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"/>
|
<circle cx="12" cy="12" r="9" stroke="currentColor" stroke-width="2.5" stroke-opacity="0.25"/>
|
||||||
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z"/>
|
<circle cx="12" cy="12" r="9" stroke="currentColor" stroke-width="2.5"
|
||||||
|
stroke-dasharray="42.4 56.6" stroke-linecap="round"
|
||||||
|
transform="rotate(-90 12 12)"/>
|
||||||
</svg>
|
</svg>
|
||||||
</span>
|
</span>
|
||||||
@endif
|
@endif
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue