document.addEventListener('DOMContentLoaded', function() { const internetBtn = document.getElementById('internetBtn'); const l2lBtn = document.getElementById('l2lBtn'); const internetForm = document.getElementById('internetForm'); const l2lForm = document.getElementById('l2lForm'); const calculateBtn = document.getElementById('calculateBtn'); const ipRangeInput = document.getElementById('ipRange'); const ipTableBody = document.getElementById('ipTableBody'); const ipTableContainer = document.getElementById('ipTableContainer'); const generateBtn = document.getElementById('generateBtn'); const outputContainer = document.getElementById('outputContainer'); const emailOutput = document.getElementById('emailOutput'); const copyBtn = document.getElementById('copyBtn'); // Toggle between service types internetBtn.addEventListener('click', function() { internetBtn.classList.add('bg-blue-600', 'text-white'); internetBtn.classList.remove('bg-gray-200', 'text-gray-800'); l2lBtn.classList.remove('bg-blue-600', 'text-white'); l2lBtn.classList.add('bg-gray-200', 'text-gray-800'); internetForm.classList.remove('hidden'); l2lForm.classList.add('hidden'); outputContainer.classList.add('hidden'); }); // Initialize Feather Icons feather.replace(); l2lBtn.addEventListener('click', function() { l2lBtn.classList.add('bg-blue-600', 'text-white'); l2lBtn.classList.remove('bg-gray-200', 'text-gray-800'); internetBtn.classList.remove('bg-blue-600', 'text-white'); internetBtn.classList.add('bg-gray-200', 'text-gray-800'); l2lForm.classList.remove('hidden'); internetForm.classList.add('hidden'); outputContainer.classList.add('hidden'); }); // Calculate IP addresses calculateBtn.addEventListener('click', function() { const ipRange = ipRangeInput.value.trim(); if (!ipRange) { alert('Please enter a valid IP range (e.g., 190.220.1.216/29)'); return; } try { const [baseIp, cidr] = ipRange.split('/'); const cidrNumber = parseInt(cidr); if (cidrNumber < 0 || cidrNumber > 32) { throw new Error('Invalid CIDR'); } const subnetMask = calculateSubnetMask(cidrNumber); const ipParts = baseIp.split('.').map(Number); const networkAddress = calculateNetworkAddress(ipParts, cidrNumber); const broadcastAddress = calculateBroadcastAddress(networkAddress, cidrNumber); // Clear previous results ipTableBody.innerHTML = ''; // Add network address row addTableRow('RED LAN', formatIp(networkAddress), subnetMask); // Calculate usable IPs (network +1 to broadcast -1) const startIp = [...networkAddress]; incrementIp(startIp); // Calculate the number of usable hosts const usableHosts = Math.pow(2, 32 - cidrNumber) - 2; // Add gateway (first usable IP) addTableRow('GATEWAY', formatIp(startIp), subnetMask); // Increment for next IP incrementIp(startIp); // Add available client IPs for (let i = 0; i < usableHosts - 1; i++) { if (formatIp(startIp) === formatIp(broadcastAddress)) break; addTableRow('DISPONIBLE CLIENTE', formatIp(startIp), subnetMask); incrementIp(startIp); } // Add broadcast address addTableRow('BROADCAST', formatIp(broadcastAddress), subnetMask); ipTableContainer.classList.remove('hidden'); } catch (error) { alert('Invalid IP range format. Please use format like 190.220.1.216/29'); console.error(error); } }); // Generate email template generateBtn.addEventListener('click', function() { if (internetBtn.classList.contains('bg-blue-600')) { generateInternetEmail(); } else { generateL2LEmail(); } outputContainer.classList.remove('hidden'); }); // Copy table to clipboard const copyTableBtn = document.getElementById('copyTableBtn'); copyTableBtn.addEventListener('click', function() { let tableText = 'Type\tIP Address\tSubnet Mask\n'; const rows = ipTableBody.querySelectorAll('tr'); rows.forEach(row => { const cells = row.querySelectorAll('td'); tableText += `${cells[0].textContent}\t${cells[1].textContent}\t${cells[2].textContent}\n`; }); navigator.clipboard.writeText(tableText).then(() => { const originalText = copyTableBtn.innerHTML; copyTableBtn.innerHTML = ' Copied!'; setTimeout(() => { copyTableBtn.innerHTML = originalText; feather.replace(); }, 2000); }); }); // Make sure calculate button works immediately calculateBtn.addEventListener('click', calculateIPs); function calculateIPs() { const ipRange = ipRangeInput.value.trim(); if (!ipRange) { alert('Please enter a valid IP range (e.g., 190.220.1.216/29)'); return; } try { const [baseIp, cidr] = ipRange.split('/'); const cidrNumber = parseInt(cidr); if (cidrNumber < 0 || cidrNumber > 32) { throw new Error('Invalid CIDR'); } const subnetMask = calculateSubnetMask(cidrNumber); const ipParts = baseIp.split('.').map(Number); const networkAddress = calculateNetworkAddress(ipParts, cidrNumber); const broadcastAddress = calculateBroadcastAddress(networkAddress, cidrNumber); // Clear previous results ipTableBody.innerHTML = ''; // Add network address row addTableRow('RED LAN', formatIp(networkAddress), subnetMask); // Calculate usable IPs (network +1 to broadcast -1) const startIp = [...networkAddress]; incrementIp(startIp); // Calculate the number of usable hosts const usableHosts = Math.pow(2, 32 - cidrNumber) - 2; // Add gateway (first usable IP) addTableRow('GATEWAY', formatIp(startIp), subnetMask); // Increment for next IP incrementIp(startIp); // Add available client IPs for (let i = 0; i < usableHosts - 1; i++) { if (formatIp(startIp) === formatIp(broadcastAddress)) break; addTableRow('DISPONIBLE CLIENTE', formatIp(startIp), subnetMask); incrementIp(startIp); } // Add broadcast address addTableRow('BROADCAST', formatIp(broadcastAddress), subnetMask); ipTableContainer.classList.remove('hidden'); } catch (error) { alert('Invalid IP range format. Please use format like 190.220.1.216/29'); console.error(error); } } // Copy email to clipboard copyBtn.addEventListener('click', function() { const textToCopy = emailOutput.textContent; navigator.clipboard.writeText(textToCopy).then(() => { const originalText = copyBtn.innerHTML; copyBtn.innerHTML = ' Copied!'; feather.replace(); setTimeout(() => { copyBtn.innerHTML = originalText; feather.replace(); }, 2000); }).catch(err => { console.error('Failed to copy text: ', err); copyBtn.innerHTML = ' Failed!'; feather.replace(); setTimeout(() => { copyBtn.innerHTML = originalText; feather.replace(); }, 2000); }); }); // Helper functions function addTableRow(type, ip, mask) { if (!ipTableBody) return; const row = document.createElement('tr'); row.innerHTML = ` ${type} ${ip} ${mask} `; ipTableBody.appendChild(row); } function calculateSubnetMask(cidr) { let mask = []; for (let i = 0; i < 4; i++) { const bits = Math.min(8, Math.max(0, cidr - i * 8)); mask.push(256 - Math.pow(2, 8 - bits)); } return mask.join('.'); } function calculateNetworkAddress(ip, cidr) { const network = [...ip]; for (let i = 0; i < 4; i++) { const bits = Math.min(8, Math.max(0, cidr - i * 8)); if (bits === 0) { network[i] = 0; } else if (bits < 8) { network[i] = network[i] & (256 - Math.pow(2, 8 - bits)); } } return network; } function calculateBroadcastAddress(network, cidr) { const broadcast = [...network]; for (let i = 0; i < 4; i++) { const bits = Math.min(8, Math.max(0, cidr - i * 8)); if (bits < 8) { broadcast[i] = broadcast[i] | (Math.pow(2, 8 - bits) - 1); } } return broadcast; } function incrementIp(ip) { for (let i = 3; i >= 0; i--) { if (ip[i] < 255) { ip[i]++; break; } else { ip[i] = 0; } } } function formatIp(ipArray) { return ipArray.join('.'); } function generateInternetEmail() { const client = document.getElementById('client').value; const serviceNumber = document.getElementById('serviceNumber').value; const address = document.getElementById('address').value; const bandwidth = document.getElementById('bandwidth').value; const ipRange = document.getElementById('ipRange').value; let emailText = `Subject: Servicio Claro - Alta Internet ${bandwidth} - N° Enlace: ${serviceNumber} ${client}\n\n`; emailText += `Estimado Cliente:\n\n`; emailText += `Le informamos que se ha realizado con éxito el ALTA a ${bandwidth} del servicio solicitado, ubicado en ${address}\n\n`; emailText += `Datos del servicio:\n`; emailText += `- Cliente: ${client}\n`; emailText += `- N° de enlace: ${serviceNumber}\n`; emailText += `- Domicilio: ${address}\n`; emailText += `- Ancho de banda: ${bandwidth}\n`; emailText += `- Rango IP: ${ipRange}\n\n`; // IP Table for email with better formatting emailText += `Detalle de configuración IP:\n\n`; // Calculate column widths const rows = ipTableBody.querySelectorAll('tr'); let maxTypeLength = 0; let maxIpLength = 0; let maxMaskLength = 0; rows.forEach(row => { const cells = row.querySelectorAll('td'); maxTypeLength = Math.max(maxTypeLength, cells[0].textContent.length); maxIpLength = Math.max(maxIpLength, cells[1].textContent.length); maxMaskLength = Math.max(maxMaskLength, cells[2].textContent.length); }); // Add padding to column headers const typeHeader = 'Tipo'.padEnd(maxTypeLength + 2); const ipHeader = 'Dirección IP'.padEnd(maxIpLength + 2); const maskHeader = 'Máscara'.padEnd(maxMaskLength + 2); // Table header emailText += `${typeHeader}${ipHeader}${maskHeader}\n`; emailText += `${'-'.repeat(typeHeader.length)}${'-'.repeat(ipHeader.length)}${'-'.repeat(maskHeader.length)}\n`; // Table rows rows.forEach(row => { const cells = row.querySelectorAll('td'); const type = cells[0].textContent.padEnd(maxTypeLength + 2); const ip = cells[1].textContent.padEnd(maxIpLength + 2); const mask = cells[2].textContent.padEnd(maxMaskLength + 2); emailText += `${type}${ip}${mask}\n`; }); emailText += `\n`; emailText += `Configuración DNS:\n`; emailText += `- DNS Primario: 186.12.238.16\n`; emailText += `- DNS Secundario: 186.12.238.15\n\n`; emailText += `Ante inconvenientes con la puesta en marcha, favor de comunicarse conmigo.\n`; emailText += `Posteriormente, por solicitudes o reclamos, Centro de Gestión Empresarial gestionempresarial@claro.com.ar\n\n`; emailText += `Atte.\n`; emailOutput.textContent = emailText; feather.replace(); } function generateL2LEmail() { const client = document.getElementById('l2lClient').value; const serviceNumber = document.getElementById('l2lServiceNumber').value; const bandwidth = document.getElementById('l2lBandwidth').value; const siteAAddress = document.getElementById('siteAAddress').value; const siteADevice = document.getElementById('siteADevice').value; const siteAPort = document.getElementById('siteAPort').value; const siteBAddress = document.getElementById('siteBAddress').value; const siteBDevice = document.getElementById('siteBDevice').value; const siteBPort = document.getElementById('siteBPort').value; let emailText = `Subject: Servicio Claro - Alta L2L ${bandwidth} - N° Enlace: ${serviceNumber} ${client}\n\n`; emailText += `Estimado Cliente:\n\n`; emailText += `Le informamos que se ha realizado con éxito el ALTA a ${bandwidth} del servicio LAN to LAN solicitado.\n\n`; emailText += `Datos del servicio:\n`; emailText += `Cliente: ${client}\n`; emailText += `N° de enlace: ${serviceNumber}\n`; emailText += `Ancho de banda: ${bandwidth}\n\n`; emailText += `Detalle de extremos:\n\n`; // Calculate column widths for L2L table const siteALabelLength = Math.max('Dirección:'.length, 'Equipo:'.length, 'Puerto:'.length); const siteBLabelLength = Math.max('Dirección:'.length, 'Equipo:'.length, 'Puerto:'.length); const siteAContentLength = Math.max(siteAAddress.length, siteADevice.length, siteAPort.length); const siteBContentLength = Math.max(siteBAddress.length, siteBDevice.length, siteBPort.length); // Site A table emailText += `Extremo A:\n`; emailText += `${'Dirección:'.padEnd(siteALabelLength + 2)}${siteAAddress.padEnd(siteAContentLength + 2)}\n`; emailText += `${'Equipo:'.padEnd(siteALabelLength + 2)}${siteADevice.padEnd(siteAContentLength + 2)}\n`; emailText += `${'Puerto:'.padEnd(siteALabelLength + 2)}${siteAPort.padEnd(siteAContentLength + 2)}\n\n`; // Site B table emailText += `Extremo B:\n`; emailText += `${'Dirección:'.padEnd(siteBLabelLength + 2)}${siteBAddress.padEnd(siteBContentLength + 2)}\n`; emailText += `${'Equipo:'.padEnd(siteBLabelLength + 2)}${siteBDevice.padEnd(siteBContentLength + 2)}\n`; emailText += `${'Puerto:'.padEnd(siteBLabelLength + 2)}${siteBPort.padEnd(siteBContentLength + 2)}\n\n`; emailText += `Ante inconvenientes con la puesta en marcha, favor de comunicarse conmigo. Posteriormente, por solicitudes o reclamos, Centro de Gestion Empresarial gestionempresarial@claro.com.ar\n\n`; emailText += `Atte.-`; emailOutput.textContent = emailText; } });