| 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); |