Implement legal document acceptance tracking requiring users to accept terms of service and privacy policy before continuing to use the system. Add automatic generation of standard project files (LICENSE, README.md, RULES.md, cookies.html, termos-de-uso.html, privacidade.html) with download functionality. Enhance prompt building with detailed Portuguese instructions and system requirements. Update seeders with comprehensive legal content and standard files configuration for all prompt templates.
762 lines
30 KiB
PHP
Executable File
762 lines
30 KiB
PHP
Executable File
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\AiModel;
|
|
use App\Models\AiProvider;
|
|
use App\Models\PromptGeneration;
|
|
use App\Models\PromptProject;
|
|
use App\Services\Ai\AiServiceFactory;
|
|
use Illuminate\Http\Client\ConnectionException;
|
|
use Illuminate\Support\Facades\Log;
|
|
use InvalidArgumentException;
|
|
use RuntimeException;
|
|
|
|
class PromptProjectService
|
|
{
|
|
/**
|
|
* Create a new service instance.
|
|
*/
|
|
public function __construct(
|
|
private readonly AiServiceFactory $aiServiceFactory,
|
|
private readonly PromptGeneration $generationModel
|
|
) {
|
|
}
|
|
|
|
/**
|
|
* Display a listing of the resource.
|
|
*
|
|
* @return array<string, mixed>
|
|
*/
|
|
public function index(): array
|
|
{
|
|
$userId = auth()->id();
|
|
$user = auth()->user();
|
|
|
|
$query = PromptProject::with(['user', 'provider', 'model'])
|
|
->latest();
|
|
|
|
if (!$user || $user->role !== 'superadmin') {
|
|
$query->where('user_id', $userId);
|
|
}
|
|
|
|
$paginator = $query->paginate(15);
|
|
|
|
return [
|
|
'data' => $paginator->items(),
|
|
'total' => $paginator->total(),
|
|
'per_page' => $paginator->perPage(),
|
|
'current_page' => $paginator->currentPage(),
|
|
'last_page' => $paginator->lastPage(),
|
|
'from' => $paginator->firstItem(),
|
|
'to' => $paginator->lastItem(),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Store a newly created resource in storage.
|
|
*/
|
|
public function store(array $data): PromptProject
|
|
{
|
|
$data['examples'] = $this->convertToArray($data['examples'] ?? null);
|
|
$data['variables'] = $this->convertToArray($data['variables'] ?? null);
|
|
|
|
return PromptProject::create($data);
|
|
}
|
|
|
|
/**
|
|
* Update the specified resource in storage.
|
|
*/
|
|
public function update(PromptProject $project, array $data): PromptProject
|
|
{
|
|
$data['examples'] = $this->convertToArray($data['examples'] ?? null);
|
|
$data['variables'] = $this->convertToArray($data['variables'] ?? null);
|
|
|
|
$project->update($data);
|
|
|
|
return $project;
|
|
}
|
|
|
|
/**
|
|
* Convert string to array.
|
|
*/
|
|
private function convertToArray(mixed $value): ?array
|
|
{
|
|
if (is_array($value)) {
|
|
return $value;
|
|
}
|
|
|
|
if (is_string($value)) {
|
|
$value = trim($value);
|
|
|
|
if ($value === '') {
|
|
return null;
|
|
}
|
|
|
|
return array_map('trim', explode(',', $value));
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Remove the specified resource from storage.
|
|
*/
|
|
public function destroy(PromptProject $project): bool
|
|
{
|
|
try {
|
|
$project->delete();
|
|
|
|
return true;
|
|
} catch (RuntimeException $e) {
|
|
Log::error('Failed to delete prompt project: ' . $e->getMessage());
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Generate prompt for the specified project.
|
|
*/
|
|
public function generate(PromptProject $project, mixed $model = null, ?int $userId = null): PromptGeneration
|
|
{
|
|
$provider = $project->provider;
|
|
|
|
if (!$provider instanceof AiProvider) {
|
|
throw new InvalidArgumentException('AI provider is required for generation.');
|
|
}
|
|
|
|
if (!$model) {
|
|
$model = $project->model;
|
|
}
|
|
|
|
if (!$model) {
|
|
throw new InvalidArgumentException('AI model is required for generation.');
|
|
}
|
|
|
|
if (is_string($model)) {
|
|
$model = AiModel::firstOrCreate(
|
|
['provider_id' => $provider->id, 'slug' => $model],
|
|
['name' => $model, 'slug' => $model, 'is_active' => true]
|
|
);
|
|
}
|
|
|
|
$modelSlug = $model->slug;
|
|
$modelId = $model->id;
|
|
|
|
$userId ??= auth()->id();
|
|
|
|
$promptText = $this->buildPrompt($project);
|
|
|
|
$aiData = [
|
|
'prompt' => $promptText,
|
|
'temperature' => (float) ($project->temperature ?? 0.7),
|
|
'max_tokens' => (int) ($project->max_tokens ?? 1024),
|
|
'model' => $modelSlug,
|
|
'api_key' => $provider->api_key,
|
|
'base_url' => $provider->base_url,
|
|
];
|
|
|
|
$startTime = microtime(true);
|
|
|
|
try {
|
|
$service = $this->aiServiceFactory->make($provider);
|
|
$result = $service->generatePrompt($aiData);
|
|
} catch (ConnectionException|RuntimeException $e) {
|
|
Log::error('Prompt generation failed: ' . $e->getMessage());
|
|
|
|
return $this->generationModel::create([
|
|
'project_id' => $project->id,
|
|
'user_id' => $userId,
|
|
'provider_id' => $provider->id,
|
|
'model_id' => $modelId,
|
|
'generated_prompt' => $promptText,
|
|
'input_data' => $aiData,
|
|
'output_data' => ['error' => $e->getMessage()],
|
|
'tokens_used' => null,
|
|
'generation_time' => round(microtime(true) - $startTime, 3),
|
|
'status' => 'failed',
|
|
]);
|
|
}
|
|
|
|
return $this->generationModel::create([
|
|
'project_id' => $project->id,
|
|
'user_id' => $userId,
|
|
'provider_id' => $provider->id,
|
|
'model_id' => $modelId,
|
|
'generated_prompt' => $promptText,
|
|
'input_data' => $aiData,
|
|
'output_data' => $result,
|
|
'tokens_used' => $result['tokens_used'] ?? null,
|
|
'generation_time' => round(microtime(true) - $startTime, 3),
|
|
'status' => 'completed',
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Build the prompt text from project data.
|
|
*/
|
|
public function buildPrompt(PromptProject $project): string
|
|
{
|
|
$parts = [];
|
|
|
|
$companyName = $project->company_name ?? $project->title;
|
|
|
|
$parts[] = "Generate a complete, ready-to-use prompt in Portuguese that another AI or developer can follow to build the project described below. The generated prompt must be self-contained and include ALL specifications, design requirements, technical constraints, and code standards needed to build the project from scratch.";
|
|
$parts[] = "IMPORTANT: Your output must be ONLY the prompt text in Portuguese. Do NOT include this instruction, do NOT wrap in markdown, do NOT add explanations — just output the prompt itself.";
|
|
|
|
if ($project->company_name) {
|
|
$parts[] = "Company Name: " . $project->company_name;
|
|
}
|
|
|
|
if ($project->company_address) {
|
|
$parts[] = "Company Address: " . $project->company_address;
|
|
}
|
|
|
|
if ($project->company_whatsapp) {
|
|
$parts[] = "Company WhatsApp: " . $project->company_whatsapp;
|
|
}
|
|
|
|
if ($project->company_website) {
|
|
$parts[] = "Company Website: " . $project->company_website;
|
|
}
|
|
|
|
if ($project->company_social_media) {
|
|
$parts[] = "Company Social Media: " . $project->company_social_media;
|
|
}
|
|
|
|
if ($project->company_business_activities) {
|
|
$parts[] = "Company Business Activities: " . $project->company_business_activities;
|
|
}
|
|
|
|
if ($project->company_services_products) {
|
|
$parts[] = "Company Services/Products: " . $project->company_services_products;
|
|
}
|
|
|
|
if ($project->objective) {
|
|
$parts[] = "Objective: " . $project->objective;
|
|
}
|
|
|
|
if ($project->context) {
|
|
$parts[] = "Context: " . $project->context;
|
|
}
|
|
|
|
if ($project->persona) {
|
|
$parts[] = "Persona/Role: " . $project->persona;
|
|
}
|
|
|
|
if ($project->tone) {
|
|
$parts[] = "Tone/Style: " . $project->tone;
|
|
}
|
|
|
|
if ($project->constraints) {
|
|
$parts[] = "Constraints: " . $project->constraints;
|
|
}
|
|
|
|
if ($project->output_format) {
|
|
$parts[] = "Output Format: " . $project->output_format;
|
|
}
|
|
|
|
if (!empty($project->examples)) {
|
|
$parts[] = "Examples:\n" . json_encode($project->examples, JSON_PRETTY_PRINT);
|
|
}
|
|
|
|
if (!empty($project->variables)) {
|
|
$parts[] = "Variables: " . json_encode($project->variables, JSON_PRETTY_PRINT);
|
|
}
|
|
|
|
$parts[] = "SYSTEM REQUIREMENTS (ALWAYS apply to every project):";
|
|
$parts[] = "- Fully responsive design (mobile-first, all screen sizes including smartphones)";
|
|
$parts[] = "- Use only MIT-licensed or permissive open-source icons, images, and dependencies that are safe for commercial use";
|
|
$parts[] = "- All password fields must include a toggle button (eye icon) to show/hide the password";
|
|
$parts[] = "- Complete SEO optimization: semantic HTML5, meta tags (title, description, keywords, OG tags for social media), structured data (JSON-LD), sitemap, robots.txt, aria labels, alt text on images, canonical URL, mobile-friendly validation";
|
|
|
|
$parts[] = "Generate the optimized prompt now. Return ONLY the prompt text, without explanations, introductions, or additional text.";
|
|
|
|
return implode("\n\n", $parts);
|
|
}
|
|
|
|
/**
|
|
* Generate LICENSE file content for the project.
|
|
*/
|
|
public function generateLicenseContent(PromptProject $project): string
|
|
{
|
|
$year = date('Y');
|
|
$company = $project->company_name ?? $project->title;
|
|
|
|
return <<<EOT
|
|
MIT License
|
|
|
|
Copyright (c) {$year} {$company}
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in all
|
|
copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
SOFTWARE.
|
|
EOT;
|
|
}
|
|
|
|
/**
|
|
* Generate README.md content for the project.
|
|
*/
|
|
public function generateReadmeContent(PromptProject $project): string
|
|
{
|
|
$company = $project->company_name ?? $project->title;
|
|
$description = $project->objective ?? 'Sistema profissional';
|
|
$activities = $project->company_business_activities ?? '';
|
|
$services = $project->company_services_products ?? '';
|
|
|
|
$readme = "# {$company}\n\n";
|
|
$readme .= "## 📋 Descrição\n\n{$description}\n\n";
|
|
|
|
if ($activities) {
|
|
$readme .= "## 🏢 Atividades\n\n{$activities}\n\n";
|
|
}
|
|
|
|
if ($services) {
|
|
$readme .= "## 🛠️ Serviços e Produtos\n\n{$services}\n\n";
|
|
}
|
|
|
|
$readme .= "## 🚀 Tecnologias\n\n";
|
|
$readme .= "- HTML5 / CSS3 / JavaScript\n";
|
|
$readme .= "- Bootstrap 5\n";
|
|
$readme .= "- Font Awesome / Bootstrap Icons\n";
|
|
$readme .= "- Responsive Design\n\n";
|
|
|
|
$readme .= "## 📦 Instalação\n\n```bash\n";
|
|
$readme .= "# Clone o repositório\ngit clone https://github.com/seu-usuario/{$this->slugify($company)}.git\n\n";
|
|
$readme .= "# Acesse o diretório\ncd {$this->slugify($company)}\n";
|
|
$readme .= "```\n\n";
|
|
|
|
$readme .= "## ⚙️ Configuração\n\n";
|
|
$readme .= "1. Configure as variáveis de ambiente necessárias\n";
|
|
$readme .= "2. Ajuste as credenciais de banco de dados no arquivo de configuração\n";
|
|
$readme .= "3. Execute as migrações (se aplicável)\n\n";
|
|
|
|
$readme .= "## 🎯 Funcionalidades\n\n";
|
|
$readme .= "- Interface responsiva e moderna\n";
|
|
$readme .= "- Design otimizado para todos os dispositivos\n";
|
|
$readme .= "- Componentes reutilizáveis\n";
|
|
$readme .= "- Performance otimizada\n\n";
|
|
|
|
if ($project->company_website) {
|
|
$readme .= "## 🌐 Website\n\n[{$project->company_website}]({$project->company_website})\n\n";
|
|
}
|
|
|
|
$readme .= "## 📄 Licença\n\nEste projeto está licenciado sob a Licença MIT.\n\n";
|
|
$readme .= "## 📞 Contato\n\n";
|
|
|
|
if ($project->company_whatsapp) {
|
|
$readme .= "- WhatsApp: {$project->company_whatsapp}\n";
|
|
}
|
|
if ($project->company_social_media) {
|
|
$readme .= "- Redes Sociais: {$project->company_social_media}\n";
|
|
}
|
|
|
|
return $readme;
|
|
}
|
|
|
|
/**
|
|
* Generate RULES.md content for the project.
|
|
*/
|
|
public function generateRulesContent(PromptProject $project): string
|
|
{
|
|
$company = $project->company_name ?? $project->title;
|
|
|
|
$rules = "# Regras de Desenvolvimento - {$company}\n\n";
|
|
$rules .= "## 📐 Padrões de Código\n\n";
|
|
$rules .= "- Seguir PSR-12 (PHP) / Airbnb Style Guide (JavaScript)\n";
|
|
$rules .= "- Usar type hints em todos os métodos e parâmetros\n";
|
|
$rules .= "- Strict typing habilitado (declare(strict_types=1))\n";
|
|
$rules .= "- PHPDoc comments em métodos públicos\n";
|
|
$rules .= "- Sem uso de `var`, usar `private/protected/public`\n\n";
|
|
|
|
$rules .= "## 🏗️ Arquitetura\n\n";
|
|
$rules .= "- Seguir princípios SOLID\n";
|
|
$rules .= "- MVC Pattern com Service Layer\n";
|
|
$rules .= "- Repository Pattern para abstração de dados\n";
|
|
$rules .= "- Injeção de dependências\n\n";
|
|
|
|
$rules .= "## 🔒 Segurança\n\n";
|
|
$rules .= "- CSRF em todos os formulários\n";
|
|
$rules .= "- XSS: usar escaping automático, evitar `{!! !!}`\n";
|
|
$rules .= "- SQL Injection: usar ORM ou Query Builder com bindings\n";
|
|
$rules .= "- Mass Assignment: usar \$fillable ou \$guarded\n";
|
|
$rules .= "- Senhas: hash com bcrypt\n";
|
|
$rules .= "- Rate Limiting em formulários públicos\n\n";
|
|
|
|
$rules .= "## 🎨 Frontend\n\n";
|
|
$rules .= "- Bootstrap 5 com Bootstrap Icons\n";
|
|
$rules .= "- Design responsivo (mobile-first)\n";
|
|
$rules .= "- Breadcrumbs em todas as páginas\n";
|
|
$rules .= "- Sem CSS ou JS inline\n";
|
|
$rules .= "- Modern, clean design\n\n";
|
|
|
|
$rules .= "## 🧪 Testes\n\n";
|
|
$rules .= "- Testes unitários para Models e Services\n";
|
|
$rules .= "- Testes de feature para CRUD\n";
|
|
$rules .= "- Cobertura mínima de 80%\n\n";
|
|
|
|
$rules .= "## 🚫 Práticas Proibidas\n\n";
|
|
$rules .= "- `dd()`, `dump()`, `var_dump()` em produção\n";
|
|
$rules .= "- Comentários `TODO`, `FIXME`, `XXX`\n";
|
|
$rules .= "- URLs ou caminhos hardcoded\n";
|
|
$rules .= "- Magic numbers (definir constantes)\n";
|
|
$rules .= "- Código comentado\n\n";
|
|
|
|
$rules .= "## ⚡ Performance\n\n";
|
|
$rules .= "- Eager load relacionamentos (N+1 prevention)\n";
|
|
$rules .= "- Indexar foreign keys no banco\n";
|
|
$rules .= "- Cache de queries pesadas\n";
|
|
$rules .= "- Paginar datasets grandes\n";
|
|
$rules .= "- Otimizar assets (compressão, minificação)\n\n";
|
|
|
|
$rules .= "## 📖 Documentação\n\n";
|
|
$rules .= "- README.md com instruções de instalação e uso\n";
|
|
$rules .= "- Documentação técnica em markdown\n";
|
|
$rules .= "- CHANGELOG.md para versionamento\n";
|
|
|
|
return $rules;
|
|
}
|
|
|
|
/**
|
|
* Generate cookies.html content (cookie consent banner in compliance with LGPD).
|
|
*/
|
|
public function generateCookieConsentContent(PromptProject $project): string
|
|
{
|
|
$company = $project->company_name ?? $project->title;
|
|
|
|
return <<<EOT
|
|
<!DOCTYPE html>
|
|
<html lang="pt-BR">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Política de Cookies - {$company}</title>
|
|
<style>
|
|
.cookie-banner{position:fixed;bottom:0;left:0;right:0;background:#fff;border-top:2px solid #4e73df;padding:1.5rem;box-shadow:0 -4px 20px rgba(0,0,0,0.15);z-index:9999;animation:slideUp 0.4s ease-out}
|
|
.cookie-banner .container{max-width:1100px;margin:0 auto}
|
|
.cookie-banner h6{color:#1a1a2e;font-weight:700;margin-bottom:0.5rem}
|
|
.cookie-banner p{font-size:0.9rem;color:#6c757d;margin-bottom:1rem;line-height:1.6}
|
|
.cookie-banner .btn-group{display:flex;flex-wrap:wrap;gap:0.5rem}
|
|
.cookie-banner .btn{padding:0.5rem 1.25rem;border-radius:8px;font-weight:500;font-size:0.9rem;cursor:pointer;border:none;transition:all 0.2s}
|
|
.cookie-banner .btn-accept{background:#4e73df;color:#fff}
|
|
.cookie-banner .btn-accept:hover{background:#224abe}
|
|
.cookie-banner .btn-reject{background:#6c757d;color:#fff}
|
|
.cookie-banner .btn-reject:hover{background:#5a6268}
|
|
.cookie-banner .btn-customize{background:#f8f9fc;color:#333;border:1px solid #dee2e6}
|
|
.cookie-modal{display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.5);z-index:10000;align-items:center;justify-content:center}
|
|
.cookie-modal.active{display:flex}
|
|
.cookie-modal .modal-content{background:#fff;border-radius:16px;padding:2rem;max-width:500px;width:90%;max-height:80vh;overflow-y:auto}
|
|
.cookie-modal h5{font-weight:700;margin-bottom:1rem}
|
|
.cookie-modal .cookie-category{padding:1rem;border-radius:8px;margin-bottom:0.75rem;border:1px solid #e9ecef}
|
|
.cookie-modal .cookie-category label{font-weight:600;display:flex;align-items:center;gap:0.5rem}
|
|
.cookie-modal .cookie-category p{margin:0.25rem 0 0 1.5rem;font-size:0.85rem;color:#6c757d}
|
|
.cookie-modal .btn-save{background:#4e73df;color:#fff;padding:0.5rem 1.5rem;border-radius:8px;border:none;cursor:pointer}
|
|
.cookie-modal .btn-cancel{background:#f8f9fc;color:#333;padding:0.5rem 1.5rem;border-radius:8px;border:1px solid #dee2e6;cursor:pointer}
|
|
@keyframes slideUp{from{transform:translateY(100%);opacity:0}to{transform:translateY(0);opacity:1}}
|
|
@media(max-width:576px){.cookie-banner .btn-group{flex-direction:column}}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<div id="cookieBanner" class="cookie-banner">
|
|
<div class="container">
|
|
<h6>Cookies e Privacidade</h6>
|
|
<p>Utilizamos cookies para melhorar sua experiencia, analisar trafego e personalizar conteudo. Ao continuar navegando, voce concorda com nossa Politica de Privacidade.</p>
|
|
<div class="btn-group">
|
|
<button class="btn btn-customize" onclick="openCookieModal()">Personalizar</button>
|
|
<button class="btn btn-reject" onclick="rejectCookies()">Recusar</button>
|
|
<button class="btn btn-accept" onclick="acceptAllCookies()">Aceitar Todos</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="cookieModal" class="cookie-modal">
|
|
<div class="modal-content">
|
|
<h5>Personalizar Cookies</h5>
|
|
<p style="color:#6c757d;font-size:0.9rem;margin-bottom:1.5rem">Selecione os tipos de cookies que voce autoriza:</p>
|
|
<div class="cookie-category">
|
|
<label><input type="checkbox" checked disabled> Necessarios</label>
|
|
<p>Essenciais para o funcionamento do site.</p>
|
|
</div>
|
|
<div class="cookie-category">
|
|
<label><input type="checkbox" id="ckStatistics" checked> Estatisticas</label>
|
|
<p>Nos ajudam a entender como o site e utilizado.</p>
|
|
</div>
|
|
<div class="cookie-category">
|
|
<label><input type="checkbox" id="ckMarketing" checked> Marketing</label>
|
|
<p>Utilizados para exibir anuncios relevantes.</p>
|
|
</div>
|
|
<div class="cookie-category">
|
|
<label><input type="checkbox" id="ckPreferences" checked> Preferencias</label>
|
|
<p>Armazenam suas configuracoes e preferencias.</p>
|
|
</div>
|
|
<div style="display:flex;justify-content:flex-end;gap:0.5rem;margin-top:1rem">
|
|
<button class="btn-cancel" onclick="closeCookieModal()">Cancelar</button>
|
|
<button class="btn-save" onclick="saveCookiePreferences()">Salvar Preferencias</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
function getCookie(name){const match=document.cookie.match(new RegExp('(^| )'+name+'=([^;]+)'));return match?match[2]:null}
|
|
function setCookie(name,value,days){const d=new Date();d.setTime(d.getTime()+days*86400000);document.cookie=name+'='+value+';expires='+d.toUTCString()+';path=/'}
|
|
if(!getCookie('cookieConsent')){document.getElementById('cookieBanner').style.display='block'}
|
|
function acceptAllCookies(){setCookie('cookieConsent',JSON.stringify({necessary:true,statistics:true,marketing:true,preferences:true}),365);document.getElementById('cookieBanner').style.display='none'}
|
|
function rejectCookies(){setCookie('cookieConsent',JSON.stringify({necessary:true,statistics:false,marketing:false,preferences:false}),365);document.getElementById('cookieBanner').style.display='none'}
|
|
function openCookieModal(){document.getElementById('cookieModal').classList.add('active')}
|
|
function closeCookieModal(){document.getElementById('cookieModal').classList.remove('active')}
|
|
function saveCookiePreferences(){const consents={necessary:true,statistics:document.getElementById('ckStatistics').checked,marketing:document.getElementById('ckMarketing').checked,preferences:document.getElementById('ckPreferences').checked};setCookie('cookieConsent',JSON.stringify(consents),365);document.getElementById('cookieBanner').style.display='none';closeCookieModal()}
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|
|
EOT;
|
|
}
|
|
|
|
/**
|
|
* Generate termos-de-uso.html content (Terms of Service compliant with Brazilian legislation).
|
|
*/
|
|
public function generateTermsContent(PromptProject $project): string
|
|
{
|
|
$company = $project->company_name ?? $project->title;
|
|
$year = date('Y');
|
|
$activities = $project->company_business_activities ?? 'servicos de tecnologia';
|
|
|
|
return <<<EOT
|
|
<!DOCTYPE html>
|
|
<html lang="pt-BR">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Termos de Uso - {$company}</title>
|
|
<style>
|
|
body{font-family:Arial,sans-serif;line-height:1.8;color:#333;max-width:900px;margin:0 auto;padding:2rem}
|
|
h1{color:#1a1a2e;font-size:1.8rem;border-bottom:2px solid #4e73df;padding-bottom:0.5rem}
|
|
h2{color:#2c3e50;font-size:1.3rem;margin-top:2rem}
|
|
p{margin-bottom:1rem;text-align:justify}
|
|
ul{margin-bottom:1rem;padding-left:2rem}
|
|
footer{margin-top:3rem;padding-top:1rem;border-top:1px solid #dee2e6;font-size:0.85rem;color:#6c757d}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<h1>Termos de Uso - {$company}</h1>
|
|
<p><strong>Versao:</strong> 1.0 | <strong>Data:</strong> {$year}</p>
|
|
|
|
<h2>1. Aceitacao dos Termos</h2>
|
|
<p>Ao acessar e utilizar os servicos da {$company}, voce concorda em cumprir integralmente estes Termos de Uso. Caso nao concorde com qualquer disposicao deste documento, voce nao deve utilizar nossos servicos.</p>
|
|
|
|
<h2>2. Descricao do Servico</h2>
|
|
<p>A {$company} oferece {$activities}. Este documento estabelece as condicoes gerais de uso dos servicos disponibilizados.</p>
|
|
|
|
<h2>3. Definicoes</h2>
|
|
<ul>
|
|
<li><strong>Plataforma:</strong> sistema, site ou aplicativo fornecido pela {$company}</li>
|
|
<li><strong>Usuario:</strong> pessoa fisica ou juridica que utiliza a plataforma</li>
|
|
<li><strong>Conteudo:</strong> qualquer informacao, dado ou material inserido na plataforma</li>
|
|
<li><strong>LGPD:</strong> Lei Geral de Protecao de Dados Pessoais (Lei no 13.709/2018)</li>
|
|
</ul>
|
|
|
|
<h2>4. Cadastro e Conta de Usuario</h2>
|
|
<p>4.1. Para utilizar a plataforma, o usuario deve criar uma conta fornecendo informacoes precisas e atualizadas.</p>
|
|
<p>4.2. O usuario e integralmente responsavel pela confidencialidade de suas credenciais de acesso.</p>
|
|
<p>4.3. O usuario compromete-se a notificar imediatamente qualquer uso nao autorizado de sua conta.</p>
|
|
|
|
<h2>5. Obrigacoes do Usuario</h2>
|
|
<p>5.1. Utilizar a plataforma em conformidade com as leis brasileiras.</p>
|
|
<p>5.2. Nao realizar atividades que possam comprometer a seguranca da plataforma.</p>
|
|
<p>5.3. Nao inserir conteudo ilegal, ofensivo ou que viole direitos de terceiros.</p>
|
|
|
|
<h2>6. Propriedade Intelectual</h2>
|
|
<p>6.1. Todo o conteudo e funcionalidades da plataforma sao de propriedade da {$company}.</p>
|
|
<p>6.2. O conteudo gerado pelo usuario e de propriedade do usuario.</p>
|
|
<p>6.3. E proibida a engenharia reversa, descompilacao ou tentativa de extrair o codigo fonte.</p>
|
|
|
|
<h2>7. Limitacao de Responsabilidade</h2>
|
|
<p>7.1. A plataforma e fornecida "como esta", sem garantias de disponibilidade continua.</p>
|
|
<p>7.2. A {$company} nao se responsabiliza por danos decorrentes do uso ou da impossibilidade de uso da plataforma.</p>
|
|
|
|
<h2>8. Privacidade e Protecao de Dados</h2>
|
|
<p>8.1. O tratamento de dados pessoais segue integralmente a LGPD (Lei no 13.709/2018).</p>
|
|
<p>8.2. Os dados coletados sao utilizados exclusivamente para as finalidades descritas na Politica de Privacidade.</p>
|
|
<p>8.3. O usuario pode exercer seus direitos de titular de dados a qualquer momento.</p>
|
|
|
|
<h2>9. Disposicoes Gerais</h2>
|
|
<p>9.1. Estes termos podem ser alterados a qualquer momento, mediante comunicacao previa aos usuarios.</p>
|
|
<p>9.2. O uso continuado apos alteracoes constitui aceitacao dos novos termos.</p>
|
|
<p>9.3. Foro: Comarca de Sao Paulo/SP para eventuais controversias.</p>
|
|
|
|
<h2>10. Contato</h2>
|
|
<p>Para esclarecimentos sobre estes termos, entre em contato atraves dos canais oficiais da {$company}.</p>
|
|
|
|
<footer>
|
|
<p>© {$year} {$company}. Todos os direitos reservados.</p>
|
|
</footer>
|
|
|
|
</body>
|
|
</html>
|
|
EOT;
|
|
}
|
|
|
|
/**
|
|
* Generate privacidade.html content (Privacy Policy compliant with LGPD).
|
|
*/
|
|
public function generatePrivacyContent(PromptProject $project): string
|
|
{
|
|
$company = $project->company_name ?? $project->title;
|
|
$year = date('Y');
|
|
|
|
return <<<EOT
|
|
<!DOCTYPE html>
|
|
<html lang="pt-BR">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Politica de Privacidade - {$company}</title>
|
|
<style>
|
|
body{font-family:Arial,sans-serif;line-height:1.8;color:#333;max-width:900px;margin:0 auto;padding:2rem}
|
|
h1{color:#1a1a2e;font-size:1.8rem;border-bottom:2px solid #4e73df;padding-bottom:0.5rem}
|
|
h2{color:#2c3e50;font-size:1.3rem;margin-top:2rem}
|
|
p{margin-bottom:1rem;text-align:justify}
|
|
ul{margin-bottom:1rem;padding-left:2rem}
|
|
footer{margin-top:3rem;padding-top:1rem;border-top:1px solid #dee2e6;font-size:0.85rem;color:#6c757d}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<h1>Politica de Privacidade - {$company} (LGPD)</h1>
|
|
<p><strong>Versao:</strong> 1.0 | <strong>Data:</strong> {$year}</p>
|
|
|
|
<h2>1. Informacoes Gerais</h2>
|
|
<p>Esta Politica de Privacidade descreve como a {$company} coleta, utiliza, armazena e protege os dados pessoais dos usuarios, em conformidade com a Lei Geral de Protecao de Dados Pessoais (LGPD - Lei no 13.709/2018).</p>
|
|
|
|
<h2>2. Titular do Tratamento</h2>
|
|
<p>{$company}</p>
|
|
<p>E-mail de contato disponivel no site oficial.</p>
|
|
|
|
<h2>3. Dados Pessoais Coletados</h2>
|
|
<p><strong>3.1. Dados fornecidos pelo usuario:</strong></p>
|
|
<ul>
|
|
<li>Nome completo</li>
|
|
<li>Endereco de e-mail</li>
|
|
<li>Senha de acesso (armazenada com criptografia)</li>
|
|
<li>Informacoes de contato, quando fornecidas</li>
|
|
</ul>
|
|
<p><strong>3.2. Dados coletados automaticamente:</strong></p>
|
|
<ul>
|
|
<li>Endereco IP</li>
|
|
<li>Agente do navegador (user agent)</li>
|
|
<li>Preferencias de cookies</li>
|
|
<li>Dados de uso da plataforma</li>
|
|
<li>Data e hora das interacoes</li>
|
|
</ul>
|
|
|
|
<h2>4. Finalidades do Tratamento</h2>
|
|
<ul>
|
|
<li>Autenticacao e autorizacao de acesso</li>
|
|
<li>Prestacao dos servicos contratados</li>
|
|
<li>Comunicacoes sobre o servico</li>
|
|
<li>Seguranca e prevencao de fraudes</li>
|
|
<li>Cumprimento de obrigacoes legais</li>
|
|
<li>Melhoria continua dos servicos</li>
|
|
</ul>
|
|
|
|
<h2>5. Bases Legais para o Tratamento (LGPD - Art. 7o)</h2>
|
|
<ul>
|
|
<li>Consentimento do titular (Art. 7o, I)</li>
|
|
<li>Execucao de contrato (Art. 7o, V)</li>
|
|
<li>Cumprimento de obrigacao legal (Art. 7o, II)</li>
|
|
<li>Legitimo interesse (Art. 7o, IX)</li>
|
|
</ul>
|
|
|
|
<h2>6. Compartilhamento de Dados</h2>
|
|
<p>6.1. Seus dados nao sao compartilhados com terceiros, exceto quando necessario para a prestacao dos servicos ou quando exigido por lei.</p>
|
|
<p>6.2. Nao vendemos dados pessoais a terceiros.</p>
|
|
|
|
<h2>7. Armazenamento e Seguranca</h2>
|
|
<p>7.1. Os dados sao armazenados em servidores seguros com acesso restrito.</p>
|
|
<p>7.2. Adotamos medidas tecnicas e organizacionais para proteger os dados contra acesso nao autorizado.</p>
|
|
<p>7.3. O periodo de armazenamento e o necessario para cumprir as finalidades descritas nesta politica.</p>
|
|
|
|
<h2>8. Direitos do Titular (LGPD - Art. 18)</h2>
|
|
<p>O titular dos dados tem direito a:</p>
|
|
<ul>
|
|
<li>Confirmar a existencia de tratamento</li>
|
|
<li>Acessar seus dados pessoais</li>
|
|
<li>Corrigir dados incompletos ou desatualizados</li>
|
|
<li>Solicitar a eliminacao de dados desnecessarios</li>
|
|
<li>Solicitar a portabilidade dos dados</li>
|
|
<li>Revogar o consentimento a qualquer momento</li>
|
|
</ul>
|
|
|
|
<h2>9. Cookies</h2>
|
|
<p>9.1. Utilizamos cookies necessarios para o funcionamento da plataforma.</p>
|
|
<p>9.2. Cookies opcionais (estatisticas, marketing, preferencias) dependem do seu consentimento.</p>
|
|
<p>9.3. Voce pode gerenciar suas preferencias de cookies atraves do banner de cookies.</p>
|
|
|
|
<h2>10. Consentimento</h2>
|
|
<p>Ao utilizar a plataforma, voce declara ter lido e compreendido esta Politica de Privacidade e autoriza o tratamento de seus dados conforme aqui descrito.</p>
|
|
|
|
<h2>11. Alteracoes</h2>
|
|
<p>Esta politica pode ser atualizada periodicamente. Alteracoes significativas serao comunicadas aos usuarios.</p>
|
|
|
|
<h2>12. Contato e DPO</h2>
|
|
<p>Para exercer seus direitos ou esclarecer duvidas sobre privacidade, entre em contato atraves dos canais oficiais da {$company}.</p>
|
|
<p>Prazo de resposta: ate 15 dias uteis (LGPD - Art. 19).</p>
|
|
|
|
<footer>
|
|
<p>© {$year} {$company}. Todos os direitos reservados.</p>
|
|
</footer>
|
|
|
|
</body>
|
|
</html>
|
|
EOT;
|
|
}
|
|
|
|
/**
|
|
* Get all standard files with their contents for the project.
|
|
*
|
|
* @return array<string, string>
|
|
*/
|
|
public function getStandardFiles(PromptProject $project): array
|
|
{
|
|
return [
|
|
'LICENSE' => $this->generateLicenseContent($project),
|
|
'README.md' => $this->generateReadmeContent($project),
|
|
'RULES.md' => $this->generateRulesContent($project),
|
|
'cookies.html' => $this->generateCookieConsentContent($project),
|
|
'termos-de-uso.html' => $this->generateTermsContent($project),
|
|
'privacidade.html' => $this->generatePrivacyContent($project),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Convert text to a URL-friendly slug.
|
|
*/
|
|
private function slugify(string $text): string
|
|
{
|
|
$text = preg_replace('/[^a-zA-Z0-9-]/', '-', $text);
|
|
$text = preg_replace('/-+/', '-', $text);
|
|
$text = trim($text, '-');
|
|
|
|
return strtolower($text);
|
|
}
|
|
}
|