Update login.html

Signed-off-by: nestict <icttechnest@gmail.com>
This commit is contained in:
nestict 2025-05-14 16:57:57 +02:00
parent 268cc7f84a
commit 5b3b3a1b4e

View File

@ -3,146 +3,122 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>yatmack</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/3.8.3/core.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link href='https://fonts.googleapis.com/css2?family=Lexend:wght@300;400;500;600;700&display=swap' rel='stylesheet'>
<title> HOTSPOT WIFI MBSA</title>
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
navy: {
DEFAULT: '#023047',
50: '#e6f0f5',
100: '#cce1eb',
200: '#99c3d7',
300: '#66a5c3',
400: '#3387af',
500: '#023047',
600: '#022640',
700: '#011d39',
800: '#011332',
900: '#010a2b'
},
orange: {
DEFAULT: '#fb8500',
50: '#fff4e6',
100: '#ffe9cc',
200: '#ffd399',
300: '#ffbd66',
400: '#ffa733',
500: '#fb8500',
600: '#cc6d00',
700: '#995200',
800: '#663600',
900: '#331b00'
}
},
fontFamily: {
'lexend': ['Lexend', 'sans-serif'],
},
animation: {
'spin-fast': 'spin 0.5s linear infinite',
'fade-in': 'fadeIn 0.3s ease-in-out',
'slide-up': 'slideUp 0.3s ease-out'
},
keyframes: {
fadeIn: {
'0%': { opacity: '0' },
'100%': { opacity: '1' }
},
slideUp: {
'0%': { transform: 'translateY(10px)', opacity: '0' },
'100%': { transform: 'translateY(0)', opacity: '1' }
}
}
}
}
}
</script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/glider-js@1.7.7/glider.min.css" />
<script src="https://cdn.jsdelivr.net/npm/glider-js@1.7.7/glider.min.js"></script>
<link rel="preconnect" href="https://cdn.jsdelivr.net">
<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
<link rel="stylesheet" href="https://rsms.me/inter/inter.css">
<!-- <link rel="stylesheet" type="text/css" href="styles.css"> -->
</head>
<body class="font-lexend min-h-screen bg-gradient-to-b from-navy to-navy/95 text-gray-100">
<div class="container mx-auto px-2 py-4 max-w-3xl">
<div class="bg-white/10 backdrop-blur-lg rounded-2xl shadow-xl mb-6 overflow-hidden border border-white/10">
<div class="p-3 relative">
<h1 class="text-2xl font-bold text-center text-orange mb-3">YATMACK HOTSPOT</h1>
<p class="text-gray-100/90 text-center text-sm mb-4">
Select package ? Enter M-Pesa number ? Complete payment
</p>
<div class="flex items-center justify-center gap-2 py-2 px-4 bg-white/5 rounded-xl">
<i class="fas fa-headset text-orange"></i>
<p class="text-sm font-medium">Support: 254705042522</p>
<body class="font-sans antialiased text-gray-900 bg-gray-900 font-inter">
<!-- Main Content -->
<div class="mx-auto max-w-screen-2xl px-4 md:px-4">
<div class="max-h-34 relative mx-auto mt-4 flex max-w-lg flex-1 shrink-0 items-center justify-center overflow-hidden shadow-lg rounded-lg bg-red-100">
<!-- overlay - start -->
<!-- <div class="absolute inset-0 mix-blend-multiply"></div> -->
<!-- overlay - end -->
<!-- text start -->
<div class="relative flex flex-col items-center p-4 sm:max-w-xl">
<p class="mb-4 text-center text-2xl font-bold text-gray-800 sm:text-xl md:mb-2 "> HOTSPOT WIFI MBSA HOTSPOT LOGIN </p>
<ol class="text-base text-left text-gray-800 mb-1 list-decimal pl-6">
<li>Click on your preferred package</li>
<li>Enter Mpesa No.</li>
<li>Enter pin</li>
<li>Wait to be connected</li>
</ol>
<p class="mb-4 text-center text-lg font-medium text-gray-700 sm:text-1xl md:mb-1 md:text-xl"> For any enquiries contact : 0700000000</p>
</div>
<!-- text end -->
</div>
</div>
<div class="py-2 sm:py-1 lg:py-1">
<div class="mx-auto max-w-screen-2xl px-1 md:px-1">
<div class="mx-auto max-w-lg grid grid-cols-2 sm:grid-cols-2 md:grid-cols-3 gap-4 p-1" id="cards-container">
</div>
</div>
</div>
<button onclick="redeemVoucher()" class="w-full bg-orange hover:bg-orange/90 text-white font-medium py-4 px-6 rounded-xl shadow-lg transition duration-200 flex items-center justify-center gap-3 mb-6">
<i class="fas fa-ticket-alt"></i>
<span>Redeem Voucher</span>
</button>
<div class="bg-white/10 backdrop-blur-lg rounded-2xl shadow-xl overflow-hidden border border-white/10 mb-6">
<div class="p-6 space-y-8">
<!-- Reconnect with M-Pesa -->
<div class="space-y-4">
<h3 class="text-lg font-semibold text-orange">Reconnect with M-Pesa</h3>
<div class="flex flex-col sm:flex-row gap-3">
<input id="mpesaCodeInput" type="text" placeholder="Enter M-Pesa code (e.g., SCK15SKB4Z)" class="flex-grow px-4 py-3 bg-white/5 border border-white/10 rounded-xl focus:outline-none focus:ring-2 focus:ring-orange/50 text-white placeholder:text-gray-400">
<button id="reconnectBtn" class="bg-orange hover:bg-orange/90 text-white font-medium py-3 px-6 rounded-xl transition duration-200">Reconnect</button>
<div class="py-2 sm:py-4 lg:py-4">
<div class="mx-auto max-w-screen-2xl px-4 md:px-4">
<div class="mx-auto max-w-lg">
<div class="flex flex-col gap-4">
<button type="button" class="flex items-center justify-center gap-2 rounded-lg bg-red-500 px-8 py-3 text-center text-sm font-semibold text-white outline-none ring-red-300 transition duration-100 hover:bg-red-600 focus-visible:ring active:bg-red-700 md:text-base" onclick="redeemVoucher()">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v13m0-13V6a2 2 0 112 2h-2zm0 0V5.5A2.5 2.5 0 109.5 8H12zm-7 4h14M5 12a2 2 0 110-4h14a2 2 0 110 4M5 12v7a2 2 0 002 2h10a2 2 0 002-2v-7"></path>
</svg>
Click here to Redeem Voucher
</button>
</div>
</div>
<div class="space-y-4">
<h3 class="text-lg font-semibold text-orange">Active Package Login</h3>
<form id="loginForm" action="$(link-login-only)" method="post" $(if chap-id)onSubmit="return doLogin()" $(endif)>
<input type="hidden" name="dst" value="$(link-orig)">
<input type="hidden" name="popup" value="true">
<input type="hidden" name="mac" id="mac" value="$(mac)">
<div class="flex flex-col sm:flex-row gap-3">
<input id="usernameInput" name="username" type="text" placeholder="Enter Username (e.g., ACC123456)" class="flex-grow px-4 py-3 bg-white/5 border border-white/10 rounded-xl focus:outline-none focus:ring-2 focus:ring-orange/50 text-white placeholder:text-gray-400">
<button id="submitBtn" type="button" onclick="submitLogin()" class="bg-orange hover:bg-orange/90 text-white font-medium py-3 px-6 rounded-xl transition duration-200">Connect</button>
</div>
<input type="hidden" name="password" value="1234">
</form>
</div>
</div>
<div class="py-2 sm:py-4 lg:py-6">
<div class="mx-auto max-w-screen-2xl px-4 md:px-8">
<div class="mx-auto max-w-lg grid grid-cols-2 sm:grid-cols-3 gap-1 p-1" id="cards-container">
</div>
</div>
</div>
<div class="text-center">
<p class="text-sm text-gray-400">&copy; 2025 yatmack. Created by Smartisp</p>
<div class="container mx-auto px-4 mb-2">
<div class="max-w-md mx-auto bg-white rounded-lg overflow-hidden md:max-w-lg">
<div class="p-3">
<h3 class="text-2xl font-semibold text-gray-900 mb-3 text-center">Enter Mpesa code to reconnect</h3>
<div class="mb-6">
<label for="mpesaCodeInput" class="block text-gray-700 text-sm font-bold mb-2">Mpesa Code or Mpesa message:</label>
<input type="text" id="mpesaCodeInput" name="mpesa_code" placeholder="Enter Mpesa Code or Full Mpesa Message" class="w-full rounded-lg border bg-gray-50 px-3 py-2 text-gray-800 outline-none ring-indigo-300 transition duration-100 focus:ring">
<button id="reconnectBtn" class="w-full mt-3 rounded-lg bg-red-500 px-4 py-2 text-white font-semibold hover:bg-red-600 transition duration-100">Reconnect</button>
</div>
</div>
<div class="p-1">
<div class="w-full p-3">
<div class="text-center">
<h3 class="text-2xl text-gray-900">Already Have an Active Package?</h3>
</div>
<form id="loginForm" class="form" name="login" action="$(link-login-only)" method="post" $(if chap-id)onSubmit="return doLogin()" $(endif)>
<input type="hidden" name="dst" value="$(link-orig)" />
<input type="hidden" name="popup" value="true" />
<div class="mb-4">
<label class="block text-gray-700 text-sm font-bold mb-2" for="username">enter username or account number.</label>
<div>
<input id="usernameInput" name="username" type="text" value="" placeholder="eg. ACC123456" class="w-full rounded-lg border bg-gray-50 px-3 py-2 text-gray-800 outline-none ring-indigo-300 transition duration-100 focus:ring" />
<button id="submitBtn" class="w-full mt-3 flex items-center justify-center gap-2 rounded-lg bg-red-500 px-8 py-3 text-center text-sm font-semibold text-white outline-none ring-red-300 transition duration-100 hover:bg-red-600 focus-visible:ring active:bg-red-700 md:text-base" type="button" onclick="submitLogin()">
Connect
</button>
</div>
</div>
<input type="hidden" name="password" value="1234">
</form>
</div>
</div>
</div>
</div>
</div>
<div class="mx-auto max-w-screen-2xl px-4 md:px-8">
<div class="mx-auto mb-4 max-w-lg">
<div class="border-t py-4">
<p class="text-xs text-red-700 text-center">&copy; 2025. Powered by <a href="https://www.nestict.africa/" target="_blank">NestICT</a></p> </div>
</div>
</div>
</body>
<script>
</script>
<script>
function fetchData() {
var domain = 'https://yatmack2.smartisp.co.ke/';
var siteUrl = domain + "/index.php?_route=plugin/hotspot_plan";
var routerName = encodeURIComponent("yatmack");
var dataparams = `routername=${routerName}`;
fetch(siteUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: dataparams
})
.then(response => {
if (!response.ok) {
throw new Error(`Error ${response.status}: ${response.statusText}`);
let domain = 'https://mbsa.nestict.net/';
let siteUrl = domain + "/index.php?_route=plugin/hotspot_plan";
let request = new XMLHttpRequest();
const routerName = encodeURIComponent("MBSA-CHAN");
const dataparams = `routername=${routerName}`;
request.open("POST", siteUrl, true);
request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
request.onload = () => {
if (request.readyState === XMLHttpRequest.DONE) {
if (request.status === 200) {
let fetchedData = JSON.parse(request.responseText);
populateCards(fetchedData);
} else {
console.log(`Error ${request.status}: ${request.statusText}`);
}
}
return response.json();
})
.then(data => {
populateCards(data);
})
.catch(error => {
console.error('Fetch error:', error);
});
};
request.onerror = () => {
console.error("Network error");
};
request.send(dataparams);
}
function populateCards(data) {
var cardsContainer = document.getElementById('cards-container');
@ -155,13 +131,13 @@ function populateCards(data) {
var cardDiv = document.createElement('div');
cardDiv.className = 'bg-white border border-black rounded-lg shadow-md overflow-hidden transition duration-300 hover:shadow-lg flex flex-col items-center justify-between mx-auto mb-4 w-40';
cardDiv.innerHTML = `
<div class="bg-blue-500 text-white w-full py-1">
<div class="bg-red-500 text-white w-full py-1">
<h2 class="text-sm font-medium uppercase text-center" style="font-size: clamp(0.75rem, 1.5vw, 1rem); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
${item.planname}
</h2>
</div>
<div class="px-4 py-2 flex-grow">
<p class="text-2xl font-bold text-blue-600 mb-1">
<p class="text-2xl font-bold text-red-600 mb-1">
<span class="text-lg font-medium text-black">${item.currency}</span>
${item.price}
</p>
@ -171,7 +147,7 @@ function populateCards(data) {
<hr class="border-black mb-2">
</div>
<div class="px-4 py-2 flex-shrink-0">
<a href="#" class="inline-block bg-gray-900 text-white hover:bg-blue-600 font-semibold py-1 px-4 rounded-lg transition duration-300 text-md"
<a href="#" class="inline-block bg-gray-900 text-white hover:bg-red-600 font-semibold py-1 px-4 rounded-lg transition duration-300 text-md"
onclick="handlePhoneNumberSubmission('${item.planId}', '${item.routerId}'); return false;"
data-plan-id="${item.planId}"
data-router-id="${item.routerId}">
@ -184,281 +160,171 @@ function populateCards(data) {
});
}
fetchData();
function getMacAddress() {
return "$(mac)"; // MikroTik replaces this with the user's MAC address
}
function getOrCreateAccountId() {
var radiaxid = localStorage.getItem('radiaxid');
if (!radiaxid) {
radiaxid = getMacAddress();
localStorage.setItem('radiaxid', radiaxid);
setCookie('radiaxid', radiaxid, 365);
}
return radiaxid;
}
function getAccountId() {
return localStorage.getItem('radiaxid') || getCookie('radiaxid') || getMacAddress();
}
function formatPhoneNumber(phoneNumber) {
if (phoneNumber.startsWith('+')) {
phoneNumber = phoneNumber.substring(1);
}
if (phoneNumber.startsWith('0')) {
phoneNumber = '254' + phoneNumber.substring(1);
}
if (phoneNumber.match(/^(7|1)/)) {
phoneNumber = '254' + phoneNumber;
}
return phoneNumber;
}
function setCookie(name, value, days) {
var expires = "";
if (days) {
var date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = "; expires=" + date.toUTCString();
}
document.cookie = name + "=" + (value || "") + expires + "; path=/";
}
function getCookie(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
}
return null;
}
var loginTimeout;
function handlePhoneNumberSubmission(planId, routerId, price) {
var accountId = getOrCreateAccountId();
var modalHtml = `
<div id="paymentModal" class='fixed inset-0 bg-black/30 backdrop-blur-sm z-50 animate-fade-in'>
<div class="fixed left-1/2 top-1/2 transform -translate-x-1/2 -translate-y-1/2 w-full max-w-md">
<div class="bg-white text-black rounded-lg shadow-xl">
<div class="flex items-center justify-between p-4 border-b border-gray-300">
<h5 class="text-xl font-semibold">
Enter Your Mpesa Number
</h5>
<button class="text-gray-500 hover:text-black" onclick="closeModal('paymentModal')">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
<div class="p-4">
<div class="bg-navy-50 border-l-4 border-navy-400 p-4 rounded-md mb-4"> <div class="flex"> <div class="flex-shrink-0"> <svg class="h-5 w-5 text-navy-400" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1 4v.01m6.938-2.162A9 9 0 1111 3v0a9 9 0 018.938 10.838z" /> </svg> </div> <div class="ml-3"> <p class="text-sm text-navy-700"> You are about to initiate M-pesa payment. Enter phone number below and click Pay Now to initialize payment. </p> </div> </div></div> <input type="text" class="w-full px-4 py-3 border border-orange-300 rounded-lg focus:ring-2 focus:ring-navy-400 focus:border-blue-500 text-black" id="phoneNumberInput" required placeholder="e.g. 0712345678">
<div class="text-red-500 mt-1 hidden" id="invalidPhone">Please enter a valid phone number!</div>
</div>
<div class="flex justify-end space-x-2 p-4 border-t border-gray-300">
<button onclick="closeModal('paymentModal')" class="px-4 py-2 bg-orange text-black rounded-lg hover:bg-gray-300">Close</button>
<button id="payNowBtn" class="px-4 py-2 bg-navy text-white font-semibold hover:from-blue-600 hover:to-blue-500 flex items-center rounded-lg">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 9V7a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2m2 4h10a2 2 0 002-2v-6a2 2 0 00-2-2H9a2 2 0 00-2 2v6a2 2 0 002 2zm7-5a2 2 0 11-4 0 2 2 0 014 0z" />
</svg>
Pay Now
</button>
</div>
</div>
</div>
</div>
`;
document.body.insertAdjacentHTML('beforeend', modalHtml);
var modal = document.getElementById('paymentModal');
modal.classList.remove('hidden');
var payNowBtn = document.getElementById('payNowBtn');
var phoneInput = document.getElementById('phoneNumberInput');
phoneInput.focus();
payNowBtn.addEventListener('click', function() { handlePayment(); });
function handlePayment() {
if (!phoneInput.value) {
document.getElementById('invalidPhone').classList.remove('hidden');
return;
</script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script>
function formatPhoneNumber(phoneNumber) {
if (phoneNumber.startsWith('+')) {
phoneNumber = phoneNumber.substring(1);
}
payNowBtn.disabled = true;
payNowBtn.innerHTML = `
<svg class='animate-spin -ml-1 mr-3 h-5 w-5 text-white' xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24'>
<circle class='opacity-25' cx='12' cy='12' r='10' stroke='currentColor' stroke-width='4'></circle>
<path class='opacity-75' fill='currentColor' d='M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z'></path>
</svg>
Processing...
`;
var formattedPhoneNumber = formatPhoneNumber(phoneInput.value);
document.getElementById('usernameInput').value = accountId;
if (phoneNumber.startsWith('0')) {
phoneNumber = '254' + phoneNumber.substring(1);
}
if (phoneNumber.match(/^(7|1)/)) {
phoneNumber = '254' + phoneNumber;
}
return phoneNumber;
}
fetch('https://yatmack2.smartisp.co.ke/index.php?_route=plugin/CreateHotspotuser&type=grant', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
phone_number: formattedPhoneNumber,
plan_id: planId,
router_id: routerId,
account_id: accountId
function setCookie(name, value, days) {
var expires = "";
if (days) {
var date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = "; expires=" + date.toUTCString();
}
document.cookie = name + "=" + (value || "") + expires + "; path=/";
}
function getCookie(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
}
return null;
}
function generateAccountId() {
return 'ACC' + Math.floor(10000 + Math.random() * 90000); // Generate a random number between 10000 and 99999
}
var loginTimeout; // Variable to store the timeout ID
function handlePhoneNumberSubmission(planId, routerId, price) {
var msg = "You are about to pay Kes: . Enter phone number below and click pay now to initialize payment";
const regexp = /\${([^{}]+)}/g;
let result = msg.replace(regexp, function(ignore, key) {
return eval(key);
});
swal.fire({
title: 'Enter Your Mpesa Number',
input: 'number',
inputAttributes: {
required: 'true'
},
inputValidator: function(value) {
if (value === '') {
return 'You need to write your phonenumber!';
}
},
text: result,
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Pay Now',
showLoaderOnConfirm: true,
preConfirm: (phoneNumber) => {
var formattedPhoneNumber = formatPhoneNumber(phoneNumber);
var accountId = getCookie('accountId');
if (!accountId) {
accountId = generateAccountId(); // Generate a new account ID
setCookie('accountId', accountId, 7); // Set account ID as a cookie
}
document.getElementById('usernameInput').value = accountId; // Use account ID as the new username
console.log("Phone number for autofill:", formattedPhoneNumber);
return fetch('https://mbsa.nestict.net/index.php?_route=plugin/CreateHotspotuser&type=grant', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({phone_number: formattedPhoneNumber, plan_id: planId, router_id: routerId, account_id: accountId}),
})
})
.then(response => response.json())
.then(data => {
if (data.status === 'error') throw new Error(data.message);
closeModal('paymentModal');
showProcessingModal();
checkPaymentStatus(formattedPhoneNumber);
})
.catch(error => {
closeModal('paymentModal');
showErrorModal(error.message);
});
}
}
function showProcessingModal() {
var processingModalHtml = `
<div id='processingModal' class='fixed inset-0 bg-black/30 backdrop-blur-sm z-50 animate-fade-in'>
<div class='fixed left-1/2 top-1/2 transform -translate-x-1/2 -translate-y-1/2 w-full max-w-md animate-slide-up'>
<div class='bg-gradient-to-br from-white to-gray-50 shadow-2xl rounded-2xl p-8 text-center border border-gray-100'>
<div class='flex justify-center'>
<svg class='animate-spin h-20 w-20 text-navy-500' xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24'>
<circle class='opacity-25' cx='12' cy='12' r='10' stroke='currentColor' stroke-width='4'></circle>
<path class='opacity-75' fill='currentColor' d='M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z'></path>
</svg>
</div>
<div class="mt-6 bg-navy-50/50 backdrop-blur-xs border border-navy-200 rounded-xl p-6 shadow-lg"> <div class="flex items-center space-x-4"> <svg class="h-8 w-8 text-navy-400 flex-shrink-0" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1 4v.01m6.938-2.162A9 9 0 1111 3v0a9 9 0 018.938 10.838z" /> </svg> <div class="flex-1"> <h2 class="text-xl font-semibold text-navy-600 font-lexend">Initializing Payment</h2> <p class="text-navy-500 mt-2">A payment request has been sent to your phone. Please wait while we process your payment.</p> </div> </div> <div class="mt-4 h-2 w-full bg-navy-100 rounded-full overflow-hidden"> <div class="h-2 bg-navy-400 rounded-full animate-pulse"></div> </div> </div> </div>
</div>
</div>
`;
document.body.insertAdjacentHTML('beforeend', processingModalHtml);
}
function closeModal(modalId) {
var modal = document.getElementById(modalId);
if (modal) {
modal.classList.add('hidden');
setTimeout(function() { modal.remove(); }, 300);
}
}
function showSuccessModal() {
var successModalHtml = `
<div id='successModal' class='fixed inset-0 bg-black/60 backdrop-blur-sm z-50 transition-all duration-300'>
<div class='fixed left-1/2 top-1/2 transform -translate-x-1/2 -translate-y-1/2 w-full max-w-lg transition-all duration-300 ease-out'>
<div class='bg-white/95 backdrop-blur-md shadow-2xl rounded-3xl p-8 text-center border border-gray-200/50 ring-1 ring-gray-900/5'>
<div class='flex justify-center mb-6'>
<div class='relative'>
<div class='absolute inset-0 rounded-full bg-green-500/20 animate-pulse'></div>
<svg class='h-16 w-16 text-green-500' xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='currentColor'>
<path stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z'/>
</svg>
</div>
</div>
<div class='space-y-4'>
<h2 class='text-2xl font-semibold text-gray-900'>Payment Successful</h2>
<div class='bg-green-50 rounded-2xl p-6 border border-green-100'>
<div class='flex items-center gap-4'>
<svg class='h-6 w-6 text-green-500 flex-shrink-0' xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='currentColor'>
<path stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M9 12l2 2 4-4'/>
</svg>
<p class='text-sm text-green-700'>Your transaction has been completed successfully. You will be redirected shortly.</p>
</div>
</div>
</div>
</div>
</div>
</div>
`;
document.body.insertAdjacentHTML('beforeend', successModalHtml);
setTimeout(function() { closeModal('successModal'); }, 2000);
}
function showErrorModal(errorMsg) {
var errorModalHtml = `
<div id='errorModal' class='fixed inset-0 bg-black/60 backdrop-blur-sm z-50 transition-all duration-300'>
<div class='fixed left-1/2 top-1/2 transform -translate-x-1/2 -translate-y-1/2 w-full max-w-lg transition-all duration-300 ease-out'>
<div class='bg-white/95 backdrop-blur-md shadow-2xl rounded-3xl p-8 text-center border border-gray-200/50 ring-1 ring-gray-900/5'>
<div class='flex justify-center mb-6'>
<div class='relative'>
<div class='absolute inset-0 rounded-full bg-red-500/20 animate-pulse'></div>
<svg class='h-16 w-16 text-red-500' xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='currentColor'>
<path stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M6 18L18 6M6 6l12 12'/>
</svg>
</div>
</div>
<div class='space-y-4'>
<h2 class='text-2xl font-semibold text-gray-900'>Payment Failed</h2>
<div class='bg-red-50 rounded-2xl p-6 border border-red-100'>
<div class='flex items-center gap-4'>
<svg class='h-6 w-6 text-red-500 flex-shrink-0' xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='currentColor'>
<path stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z'/>
</svg>
<p class='text-sm text-red-700'>An error occurred while processing your payment. Please try again.</p>
</div>
</div>
</div>
</div>
</div>
</div>
`;
document.body.insertAdjacentHTML('beforeend', errorModalHtml);
setTimeout(function() { closeModal('errorModal'); }, 2000);
.then(response => {
if (!response.ok) throw new Error('Network response was not ok');
return response.json();
})
.then(data => {
if (data.status === 'error') throw new Error(data.message);
Swal.fire({
icon: 'info',
title: 'Processing..',
html: `A payment request has been sent to your phone. Please wait while we process your payment.`,
showConfirmButton: false,
allowOutsideClick: false,
didOpen: () => {
Swal.showLoading();
checkPaymentStatus(formattedPhoneNumber);
}
});
return formattedPhoneNumber;
})
.catch(error => {
Swal.fire({
icon: 'error',
title: 'Oops...',
text: error.message,
});
});
},
allowOutsideClick: () => !Swal.isLoading()
});
}
function checkPaymentStatus(phoneNumber) {
var accountId = getOrCreateAccountId();
var checkInterval = setInterval(function() {
fetch('https://yatmack2.smartisp.co.ke/index.php?_route=plugin/CreateHotspotuser&type=verify', {
let checkInterval = setInterval(() => {
$.ajax({
url: 'https://mbsa.nestict.net/index.php?_route=plugin/CreateHotspotuser&type=verify',
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({account_id: accountId})
})
.then(function(response) { return response.json(); })
.then(function(data) {
console.log('Raw Response:', data);
if (data.Resultcode === '3') {
clearInterval(checkInterval);
closeModal('processingModal');
showSuccessModal();
if (loginTimeout) clearTimeout(loginTimeout);
loginTimeout = setTimeout(function() { document.getElementById('loginForm').submit(); }, 2000);
} else if (data.Resultcode === '2') {
clearInterval(checkInterval);
closeModal('processingModal');
showErrorModal(data.Message);
} else {
console.error('Unexpected result code:', data.Resultcode);
data: JSON.stringify({account_id: document.getElementById('usernameInput').value}),
contentType: 'application/json',
dataType: 'json',
success: function(data) {
console.log('Raw Response:', data); // Debugging
if (data.Resultcode === '3') { // Success
clearInterval(checkInterval);
Swal.fire({
icon: 'success',
title: 'Payment Successful',
text: data.Message,
showConfirmButton: false
});
if (loginTimeout) {
clearTimeout(loginTimeout);
}
loginTimeout = setTimeout(function() {
document.getElementById('loginForm').submit();
}, 2000);
} else if (data.Resultcode === '2') { // Error
clearInterval(checkInterval);
let iconType = data.Status === 'danger' ? 'error' : data.Status;
Swal.fire({
icon: iconType,
title: 'Payment Issue',
text: data.Message,
});
} else if (data.Resultcode === '1') { // Primary
// Continue checking
}
},
error: function(xhr, textStatus, errorThrown) {
console.log('Error: ' + errorThrown);
}
})
.catch(function(error) {
console.error('Error during fetch request:', error);
clearInterval(checkInterval);
closeModal('processingModal');
showErrorModal('An error occurred while checking payment status.');
});
}, 1000);
}, 2000);
setTimeout(function() {
setTimeout(() => {
clearInterval(checkInterval);
closeModal('processingModal');
showErrorModal('Timeout while waiting for payment confirmation.');
}, 300000); // 5 minutes
}
document.addEventListener('DOMContentLoaded', function() {
var accountId = getOrCreateAccountId();
var usernameInput = document.getElementById('usernameInput');
if (usernameInput && !usernameInput.value) {
usernameInput.value = accountId;
}
var submitBtn = document.getElementById('submitBtn');
if (submitBtn) {
submitBtn.addEventListener('click', function() {
document.getElementById('loginForm').submit();
Swal.fire({
icon: 'warning',
title: 'Timeout',
text: 'Payment verification timed out. Please try again.',
});
}
});
}, 600000); // Stop checking after 60 seconds
}
</script>
</script>
<script>
var loginTimeout; // Variable to store the timeout ID
function redeemVoucher() {
Swal.fire({
@ -476,7 +342,11 @@ function redeemVoucher() {
showLoaderOnConfirm: true,
preConfirm: (voucherCode) => {
var accountId = voucherCode;
return fetch('https://yatmack2.smartisp.co.ke/index.php?_route=plugin/CreateHotspotuser&type=voucher', {
if (!accountId) {
accountId = voucherCode;
setCookie('accountId', accountId, 7);
}
return fetch('https://mbsa.nestict.net/index.php?_route=plugin/CreateHotspotuser&type=voucher', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({voucher_code: voucherCode, account_id: accountId}),
@ -539,105 +409,94 @@ function redeemVoucher() {
});
});
}
</script>
<script>
var loginTimeout; // Variable to store the timeout ID
document.addEventListener('DOMContentLoaded', function() {
var reconnectBtn = document.getElementById('reconnectBtn');
var mpesaCodeInput = document.getElementById('mpesaCodeInput');
var macInput = document.getElementById('mac');
var loginForm = document.getElementById('loginForm');
if (reconnectBtn) {
reconnectBtn.addEventListener('click', function() {
// Validate inputs before processing
if (!mpesaCodeInput || !macInput || !loginForm) {
document.getElementById('reconnectBtn').addEventListener('click', function() {
var mpesaCode = document.getElementById('mpesaCodeInput').value;
var firstWord = mpesaCode.split(' ')[0]; // Get the first word in the MPESA code
fetch('https://mbsa.nestict.net/index.php?_route=plugin/CreateHotspotuser&type=reconnect', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({mpesa_code: firstWord}),
})
.then(response => response.json())
.then(data => {
if (data.Status === 'success') {
Swal.fire({
icon: 'error',
title: 'Error',
text: 'Required form elements are missing'
});
return;
}
var mpesaCode = mpesaCodeInput.value.trim().split(' ')[0];
var mac = macInput.value.trim();
fetch('https://yatmack2.smartisp.co.ke/index.php?_route=plugin/ReconnectUser', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({ mpesa_code: mpesaCode, mac: mac }),
})
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
console.log('Response data:', data);
var resultCode = data.Resultcode;
var message = data.Message;
var status = data.Status;
var username = data.username;
if (resultCode === '1') {
Swal.fire({
icon: 'error',
title: 'Invalid Code',
text: message
});
}
else if (resultCode === '3') {
Swal.fire({
icon: 'error',
title: 'Expired Package',
text: message
});
}
else if (resultCode === '2') {
Swal.fire({
icon: 'success',
title: status,
text: message,
showConfirmButton: false,
allowOutsideClick: false,
didOpen: () => {
Swal.showLoading();
console.log('Received username from server:', username);
var usernameInput = document.querySelector('input[name="username"]');
if (usernameInput) {
console.log('Found username input element.');
usernameInput.value = username;
setTimeout(function() {
var loginForm = document.getElementById('loginForm');
if (loginForm) {
loginForm.submit();
} else {
console.error('Login form not found.');
Swal.fire({
icon: 'error',
title: 'Error',
text: 'Login form not found. Please try again.',
});
}
}, 2000);
} else {
console.error('Username input element not found.');
Swal.fire({
icon: 'error',
title: 'Error',
text: 'Username input not found. Please try again.',
});
}
icon: 'success',
title: 'Reconnection Successful',
text: data.Message,
showConfirmButton: false,
allowOutsideClick: false,
didOpen: () => {
Swal.showLoading();
var username = data.username; // Replace with actual JSON field name
console.log('Received username from server:', username);
var usernameInput = document.querySelector('input[name="username"]');
if (usernameInput) {
console.log('Found username input element.');
usernameInput.value = username;
loginTimeout = setTimeout(function() {
var loginForm = document.getElementById('loginForm');
if (loginForm) {
loginForm.submit();
} else {
console.error('Login form not found.');
Swal.fire({
icon: 'error',
title: 'Error',
text: 'Login form not found. Please try again.',
});
}
}, 2000);
} else {
console.error('Username input element not found.');
Swal.fire({
icon: 'error',
title: 'Error',
text: 'Username input not found. Please try again.',
});
}
});
}
})
.catch(error => {
}
});
} else {
Swal.fire({
icon: 'error',
title: 'Oops...',
text: error.message
title: 'Reconnection Failed',
text: data.Message,
});
}
})
.catch(error => {
console.error('Error:', error);
Swal.fire({
icon: 'error',
title: 'Error',
text: 'Failed to reconnect. Please try again later.',
});
});
} else {
console.error('Reconnect button not found');
}
});
});
</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Ensure the button is correctly targeted by its ID.
var submitBtn = document.getElementById('submitBtn');
// Add a click event listener to the "Login Now" button.
submitBtn.addEventListener('click', function(event) {
event.preventDefault(); // Prevent the default button action.
// Optional: Log to console for debugging purposes.
console.log("Login Now button clicked.");
// Direct form submission, bypassing the doLogin function for simplicity.
var form = document.getElementById('loginForm');
form.submit(); // Submit the form directly.
});
});
</script>
</html>