Files
dockergprompt/resources/views/prompt-projects/create.blade.php
T
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

389 lines
25 KiB
PHP
Executable File

@extends('layouts.app')
@section('header', 'Novo Projeto de Prompt')
@section('breadcrumbs')
@php
$breadcrumbs = [
'Projetos' => route('prompt-projects.index'),
'Novo' => null
];
@endphp
@endsection
@section('content')
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 fw-bold text-primary">Criar Projeto</h6>
</div>
<div class="card-body">
<form method="POST" action="{{ route('prompt-projects.store') }}">
@csrf
<div class="mb-3">
<label for="template-search-input" class="form-label">Modelo de Projeto</label>
<div style="position: relative;">
<input type="text" class="form-control" id="template-search-input" placeholder="Digite para buscar (ex: clínica, laravel, api)..." autocomplete="off">
<input type="hidden" id="template" name="template" value="">
<div id="template-dropdown" style="display:none; position:absolute; z-index:1050; background:#fff; border:1px solid #dee2e6; border-radius:0.375rem; box-shadow:0 0.5rem 1rem rgba(0,0,0,0.15); max-height:300px; overflow-y:auto; width:100%; top: 100%; left: 0;"></div>
</div>
<select class="form-select d-none" id="template-source">
<option value="">*** Personalizado ***</option>
<optgroup label="Sites & Landing Pages">
<option value="landing-corporativa">Landing Page Corporativa</option>
<option value="landing-saas">Landing Page SaaS</option>
<option value="landing-produto">Landing Page Produto Digital</option>
<option value="landing-evento">Landing Page Evento</option>
<option value="landing-ebook">Landing Page E-book / Lead Magnet</option>
<option value="landing-curso">Landing Page Curso Online</option>
<option value="landing-app">Landing Page App Mobile</option>
<option value="landing-agencia">Landing Page Agência</option>
<option value="landing-restaurante">Landing Page Restaurante</option>
<option value="landing-imobiliaria">Landing Page Imobiliária</option>
<option value="landing-saude">Landing Page Saúde / Bem-estar</option>
<option value="landing-educacao">Landing Page Educação</option>
<option value="landing-restaurante-2">Landing Page Delivery</option>
<option value="site-institucional">Site Institucional</option>
<option value="portfolio-profissional">Portfolio Profissional</option>
<option value="portfolio-criativo">Portfolio Criativo</option>
<option value="blog-pessoal">Blog Pessoal</option>
<option value="ecommerce">E-commerce</option>
</optgroup>
<optgroup label="Frameworks & APIs">
<option value="saas">Sistema SaaS</option>
<option value="dashboard-admin">Dashboard Admin</option>
<option value="laravel-13-app">Laravel 13 + Blade + Tailwind</option>
<option value="laravel-13-api">Laravel 13 + API RESTful</option>
<option value="laravel-vue-fullstack">Laravel 13 + Vue.js 3 Fullstack</option>
<option value="laravel-fullstack-2">Laravel Full Stack 2</option>
<option value="slim-4-api">Slim Framework 4 + API REST</option>
<option value="slim-4-web">Slim Framework 4 + Twig</option>
<option value="vue-spa">Vue.js 3 + Vite SPA</option>
<option value="react-spa">React + Vite SPA</option>
<option value="nextjs-app">Next.js 14 App Router</option>
<option value="node-express">Node.js + Express + TypeScript</option>
<option value="fastapi-python">FastAPI + Python</option>
<option value="api-jwt-auth">API com Autenticação JWT</option>
<option value="microservice">Arquitetura de Microsserviços</option>
<option value="chatbot-ia">Chatbot com IA</option>
<option value="automacao-workflow">Automação de Workflow</option>
<option value="integracao-api">Integração entre APIs</option>
</optgroup>
<optgroup label="Sistemas de Gestão - Serviços">
<option value="gestao-clinica">Sistema de Gestão para Clínica Médica</option>
<option value="gestao-odontologica">Sistema de Gestão para Odontologia</option>
<option value="gestao-advocacia">Sistema de Gestão para Advocacia</option>
<option value="gestao-contabilidade">Sistema de Gestão para Contabilidade</option>
<option value="gestao-consultoria">Sistema de Gestão para Consultoria</option>
<option value="gestao-hotel">Sistema de Gestão para Hotel/Pousada</option>
<option value="gestao-transportadora">Sistema de Gestão para Transportadora</option>
<option value="gestao-oficina">Sistema de Gestão para Oficina Mecânica</option>
<option value="gestao-salao">Sistema de Gestão para Salão de Beleza</option>
<option value="gestao-academia">Sistema de Gestão para Academia</option>
<option value="gestao-veterinaria">Sistema de Gestão para Clínica Veterinária</option>
<option value="gestao-fisioterapia">Sistema de Gestão para Fisioterapia</option>
<option value="gestao-psicologia">Sistema de Gestão para Psicologia</option>
<option value="gestao-seguradora">Sistema de Gestão para Corretora de Seguros</option>
<option value="gestao-agencia-digital">Sistema de Gestão para Agência de Marketing Digital</option>
<option value="gestao-arquitetura">Sistema de Gestão para Escritório de Arquitetura</option>
<option value="gestao-condominio">Sistema de Gestão para Condomínio</option>
<option value="gestao-lavanderia">Sistema de Gestão para Lavanderia</option>
<option value="gestao-buffet">Sistema de Gestão para Buffet / Eventos</option>
<option value="gestao-farmacia">Sistema de Gestão para Farmácia</option>
</optgroup>
<optgroup label="Sistemas de Gestão - Comercial">
<option value="gestao-comercial">Sistema de Gestão Comercial</option>
<option value="gestao-pdv">Sistema de PDV (Ponto de Venda)</option>
<option value="gestao-estoque">Sistema de Controle de Estoque</option>
<option value="gestao-vendas">Sistema de Gestão de Vendas</option>
<option value="gestao-compras">Sistema de Gestão de Compras</option>
<option value="gestao-crm">Sistema de CRM</option>
<option value="gestao-financeira">Sistema de Gestão Financeira</option>
<option value="gestao-faturamento">Sistema de Faturamento/NF-e</option>
<option value="gestao-franquias">Sistema de Gestão de Franquias</option>
<option value="gestao-atacado">Sistema de Gestão de Atacado / Distribuição</option>
<option value="gestao-supermercado">Sistema de Gestão para Supermercado</option>
</optgroup>
<optgroup label="Sistemas de Gestão - Educacional">
<option value="gestao-escolar">Sistema de Gestão Escolar</option>
<option value="gestao-universitaria">Sistema de Gestão Universitária</option>
<option value="gestao-ead">Sistema de EAD</option>
<option value="gestao-cursos">Sistema de Gestão de Cursos</option>
<option value="gestao-biblioteca">Sistema de Biblioteca</option>
</optgroup>
<optgroup label="Sistemas de Gestão - ONGs / Organizações">
<option value="gestao-ong">Sistema de Gestão para ONG</option>
<option value="gestao-projetos-sociais">Sistema de Gestão de Projetos Sociais</option>
<option value="gestao-voluntarios">Sistema de Gestão de Voluntários</option>
<option value="gestao-doacoes">Sistema de Gestão de Doações</option>
</optgroup>
<optgroup label="Sistemas de Gestão - Industrial">
<option value="gestao-industrial">Sistema de Gestão Industrial</option>
<option value="gestao-producao">Sistema de Controle de Produção</option>
<option value="gestao-qualidade">Sistema de Gestão de Qualidade</option>
<option value="gestao-manutencao">Sistema de Manutenção Preventiva</option>
<option value="gestao-seguranca">Sistema de Gestão de Segurança do Trabalho</option>
<option value="gestao-patrimonio">Sistema de Gestão de Patrimônio</option>
<option value="gestao-frota">Sistema de Gestão de Frota</option>
</optgroup>
<optgroup label="Sistemas de Gestão - Outros">
<option value="gestao-petshop">Sistema de Gestão para Pet Shop</option>
<option value="gestao-clube">Sistema de Gestão para Clube Social / Esportivo</option>
<option value="gestao-grafica">Sistema de Gestão para Gráfica</option>
<option value="gestao-padaria">Sistema de Gestão para Padaria / Mercearia</option>
</optgroup>
</select>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="title" class="form-label">Nome do Projeto</label>
<input type="text" class="form-control" id="title" name="title" value="{{ old('title') }}" required>
@error('title') <div class="text-danger small">{{ $message }}</div> @enderror
</div>
<div class="col-md-6 mb-3">
<label for="company_name" class="form-label">Nome da Empresa</label>
<input type="text" class="form-control" id="company_name" name="company_name" value="{{ old('company_name') }}">
@error('company_name') <div class="text-danger small">{{ $message }}</div> @enderror
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="company_address" class="form-label">Endereço da Empresa</label>
<input type="text" class="form-control" id="company_address" name="company_address" value="{{ old('company_address') }}">
@error('company_address') <div class="text-danger small">{{ $message }}</div> @enderror
</div>
<div class="col-md-6 mb-3">
<label for="company_whatsapp" class="form-label">WhatsApp da Empresa</label>
<input type="text" class="form-control" id="company_whatsapp" name="company_whatsapp" value="{{ old('company_whatsapp') }}">
@error('company_whatsapp') <div class="text-danger small">{{ $message }}</div> @enderror
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="company_website" class="form-label">Website da Empresa</label>
<input type="url" class="form-control" id="company_website" name="company_website" value="{{ old('company_website') }}">
@error('company_website') <div class="text-danger small">{{ $message }}</div> @enderror
</div>
<div class="col-md-6 mb-3">
<label for="company_social_media" class="form-label">Redes Sociais da Empresa</label>
<input type="text" class="form-control" id="company_social_media" name="company_social_media" value="{{ old('company_social_media') }}" placeholder="Ex: Instagram, LinkedIn, Facebook">
@error('company_social_media') <div class="text-danger small">{{ $message }}</div> @enderror
</div>
</div>
<div class="mb-3">
<label for="company_business_activities" class="form-label">Atividades de Negócio da Empresa</label>
<textarea class="form-control" id="company_business_activities" name="company_business_activities" rows="2">{{ old('company_business_activities') }}</textarea>
@error('company_business_activities') <div class="text-danger small">{{ $message }}</div> @enderror
</div>
<div class="mb-3">
<label for="company_services_products" class="form-label">Serviços e Produtos da Empresa</label>
<textarea class="form-control" id="company_services_products" name="company_services_products" rows="2">{{ old('company_services_products') }}</textarea>
@error('company_services_products') <div class="text-danger small">{{ $message }}</div> @enderror
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="provider_id" class="form-label">Provedor</label>
<select class="form-select" id="provider_id" name="provider_id" required>
<option value="">Selecione...</option>
@foreach($providers ?? [] as $provider)
<option value="{{ $provider->id }}" {{ old('provider_id') == $provider->id ? 'selected' : '' }}>
{{ $provider->name }}
</option>
@endforeach
</select>
@error('provider_id') <div class="text-danger small">{{ $message }}</div> @enderror
</div>
</div>
<div class="mb-3">
<label for="objective" class="form-label">Objetivo</label>
<textarea class="form-control" id="objective" name="objective" rows="2" required>{{ old('objective') }}</textarea>
@error('objective') <div class="text-danger small">{{ $message }}</div> @enderror
</div>
<div class="mb-3">
<label for="context" class="form-label">Contexto</label>
<textarea class="form-control" id="context" name="context" rows="3">{{ old('context') }}</textarea>
@error('context') <div class="text-danger small">{{ $message }}</div> @enderror
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="persona" class="form-label">Persona / Papel</label>
<input type="text" class="form-control" id="persona" name="persona" value="{{ old('persona') }}">
@error('persona') <div class="text-danger small">{{ $message }}</div> @enderror
</div>
<div class="col-md-6 mb-3">
<label for="tone" class="form-label">Tom / Estilo</label>
<input type="text" class="form-control" id="tone" name="tone" value="{{ old('tone') }}">
@error('tone') <div class="text-danger small">{{ $message }}</div> @enderror
</div>
</div>
<div class="mb-3">
<label for="constraints" class="form-label">Restrições</label>
<textarea class="form-control" id="constraints" name="constraints" rows="2">{{ old('constraints') }}</textarea>
@error('constraints') <div class="text-danger small">{{ $message }}</div> @enderror
</div>
<div class="mb-3">
<label for="output_format" class="form-label">Formato de Saída</label>
<input type="text" class="form-control" id="output_format" name="output_format" value="{{ old('output_format') }}">
@error('output_format') <div class="text-danger small">{{ $message }}</div> @enderror
</div>
<div class="mb-3">
<label for="examples" class="form-label">Exemplos</label>
<textarea class="form-control" id="examples" name="examples" rows="3">{{ old('examples') }}</textarea>
@error('examples') <div class="text-danger small">{{ $message }}</div> @enderror
</div>
<div class="mb-3">
<label for="variables" class="form-label">Variáveis</label>
<textarea class="form-control" id="variables" name="variables" rows="2" placeholder="var1, var2">{{ old('variables') }}</textarea>
@error('variables') <div class="text-danger small">{{ $message }}</div> @enderror
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="temperature" class="form-label">Temperatura</label>
<input type="number" step="0.1" min="0" max="1" class="form-control" id="temperature" name="temperature" value="{{ old('temperature', 0.7) }}" required>
@error('temperature') <div class="text-danger small">{{ $message }}</div> @enderror
</div>
<div class="col-md-6 mb-3">
<label for="max_tokens" class="form-label">Max Tokens</label>
<input type="number" class="form-control" id="max_tokens" name="max_tokens" value="{{ old('max_tokens', 1024) }}" required>
@error('max_tokens') <div class="text-danger small">{{ $message }}</div> @enderror
</div>
</div>
<button type="submit" class="btn btn-primary"><i class="bi bi-save"></i> Salvar</button>
<a href="{{ route('prompt-projects.index') }}" class="btn btn-secondary">Cancelar</a>
</form>
</div>
</div>
@section('scripts')
<script>
const templatesApiUrl = "{{ route('prompt-templates.api') }}";
window.templates = {};
window.templatesLoaded = false;
function loadTemplates() {
fetch(templatesApiUrl, {
headers: {
'Accept': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
}
})
.then(response => {
if (!response.ok) {
throw new Error('HTTP ' + response.status);
}
return response.json();
})
.then(data => {
window.templates = data;
window.templatesLoaded = true;
console.log('Templates loaded:', Object.keys(data).length);
})
.catch(error => {
console.error('Failed to load templates:', error);
});
}
document.addEventListener('DOMContentLoaded', loadTemplates);
const allOptions = Array.from(document.querySelectorAll('#template-source option')).map(opt => ({
value: opt.value,
text: opt.textContent,
group: opt.parentElement.tagName === 'OPTGROUP' ? opt.parentElement.getAttribute('label') : ''
}));
const searchInput = document.getElementById('template-search-input');
const dropdown = document.getElementById('template-dropdown');
const hiddenInput = document.getElementById('template');
function renderDropdown(filterText = '') {
const term = filterText.toLowerCase();
const filtered = allOptions.filter(opt => opt.value === '' || opt.text.toLowerCase().includes(term));
dropdown.innerHTML = '';
if (filtered.length === 0) {
dropdown.innerHTML = '<div class="dropdown-item disabled" style="padding:0.5rem 1rem; color:#6c757d;">Nenhum modelo encontrado</div>';
dropdown.style.display = 'block';
return;
}
filtered.forEach(opt => {
const item = document.createElement('div');
item.className = 'dropdown-item';
item.textContent = opt.text;
item.style.cssText = 'padding: 0.5rem 1rem; cursor: pointer;';
item.addEventListener('mouseenter', function() {
item.style.backgroundColor = '#f8f9fa';
});
item.addEventListener('mouseleave', function() {
item.style.backgroundColor = '';
});
item.addEventListener('click', function(e) {
e.preventDefault();
searchInput.value = opt.text;
hiddenInput.value = opt.value;
dropdown.style.display = 'none';
const template = window.templates[opt.text] || {};
if (Object.keys(template).length > 0) {
document.getElementById('title').value = template.title || '';
document.getElementById('objective').value = template.objective || '';
document.getElementById('context').value = template.context || '';
document.getElementById('persona').value = template.persona || '';
document.getElementById('tone').value = template.tone || '';
document.getElementById('constraints').value = template.constraints || '';
document.getElementById('output_format').value = template.output_format || '';
document.getElementById('examples').value = template.examples || '';
document.getElementById('variables').value = template.variables || '';
document.getElementById('temperature').value = template.temperature ?? 0.7;
document.getElementById('max_tokens').value = template.max_tokens ?? 1024;
if (template.standard_files !== false) {
const stdFilesNote = "\n\n---\nNOTA: Os arquivos padrao (LICENSE, README.md, RULES.md, cookies.html, termos-de-uso.html, privacidade.html) serao gerados automaticamente pelo sistema apos a geracao do prompt. NAO os inclua na sua resposta.";
const constraintsEl = document.getElementById('constraints');
if (constraintsEl && !constraintsEl.value.includes('Arquivos padrao')) {
constraintsEl.value = constraintsEl.value.trim() + stdFilesNote;
}
}
} else {
const fields = ['title', 'objective', 'context', 'persona', 'tone', 'constraints', 'output_format', 'examples', 'variables', 'temperature', 'max_tokens'];
fields.forEach(field => {
const el = document.getElementById(field);
if (el) {
if (field === 'temperature') el.value = '0.7';
else if (field === 'max_tokens') el.value = '1024';
else el.value = '';
}
});
}
});
dropdown.appendChild(item);
});
if (filterText.length > 0) {
dropdown.style.display = 'block';
}
}
searchInput.addEventListener('input', function() {
renderDropdown(this.value);
});
searchInput.addEventListener('focus', function() {
renderDropdown(this.value);
});
document.addEventListener('click', function(e) {
if (!searchInput.contains(e.target) && !dropdown.contains(e.target)) {
dropdown.style.display = 'none';
}
});
</script>
@endsection('scripts')
@endsection('content')