| class CustomSolarIntegratorForm extends HTMLElement { |
| constructor() { |
| super(); |
| this.currentStep = 1; |
| this.totalSteps = 3; |
| this.formData = { |
| company_id: '', |
| integrator_type: 'RESIDENTIAL_INSTALLER', |
| certification_level: 'LEVEL_1', |
| license_number: '', |
| license_expiry_date: '', |
| years_of_experience: 0, |
| completed_projects: 0, |
| warranty_offered: '', |
| insurance_coverage: '', |
| specialization: [], |
| coverage_area: [], |
| certifications: [], |
| equipment_brands: [], |
| minimum_project_size: '', |
| maximum_project_size: '', |
| installation_time_frame: '', |
| warranty_period: 10, |
| maintenance_services: false, |
| emergency_support: false, |
| design_services: false, |
| project_management: false, |
| }; |
| } |
|
|
| connectedCallback() { |
| this.attachShadow({ mode: 'open' }); |
| this.render(); |
| } |
|
|
| handleInputChange(e) { |
| const { name, value, type, checked } = e.target; |
| if (type === 'checkbox') { |
| this.formData[name] = checked; |
| } else { |
| this.formData[name] = value; |
| } |
| this.render(); |
| } |
|
|
| handleArrayChange(name, value) { |
| const currentArray = this.formData[name]; |
| const newArray = currentArray.includes(value) |
| ? currentArray.filter(item => item !== value) |
| : [...currentArray, value]; |
| this.formData[name] = newArray; |
| this.render(); |
| } |
|
|
| nextStep() { |
| if (this.currentStep < this.totalSteps) { |
| this.currentStep++; |
| this.render(); |
| } |
| } |
|
|
| prevStep() { |
| if (this.currentStep > 1) { |
| this.currentStep--; |
| this.render(); |
| } |
| } |
|
|
| renderStep1() { |
| return ` |
| <div class="space-y-4"> |
| <h3 class="text-lg font-semibold">Informações Básicas</h3> |
| |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-4"> |
| <div> |
| <label class="text-sm font-medium text-gray-700">Tipo de Integrador *</label> |
| <select |
| name="integrator_type" |
| value="${this.formData.integrator_type}" |
| onchange="this.getRootNode().host.handleInputChange(event)" |
| class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" |
| > |
| <option value="RESIDENTIAL_INSTALLER">Instalador Residencial</option> |
| <option value="COMMERCIAL_INSTALLER">Instalador Comercial</option> |
| <option value="UTILITY_INSTALLER">Instalador de Utilidade</option> |
| <option value="DESIGNER">Designer</option> |
| <option value="DISTRIBUTOR">Distribuidor</option> |
| </select> |
| </div> |
| |
| <div> |
| <label class="text-sm font-medium text-gray-700">Nível de Certificação</label> |
| <select |
| name="certification_level" |
| value="${this.formData.certification_level}" |
| onchange="this.getRootNode().host.handleInputChange(event)" |
| class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" |
| > |
| <option value="LEVEL_1">Nível 1</option> |
| <option value="LEVEL_2">Nível 2</option> |
| <option value="LEVEL_3">Nível 3</option> |
| <option value="MASTER">Master</option> |
| </select> |
| </div> |
| </div> |
| |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-4"> |
| <div> |
| <label class="text-sm font-medium text-gray-700">Número da Licença</label> |
| <input |
| type="text" |
| name="license_number" |
| value="${this.formData.license_number}" |
| onchange="this.getRootNode().host.handleInputChange(event)" |
| class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" |
| /> |
| </div> |
| |
| <div> |
| <label class="text-sm font-medium text-gray-700">Data de Expiração da Licença</label> |
| <input |
| type="date" |
| name="license_expiry_date" |
| value="${this.formData.license_expiry_date}" |
| onchange="this.getRootNode().host.handleInputChange(event)" |
| class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" |
| /> |
| </div> |
| </div> |
| |
| <div class="grid grid-cols-1 md:grid-cols-3 gap-4"> |
| <div> |
| <label class="text-sm font-medium text-gray-700">Anos de Experiência</label> |
| <input |
| type="number" |
| name="years_of_experience" |
| value="${this.formData.years_of_experience}" |
| onchange="this.getRootNode().host.handleInputChange(event)" |
| class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" |
| /> |
| </div> |
| |
| <div> |
| <label class="text-sm font-medium text-gray-700">Projetos Completados</label> |
| <input |
| type="number" |
| name="completed_projects" |
| value="${this.formData.completed_projects}" |
| onchange="this.getRootNode().host.handleInputChange(event)" |
| class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" |
| /> |
| </div> |
| |
| <div> |
| <label class="text-sm font-medium text-gray-700">Período de Garantia (anos)</label> |
| <input |
| type="number" |
| name="warranty_period" |
| value="${this.formData.warranty_period}" |
| onchange="this.getRootNode().host.handleInputChange(event)" |
| class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" |
| /> |
| </div> |
| </div> |
| </div> |
| `; |
| } |
|
|
| renderStep2() { |
| return ` |
| <div class="space-y-4"> |
| <h3 class="text-lg font-semibold">Serviços e Capabilities</h3> |
| |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-4"> |
| <div> |
| <label class="text-sm font-medium text-gray-700">Áreas de Especialização</label> |
| <div class="mt-1 space-y-2"> |
| ${['roof_mount', 'ground_mount', 'tracking_systems', 'commercial', 'residential'].map(spec => ` |
| <div key="${spec}" class="flex items-center"> |
| <input |
| id="spec-${spec}" |
| name="specialization" |
| type="checkbox" |
| ${this.formData.specialization.includes(spec) ? 'checked' : ''} |
| onchange="this.getRootNode().host.handleArrayChange('specialization', '${spec}')" |
| class="h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500" |
| /> |
| <label for="spec-${spec}" class="ml-2 block text-sm text-gray-900 capitalize"> |
| ${spec.replace('_', ' ')} |
| </label> |
| </div> |
| `).join('')} |
| </div> |
| </div> |
| |
| <div> |
| <label class="text-sm font-medium text-gray-700">Marcas de Equipamentos</label> |
| <textarea |
| name="equipment_brands" |
| value="${this.formData.equipment_brands.join(', ')}" |
| onchange="this.getRootNode().host.handleInputChange(event)" |
| placeholder="Digite marcas separadas por vírgula" |
| class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" |
| ></textarea> |
| </div> |
| </div> |
| |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-4"> |
| <div> |
| <label class="text-sm font-medium text-gray-700">Tamanho Mínimo do Projeto</label> |
| <input |
| type="text" |
| name="minimum_project_size" |
| value="${this.formData.minimum_project_size}" |
| onchange="this.getRootNode().host.handleInputChange(event)" |
| placeholder="ex: 5kW" |
| class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" |
| /> |
| </div> |
| |
| <div> |
| <label class="text-sm font-medium text-gray-700">Tamanho Máximo do Projeto</label> |
| <input |
| type="text" |
| name="maximum_project_size" |
| value="${this.formData.maximum_project_size}" |
| onchange="this.getRootNode().host.handleInputChange(event)" |
| placeholder="ex: 1MW" |
| class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" |
| /> |
| </div> |
| </div> |
| |
| <div> |
| <label class="text-sm font-medium text-gray-700">Prazo de Instalação</label> |
| <input |
| type="text" |
| name="installation_time_frame" |
| value="${this.formData.installation_time_frame}" |
| onchange="this.getRootNode().host.handleInputChange(event)" |
| placeholder="ex: 4-6 semanas" |
| class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" |
| /> |
| </div> |
| |
| <div class="grid grid-cols-2 md:grid-cols-4 gap-4"> |
| <div class="flex items-center"> |
| <input |
| id="maintenance_services" |
| name="maintenance_services" |
| type="checkbox" |
| ${this.formData.maintenance_services ? 'checked' : ''} |
| onchange="this.getRootNode().host.handleInputChange(event)" |
| class="h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500" |
| /> |
| <label for="maintenance_services" class="ml-2 block text-sm text-gray-900"> |
| Serviços de Manutenção |
| </label> |
| </div> |
| |
| <div class="flex items-center"> |
| <input |
| id="emergency_support" |
| name="emergency_support" |
| type="checkbox" |
| ${this.formData.emergency_support ? 'checked' : ''} |
| onchange="this.getRootNode().host.handleInputChange(event)" |
| class="h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500" |
| /> |
| <label for="emergency_support" class="ml-2 block text-sm text-gray-900"> |
| Suporte de Emergência |
| </label> |
| </div> |
| |
| <div class="flex items-center"> |
| <input |
| id="design_services" |
| name="design_services" |
| type="checkbox" |
| ${this.formData.design_services ? 'checked' : ''} |
| onchange="this.getRootNode().host.handleInputChange(event)" |
| class="h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500" |
| /> |
| <label for="design_services" class="ml-2 block text-sm text-gray-900"> |
| Serviços de Design |
| </label> |
| </div> |
| |
| <div class="flex items-center"> |
| <input |
| id="project_management" |
| name="project_management" |
| type="checkbox" |
| ${this.formData.project_management ? 'checked' : ''} |
| onchange="this.getRootNode().host.handleInputChange(event)" |
| class="h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500" |
| /> |
| <label for="project_management" class="ml-2 block text-sm text-gray-900"> |
| Gerenciamento de Projetos |
| </label> |
| </div> |
| </div> |
| </div> |
| `; |
| } |
|
|
| renderStep3() { |
| return ` |
| <div class="space-y-4"> |
| <h3 class="text-lg font-semibold">Cobertura e Certificações</h3> |
| |
| <div> |
| <label class="text-sm font-medium text-gray-700">Áreas de Cobertura</label> |
| <textarea |
| name="coverage_area" |
| value="${this.formData.coverage_area.join(', ')}" |
| onchange="this.getRootNode().host.handleInputChange(event)" |
| placeholder="Digite áreas separadas por vírgula, ex: São Paulo, Rio de Janeiro" |
| class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" |
| ></textarea> |
| </div> |
| |
| <div> |
| <label class="text-sm font-medium text-gray-700">Certificações</label> |
| <textarea |
| name="certifications" |
| value="${this.formData.certifications.join(', ')}" |
| onchange="this.getRootNode().host.handleInputChange(event)" |
| placeholder="Digite certificações separadas por vírgula, ex: NABCEP, UL, CSA" |
| class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" |
| ></textarea> |
| </div> |
| |
| <div> |
| <label class="text-sm font-medium text-gray-700">Cobertura de Seguro</label> |
| <input |
| type="text" |
| name="insurance_coverage" |
| value="${this.formData.insurance_coverage}" |
| onchange="this.getRootNode().host.handleInputChange(event)" |
| placeholder="ex: 500k de responsabilidade civil" |
| class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" |
| /> |
| </div> |
| |
| <div> |
| <label class="text-sm font-medium text-gray-700">Garantia Oferecida</label> |
| <input |
| type="text" |
| name="warranty_offered" |
| value="${this.formData.warranty_offered}" |
| onchange="this.getRootNode().host.handleInputChange(event)" |
| placeholder="ex: 20 anos" |
| class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" |
| /> |
| </div> |
| </div> |
| `; |
| } |
|
|
| render() { |
| this.shadowRoot.innerHTML = ` |
| <style> |
| @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap'); |
| |
| :host { |
| display: block; |
| font-family: 'Inter', sans-serif; |
| } |
| |
| .space-y-4 > * + * { |
| margin-top: 1rem; |
| } |
| |
| .space-y-6 > * + * { |
| margin-top: 1.5rem; |
| } |
| |
| .grid { |
| display: grid; |
| } |
| |
| .gap-4 { |
| gap: 1rem; |
| } |
| |
| .rounded-md { |
| border-radius: 0.375rem; |
| } |
| |
| .border-gray-300 { |
| border-color: #d1d5db; |
| } |
| |
| .focus\\:border-indigo-500:focus { |
| border-color: #6366f1; |
| } |
| |
| .focus\\:ring-indigo-500:focus { |
| --tw-ring-color: #6366f1; |
| } |
| |
| .shadow-sm { |
| box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05); |
| } |
| |
| .text-sm { |
| font-size: 0.875rem; |
| line-height: 1.25rem; |
| } |
| |
| .text-lg { |
| font-size: 1.125rem; |
| line-height: 1.75rem; |
| } |
| |
| .text-xl { |
| font-size: 1.25rem; |
| line-height: 1.75rem; |
| } |
| |
| .font-semibold { |
| font-weight: 600; |
| } |
| |
| .font-bold { |
| font-weight: 700; |
| } |
| |
| .text-gray-700 { |
| color: #374151; |
| } |
| |
| .text-gray-900 { |
| color: #111827; |
| } |
| |
| .text-gray-500 { |
| color: #6b7280; |
| } |
| |
| .text-indigo-600 { |
| color: #4f46e5; |
| } |
| |
| .bg-gray-200 { |
| background-color: #e5e7eb; |
| } |
| |
| .bg-blue-600 { |
| background-color: #2563eb; |
| } |
| |
| .h-2\\.5 { |
| height: 0.625rem; |
| } |
| |
| .rounded-full { |
| border-radius: 9999px; |
| } |
| |
| .transition-all { |
| transition-property: all; |
| } |
| |
| .duration-300 { |
| transition-duration: 300ms; |
| } |
| |
| .w-full { |
| width: 100%; |
| } |
| |
| .block { |
| display: block; |
| } |
| |
| .flex { |
| display: flex; |
| } |
| |
| .items-center { |
| align-items: center; |
| } |
| |
| .justify-between { |
| justify-content: space-between; |
| } |
| |
| .mt-1 { |
| margin-top: 0.25rem; |
| } |
| |
| .mb-4 { |
| margin-bottom: 1rem; |
| } |
| |
| .mb-6 { |
| margin-bottom: 1.5rem; |
| } |
| |
| .ml-2 { |
| margin-left: 0.5rem; |
| } |
| |
| .pt-4 { |
| padding-top: 1rem; |
| } |
| |
| .p-6 { |
| padding: 1.5rem; |
| } |
| |
| .p-8 { |
| padding: 2rem; |
| } |
| |
| .space-x-3 > * + * { |
| margin-left: 0.75rem; |
| } |
| |
| @media (min-width: 768px) { |
| .md\\:grid-cols-2 { |
| grid-template-columns: repeat(2, minmax(0, 1fr)); |
| } |
| |
| .md\\:grid-cols-3 { |
| grid-template-columns: repeat(3, minmax(0, 1fr)); |
| } |
| |
| .md\\:grid-cols-4 { |
| grid-template-columns: repeat(4, minmax(0, 1fr)); |
| } |
| } |
| </style> |
| |
| <form class="space-y-6"> |
| <div class="mb-6"> |
| <div class="flex items-center justify-between mb-4"> |
| <h2 class="text-xl font-bold">Registro de Integrador Solar</h2> |
| <div class="text-sm text-gray-500"> |
| Passo ${this.currentStep} de ${this.totalSteps} |
| </div> |
| </div> |
| |
| <div class="w-full bg-gray-200 rounded-full h-2.5"> |
| <div |
| class="bg-blue-600 h-2.5 rounded-full transition-all duration-300" |
| style="width: ${(this.currentStep / this.totalSteps) * 100}%" |
| ></div> |
| </div> |
| </div> |
| |
| ${this.currentStep === 1 ? this.renderStep1() : ''} |
| ${this.currentStep === 2 ? this.renderStep2() : ''} |
| ${this.currentStep === 3 ? this.renderStep3() : ''} |
| |
| <div class="flex justify-between pt-4"> |
| <div> |
| ${this.currentStep > 1 ? ` |
| <button |
| type="button" |
| onclick="this.getRootNode().host.prevStep()" |
| class="px-4 py-2 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" |
| > |
| Voltar |
| </button> |
| ` : ''} |
| </div> |
| |
| <div class="flex space-x-3"> |
| ${this.currentStep < this.totalSteps ? ` |
| <button |
| type="button" |
| onclick="this.getRootNode().host.nextStep()" |
| class="px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" |
| > |
| Próximo |
| </button> |
| ` : ` |
| <button |
| type="button" |
| onclick="this.getRootNode().host.dispatchEvent(new CustomEvent('cancel'))" |
| class="px-4 py-2 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" |
| > |
| Cancelar |
| </button> |
| <button |
| type="button" |
| onclick="this.getRootNode().host.dispatchEvent(new CustomEvent('submit', { detail: this.getRootNode().host.formData }))" |
| class="px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" |
| > |
| Cadastrar |
| </button> |
| `} |
| </div> |
| </div> |
| </form> |
| `; |
| } |
| } |
|
|
| customElements.define('custom-solar-integrator-form', CustomSolarIntegratorForm); |