/* ── Bijnor Services – Frontend App v2.1.0 ────────────────────────────────── * Mobile-first customer + staff portal PWA * Requires: BS_Ajax.url, BS_Ajax.nonce (localized by PHP via wp_localize_script) * * ⚠️ All functions MUST be defined as inline named methods inside window.BSApp. * Do NOT declare functions with var/const/let outside this object. * Separate declarations cause ReferenceError on some shared hosting (Hostinger). * ─────────────────────────────────────────────────────────────────────────── */ (function () { 'use strict'; /* ════════════════════════════════════════════════════════════════════════ BSApp — Single global namespace for the entire frontend application. Provides: customer status check, repair enquiry, pick & drop scheduling, staff mobile portal (OTP login, claim management, payment QR), Excel upload and template download. ════════════════════════════════════════════════════════════════════════ */ window.BSApp = { /* ── App State ───────────────────────────────────────────────── */ version: '2.1.0', currentView: 'home', prevView: null, staffMode: false, staffId: 0, staffName: '', otpTimer: null, activeClaim: null, /* ──────────────────────────────────────────────────────────────── INIT — Entry point called on DOMContentLoaded ──────────────────────────────────────────────────────────────── */ init: function init() { var app = this; // Build the app shell if it doesn't exist yet if (!document.getElementById('bs-app-root')) { app.buildShell(); } // Restore staff session from cookie (persists across page loads) var sid = app.getCookie('bs_staff_id'); var sname = app.getCookie('bs_staff_name'); if (sid && sname) { app.staffMode = true; app.staffId = parseInt(sid, 10); app.staffName = sname; } // Upgrade PHP shortcode forms with AJAX behaviour app.upgradePhpForms(); // Show home view inside the app shell app.showView('home'); }, /* ──────────────────────────────────────────────────────────────── SHELL BUILDER Creates #bs-app-root if the page doesn't already have it. Injects before the first .entry-content paragraph. ──────────────────────────────────────────────────────────────── */ buildShell: function buildShell() { var logoSrc = (window.BS_Ajax && BS_Ajax.logo_url) ? BS_Ajax.logo_url : ''; var div = document.createElement('div'); div.id = 'bs-app-root'; div.className = 'bs-app'; div.innerHTML = '
' + '' + (logoSrc ? 'Bijnor Services' : '') + '

Bijnor Services

' + '' + '
' + '
'; var anchor = document.querySelector( '.entry-content, .page-content, main, #main, #content, article' ); if (anchor) { anchor.insertBefore(div, anchor.firstChild); } else { document.body.insertBefore(div, document.body.firstChild); } }, /* ──────────────────────────────────────────────────────────────── PHP FORM UPGRADE Intercepts server-rendered shortcode forms and converts them to AJAX calls so the page doesn't need a full reload. ──────────────────────────────────────────────────────────────── */ upgradePhpForms: function upgradePhpForms() { // [bijnor_enquiry] form var eq = document.querySelector('.bs-enquiry-form form'); if (eq) { eq.addEventListener('submit', function (e) { BSApp.handlePhpEnquirySubmit(e, eq); }); } // [bijnor_imei_check] form var im = document.querySelector('.bs-imei-check form'); if (im) { im.addEventListener('submit', function (e) { BSApp.handlePhpImeiSubmit(e, im); }); } }, /* ──────────────────────────────────────────────────────────────── NAVIGATION ──────────────────────────────────────────────────────────────── */ showView: function showView(viewName, data) { this.prevView = this.currentView; this.currentView = viewName; var container = document.getElementById('bs-view-container'); var backBtn = document.getElementById('bs-back-btn'); if (!container) { return; } // Back button visibility if (backBtn) { backBtn.style.display = (viewName === 'home') ? 'none' : 'inline-block'; } // Staff session badge var badge = document.getElementById('bs-staff-badge'); if (badge) { if (this.staffMode) { badge.style.display = 'inline-block'; badge.textContent = '\uD83D\uDC64 ' + this.staffName; } else { badge.style.display = 'none'; } } // Route to view renderer switch (viewName) { case 'home': this.renderHome(container); break; case 'status': this.renderStatusCheck(container); break; case 'enquiry': this.renderEnquiryForm(container); break; case 'pickup': this.renderPickDrop(container); break; case 'payment': this.renderPaymentView(container, data); break; case 'otp-login': this.renderOtpLogin(container); break; case 'staff-home': this.renderStaffHome(container); break; case 'staff-claims': this.renderStaffClaims(container); break; case 'staff-detail': this.renderStaffClaimDetail(container, data); break; case 'excel-upload': this.renderExcelUpload(container); break; case 'about': this.renderAbout(container); break; default: this.renderHome(container); break; } }, goBack: function goBack() { var map = { 'staff-detail': 'staff-claims', 'staff-claims': 'staff-home', 'staff-home': 'home', 'otp-login': 'home', 'payment': this.prevView || 'home', }; var target = map[this.currentView] || this.prevView || 'home'; this.showView(target); }, setHeader: function setHeader(title) { var el = document.getElementById('bs-header-title'); if (el) { el.textContent = title; } }, /* ──────────────────────────────────────────────────────────────── HOME SCREEN ──────────────────────────────────────────────────────────────── */ renderHome: function renderHome(container) { this.setHeader('Bijnor Services'); var staffCard = this.staffMode ? '
' + '

\uD83D\uDCCB My Claims

' + '

View and manage your assigned claims

' + '
' : '
' + '

\uD83D\uDC64 Staff Login

' + '

Log in to manage your assigned repair claims

' + '
'; container.innerHTML = '
' + '
' + '

\uD83D\uDD0D Check Repair / Claim Status

' + '

Enter your IMEI or claim number to track your repair

' + '
' + '
' + '

\uD83D\uDEE0\uFE0F Request a Repair

' + '

Submit a new Samsung repair or Bajaj insurance enquiry

' + '
' + '
' + '

\uD83D\uDE9A Schedule Pick & Drop

' + '

Book a doorstep pickup and delivery for your device

' + '
' + staffCard + '
' + '

\u2139\uFE0F About Bijnor Services

' + '

Samsung authorized service center & Bajaj insurance claim point

' + '
' + '
'; }, /* ──────────────────────────────────────────────────────────────── STATUS CHECK — PUBLIC (no login required) ──────────────────────────────────────────────────────────────── */ renderStatusCheck: function renderStatusCheck(container) { this.setHeader('Check Status'); container.innerHTML = '
' + '

' + 'Enter your IMEI number or claim number to check the current status of your repair or insurance claim.' + '

' + '
' + '' + '' + '
' + '' + '
' + '
'; var inp = document.getElementById('status-query'); if (inp) { inp.focus(); inp.addEventListener('keydown', function (e) { if (e.key === 'Enter') { BSApp.checkStatus(); } }); } }, checkStatus: function checkStatus() { var q = ((document.getElementById('status-query') || {}).value || '').trim(); if (!q) { this.showError('status-result', 'Please enter an IMEI or claim number.'); return; } this.showLoader('status-result'); this.ajax('bs_public_status_check', { query: q }, function (d) { if (d.success && d.data) { BSApp.renderClaimStatusResult('status-result', d.data); } else { BSApp.renderNotFound('status-result', q); } }, function () { BSApp.showError('status-result', 'Could not connect. Please check your internet and try again.'); }); }, renderClaimStatusResult: function renderClaimStatusResult(containerId, claim) { var statusColors = { 'Open': '#1565c0', 'In Progress': '#fb8c00', 'Repair Complete':'#43a047', 'Closed': '#43a047', 'Delivered': '#43a047', 'Cancelled': '#e53935', 'Repudiated': '#e53935', }; var sc = statusColors[claim.claim_status] || '#555'; var mob = (claim.mobile || '').replace(/\D/g, ''); var wa = 'https://wa.me/91' + mob + '?text=' + encodeURIComponent('Hi, I am following up on my repair/claim: ' + claim.claim_number); var html = '
' + '

\u2705 Record Found

' + '' + '' + '' + '' + '' + '' + '' + '
Claim No.' + this.esc(claim.claim_number) + '
Customer' + this.esc(claim.customer_name) + '
Device' + this.esc((claim.manufacturer || '') + (claim.model_number ? ' ' + claim.model_number : '')) + '
Status' + this.esc(claim.claim_status) + '
Stage' + this.esc(claim.workflow_status || '\u2014') + '
Registered' + this.esc(claim.registration_date || '\u2014') + '
' + '
' + '' + '\uD83D\uDCAC Chat on WhatsApp' + '
' + '
'; var el = document.getElementById(containerId); if (el) { el.innerHTML = html; } }, renderNotFound: function renderNotFound(containerId, query) { var wa = 'https://wa.me/919999999999?text=' + encodeURIComponent('Hi, I want to check status for IMEI/claim: ' + query); var html = '
' + '

No record found for: ' + this.esc(query) + '

' + '

' + 'If you recently submitted a repair, allow some time for it to be registered.' + '

' + '' + '\uD83D\uDCAC Ask on WhatsApp' + '
'; var el = document.getElementById(containerId); if (el) { el.innerHTML = html; } }, /* ──────────────────────────────────────────────────────────────── PHP FORM AJAX UPGRADES ──────────────────────────────────────────────────────────────── */ handlePhpEnquirySubmit: function handlePhpEnquirySubmit(e, form) { e.preventDefault(); // Inject a result container before the form var existing = form.parentNode.querySelector('#php-eq-result'); if (!existing) { existing = document.createElement('div'); existing.id = 'php-eq-result'; form.parentNode.insertBefore(existing, form); } var fd = new FormData(form); var data = { name: (fd.get('bs_name') || '').trim(), mobile: (fd.get('bs_mobile') || '').trim(), device: (fd.get('bs_device') || '').trim(), issue: (fd.get('bs_issue') || '').trim(), imei: (fd.get('bs_imei') || '').trim(), }; var btn = form.querySelector('button[type=submit]'); if (btn) { btn.disabled = true; btn.textContent = '\u23F3 Submitting\u2026'; } this.ajax('bs_public_enquiry', data, function (d) { if (btn) { btn.disabled = false; btn.textContent = 'Submit Enquiry'; } if (d.success) { existing.className = 'bs-success'; existing.textContent = 'Thank you! We will contact you on ' + data.mobile + ' shortly.'; form.reset(); } else { existing.className = 'bs-error'; existing.textContent = d.data || 'Submission failed. Please try again.'; } }, function () { if (btn) { btn.disabled = false; btn.textContent = 'Submit Enquiry'; } existing.className = 'bs-error'; existing.textContent = 'Network error. Please try again.'; }); }, handlePhpImeiSubmit: function handlePhpImeiSubmit(e, form) { e.preventDefault(); var inp = form.querySelector('input[name=bs_imei]'); var q = inp ? inp.value.trim() : ''; if (!q) { return; } // Find or create result container var res = form.parentNode.querySelector('#php-imei-result'); if (!res) { res = document.createElement('div'); res.id = 'php-imei-result'; form.parentNode.appendChild(res); } // Remove old PHP-rendered result card if present var old = form.parentNode.querySelector('.bs-result-card'); if (old) { old.remove(); } this.showLoader('php-imei-result'); this.ajax('bs_public_status_check', { query: q }, function (d) { if (d.success && d.data) { BSApp.renderClaimStatusResult('php-imei-result', d.data); } else { BSApp.renderNotFound('php-imei-result', q); } }, function () { BSApp.showError('php-imei-result', 'Could not connect. Please try again.'); }); }, /* ──────────────────────────────────────────────────────────────── ENQUIRY FORM — PUBLIC (inside app shell) ──────────────────────────────────────────────────────────────── */ renderEnquiryForm: function renderEnquiryForm(container) { this.setHeader('Request a Repair'); container.innerHTML = '
' + '
' + '
' + '
' + '' + '' + '
' + '
' + '' + '' + '
' + '
' + '' + '' + '
' + '
' + '' + '' + '
' + '
' + '' + '' + '
' + '
' + '' + '' + '
' + '' + '
' + '
'; }, submitEnquiry: function submitEnquiry(e) { e.preventDefault(); var form = document.getElementById('bs-enquiry-form'); if (!form) { return; } var data = { name: (form.querySelector('[name=name]').value || '').trim(), mobile: (form.querySelector('[name=mobile]').value || '').trim(), device: (form.querySelector('[name=device]').value || '').trim(), issue: (form.querySelector('[name=issue]').value || '').trim(), imei: (form.querySelector('[name=imei]').value || '').trim(), service_type: (form.querySelector('[name=service_type]').value|| ''), }; if (!data.name) { this.showError('enquiry-msg', 'Please enter your name.'); return; } if (!/^[0-9]{10}$/.test(data.mobile)) { this.showError('enquiry-msg', 'Please enter a valid 10-digit mobile number.'); return; } var btn = form.querySelector('button[type=submit]'); if (btn) { btn.disabled = true; btn.textContent = '\u23F3 Submitting\u2026'; } this.ajax('bs_public_enquiry', data, function (d) { if (btn) { btn.disabled = false; btn.textContent = '\u2705 Submit Enquiry'; } if (d.success) { BSApp.showSuccess('enquiry-msg', '\uD83C\uDF89 Enquiry submitted! We will call you at ' + data.mobile + ' shortly.'); form.reset(); } else { BSApp.showError('enquiry-msg', d.data || 'Submission failed. Please try again.'); } }, function () { if (btn) { btn.disabled = false; btn.textContent = '\u2705 Submit Enquiry'; } BSApp.showError('enquiry-msg', 'Network error. Please try again.'); }); }, /* ──────────────────────────────────────────────────────────────── PICK & DROP SCHEDULING — PUBLIC ──────────────────────────────────────────────────────────────── */ renderPickDrop: function renderPickDrop(container) { this.setHeader('Pick & Drop'); var tomorrow = new Date(); tomorrow.setDate(tomorrow.getDate() + 1); var minDate = tomorrow.toISOString().split('T')[0]; container.innerHTML = '
' + '

' + 'Schedule a doorstep pickup. Our team will collect your device, repair it, and return it at your convenience.' + '

' + '
' + '
' + '
' + '' + '' + '
' + '
' + '' + '' + '
' + '
' + '' + '' + '
' + '
' + '' + '' + '
' + '
' + '' + '' + '
' + '
' + '' + '' + '
' + '
' + '' + '' + '
' + '' + '
' + '
'; }, submitPickDrop: function submitPickDrop(e) { e.preventDefault(); var form = document.getElementById('bs-pickup-form'); if (!form) { return; } var g = function (n) { return (form.querySelector('[name=' + n + ']').value || '').trim(); }; var data = { name: g('name'), mobile: g('mobile'), address: g('address'), device: g('device'), pickup_date: g('pickup_date'), time_slot: g('time_slot'), issue: g('issue'), }; if (!data.name || !data.mobile || !data.address || !data.pickup_date) { this.showError('pickup-msg', 'Please fill in all required fields.'); return; } if (!/^[0-9]{10}$/.test(data.mobile)) { this.showError('pickup-msg', 'Please enter a valid 10-digit mobile number.'); return; } var btn = form.querySelector('button[type=submit]'); if (btn) { btn.disabled = true; btn.textContent = '\u23F3 Scheduling\u2026'; } this.ajax('bs_public_pickup', data, function (d) { if (btn) { btn.disabled = false; btn.textContent = '\uD83D\uDE9A Schedule Pickup'; } if (d.success) { BSApp.showSuccess('pickup-msg', '\uD83C\uDF89 Pickup scheduled! Reference: ' + (d.data && d.data.ref ? d.data.ref : 'Confirmed') + '. Our team will call ' + data.mobile + ' to confirm the slot.'); form.reset(); } else { BSApp.showError('pickup-msg', d.data || 'Scheduling failed. Please try again.'); } }, function () { if (btn) { btn.disabled = false; btn.textContent = '\uD83D\uDE9A Schedule Pickup'; } BSApp.showError('pickup-msg', 'Network error. Please try again.'); }); }, /* ──────────────────────────────────────────────────────────────── UPI PAYMENT QR ──────────────────────────────────────────────────────────────── */ renderPaymentView: function renderPaymentView(container, data) { this.setHeader('Pay via UPI'); data = data || {}; var amount = data.amount || ''; var claimNo = data.claimNo || ''; var upiId = data.upiId || 'bijnorservices@upi'; var upiName = data.upiName || 'Bijnor Services'; var qrUrl = this.generateQRUrl(amount, claimNo, upiId, upiName); container.innerHTML = '
' + '

' + 'Scan with PhonePe, Google Pay, Paytm or any UPI app

' + '
' + 'UPI QR Code' + '
' + (amount ? '

' + '\u20B9' + this.formatCurrency(amount) + '

' : '') + '

' + this.esc(upiName) + '

' + '

' + this.esc(upiId) + '

' + (claimNo ? '

Ref: ' + this.esc(claimNo) + '

' : '') + '
' + '

' + 'After payment, share the confirmation screenshot on WhatsApp.' + '

' + '
' + '
'; }, generateQRUrl: function generateQRUrl(amount, claimNo, upiId, upiName) { upiId = upiId || 'bijnorservices@upi'; upiName = upiName || 'Bijnor Services'; var upiStr = 'upi://pay?pa=' + encodeURIComponent(upiId) + '&pn=' + encodeURIComponent(upiName) + '&tn=' + encodeURIComponent('Payment – ' + (claimNo || 'Repair Service')); if (amount) { upiStr += '&am=' + encodeURIComponent(String(amount)) + '&cu=INR'; } return 'https://api.qrserver.com/v1/create-qr-code/?size=220x220&data=' + encodeURIComponent(upiStr); }, showPaymentQR: function showPaymentQR(amount, claimNo, upiId, upiName) { this.showView('payment', { amount: amount, claimNo: claimNo, upiId: upiId, upiName: upiName, }); }, /* ──────────────────────────────────────────────────────────────── OTP STAFF LOGIN ──────────────────────────────────────────────────────────────── */ renderOtpLogin: function renderOtpLogin(container) { this.setHeader('Staff Login'); container.innerHTML = '
' + '

' + 'Enter your registered mobile number to receive a one-time login code.' + '

' + '
' + '
' + '
' + '' + '' + '
' + '' + '
' + '' + '
'; var inp = document.getElementById('otp-mobile'); if (inp) { inp.focus(); inp.addEventListener('keydown', function (e) { if (e.key === 'Enter') { BSApp.sendOtp(); } }); } }, sendOtp: function sendOtp() { var mobile = ((document.getElementById('otp-mobile') || {}).value || '').trim(); if (!/^[0-9]{10}$/.test(mobile)) { this.showError('otp-msg', 'Please enter a valid 10-digit mobile number.'); return; } this.clearMsg('otp-msg'); this.ajax('bs_staff_send_otp', { mobile: mobile }, function (d) { if (d.success) { var s1 = document.getElementById('otp-step-1'); var s2 = document.getElementById('otp-step-2'); if (s1) { s1.style.display = 'none'; } if (s2) { s2.style.display = 'block'; } BSApp.startOtpTimer(); BSApp.showSuccess('otp-msg', 'OTP sent to ' + mobile + '. Valid for 10 minutes.'); } else { BSApp.showError('otp-msg', d.data || 'Mobile not registered. Contact admin to be added as staff.'); } }, function () { BSApp.showError('otp-msg', 'Network error. Please try again.'); }); }, verifyOtp: function verifyOtp() { var mobile = ((document.getElementById('otp-mobile') || {}).value || '').trim(); var code = ((document.getElementById('otp-code') || {}).value || '').trim(); if (!code || code.length < 4) { this.showError('otp-msg', 'Please enter the OTP from your SMS.'); return; } this.clearMsg('otp-msg'); this.ajax('bs_staff_verify_otp', { mobile: mobile, otp: code }, function (d) { if (d.success) { BSApp.staffMode = true; BSApp.staffId = parseInt(d.data.user_id, 10); BSApp.staffName = d.data.display_name || 'Staff'; BSApp.setCookie('bs_staff_id', String(d.data.user_id), 1); BSApp.setCookie('bs_staff_name', BSApp.staffName, 1); if (BSApp.otpTimer) { clearInterval(BSApp.otpTimer); } BSApp.showView('staff-home'); } else { BSApp.showError('otp-msg', d.data || 'Incorrect OTP. Please try again.'); } }, function () { BSApp.showError('otp-msg', 'Network error. Please try again.'); }); }, resendOtp: function resendOtp() { if (this.otpTimer) { clearInterval(this.otpTimer); } this.clearMsg('otp-msg'); var s1 = document.getElementById('otp-step-1'); var s2 = document.getElementById('otp-step-2'); if (s1) { s1.style.display = 'block'; } if (s2) { s2.style.display = 'none'; } }, startOtpTimer: function startOtpTimer() { var seconds = 60; var display = document.getElementById('otp-timer-display'); var resend = document.getElementById('otp-resend-btn'); if (resend) { resend.disabled = true; } if (this.otpTimer) { clearInterval(this.otpTimer); } this.otpTimer = setInterval(function () { seconds--; if (display) { display.textContent = '(' + seconds + 's)'; } if (seconds <= 0) { clearInterval(BSApp.otpTimer); if (display) { display.textContent = ''; } if (resend) { resend.disabled = false; } } }, 1000); }, /* ──────────────────────────────────────────────────────────────── STAFF HOME DASHBOARD ──────────────────────────────────────────────────────────────── */ renderStaffHome: function renderStaffHome(container) { this.setHeader('Staff Dashboard'); container.innerHTML = '
' + '
' + '

Welcome back, ' + '' + this.esc(this.staffName) + '

' + '
' + '
' + '
' + '
\u2014
' + '
Total
' + '
' + '
' + '
\u2014
' + '
Open
' + '
' + '
' + '
\u2014
' + '
Overdue
' + '
' + '
' + '
\u2014
' + '
High
' + '
' + '
' + '
' + '

\uD83D\uDCCB My Claims

' + '

View, search and update your assigned claims

' + '
' + '
' + '

\uD83D\uDCC2 Upload Excel

' + '

Upload Bajaj ExportReqReport (.xls / .xlsx)

' + '
' + '
' + '

\u2B07\uFE0F Download CSV Template

' + '

Get the claim entry template for manual filing

' + '
' + '
' + '

\uD83D\uDEAA Logout

' + '

Sign out of the staff portal

' + '
' + '
'; this.loadStaffStats(); }, loadStaffStats: function loadStaffStats() { this.ajax('bs_alert_stats', {}, function (d) { if (!d.success) { return; } var s = d.data; ['total', 'open', 'overdue', 'high'].forEach(function (k) { var el = document.getElementById('ss-' + k); if (el) { el.textContent = (s[k] !== undefined ? s[k] : '\u2014'); } }); }, null); }, staffLogout: function staffLogout() { this.staffMode = false; this.staffId = 0; this.staffName = ''; this.deleteCookie('bs_staff_id'); this.deleteCookie('bs_staff_name'); this.showView('home'); }, /* ──────────────────────────────────────────────────────────────── STAFF CLAIMS LIST ──────────────────────────────────────────────────────────────── */ renderStaffClaims: function renderStaffClaims(container) { this.setHeader('My Claims'); container.innerHTML = '
' + '' + '
' + '' + '' + '
' + '
' + '
'; // Live search with debounce var timer; var inp = document.getElementById('staff-search'); if (inp) { inp.addEventListener('input', function () { clearTimeout(timer); timer = setTimeout(function () { BSApp.loadStaffClaims(); }, 350); }); } this.loadStaffClaims(); }, loadStaffClaims: function loadStaffClaims() { var search = ((document.getElementById('staff-search') || {}).value || '').trim(); var status = ((document.getElementById('sc-status') || {}).value || ''); var priority = ((document.getElementById('sc-priority') || {}).value || ''); this.showLoader('staff-claims-wrap'); this.ajax('bs_get_claims', { search: search, status: status, priority: priority, paged: 1, }, function (d) { if (!d.success) { BSApp.showError('staff-claims-wrap', 'Could not load claims. Please try again.'); return; } var rows = d.data.rows || []; var el = document.getElementById('staff-claims-wrap'); if (!el) { return; } if (!rows.length) { el.innerHTML = '

No claims found.

'; return; } el.innerHTML = rows.map(function (r) { return BSApp.buildClaimCard(r); }).join(''); }, function () { BSApp.showError('staff-claims-wrap', 'Network error. Please try again.'); }); }, buildClaimCard: function buildClaimCard(r) { var pc = { high: '#e53935', medium: '#fb8c00', low: '#1e88e5' }; var p = (r.priority || 'low').toLowerCase(); var fee = parseFloat(r.processing_fee || 0); return '
' + '
' + '' + this.esc(r.claim_number) + '' + '' + p.toUpperCase() + '' + '
' + '

' + this.esc(r.customer_name) + ' · ' + this.esc(r.mobile) + '

' + '

' + this.esc(r.claim_status || '\u2014') + ' · ' + (r.ageing_days || 0) + ' days · ' + '\u20B9' + this.formatCurrency(fee) + (r.fee_received ? ' \u2705' : ' \u23F3') + '

' + '
'; }, /* ──────────────────────────────────────────────────────────────── STAFF CLAIM DETAIL ──────────────────────────────────────────────────────────────── */ viewStaffClaim: function viewStaffClaim(claimId) { this.showView('staff-detail', { id: claimId }); }, renderStaffClaimDetail: function renderStaffClaimDetail(container, data) { this.setHeader('Claim Detail'); var claimId = (data && data.id) ? data.id : 0; this.showLoader('bs-view-container'); this.ajax('bs_get_claim_detail', { id: claimId }, function (d) { if (!d.success || !d.data) { BSApp.showError('bs-view-container', 'Could not load claim details.'); return; } BSApp.activeClaim = d.data; BSApp.buildDetailView(container, d.data); }, function () { BSApp.showError('bs-view-container', 'Network error. Please try again.'); }); }, buildDetailView: function buildDetailView(container, c) { var pc = { high: '#e53935', medium: '#fb8c00', low: '#1e88e5' }; var p = (c.priority || 'low').toLowerCase(); var fee = parseFloat(c.custom_payment_amount || c.processing_fee || 0); var upiId = (window.BS_Ajax && BS_Ajax.upi_id) ? BS_Ajax.upi_id : 'bijnorservices@upi'; var mob = (c.mobile || '').replace(/\D/g, ''); var waMsg = encodeURIComponent( 'Hi ' + (c.customer_name || '') + ', your claim ' + c.claim_number + ' — please check for updates.'); container.innerHTML = '
' + /* ── Info card ── */ '
' + '
' + '
' + '

' + this.esc(c.claim_number) + '

' + '

' + this.esc(c.customer_name) + '

' + '

' + this.esc(c.mobile) + '

' + '
' + '' + p.toUpperCase() + '' + '
' + '
' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '
Manufacturer' + this.esc(c.manufacturer || '\u2014') + '
Model' + this.esc(c.model_number || '\u2014') + '
Serial / IMEI' + this.esc(c.serial_number || '\u2014') + '
Sum Insured\u20B9' + this.formatCurrency(c.sum_insured || 0) + '
Processing Fee\u20B9' + this.formatCurrency(fee) + ' ' + (c.fee_received ? '\u2705 Paid' : '\u23F3 Pending') + '
Claim Status' + this.esc(c.claim_status || '\u2014') + '
Workflow' + this.esc(c.workflow_status || '\u2014') + '
Age' + (c.ageing_days || 0) + ' days
' + '
' + /* ── Quick actions ── */ '
' + '' + '' + '\uD83D\uDCAC WhatsApp' + '
' + /* ── Update status ── */ '
' + '

Update Claim Status

' + '
' + '' + '' + '
' + /* ── Mark paid (only if not yet paid) ── */ (c.fee_received ? '' : '
' + '

Mark Payment Received

' + '
' + '' + '
' ) + '
'; }, doUpdateStatus: function doUpdateStatus(claimId) { var sel = document.getElementById('new-status'); var status = sel ? sel.value : ''; if (!status) { this.showError('status-up-msg', 'Please select a new status.'); return; } this.ajax('bs_update_claim_status', { id: claimId, status: status }, function (d) { if (d.success) { BSApp.showSuccess('status-up-msg', '\u2705 Status updated to: ' + status); } else { BSApp.showError('status-up-msg', d.data || 'Update failed.'); } }, function () { BSApp.showError('status-up-msg', 'Network error. Please try again.'); }); }, doMarkPaid: function doMarkPaid(claimId) { this.ajax('bs_mark_paid', { id: claimId }, function (d) { if (d.success) { BSApp.showSuccess('pay-up-msg', '\u2705 Payment marked as received.'); var btn = document.querySelector( 'button[onclick*="doMarkPaid(' + claimId + ')"]'); if (btn) { btn.disabled = true; btn.textContent = '\u2705 Paid'; } } else { BSApp.showError('pay-up-msg', d.data || 'Update failed.'); } }, function () { BSApp.showError('pay-up-msg', 'Network error. Please try again.'); }); }, /* ──────────────────────────────────────────────────────────────── EXCEL UPLOAD ──────────────────────────────────────────────────────────────── */ renderExcelUpload: function renderExcelUpload(container) { this.setHeader('Upload Excel'); container.innerHTML = '
' + '

' + 'Upload the Bajaj ExportReqReport file (.xls or .xlsx). ' + 'Claims will be inserted or updated by claim number automatically.' + '

' + '
' + '
' + '
' + '
\uD83D\uDCC2
' + '' + '

' + 'Supported: .xls and .xlsx (Bajaj ExportReqReport format)

' + '
' + '' + '
' + '
' + '' + '
' + '
'; }, handleExcelUpload: async function handleExcelUpload(e) { e.preventDefault(); var form = document.getElementById('bs-excel-form'); var fileInput = document.getElementById('bs-excel-file'); if (!form || !fileInput || !fileInput.files || !fileInput.files.length) { BSApp.showError('excel-msg', 'Please select a .xls or .xlsx file.'); return; } var btn = form.querySelector('button[type=submit]'); if (btn) { btn.disabled = true; btn.textContent = '\u23F3 Processing\u2026'; } BSApp.clearMsg('excel-msg'); var fd = new FormData(form); fd.append('action', 'bs_upload_excel'); fd.append('nonce', window.BS_Ajax ? BS_Ajax.nonce : ''); try { var url = window.BS_Ajax ? BS_Ajax.url : '/wp-admin/admin-ajax.php'; var res = await fetch(url, { method: 'POST', credentials: 'include', body: fd, }); var data = await res.json(); if (btn) { btn.disabled = false; btn.textContent = '\uD83D\uDE80 Upload & Sync'; } if (data.success) { var r = data.data || {}; BSApp.showSuccess('excel-msg', '\u2705 Upload complete! ' + 'Inserted: ' + (r.inserted || 0) + '  |  ' + 'Updated: ' + (r.updated || 0) + '  |  ' + 'Skipped: ' + (r.skipped || 0) + (r.errors ? '  |  Errors: ' + r.errors : '')); form.reset(); } else { var msg = (data.data && data.data.message) ? data.data.message : (data.data || 'Upload failed. Please try again.'); BSApp.showError('excel-msg', msg); } } catch (err) { if (btn) { btn.disabled = false; btn.textContent = '\uD83D\uDE80 Upload & Sync'; } BSApp.showError('excel-msg', 'Network error: ' + (err.message || 'Please try again.')); } }, /* ──────────────────────────────────────────────────────────────── EXCEL TEMPLATE DOWNLOAD Generates a CSV with standard claim entry headers and saves it. ──────────────────────────────────────────────────────────────── */ downloadExcelTemplate: function downloadExcelTemplate() { var headers = [ 'Customer Name', 'Mobile', 'Email', 'Device Brand', 'Device Model', 'Issue Description', 'IMEI / Serial Number', 'Claim Number', 'Policy Number', 'Sum Insured', 'Claim Status', 'Workflow Status', 'Registration Date', 'Loss Date', 'Loss Type', 'Address', 'City', 'State', 'Comments', ]; var sample = [ 'Sample Customer', '9876543210', 'customer@email.com', 'Samsung', 'Galaxy A55', 'Screen cracked, touch not working', '358901234567890', 'CLM/26/001', 'POL/26/00001', '15000', 'Open', 'Inspection Initiated', new Date().toLocaleDateString('en-IN'), '', 'Accidental Damage', '123 Main Street, Near Clock Tower', 'Bijnor', 'Uttar Pradesh', 'Device received in working condition except screen', ]; var rows = [headers, sample]; var csv = rows.map(function (row) { return row.map(function (cell) { var s = String(cell === null || cell === undefined ? '' : cell); if (s.indexOf(',') >= 0 || s.indexOf('"') >= 0 || s.indexOf('\n') >= 0) { s = '"' + s.replace(/"/g, '""') + '"'; } return s; }).join(','); }).join('\r\n'); var blob = new Blob(['\uFEFF' + csv], { type: 'text/csv;charset=utf-8;' }); var url = URL.createObjectURL(blob); var a = document.createElement('a'); a.href = url; a.download = 'bijnor-claim-template.csv'; a.style.display = 'none'; document.body.appendChild(a); a.click(); document.body.removeChild(a); setTimeout(function () { URL.revokeObjectURL(url); }, 1000); }, /* ──────────────────────────────────────────────────────────────── ABOUT PAGE ──────────────────────────────────────────────────────────────── */ renderAbout: function renderAbout(container) { this.setHeader('About Us'); container.innerHTML = '
' + '
' + '

Bijnor Services

' + '

' + 'Samsung Authorized Service Center & ' + 'Bajaj Allianz Insurance Claim Point' + '

' + '
' + '

' + '\uD83D\uDCCD Address: Bijnor, Uttar Pradesh, India

' + '

' + '\uD83D\uDCDE Contact: Available via WhatsApp

' + '

' + '\uD83D\uDD50 Hours: Mon \u2013 Sat, 10 AM \u2013 7 PM

' + '

' + '\u2139\uFE0F Note: Sunday by appointment only

' + '
' + '
' + '

Our Services

' + '

' + '\u2705 Samsung Mobile Repair (Authorized Center)

' + '

' + '\u2705 Bajaj Allianz Insurance Claim Processing

' + '

' + '\u2705 Doorstep Pick & Drop Service

' + '

' + '\u2705 Genuine Spare Parts & Warranty

' + '

' + '\u2705 All Major Mobile Brands Serviced

' + '

' + '\u2705 UPI / Online Payment Accepted

' + '
' + '
'; }, /* ──────────────────────────────────────────────────────────────── AJAX CORE ──────────────────────────────────────────────────────────────── */ ajax: function ajax(action, data, onSuccess, onError) { var params = { action: action }; if (window.BS_Ajax && BS_Ajax.nonce) { params.nonce = BS_Ajax.nonce; } if (data) { var k; for (k in data) { if (Object.prototype.hasOwnProperty.call(data, k)) { params[k] = data[k]; } } } var ajaxUrl = window.BS_Ajax ? BS_Ajax.url : '/wp-admin/admin-ajax.php'; fetch(ajaxUrl, { method: 'POST', credentials: 'include', body: new URLSearchParams(params), }) .then(function (r) { if (!r.ok) { throw new Error('HTTP ' + r.status); } return r.json(); }) .then(function (d) { if (typeof onSuccess === 'function') { onSuccess(d); } }) .catch(function (err) { console.error('BSApp.ajax error [' + action + ']:', err); if (typeof onError === 'function') { onError(err); } }); }, /* ──────────────────────────────────────────────────────────────── UI HELPERS ──────────────────────────────────────────────────────────────── */ showLoader: function showLoader(id) { var el = (typeof id === 'string') ? document.getElementById(id) : id; if (el) { el.innerHTML = '
'; } }, showError: function showError(id, msg) { var el = (typeof id === 'string') ? document.getElementById(id) : id; if (el) { el.innerHTML = '
' + this.esc(msg) + '
'; } }, showSuccess: function showSuccess(id, html) { var el = (typeof id === 'string') ? document.getElementById(id) : id; if (el) { el.innerHTML = '
' + html + '
'; } }, clearMsg: function clearMsg(id) { var el = (typeof id === 'string') ? document.getElementById(id) : id; if (el) { el.innerHTML = ''; } }, /* ──────────────────────────────────────────────────────────────── FORMAT HELPERS ──────────────────────────────────────────────────────────────── */ formatCurrency: function formatCurrency(n) { return (parseFloat(n) || 0).toLocaleString('en-IN', { minimumFractionDigits: 0, maximumFractionDigits: 2, }); }, formatDate: function formatDate(d) { if (!d) { return '\u2014'; } var dt = new Date(d); return isNaN(dt.getTime()) ? String(d) : dt.toLocaleDateString('en-IN', { day: '2-digit', month: 'short', year: 'numeric', }); }, esc: function esc(str) { return String(str === null || str === undefined ? '' : str) .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, '''); }, /* ──────────────────────────────────────────────────────────────── COOKIE HELPERS ──────────────────────────────────────────────────────────────── */ getCookie: function getCookie(name) { var m = document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]+)'); return m ? decodeURIComponent(m.pop()) : ''; }, setCookie: function setCookie(name, value, days) { var d = new Date(); d.setTime(d.getTime() + (days * 86400000)); document.cookie = name + '=' + encodeURIComponent(value) + ';expires=' + d.toUTCString() + ';path=/;SameSite=Lax'; }, deleteCookie: function deleteCookie(name) { document.cookie = name + '=;expires=Thu, 01 Jan 1970 00:00:00 UTC;path=/;'; }, /* ──────────────────────────────────────────────────────────────── WHATSAPP HELPER ──────────────────────────────────────────────────────────────── */ whatsappLink: function whatsappLink(mobile, message) { var num = String(mobile || '').replace(/\D/g, ''); if (num.length === 10) { num = '91' + num; } return 'https://wa.me/' + num + (message ? '?text=' + encodeURIComponent(message) : ''); }, }; /* ── end window.BSApp ── */ /* ── Auto-initialize ────────────────────────────────────────────────── */ if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', function () { window.BSApp.init(); }); } else { window.BSApp.init(); } }()); /* ── end IIFE ── */ https://bijnorservices.in/wp-sitemap-posts-post-1.xmlhttps://bijnorservices.in/wp-sitemap-posts-page-1.xmlhttps://bijnorservices.in/wp-sitemap-taxonomies-category-1.xmlhttps://bijnorservices.in/wp-sitemap-users-1.xml