Remove maximum line count restrictions from prompt templates and enhance the prompt building service to require complete multi-file project outputs. Update generated prompts to explicitly instruct creation of standard legal documents (LICENSE, README.md, RULES.md, cookies.html, termos-de-uso.html, privacidade.html) with full content from scratch. Modify UI text to reflect the new multi-file requirements.
765 lines
31 KiB
PHP
Executable File
765 lines
31 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[] = "- The generated prompt must produce a COMPLETE MULTI-FILE PROJECT structure (not a single file). Generate separate files organized in a proper project folder structure";
|
|
$parts[] = "- The prompt MUST instruct to create EACH of the following standard files FROM SCRATCH with COMPLETE content (not just descriptions): LICENSE (MIT with company name and year), README.md (full documentation in Portuguese), RULES.md (coding rules in Portuguese), cookies.html (complete LGPD cookie banner page with HTML/CSS/JS), termos-de-uso.html (complete Terms of Service page), privacidade.html (complete Privacy Policy page compliant with LGPD)";
|
|
$parts[] = "- Do NOT just describe what the files should contain — the generated prompt must explicitly tell the developer/AI to CREATE each file with full, ready-to-use content";
|
|
$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);
|
|
}
|
|
}
|