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");
|
||||
|
||||
$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}
|
||||
Total links analysed: {$linkCount} | Total clicks: {$totalClicks}
|
||||
Links analysed: {$linkCount} | Total clicks: {$totalClicks}
|
||||
|
||||
Top links:
|
||||
Data:
|
||||
{$summary}
|
||||
|
||||
Provide 3–4 short, specific insights:
|
||||
- Which link types or destinations perform best and why
|
||||
- Patterns across target domains (e.g. social, docs, pricing pages)
|
||||
- What the low-click links have in common and how to improve them
|
||||
- One concrete next action for this workspace
|
||||
|
||||
No generic marketing advice. Base every insight on the data above. Be direct, no fluff.
|
||||
Rules:
|
||||
- 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.
|
||||
- Otherwise give 3–4 insights: best-performing destination types, domain patterns, what underperforming links share, one concrete next action.
|
||||
- Every claim must reference a specific slug or URL from the data above.
|
||||
- No generic marketing advice. No padding. Plain language, no excessive formatting.
|
||||
PROMPT;
|
||||
|
||||
$result = app(AiService::class)->complete($prompt);
|
||||
|
|
|
|||
|
|
@ -21,14 +21,16 @@ $cls = $base . ' ' . ($variants[$variant] ?? $variants['primary']);
|
|||
{{ $attributes->merge(['type' => $type, 'class' => $cls]) }}
|
||||
@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 }}
|
||||
</span>
|
||||
@if($action)
|
||||
<span wire:loading wire:target="{{ $action }}" class="absolute inset-0 flex items-center justify-center rounded-lg bg-inherit">
|
||||
<svg class="animate-spin h-5 w-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"/>
|
||||
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z"/>
|
||||
<span wire:loading wire:target="{{ $action }}" class="flex items-center justify-center">
|
||||
<svg class="animate-spin w-5 h-5 flex-shrink-0" viewBox="0 0 24 24" fill="none">
|
||||
<circle cx="12" cy="12" r="9" stroke="currentColor" stroke-width="2.5" stroke-opacity="0.25"/>
|
||||
<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>
|
||||
</span>
|
||||
@endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue