First Commit
This commit is contained in:
Executable
+98
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\AiModel;
|
||||
use App\Models\AiProvider;
|
||||
use App\Models\PromptProject;
|
||||
use App\Services\Ai\AiServiceFactory;
|
||||
use App\Services\AiAgentService;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class AiAgentController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
private readonly AiAgentService $aiAgentService
|
||||
) {}
|
||||
|
||||
public function index(): View
|
||||
{
|
||||
$user = auth()->user();
|
||||
|
||||
$projectsQuery = PromptProject::with(['provider', 'model'])->latest();
|
||||
|
||||
if (!$user || $user->role !== 'superadmin') {
|
||||
$projectsQuery->where('user_id', $user->id);
|
||||
}
|
||||
|
||||
$projects = $projectsQuery->get();
|
||||
|
||||
$providers = AiProvider::where('is_active', true)
|
||||
->orderBy('name')
|
||||
->get();
|
||||
|
||||
$defaultProviderId = 1;
|
||||
$defaultModelId = 11;
|
||||
|
||||
return view('ai-agent.index', compact('projects', 'providers', 'defaultProviderId', 'defaultModelId'));
|
||||
}
|
||||
|
||||
public function execute(Request $request): RedirectResponse
|
||||
{
|
||||
$request->validate([
|
||||
'project_id' => 'nullable|exists:prompt_projects,id',
|
||||
'prompt_text' => 'required|string',
|
||||
'provider_id' => 'required|exists:ai_providers,id',
|
||||
'model_id' => 'required|exists:ai_models,id',
|
||||
'temperature' => 'nullable|numeric|min:0|max:1',
|
||||
'max_tokens' => 'nullable|integer|min:1|max:128000',
|
||||
]);
|
||||
|
||||
$provider = AiProvider::where('id', $request->provider_id)
|
||||
->where('is_active', true)
|
||||
->firstOrFail();
|
||||
|
||||
$model = AiModel::where('id', $request->model_id)
|
||||
->where('provider_id', $provider->id)
|
||||
->where('is_active', true)
|
||||
->firstOrFail();
|
||||
|
||||
$result = $this->aiAgentService->execute(
|
||||
prompt: $request->prompt_text,
|
||||
provider: $provider,
|
||||
model: $model,
|
||||
temperature: (float) ($request->temperature ?? 0.7),
|
||||
maxTokens: (int) ($request->max_tokens ?? 1024),
|
||||
);
|
||||
|
||||
return redirect()->route('ai-agent.index')
|
||||
->with('success', 'Execução concluída com sucesso.')
|
||||
->with('agent_result', $result)
|
||||
->withInput([
|
||||
'project_id' => $request->project_id,
|
||||
'prompt_text' => $request->prompt_text,
|
||||
'provider_id' => $request->provider_id,
|
||||
'model_id' => $request->model_id,
|
||||
'temperature' => $request->temperature,
|
||||
'max_tokens' => $request->max_tokens,
|
||||
]);
|
||||
}
|
||||
|
||||
public function getModels(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'provider_id' => 'required|exists:ai_providers,id',
|
||||
]);
|
||||
|
||||
$models = AiModel::where('provider_id', $request->provider_id)
|
||||
->where('is_active', true)
|
||||
->orderBy('name')
|
||||
->get(['id', 'name', 'slug']);
|
||||
|
||||
return response()->json($models);
|
||||
}
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Controllers\AiProvider;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\AiProvider\StoreAiProviderRequest;
|
||||
use App\Http\Requests\AiProvider\UpdateAiProviderRequest;
|
||||
use App\Services\AiProviderService;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class AiProviderController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly AiProviderService $aiProviderService
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index(): View
|
||||
{
|
||||
$this->authorize('viewAny', \App\Models\AiProvider::class);
|
||||
|
||||
$result = $this->aiProviderService->index();
|
||||
$providers = $result['data'] ?? [];
|
||||
|
||||
return view('ai-providers.index', compact('providers'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*/
|
||||
public function show(\App\Models\AiProvider $aiProvider): View
|
||||
{
|
||||
$this->authorize('view', $aiProvider);
|
||||
|
||||
return view('ai-providers.show', compact('aiProvider'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*/
|
||||
public function create(): View
|
||||
{
|
||||
$this->authorize('create', \App\Models\AiProvider::class);
|
||||
|
||||
return view('ai-providers.create');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(StoreAiProviderRequest $request): RedirectResponse
|
||||
{
|
||||
$this->authorize('create', \App\Models\AiProvider::class);
|
||||
|
||||
$this->aiProviderService->store($request->validated());
|
||||
|
||||
return redirect()->route('ai-providers.index')
|
||||
->with('success', 'Provider created successfully.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*/
|
||||
public function edit(\App\Models\AiProvider $aiProvider): View
|
||||
{
|
||||
$this->authorize('update', $aiProvider);
|
||||
|
||||
return view('ai-providers.edit', compact('aiProvider'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update(UpdateAiProviderRequest $request, \App\Models\AiProvider $aiProvider): RedirectResponse
|
||||
{
|
||||
$this->authorize('update', $aiProvider);
|
||||
|
||||
$this->aiProviderService->update($aiProvider, $request->validated());
|
||||
|
||||
return redirect()->route('ai-providers.index')
|
||||
->with('success', 'Provider updated successfully.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*/
|
||||
public function destroy(\App\Models\AiProvider $aiProvider): RedirectResponse
|
||||
{
|
||||
$this->authorize('delete', $aiProvider);
|
||||
|
||||
$this->aiProviderService->destroy($aiProvider);
|
||||
|
||||
return redirect()->route('ai-providers.index')
|
||||
->with('success', 'Provider deleted successfully.');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Auth\LoginRequest;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class AuthenticatedSessionController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display the login view.
|
||||
*/
|
||||
public function create(): View
|
||||
{
|
||||
return view('auth.login');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming authentication request.
|
||||
*/
|
||||
public function store(LoginRequest $request): RedirectResponse
|
||||
{
|
||||
$request->authenticate();
|
||||
|
||||
$request->session()->regenerate();
|
||||
|
||||
return redirect()->intended(route('dashboard', absolute: false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy an authenticated session.
|
||||
*/
|
||||
public function destroy(Request $request): RedirectResponse
|
||||
{
|
||||
Auth::guard('web')->logout();
|
||||
|
||||
$request->session()->invalidate();
|
||||
|
||||
$request->session()->regenerateToken();
|
||||
|
||||
return redirect('/');
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
|
||||
class CaptchaController extends Controller
|
||||
{
|
||||
/**
|
||||
* Generate a new arithmetic captcha.
|
||||
*/
|
||||
public function generate(Request $request): \Illuminate\Http\JsonResponse
|
||||
{
|
||||
$a = random_int(1, 20);
|
||||
$b = random_int(1, 20);
|
||||
$operations = ['+', '-', '*'];
|
||||
$operation = $operations[array_rand($operations)];
|
||||
|
||||
if ($operation === '+') {
|
||||
$answer = $a + $b;
|
||||
} elseif ($operation === '-') {
|
||||
$answer = $a - $b;
|
||||
} else {
|
||||
$answer = $a * $b;
|
||||
}
|
||||
|
||||
$expression = "{$a} {$operation} {$b} = ?";
|
||||
|
||||
Session::put('captcha_answer', (string) $answer);
|
||||
|
||||
return response()->json([
|
||||
'expression' => $expression,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class ConfirmablePasswordController extends Controller
|
||||
{
|
||||
/**
|
||||
* Show the confirm password view.
|
||||
*/
|
||||
public function show(): View
|
||||
{
|
||||
return view('auth.confirm-password');
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm the user's password.
|
||||
*/
|
||||
public function store(Request $request): RedirectResponse
|
||||
{
|
||||
if (! Auth::guard('web')->validate([
|
||||
'email' => $request->user()->email,
|
||||
'password' => $request->password,
|
||||
])) {
|
||||
throw ValidationException::withMessages([
|
||||
'password' => __('auth.password'),
|
||||
]);
|
||||
}
|
||||
|
||||
$request->session()->put('auth.password_confirmed_at', time());
|
||||
|
||||
return redirect()->intended(route('dashboard', absolute: false));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class EmailVerificationNotificationController extends Controller
|
||||
{
|
||||
/**
|
||||
* Send a new email verification notification.
|
||||
*/
|
||||
public function store(Request $request): RedirectResponse
|
||||
{
|
||||
if ($request->user()->hasVerifiedEmail()) {
|
||||
return redirect()->intended(route('dashboard', absolute: false));
|
||||
}
|
||||
|
||||
$request->user()->sendEmailVerificationNotification();
|
||||
|
||||
return back()->with('status', 'verification-link-sent');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class EmailVerificationPromptController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display the email verification prompt.
|
||||
*/
|
||||
public function __invoke(Request $request): RedirectResponse|View
|
||||
{
|
||||
return $request->user()->hasVerifiedEmail()
|
||||
? redirect()->intended(route('dashboard', absolute: false))
|
||||
: view('auth.verify-email');
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\User;
|
||||
use Illuminate\Auth\Events\PasswordReset;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\Rules;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class NewPasswordController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display the password reset view.
|
||||
*/
|
||||
public function create(Request $request): View
|
||||
{
|
||||
return view('auth.reset-password', ['request' => $request]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming new password request.
|
||||
*
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function store(Request $request): RedirectResponse
|
||||
{
|
||||
$request->validate([
|
||||
'token' => ['required'],
|
||||
'email' => ['required', 'email'],
|
||||
'password' => ['required', 'confirmed', Rules\Password::defaults()],
|
||||
]);
|
||||
|
||||
// Here we will attempt to reset the user's password. If it is successful we
|
||||
// will update the password on an actual user model and persist it to the
|
||||
// database. Otherwise we will parse the error and return the response.
|
||||
$status = Password::reset(
|
||||
$request->only('email', 'password', 'password_confirmation', 'token'),
|
||||
function (User $user) use ($request) {
|
||||
$user->forceFill([
|
||||
'password' => Hash::make($request->password),
|
||||
'remember_token' => Str::random(60),
|
||||
])->save();
|
||||
|
||||
event(new PasswordReset($user));
|
||||
}
|
||||
);
|
||||
|
||||
// If the password was successfully reset, we will redirect the user back to
|
||||
// the application's home authenticated view. If there is an error we can
|
||||
// redirect them back to where they came from with their error message.
|
||||
return $status == Password::PASSWORD_RESET
|
||||
? redirect()->route('login')->with('status', __($status))
|
||||
: back()->withInput($request->only('email'))
|
||||
->withErrors(['email' => __($status)]);
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Validation\Rules\Password;
|
||||
|
||||
class PasswordController extends Controller
|
||||
{
|
||||
/**
|
||||
* Update the user's password.
|
||||
*/
|
||||
public function update(Request $request): RedirectResponse
|
||||
{
|
||||
$validated = $request->validateWithBag('updatePassword', [
|
||||
'password' => ['required', 'confirmed', Password::defaults()],
|
||||
]);
|
||||
|
||||
$request->user()->update([
|
||||
'password' => Hash::make($validated['password']),
|
||||
]);
|
||||
|
||||
return back()->with('status', 'password-updated');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class PasswordResetLinkController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display the password reset link request view.
|
||||
*/
|
||||
public function create(): View
|
||||
{
|
||||
return view('auth.forgot-password');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming password reset link request.
|
||||
*
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function store(Request $request): RedirectResponse
|
||||
{
|
||||
$request->validate([
|
||||
'email' => ['required', 'email'],
|
||||
]);
|
||||
|
||||
// We will send the password reset link to this user. Once we have attempted
|
||||
// to send the link, we will examine the response then see the message we
|
||||
// need to show to the user. Finally, we'll send out a proper response.
|
||||
$status = Password::sendResetLink(
|
||||
$request->only('email')
|
||||
);
|
||||
|
||||
return $status == Password::RESET_LINK_SENT
|
||||
? back()->with('status', __($status))
|
||||
: back()->withInput($request->only('email'))
|
||||
->withErrors(['email' => __($status)]);
|
||||
}
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Auth\RegisterRequest;
|
||||
use App\Models\User;
|
||||
use Illuminate\Auth\Events\Registered;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class RegisteredUserController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display the registration view.
|
||||
*/
|
||||
public function create(): View
|
||||
{
|
||||
return view('auth.register');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming registration request.
|
||||
*
|
||||
* @throws \Illuminate\Validation\ValidationException
|
||||
*/
|
||||
public function store(RegisterRequest $request): RedirectResponse
|
||||
{
|
||||
$user = User::create([
|
||||
'name' => $request->name,
|
||||
'email' => $request->email,
|
||||
'password' => Hash::make($request->password),
|
||||
'role' => 'pending',
|
||||
'is_approved' => false,
|
||||
]);
|
||||
|
||||
event(new Registered($user));
|
||||
|
||||
Auth::login($user);
|
||||
|
||||
$this->recordDocumentAcceptances($user, $request);
|
||||
|
||||
return redirect(route('dashboard'));
|
||||
}
|
||||
|
||||
private function recordDocumentAcceptances(User $user, RegisterRequest $request): void
|
||||
{
|
||||
$documents = \App\Models\LegalDocument::all()->groupBy('type');
|
||||
|
||||
foreach ($documents as $type => $docs) {
|
||||
$latest = $docs->sortByDesc('version')->first();
|
||||
|
||||
if (!$latest) {
|
||||
continue;
|
||||
}
|
||||
|
||||
\App\Models\UserDocumentAcceptance::create([
|
||||
'user_id' => $user->id,
|
||||
'legal_document_id' => $latest->id,
|
||||
'document_version' => $latest->version,
|
||||
'ip_address' => $request->ip(),
|
||||
'user_agent' => $request->userAgent(),
|
||||
'accepted_at' => now(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Auth\Events\Verified;
|
||||
use Illuminate\Foundation\Auth\EmailVerificationRequest;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
|
||||
class VerifyEmailController extends Controller
|
||||
{
|
||||
/**
|
||||
* Mark the authenticated user's email address as verified.
|
||||
*/
|
||||
public function __invoke(EmailVerificationRequest $request): RedirectResponse
|
||||
{
|
||||
if ($request->user()->hasVerifiedEmail()) {
|
||||
return redirect()->intended(route('dashboard', absolute: false).'?verified=1');
|
||||
}
|
||||
|
||||
if ($request->user()->markEmailAsVerified()) {
|
||||
event(new Verified($request->user()));
|
||||
}
|
||||
|
||||
return redirect()->intended(route('dashboard', absolute: false).'?verified=1');
|
||||
}
|
||||
}
|
||||
Executable
+86
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\AiModel;
|
||||
use App\Models\AiProvider;
|
||||
use App\Services\ChatService;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class ChatController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
private readonly ChatService $chatService
|
||||
) {}
|
||||
|
||||
public function index(): View
|
||||
{
|
||||
$providers = AiProvider::where('is_active', true)
|
||||
->orderBy('name')
|
||||
->get();
|
||||
|
||||
$history = $this->chatService->getHistory();
|
||||
|
||||
$defaultProviderId = 1;
|
||||
$defaultModelId = 2;
|
||||
|
||||
return view('chat.index', compact('providers', 'history', 'defaultProviderId', 'defaultModelId'));
|
||||
}
|
||||
|
||||
public function send(Request $request): JsonResponse
|
||||
{
|
||||
$request->validate([
|
||||
'message' => 'required|string',
|
||||
'provider_id' => 'required|exists:ai_providers,id',
|
||||
'model_id' => 'required|exists:ai_models,id',
|
||||
'temperature' => 'nullable|numeric|min:0|max:1',
|
||||
'max_tokens' => 'nullable|integer|min:1|max:128000',
|
||||
]);
|
||||
|
||||
$provider = AiProvider::where('id', $request->provider_id)
|
||||
->where('is_active', true)
|
||||
->firstOrFail();
|
||||
|
||||
$model = AiModel::where('id', $request->model_id)
|
||||
->where('provider_id', $provider->id)
|
||||
->where('is_active', true)
|
||||
->firstOrFail();
|
||||
|
||||
$result = $this->chatService->sendMessage(
|
||||
userMessage: $request->message,
|
||||
provider: $provider,
|
||||
model: $model,
|
||||
temperature: (float) ($request->temperature ?? 0.7),
|
||||
maxTokens: (int) ($request->max_tokens ?? 8192),
|
||||
);
|
||||
|
||||
return response()->json($result);
|
||||
}
|
||||
|
||||
public function reset(): RedirectResponse
|
||||
{
|
||||
$this->chatService->reset();
|
||||
|
||||
return redirect()->route('chat.index')
|
||||
->with('success', 'Conversa reiniciada.');
|
||||
}
|
||||
|
||||
public function getModels(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'provider_id' => 'required|exists:ai_providers,id',
|
||||
]);
|
||||
|
||||
$models = AiModel::where('provider_id', $request->provider_id)
|
||||
->where('is_active', true)
|
||||
->orderBy('name')
|
||||
->get(['id', 'name', 'slug']);
|
||||
|
||||
return response()->json($models);
|
||||
}
|
||||
}
|
||||
Executable
+12
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
|
||||
abstract class Controller extends BaseController
|
||||
{
|
||||
use AuthorizesRequests, ValidatesRequests;
|
||||
}
|
||||
Executable
+46
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\AiProvider;
|
||||
use App\Services\PromptGenerationService;
|
||||
use App\Services\PromptProjectService;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class DashboardController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
private readonly PromptProjectService $promptProjectService,
|
||||
private readonly PromptGenerationService $promptGenerationService
|
||||
) {}
|
||||
|
||||
public function index(): View
|
||||
{
|
||||
$userId = auth()->id();
|
||||
$user = auth()->user();
|
||||
|
||||
$stats = [
|
||||
'projects' => $this->promptProjectService->index()['total'] ?? 0,
|
||||
'generations' => $this->promptGenerationService->index()->total() ?? 0,
|
||||
'providers' => AiProvider::count(),
|
||||
'tokens' => $user && $user->role === 'superadmin'
|
||||
? \App\Models\PromptGeneration::sum('tokens_used') ?? 0
|
||||
: \App\Models\PromptGeneration::where('user_id', $userId)->sum('tokens_used') ?? 0,
|
||||
];
|
||||
|
||||
$recentGenerationsQuery = \App\Models\PromptGeneration::with(['project', 'model'])
|
||||
->latest()
|
||||
->limit(5);
|
||||
|
||||
if (!$user || $user->role !== 'superadmin') {
|
||||
$recentGenerationsQuery->where('user_id', $userId);
|
||||
}
|
||||
|
||||
$recentGenerations = $recentGenerationsQuery->get();
|
||||
|
||||
return view('dashboard', compact('stats', 'recentGenerations'));
|
||||
}
|
||||
}
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class HomeController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display the welcome page.
|
||||
*/
|
||||
public function index(): View
|
||||
{
|
||||
return view('welcome');
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Controllers\Legal;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\CookieConsent;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class CookieConsentController extends Controller
|
||||
{
|
||||
/**
|
||||
* Store cookie consent preferences.
|
||||
*/
|
||||
public function store(Request $request): JsonResponse
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'consents' => ['required', 'array'],
|
||||
'consents.necessary' => ['required', 'boolean'],
|
||||
'consents.statistics' => ['nullable', 'boolean'],
|
||||
'consents.marketing' => ['nullable', 'boolean'],
|
||||
'consents.preferences' => ['nullable', 'boolean'],
|
||||
]);
|
||||
|
||||
$consent = CookieConsent::updateOrCreate(
|
||||
[
|
||||
'user_id' => Auth::id(),
|
||||
'session_id' => $request->session()->getId(),
|
||||
],
|
||||
[
|
||||
'ip_address' => $request->ip(),
|
||||
'user_agent' => $request->userAgent(),
|
||||
'consents' => $validated['consents'],
|
||||
'accepted_at' => now(),
|
||||
]
|
||||
);
|
||||
|
||||
return response()->json(['success' => true, 'consent_id' => $consent->id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current cookie consent preferences.
|
||||
*/
|
||||
public function show(Request $request)
|
||||
{
|
||||
$consent = CookieConsent::where('user_id', Auth::id())
|
||||
->orWhere('session_id', $request->session()->getId())
|
||||
->latest()
|
||||
->first();
|
||||
|
||||
return response()->json($consent ? $consent->consents : null);
|
||||
}
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Controllers\Legal;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\LegalDocument;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class LegalDocumentController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of legal documents.
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$this->authorize('viewAny', LegalDocument::class);
|
||||
|
||||
$documents = LegalDocument::orderBy('type')->orderByDesc('version')->paginate(20);
|
||||
|
||||
return view('legal.documents.index', compact('documents'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing a legal document.
|
||||
*/
|
||||
public function edit(string $type)
|
||||
{
|
||||
$document = LegalDocument::where('type', $type)->latest('version')->first();
|
||||
|
||||
if (!$document) {
|
||||
$document = new LegalDocument(['type' => $type]);
|
||||
}
|
||||
|
||||
$this->authorize('update', $document);
|
||||
|
||||
return view('legal.documents.edit', compact('document'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update or create a legal document.
|
||||
*/
|
||||
public function update(Request $request, string $type)
|
||||
{
|
||||
$this->authorize('create', LegalDocument::class);
|
||||
|
||||
$validated = $request->validate([
|
||||
'title' => ['required', 'string', 'max:255'],
|
||||
'content' => ['required', 'string'],
|
||||
'version' => ['required', 'string', 'max:50'],
|
||||
'published_at' => ['nullable', 'date'],
|
||||
]);
|
||||
|
||||
$document = LegalDocument::where('type', $type)->latest('version')->first();
|
||||
|
||||
if ($document && $document->version === $validated['version']) {
|
||||
$document->update([
|
||||
'title' => $validated['title'],
|
||||
'content' => $validated['content'],
|
||||
'published_at' => $validated['published_at'] ? now() : null,
|
||||
]);
|
||||
} else {
|
||||
$document = LegalDocument::create(array_merge($validated, [
|
||||
'type' => $type,
|
||||
'published_by' => Auth::id(),
|
||||
'published_at' => $validated['published_at'] ?? now(),
|
||||
]));
|
||||
}
|
||||
|
||||
return redirect()->route('legal.documents.index')->with('success', 'Documento atualizado com sucesso.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the legal document page.
|
||||
*/
|
||||
public function show(string $type)
|
||||
{
|
||||
$document = LegalDocument::where('type', $type)->latest('version')->firstOrFail();
|
||||
|
||||
return view('legal.documents.show', compact('document'));
|
||||
}
|
||||
}
|
||||
Executable
+58
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\PromptGeneration;
|
||||
use App\Models\PromptProject;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class ProfileController extends Controller
|
||||
{
|
||||
public function index(): View
|
||||
{
|
||||
$user = auth()->user();
|
||||
|
||||
$stats = [
|
||||
'projects' => PromptProject::where('user_id', $user->id)->count(),
|
||||
'generations' => PromptGeneration::where('user_id', $user->id)->count(),
|
||||
'tokens' => PromptGeneration::where('user_id', $user->id)->sum('tokens_used') ?? 0,
|
||||
];
|
||||
|
||||
return view('profile.index', compact('user', 'stats'));
|
||||
}
|
||||
|
||||
public function edit(): View
|
||||
{
|
||||
$user = auth()->user();
|
||||
|
||||
return view('profile.edit', compact('user'));
|
||||
}
|
||||
|
||||
public function update(Request $request): RedirectResponse
|
||||
{
|
||||
$user = auth()->user();
|
||||
|
||||
$validated = $request->validate([
|
||||
'name' => 'required|string|max:255',
|
||||
'email' => 'required|email|max:255|unique:users,email,' . $user->id,
|
||||
'avatar' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048',
|
||||
]);
|
||||
|
||||
if ($request->hasFile('avatar')) {
|
||||
$path = $request->file('avatar')->store('avatars', 'public');
|
||||
$user->avatar = $path;
|
||||
}
|
||||
|
||||
$user->name = $validated['name'];
|
||||
$user->email = $validated['email'];
|
||||
|
||||
$user->save();
|
||||
|
||||
return redirect()->route('profile.index')
|
||||
->with('success', 'Perfil atualizado com sucesso.');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Controllers\PromptGeneration;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\PromptGeneration\GeneratePromptRequest;
|
||||
use App\Models\PromptGeneration;
|
||||
use App\Services\PromptGenerationService;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class PromptGenerationController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly PromptGenerationService $promptGenerationService
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Display a listing of prompt generations.
|
||||
*/
|
||||
public function index(): View
|
||||
{
|
||||
$generations = $this->promptGenerationService->index();
|
||||
|
||||
return view('prompt-generations.index', compact('generations'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a new prompt.
|
||||
*/
|
||||
public function generate(GeneratePromptRequest $request): RedirectResponse
|
||||
{
|
||||
$result = $this->promptGenerationService->generate($request->validated());
|
||||
|
||||
return redirect()->route('prompt-generations.index')
|
||||
->with('success', 'Prompt generated successfully.')
|
||||
->with('generation', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified prompt generation.
|
||||
*/
|
||||
public function destroy(Request $request, PromptGeneration $generation): RedirectResponse
|
||||
{
|
||||
$this->authorize('delete', $generation);
|
||||
|
||||
$this->promptGenerationService->destroy($generation);
|
||||
|
||||
return redirect()->back()->with('success', 'Prompt generation deleted successfully.');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Controllers\PromptProject;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\PromptProject\StorePromptProjectRequest;
|
||||
use App\Http\Requests\PromptProject\UpdatePromptProjectRequest;
|
||||
use App\Models\AiProvider;
|
||||
use App\Services\PromptProjectService;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class PromptProjectController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly PromptProjectService $promptProjectService
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index(): View
|
||||
{
|
||||
$result = $this->promptProjectService->index();
|
||||
$projects = $result['data'] ?? [];
|
||||
|
||||
return view('prompt-projects.index', compact('projects'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*/
|
||||
public function create(): View
|
||||
{
|
||||
$this->authorize('create', \App\Models\PromptProject::class);
|
||||
|
||||
$providers = AiProvider::where('is_active', true)->get();
|
||||
|
||||
return view('prompt-projects.create', compact('providers'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(StorePromptProjectRequest $request): RedirectResponse
|
||||
{
|
||||
$this->authorize('create', \App\Models\PromptProject::class);
|
||||
|
||||
$this->promptProjectService->store($request->validated());
|
||||
|
||||
return redirect()->route('prompt-projects.index')
|
||||
->with('success', 'Project created successfully.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*/
|
||||
public function show(\App\Models\PromptProject $promptProject): View
|
||||
{
|
||||
$this->authorize('view', $promptProject);
|
||||
|
||||
$providerModels = \App\Models\AiModel::where('provider_id', $promptProject->provider_id)
|
||||
->where('is_active', true)
|
||||
->get();
|
||||
|
||||
$models = $providerModels->isNotEmpty()
|
||||
? $providerModels
|
||||
: \App\Models\AiModel::where('is_active', true)->get();
|
||||
|
||||
$generations = \App\Models\PromptGeneration::where('project_id', $promptProject->id)
|
||||
->latest()
|
||||
->take(5)
|
||||
->get();
|
||||
|
||||
return view('prompt-projects.show', compact('promptProject', 'models', 'generations'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*/
|
||||
public function edit(\App\Models\PromptProject $promptProject): View
|
||||
{
|
||||
$this->authorize('update', $promptProject);
|
||||
|
||||
$providers = AiProvider::where('is_active', true)->get();
|
||||
|
||||
return view('prompt-projects.edit', compact('promptProject', 'providers'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update(UpdatePromptProjectRequest $request, \App\Models\PromptProject $promptProject): RedirectResponse
|
||||
{
|
||||
$this->authorize('update', $promptProject);
|
||||
|
||||
$this->promptProjectService->update($promptProject, $request->validated());
|
||||
|
||||
return redirect()->route('prompt-projects.show', $promptProject)
|
||||
->with('success', 'Project updated successfully.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*/
|
||||
public function destroy(\App\Models\PromptProject $promptProject): RedirectResponse
|
||||
{
|
||||
$this->authorize('delete', $promptProject);
|
||||
|
||||
$this->promptProjectService->destroy($promptProject);
|
||||
|
||||
return redirect()->route('prompt-projects.index')
|
||||
->with('success', 'Project deleted successfully.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate prompt for the specified project.
|
||||
*/
|
||||
public function generate(\App\Models\PromptProject $promptProject, Request $request): RedirectResponse
|
||||
{
|
||||
$this->authorize('update', $promptProject);
|
||||
|
||||
$model = null;
|
||||
if ($request->filled('model')) {
|
||||
$modelSlug = $request->input('model');
|
||||
|
||||
if ($modelSlug === 'outros') {
|
||||
$customModel = $request->input('custom_model');
|
||||
if ($customModel) {
|
||||
$model = $customModel;
|
||||
}
|
||||
} else {
|
||||
$model = \App\Models\AiModel::where('slug', $modelSlug)
|
||||
->where('is_active', true)
|
||||
->first();
|
||||
}
|
||||
}
|
||||
|
||||
$this->promptProjectService->generate($promptProject, $model, Auth::id());
|
||||
|
||||
return redirect()->route('prompt-projects.show', $promptProject)
|
||||
->with('success', 'Prompt generated successfully.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get built prompt for the specified project.
|
||||
*/
|
||||
public function getPrompt(\App\Models\PromptProject $promptProject): \Illuminate\Http\JsonResponse
|
||||
{
|
||||
$this->authorize('view', $promptProject);
|
||||
|
||||
$prompt = $this->promptProjectService->buildPrompt($promptProject);
|
||||
|
||||
return response()->json(['prompt' => $prompt]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Controllers\PromptTemplate;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\PromptTemplate\StorePromptTemplateRequest;
|
||||
use App\Http\Requests\PromptTemplate\UpdatePromptTemplateRequest;
|
||||
use App\Models\PromptTemplate;
|
||||
use App\Services\PromptTemplateService;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class PromptTemplateController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly PromptTemplateService $promptTemplateService
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index(): View
|
||||
{
|
||||
$this->authorize('viewAny', \App\Models\PromptTemplate::class);
|
||||
|
||||
$result = $this->promptTemplateService->index();
|
||||
$templates = $result['data'] ?? [];
|
||||
|
||||
return view('prompt-templates.index', compact('templates'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*/
|
||||
public function create(): View
|
||||
{
|
||||
$this->authorize('create', \App\Models\PromptTemplate::class);
|
||||
|
||||
return view('prompt-templates.create');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(StorePromptTemplateRequest $request): RedirectResponse
|
||||
{
|
||||
$this->authorize('create', \App\Models\PromptTemplate::class);
|
||||
|
||||
$data = $request->validated();
|
||||
|
||||
if (isset($data['template_data']) && is_string($data['template_data'])) {
|
||||
$data['template_data'] = json_decode($data['template_data'], true);
|
||||
}
|
||||
|
||||
$this->promptTemplateService->store($data);
|
||||
|
||||
return redirect()->route('prompt-templates.index')
|
||||
->with('success', 'Template created successfully.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*/
|
||||
public function edit(\App\Models\PromptTemplate $promptTemplate): View
|
||||
{
|
||||
$this->authorize('update', $promptTemplate);
|
||||
|
||||
return view('prompt-templates.edit', compact('promptTemplate'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update(UpdatePromptTemplateRequest $request, \App\Models\PromptTemplate $promptTemplate): RedirectResponse
|
||||
{
|
||||
$this->authorize('update', $promptTemplate);
|
||||
|
||||
$data = $request->validated();
|
||||
|
||||
if (isset($data['template_data']) && is_string($data['template_data'])) {
|
||||
$data['template_data'] = json_decode($data['template_data'], true);
|
||||
}
|
||||
|
||||
$this->promptTemplateService->update($promptTemplate, $data);
|
||||
|
||||
return redirect()->route('prompt-templates.index')
|
||||
->with('success', 'Template updated successfully.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*/
|
||||
public function destroy(\App\Models\PromptTemplate $promptTemplate): RedirectResponse
|
||||
{
|
||||
$this->authorize('delete', $promptTemplate);
|
||||
|
||||
$this->promptTemplateService->destroy($promptTemplate);
|
||||
|
||||
return redirect()->route('prompt-templates.index')
|
||||
->with('success', 'Template deleted successfully.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all templates as JSON for the dropdown.
|
||||
*/
|
||||
public function api(): JsonResponse
|
||||
{
|
||||
$templates = PromptTemplate::where('is_public', true)
|
||||
->orWhere('user_id', auth()->id())
|
||||
->get(['name', 'template_data']);
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($templates as $template) {
|
||||
$data = $template->template_data;
|
||||
$result[$template->name] = [
|
||||
'title' => $data['title'] ?? $template->name,
|
||||
'objective' => $data['objective'] ?? '',
|
||||
'context' => $data['context'] ?? '',
|
||||
'persona' => $data['persona'] ?? '',
|
||||
'tone' => $data['tone'] ?? '',
|
||||
'constraints' => $data['constraints'] ?? '',
|
||||
'output_format' => $data['output_format'] ?? '',
|
||||
'examples' => $data['examples'] ?? '',
|
||||
'variables' => $data['variables'] ?? '',
|
||||
'temperature' => $data['temperature'] ?? 0.7,
|
||||
'max_tokens' => $data['max_tokens'] ?? 1024,
|
||||
];
|
||||
}
|
||||
|
||||
return response()->json($result);
|
||||
}
|
||||
}
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Controllers\Tutorial;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\TutorialLesson;
|
||||
use App\Models\TutorialQuestion;
|
||||
use App\Models\TutorialUserProgress;
|
||||
use App\Services\TutorialService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\View\View;
|
||||
use Barryvdh\DomPDF\Facade\Pdf;
|
||||
|
||||
class TutorialController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
private readonly TutorialService $tutorialService
|
||||
) {}
|
||||
|
||||
public function index(): View
|
||||
{
|
||||
$lessons = TutorialLesson::orderBy('order')->get();
|
||||
$progress = TutorialUserProgress::where('user_id', Auth::id())->first();
|
||||
|
||||
return view('tutorial.index', compact('lessons', 'progress'));
|
||||
}
|
||||
|
||||
public function lesson(int $id): View
|
||||
{
|
||||
$lesson = TutorialLesson::findOrFail($id);
|
||||
$lessons = TutorialLesson::orderBy('order')->get();
|
||||
$progress = TutorialUserProgress::where('user_id', Auth::id())->first();
|
||||
|
||||
$completedLessons = $progress?->completed_lessons ?? [];
|
||||
if (!in_array($id, $completedLessons)) {
|
||||
$completedLessons[] = $id;
|
||||
if (!$progress) {
|
||||
$progress = TutorialUserProgress::create(['user_id' => Auth::id(), 'completed_lessons' => $completedLessons]);
|
||||
} else {
|
||||
$progress->update(['completed_lessons' => $completedLessons]);
|
||||
}
|
||||
}
|
||||
|
||||
return view('tutorial.lesson', compact('lesson', 'lessons', 'progress'));
|
||||
}
|
||||
|
||||
public function quiz(): View
|
||||
{
|
||||
$questions = TutorialQuestion::orderBy('order')->get();
|
||||
$progress = TutorialUserProgress::where('user_id', Auth::id())->first();
|
||||
|
||||
return view('tutorial.quiz', compact('questions', 'progress'));
|
||||
}
|
||||
|
||||
public function submitQuiz(Request $request): View
|
||||
{
|
||||
$request->validate([
|
||||
'answers' => 'required|array',
|
||||
'answers.*' => 'required|string',
|
||||
]);
|
||||
|
||||
$questions = TutorialQuestion::orderBy('order')->get();
|
||||
$score = 0;
|
||||
$answers = $request->input('answers', []);
|
||||
$results = [];
|
||||
|
||||
foreach ($questions as $question) {
|
||||
$isCorrect = isset($answers[$question->id]) && $answers[$question->id] === $question->correct_answer;
|
||||
if ($isCorrect) {
|
||||
$score++;
|
||||
}
|
||||
$results[] = [
|
||||
'question' => $question->question,
|
||||
'your_answer' => $answers[$question->id] ?? null,
|
||||
'correct_answer' => $question->correct_answer,
|
||||
'is_correct' => $isCorrect,
|
||||
'explanation' => $question->explanation,
|
||||
];
|
||||
}
|
||||
|
||||
$passed = $score >= 6;
|
||||
|
||||
$progress = TutorialUserProgress::where('user_id', Auth::id())->first();
|
||||
if (!$progress) {
|
||||
$progress = TutorialUserProgress::create(['user_id' => Auth::id()]);
|
||||
}
|
||||
|
||||
$progress->update([
|
||||
'quiz_answers' => $answers,
|
||||
'quiz_score' => $score,
|
||||
'quiz_passed' => $passed,
|
||||
'quiz_completed_at' => now(),
|
||||
]);
|
||||
|
||||
return view('tutorial.result', compact('score', 'results', 'passed', 'progress'));
|
||||
}
|
||||
|
||||
public function certificate(): \Illuminate\Http\Response
|
||||
{
|
||||
$user = Auth::user();
|
||||
$progress = TutorialUserProgress::where('user_id', $user->id)->firstOrFail();
|
||||
|
||||
if (!$progress->quiz_passed) {
|
||||
return redirect()->route('tutorial.quiz')->with('error', 'Você precisa passar no quiz para gerar o certificado.');
|
||||
}
|
||||
|
||||
$progress->update(['certificate_generated_at' => now()]);
|
||||
|
||||
$pdf = Pdf::loadView('tutorial.certificate', compact('user', 'progress'));
|
||||
$pdf->setPaper('a4', 'landscape');
|
||||
|
||||
return $pdf->download('certificado-engenharia-prompt-gprompt.pdf');
|
||||
}
|
||||
}
|
||||
Executable
+83
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class UserController extends Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware(['auth', 'verified', 'user.approved']);
|
||||
}
|
||||
|
||||
public function index(): View
|
||||
{
|
||||
$this->authorize('viewAny', User::class);
|
||||
|
||||
$users = User::query()
|
||||
->select(['id', 'name', 'email', 'role', 'is_approved', 'created_at'])
|
||||
->orderByDesc('created_at')
|
||||
->paginate(15);
|
||||
|
||||
$users->each(function ($user) {
|
||||
$user->tokens_used = $user->generations()
|
||||
->where('status', 'completed')
|
||||
->sum('tokens_used') ?? 0;
|
||||
|
||||
$user->generations_count = $user->generations()->count();
|
||||
});
|
||||
|
||||
return view('users.index', compact('users'));
|
||||
}
|
||||
|
||||
public function edit(User $user): View
|
||||
{
|
||||
$this->authorize('update', $user);
|
||||
|
||||
return view('users.edit', compact('user'));
|
||||
}
|
||||
|
||||
public function update(Request $request, User $user): RedirectResponse
|
||||
{
|
||||
$this->authorize('update', $user);
|
||||
|
||||
$validated = $request->validate([
|
||||
'name' => 'required|string|max:255',
|
||||
'email' => 'required|email|max:255|unique:users,email,' . $user->id,
|
||||
'role' => 'required|in:superadmin,user',
|
||||
'is_approved' => 'required|boolean',
|
||||
'password' => 'nullable|string|min:6|confirmed',
|
||||
]);
|
||||
|
||||
if (empty($validated['password'])) {
|
||||
unset($validated['password']);
|
||||
}
|
||||
|
||||
$user->update($validated);
|
||||
|
||||
return redirect()->route('users.index')
|
||||
->with('success', 'Usuário atualizado com sucesso.');
|
||||
}
|
||||
|
||||
public function destroy(User $user): RedirectResponse
|
||||
{
|
||||
$this->authorize('delete', $user);
|
||||
|
||||
if ($user->id === auth()->id()) {
|
||||
return redirect()->route('users.index')
|
||||
->with('error', 'Você não pode excluir a si mesmo.');
|
||||
}
|
||||
|
||||
$user->delete();
|
||||
|
||||
return redirect()->route('users.index')
|
||||
->with('success', 'Usuário excluído com sucesso.');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user