71 lines
2.1 KiB
PHP
71 lines
2.1 KiB
PHP
<?php
|
|
|
|
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;
|
|
|
|
class Insights extends Component
|
|
{
|
|
public string $insights = '';
|
|
|
|
public string $error = '';
|
|
|
|
public int $workspaceId = 0;
|
|
|
|
public function mount(): void
|
|
{
|
|
$this->workspaceId = require_workspace()->id;
|
|
}
|
|
|
|
public function generate(): void
|
|
{
|
|
$this->error = '';
|
|
$this->insights = '';
|
|
|
|
if (! config('services.openai.api_key')) {
|
|
$this->error = 'OPENAI_API_KEY is not configured. Add it to .env and restart.';
|
|
return;
|
|
}
|
|
|
|
try {
|
|
$workspace = Workspace::findOrFail($this->workspaceId);
|
|
|
|
$topLinks = Link::where('workspace_id', $workspace->id)
|
|
->withCount('clicks')
|
|
->orderByDesc('clicks_count')
|
|
->limit(10)
|
|
->get(['slug', 'target_url', 'clicks_count']);
|
|
|
|
if ($topLinks->isEmpty()) {
|
|
$this->error = 'No links with clicks found. Create and share some links first.';
|
|
return;
|
|
}
|
|
|
|
$summary = $topLinks->map(fn ($l) => "{$l->slug}: {$l->clicks_count} clicks → {$l->target_url}")->implode("\n");
|
|
|
|
$prompt = "You are a marketing analyst. Analyze these link performance stats and provide 3-5 actionable insights:\n\n{$summary}\n\nBe concise and specific.";
|
|
|
|
$result = app(AiService::class)->complete($prompt);
|
|
|
|
if ($result === '') {
|
|
$this->error = 'AI returned an empty response. Check your API key and try again.';
|
|
return;
|
|
}
|
|
|
|
$this->insights = $result;
|
|
} catch (\Throwable $e) {
|
|
$this->error = 'Failed to generate insights: ' . $e->getMessage();
|
|
}
|
|
}
|
|
|
|
public function render(): View
|
|
{
|
|
return view('livewire.pages.ai.insights')
|
|
->layout('layouts.nimuli-app', ['title' => 'AI Insights']);
|
|
}
|
|
}
|