Files
marcocosta10000 f2bca340f9 feat: add legal document acceptance and standard project files generation
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.
2026-10-07 21:30:40 -03:00

248 lines
13 KiB
PHP
Executable File

@extends('layouts.app')
@section('header', $promptProject->title)
@section('breadcrumbs')
@php
$breadcrumbs = [
'Projetos' => route('prompt-projects.index'),
$promptProject->title => null
];
@endphp
@endsection
@section('content')
<div class="card shadow mb-4">
<div class="card-header py-3 d-flex justify-content-between align-items-center">
<h6 class="m-0 fw-bold text-primary">Detalhes do Projeto</h6>
<div>
<a href="{{ route('prompt-projects.edit', $promptProject) }}" class="btn btn-warning btn-sm me-2">
<i class="bi bi-pencil"></i> Editar
</a>
<form action="{{ route('prompt-projects.destroy', $promptProject) }}" method="POST" class="d-inline" onsubmit="return confirm('Tem certeza?')">
@csrf @method('DELETE')
<button class="btn btn-danger btn-sm"><i class="bi bi-trash"></i> Excluir</button>
</form>
</div>
</div>
<div class="card-body">
<dl class="row">
<dt class="col-sm-3">Nome</dt>
<dd class="col-sm-9">{{ $promptProject->title }}</dd>
<dt class="col-sm-3">Nome da Empresa</dt>
<dd class="col-sm-9">{{ $promptProject->company_name ?: '-' }}</dd>
<dt class="col-sm-3">Endereço da Empresa</dt>
<dd class="col-sm-9">{{ $promptProject->company_address ?: '-' }}</dd>
<dt class="col-sm-3">WhatsApp da Empresa</dt>
<dd class="col-sm-9">{{ $promptProject->company_whatsapp ?: '-' }}</dd>
<dt class="col-sm-3">Website da Empresa</dt>
<dd class="col-sm-9">{{ $promptProject->company_website ?: '-' }}</dd>
<dt class="col-sm-3">Redes Sociais da Empresa</dt>
<dd class="col-sm-9">{{ $promptProject->company_social_media ?: '-' }}</dd>
<dt class="col-sm-3">Atividades de Negócio da Empresa</dt>
<dd class="col-sm-9">{{ $promptProject->company_business_activities ?: '-' }}</dd>
<dt class="col-sm-3">Serviços e Produtos da Empresa</dt>
<dd class="col-sm-9">{{ $promptProject->company_services_products ?: '-' }}</dd>
<dt class="col-sm-3">Objetivo</dt>
<dd class="col-sm-9">{{ $promptProject->objective }}</dd>
<dt class="col-sm-3">Contexto</dt>
<dd class="col-sm-9">{{ $promptProject->context ?: '-' }}</dd>
<dt class="col-sm-3">Persona</dt>
<dd class="col-sm-9">{{ $promptProject->persona ?: '-' }}</dd>
<dt class="col-sm-3">Tom</dt>
<dd class="col-sm-9">{{ $promptProject->tone ?: '-' }}</dd>
<dt class="col-sm-3">Restrições</dt>
<dd class="col-sm-9">{{ $promptProject->constraints ?: '-' }}</dd>
<dt class="col-sm-3">Formato de Saída</dt>
<dd class="col-sm-9">{{ $promptProject->output_format ?: '-' }}</dd>
<dt class="col-sm-3">Exemplos</dt>
<dd class="col-sm-9">{{ is_array($promptProject->examples) ? implode(', ', $promptProject->examples) : ($promptProject->examples ?: '-') }}</dd>
<dt class="col-sm-3">Variáveis</dt>
<dd class="col-sm-9">{{ is_array($promptProject->variables) ? implode(', ', $promptProject->variables) : ($promptProject->variables ?: '-') }}</dd>
<dt class="col-sm-3">Temperatura</dt>
<dd class="col-sm-9">{{ $promptProject->temperature }}</dd>
<dt class="col-sm-3">Max Tokens</dt>
<dd class="col-sm-9">{{ $promptProject->max_tokens }}</dd>
<dt class="col-sm-3">Provedor</dt>
<dd class="col-sm-9">{{ $promptProject->provider->name ?? 'N/A' }}</dd>
<dt class="col-sm-3">Modelo</dt>
<dd class="col-sm-9">{{ $promptProject->model->name ?? 'N/A' }}</dd>
</dl>
</div>
</div>
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 fw-bold text-primary">Gerar Prompt</h6>
</div>
<div class="card-body">
<form method="POST" action="{{ route('prompt-projects.generate', $promptProject) }}">
@csrf
<div class="mb-3">
<label for="model" class="form-label">Modelo</label>
<select class="form-select" id="model" name="model" required>
<option value="">Selecione...</option>
@foreach($models ?? [] as $model)
<option value="{{ $model->slug }}" {{ old('model', $promptProject->model->slug ?? '') == $model->slug ? 'selected' : '' }}>
{{ $model->name }}
</option>
@endforeach
<option value="outros">Outros</option>
</select>
</div>
<div class="mb-3 d-none" id="custom-model-container">
<label for="custom_model" class="form-label">Modelo Personalizado</label>
<input type="text" class="form-control" id="custom_model" name="custom_model" placeholder="Ex: gpt-4, claude-3, etc.">
</div>
<button type="submit" class="btn btn-success"><i class="bi bi-play-circle"></i> Gerar</button>
</form>
</div>
</div>
@if($generations->isNotEmpty())
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 fw-bold text-primary">Gerações Recentes</h6>
</div>
<div class="card-body">
@foreach($generations as $generation)
<div class="card mb-3">
<div class="card-header d-flex justify-content-between align-items-center">
<span>
<i class="bi bi-robot me-1"></i>
{{ $generation->model->name ?? 'Modelo desconhecido' }}
@if($generation->status === 'failed')
<span class="badge bg-danger ms-2">Falha</span>
@else
<span class="badge bg-success ms-2">Sucesso</span>
@endif
</span>
<small class="text-muted">{{ $generation->created_at->format('d/m/Y H:i') }}</small>
</div>
<div class="card-body">
<h6 class="card-title">Prompt Enviado</h6>
<pre class="bg-light p-3 rounded small mb-3" style="white-space: pre-wrap;">{{ $generation->generated_prompt }}</pre>
@if($generation->status === 'completed' && !empty($generation->output_data['content'] ?? ''))
<div class="d-flex justify-content-between align-items-center mb-2">
<h6 class="card-title mb-0">Resposta da IA</h6>
<button class="btn btn-sm btn-outline-secondary copy-btn" type="button" data-target="response-{{ $generation->id }}">
<i class="bi bi-clipboard me-1"></i> Copy
</button>
</div>
<textarea class="form-control font-monospace small" id="response-{{ $generation->id }}" rows="12">{{ $generation->output_data['content'] }}</textarea>
@elseif($generation->status === 'failed')
<div class="alert alert-danger small">
<strong>Erro:</strong> {{ $generation->output_data['error'] ?? 'Erro desconhecido' }}
</div>
@endif
@if($generation->tokens_used)
<p class="text-muted small mt-2 mb-0">
<i class="bi bi-lightning me-1"></i>Tokens: {{ $generation->tokens_used }} |
<i class="bi bi-clock me-1"></i>Tempo: {{ $generation->generation_time }}s
</p>
@endif
<form action="{{ route('prompt-generations.destroy', $generation) }}" method="POST" class="mt-2" onsubmit="return confirm('Tem certeza que deseja excluir esta geração?')">
@csrf @method('DELETE')
<button type="submit" class="btn btn-danger btn-sm"><i class="bi bi-trash"></i> Excluir</button>
</form>
</div>
</div>
@endforeach
</div>
</div>
@endif
<div class="card shadow mb-4">
<div class="card-header py-3 d-flex justify-content-between align-items-center">
<h6 class="m-0 fw-bold text-primary">Arquivos Padrão do Projeto</h6>
<span class="badge bg-info">LICENSE · README.md · RULES.md · LGPD</span>
</div>
<div class="card-body">
<div class="alert alert-info small mb-3">
<i class="bi bi-info-circle me-1"></i>
Estes arquivos são gerados automaticamente com base nos dados do projeto e devem ser incluídos no repositório.
</div>
<ul class="nav nav-tabs mb-3" id="standardFilesTab" role="tablist">
@foreach($standardFiles as $filename => $content)
<li class="nav-item" role="presentation">
<button class="nav-link {{ $loop->first ? 'active' : '' }}"
id="file-{{ Str::slug($filename) }}-tab"
data-bs-toggle="tab"
data-bs-target="#file-{{ Str::slug($filename) }}"
type="button" role="tab">
<i class="bi bi-file-text me-1"></i>{{ $filename }}
</button>
</li>
@endforeach
</ul>
<div class="tab-content" id="standardFilesTabContent">
@foreach($standardFiles as $filename => $content)
<div class="tab-pane fade {{ $loop->first ? 'show active' : '' }}"
id="file-{{ Str::slug($filename) }}" role="tabpanel">
<div class="d-flex justify-content-between align-items-center mb-2">
<small class="text-muted">{{ $filename }} — {{ str_word_count($content) }} palavras</small>
<div>
<a href="{{ route('prompt-projects.download-file', [$promptProject, $filename]) }}" class="btn btn-sm btn-outline-primary me-1" download>
<i class="bi bi-download me-1"></i> Download
</a>
<button class="btn btn-sm btn-outline-secondary copy-btn" type="button" data-target="file-content-{{ Str::slug($filename) }}">
<i class="bi bi-clipboard me-1"></i> Copiar
</button>
</div>
</div>
<textarea class="form-control font-monospace small" id="file-content-{{ Str::slug($filename) }}" rows="15" readonly>{{ $content }}</textarea>
</div>
@endforeach
</div>
</div>
</div>
@section('scripts')
<script>
document.getElementById('model').addEventListener('change', function() {
const customContainer = document.getElementById('custom-model-container');
if (this.value === 'outros') {
customContainer.classList.remove('d-none');
document.getElementById('custom_model').setAttribute('required', 'required');
} else {
customContainer.classList.add('d-none');
document.getElementById('custom_model').removeAttribute('required');
}
});
document.querySelectorAll('.copy-btn').forEach(button => {
button.addEventListener('click', function() {
const targetId = this.getAttribute('data-target');
const textarea = document.getElementById(targetId);
if (textarea) {
textarea.select();
document.execCommand('copy');
alert('Conteúdo copiado para a área de transferência!');
}
});
});
</script>
@endsection
@endsection