First Commit
This commit is contained in:
+170
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Subject;
|
||||
use App\Models\UserInterest;
|
||||
use App\Models\UserSubject;
|
||||
use App\Services\AIService;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\View\View;
|
||||
|
||||
/**
|
||||
* Manages user interests and AI-generated subject suggestions.
|
||||
*/
|
||||
class InterestController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display the user's interests and AI suggestions.
|
||||
*/
|
||||
public function index(): View
|
||||
{
|
||||
/** @var \App\Models\User $user */
|
||||
$user = Auth::user();
|
||||
|
||||
$interests = $user->userInterests()->orderByDesc('created_at')->get();
|
||||
$suggestions = session('suggestions', []);
|
||||
|
||||
return view('admin.interests.index', compact('interests', 'suggestions'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a new user interest.
|
||||
*/
|
||||
public function store(Request $request): RedirectResponse
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'interest' => ['required', 'string', 'max:255'],
|
||||
]);
|
||||
|
||||
/** @var \App\Models\User $user */
|
||||
$user = Auth::user();
|
||||
|
||||
$user->userInterests()->create([
|
||||
'interest' => $validated['interest'],
|
||||
]);
|
||||
|
||||
return back()->with('success', __('Interest added successfully.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified user interest.
|
||||
*/
|
||||
public function destroy(UserInterest $userInterest): RedirectResponse
|
||||
{
|
||||
$this->authorize('delete', $userInterest);
|
||||
|
||||
$userInterest->delete();
|
||||
|
||||
return back()->with('success', __('Interest removed successfully.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate AI subject suggestions based on user interests.
|
||||
*/
|
||||
public function generateSuggestions(Request $request): RedirectResponse
|
||||
{
|
||||
/** @var \App\Models\User $user */
|
||||
$user = Auth::user();
|
||||
|
||||
$interests = $user->userInterests()->pluck('interest')->toArray();
|
||||
|
||||
if (empty($interests)) {
|
||||
return back()->with('error', __('Add at least one interest before generating suggestions.'));
|
||||
}
|
||||
|
||||
$interestsList = implode(', ', $interests);
|
||||
|
||||
$prompt = "Com base nos interesses do usuário: {$interestsList}. Sugira de 3 a 5 temas de assuntos de aprendizado que seriam relevantes para este usuário. Para cada tema, forneça: 1) name (formato: 'Aprendizado e Treinamento de [Tema]'), 2) description (máximo 1000 caracteres), 3) introduction (máximo 5000 caracteres). Retorne APENAS um array JSON válido (sem texto adicional, sem markdown, sem code blocks) com objetos contendo esses campos. Todo o conteúdo deve estar em Português do Brasil.";
|
||||
|
||||
/** @var \App\Services\AIService $ai */
|
||||
$ai = app(AIService::class);
|
||||
$result = $ai->generateInsight('Sugestões de assuntos', $prompt, ['language' => 'pt_BR']);
|
||||
|
||||
if (!$result['success']) {
|
||||
return back()->with('error', __('Failed to generate suggestions: :error', ['error' => $result['error'] ?? __('Unknown error')]));
|
||||
}
|
||||
|
||||
$suggestions = $this->extractJsonFromAiResponse($result['content']);
|
||||
|
||||
if (!$suggestions || !is_array($suggestions)) {
|
||||
return back()->with('error', __('Failed to parse AI suggestions. Please try again.'));
|
||||
}
|
||||
|
||||
return back()->with('suggestions', $suggestions)->with('success', __('Suggestions generated successfully.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a subject automatically from a suggestion.
|
||||
*/
|
||||
public function createSubjectFromSuggestion(Request $request): RedirectResponse
|
||||
{
|
||||
$request->validate([
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
'description' => ['nullable', 'string', 'max:1000'],
|
||||
'introduction' => ['nullable', 'string', 'max:5000'],
|
||||
]);
|
||||
|
||||
$existing = Subject::where('name', $request->name)->first();
|
||||
|
||||
if ($existing) {
|
||||
return back()->with('error', __('A subject with this name already exists.'));
|
||||
}
|
||||
|
||||
$subject = Subject::create([
|
||||
'user_id' => Auth::id(),
|
||||
'name' => $request->name,
|
||||
'description' => $request->description,
|
||||
'introduction' => $request->introduction,
|
||||
'is_system' => false,
|
||||
'is_active' => true,
|
||||
]);
|
||||
|
||||
UserSubject::firstOrCreate(
|
||||
[
|
||||
'user_id' => Auth::id(),
|
||||
'subject_id' => $subject->id,
|
||||
],
|
||||
[
|
||||
'frequency' => 'daily',
|
||||
'preferred_times' => ['09:00'],
|
||||
'insight_language' => Auth::user()->locale ?? 'en',
|
||||
'delivery_channels' => ['dashboard'],
|
||||
'is_active' => true,
|
||||
]
|
||||
);
|
||||
|
||||
return back()->with('success', __('Subject created successfully.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract JSON from AI response, handling code blocks and plain text.
|
||||
*/
|
||||
private function extractJsonFromAiResponse(string $content): ?array
|
||||
{
|
||||
$content = trim($content);
|
||||
|
||||
if (str_starts_with($content, '```')) {
|
||||
$content = preg_replace('/^```(?:json)?\s*/', '', $content);
|
||||
$content = preg_replace('/\s*```$/', '', $content);
|
||||
}
|
||||
|
||||
$data = json_decode($content, true);
|
||||
|
||||
if (json_last_error() === JSON_ERROR_NONE && is_array($data)) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
if (preg_match('/\[.*\]/s', $content, $matches)) {
|
||||
$data = json_decode($matches[0], true);
|
||||
if (json_last_error() === JSON_ERROR_NONE && is_array($data)) {
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user