UDGAM MICROFINANCE - Employee Portal

👤 प्रोफाइल

E
Present0
Absent0
Earned Leave0
Branch Pres.0
Half Day0

📢 महत्वपूर्ण सूचना

  • सिर्फ Earned Leave (EL) को कैलेंडर में नीले रंग से दर्शाया गया है।
  • सुबह 7:00 से पहले अटेंडेंस न लगाने पर Absent माना जाएगा।
  • Branch Present न होने पर दिन को Half Day गिना जाएगा।

— प्रबंधन, Udgam

00:00:00 AM
LOADING SECURE DATA...
SECURE SERVER TELEMETRY: ACTIVE
📅

First Meeting present

Check-In Now
🏢

Branch Present

Office Check-In
⚠️

अधिसूचना – सख्त उपस्थिति एवं अनुशासनात्मक नियम

तत्काल प्रभाव से लागू (Strictly Enforced)

01
उपस्थिति प्रत्येक कार्यदिवस सुबह 7:00 बजे से पहले अनिवार्य रूप से दर्ज करनी होगी अन्यथा उपस्थिति दर्ज नहीं हो पाएगी।
02
उपस्थिति केवल आपकी संबंधित ब्रांच के पिन कोड क्षेत्र के भीतर ही मान्य होगी।
03
उपस्थिति पहली मीटिंग (First Meeting) के दौरान ही लगाना अनिवार्य है।
04
एक ही लोकेशन से एक से अधिक कर्मचारियों की उपस्थिति मान्य नहीं होगी।
05
एक मोबाइल से केवल एक ही कर्मचारी की उपस्थिति लगेगी; नियम उल्लंघन पर Device Automatically Block हो जाएगा।
06
Branch Present तभी लगेगी जब कर्मचारी वास्तव में ब्रांच में उपस्थित हो। ⏰ समयावधि: शाम 10:00 PM से 12:00 PM तक।
07
यदि Branch Present नहीं लगाई जाती है, तो उस दिन स्वतः Half Day माना जाएगा।
08
Monday या Saturday को बिना पूर्व अनुमति (Leave) अनुपस्थित रहने पर Sunday भी Absent काउंट होगा।

CRITICAL ENFORCEMENT NOTICE

Security protocol initialized.

⏰ Half Day Leave

EL Balance 0
EL Taken 0
PL Taken 0
SL/Med Taken 0

✏️ छुट्टी के लिए आवेदन

📜 आपकी छुट्टी का इतिहास

₹0
आज की OD
₹0
इस महीने की OD
₹0
कुल OD
₹0
HO Approved
₹0
10% Incentive

💰 OD Collection Entry

📊 OD रिपोर्ट

0
✅ पूर्ण
0
⏳ बाकी
0
📌 बकाया

⏳ बाकी कार्य और पिछला बकाया

डेटा लोड हो रहा है...

✅ पूरे हुए कार्य

📝 नई शिकायत दर्ज करें

📋 आपकी शिकायतें 0

📄
वेतन पर्ची
📊
विवरण

नए सेंटर का विज़िट

GEO VERIFIED VISIT

🏢 Center Visit

Branch location से 300 मीटर के अंदर ही form submit होगा।

Location लेने के लिए ऊपर button दबाएँ।

📝 इस्तीफ़ा सबमिट करें

👤 प्रोफाइल

S

📋 छुट्टी अनुमोदन

📅 हाज़िरी इतिहास

🗓️ छुट्टी आवेदन

🏢 Center Visit Report

🏪 Branch Present (7:00 AM तक)

⚠️ नोट: यह ऑप्शन केवल 7:00 AM तक सक्रिय है।

⭐ कर्मचारी रेटिंग

⚠️ Complaint Management System

🔎 Search & Filter

🏢 Branch Complaint Form

UDGAM MICROFINANCE
ADMIN CONTROL CENTER
LIVE CONTROL
WELCOME ADMIN

All Over Control Dashboard

Staff, Supervisor, Attendance, Complaints, Notifications और complete sheet data.

⚡ Quick Control

📌 System Status

Loading...
EMPLOYEE CONTROL

👥 Employee Registration

Employee data, approval status और Block / Unblock.

ATTENDANCE CONTROL

🕒 Attendance / Half Day

Screenshot-style monthly matrix — Code, Name और हर दिन का status एक साथ.

LIVE SHEET DATA

Sheet Data

A to Z rows और columns — password/OTP जैसे sensitive columns hide रहेंगे.

STAFF SUPPORT

📢 Complaint Control

Employee / Branch complaint records देखें और resolve करें.

COMMUNICATION

🔔 Publish Notification

Active staff के लिए official notification publish करें.

SUPERVISOR MANAGEMENT

👨‍💼 Supervisor CREATE

Code, name, email, branch और status control.

SUPERVISOR FEATURE

⭐ Employee Rating

Supervisor के लिए employee rating ON/OFF.

Supervisor Employee RatingChecking...
DATA IMPORT

⬆️ Data Upload

Selected sheet में data append करें; existing rows delete नहीं होंगे.

COMPLETE CONTROL

🗂️ All Modules

Admin के लिए सभी available modules.

`; throw new Error("Device is Locked."); } } })(); // GLOBAL VARIABLES let currentUser = null; let currentPage = "profile"; // LOGIN TAB SWITCHING function showLoginTab(tab) { // एरर से बचने के लिए event check करें if (window.event) event.preventDefault(); document.querySelectorAll('.tab-content').forEach(el => el.classList.remove('active')); document.querySelectorAll('.tab-btn').forEach(el => el.classList.remove('active')); const tabMap = { 'employee': 'employeeLogin', 'supervisor': 'supervisorLogin', 'admin': 'adminLogin', 'register': 'registrationTab' }; const tabElement = document.getElementById(tabMap[tab]); if (tabElement) { tabElement.classList.add('active'); event.target.classList.add('active'); } } // EMPLOYEE LOGIN // === पासवर्ड लॉगिन फ़ंक्शन (अब बैकएंड के 'processEmployeeLogin' को कॉल करेगा) === function employeeLogin() { const email = document.getElementById('empEmail').value; const password = document.getElementById('empPassword').value; if (!email || !password) { showAlert('कृपया सभी फील्ड भरें', 'error'); return; } const btn = document.getElementById('empLoginBtn'); btn.disabled = true; btn.innerHTML = ' लॉड हो रहा है...'; google.script.run.withSuccessHandler(function(result) { if (result.success) { sessionStorage.setItem('currentUser', JSON.stringify(result)); showAlert('✅ लॉगिन सफल!', 'success'); currentUser = result; document.getElementById('loginPage').style.display = 'none'; document.getElementById('dashboardPage').classList.add('active'); initDashboard(); } else { showAlert(result.message, 'error'); btn.disabled = false; btn.innerHTML = 'लॉगिन करें'; } }).withFailureHandler(function(error) { showAlert('Error: ' + error, 'error'); btn.disabled = false; btn.innerHTML = 'लॉगिन करें'; }).processEmployeeLogin(email, password); } // === पासवर्ड दिखाने/छिपाने का फ़ंक्शन === function togglePasswordVisibility() { const passwordInput = document.getElementById('empPassword'); const eyeIcon = document.getElementById('eyeIcon'); if (passwordInput.type === 'password') { passwordInput.type = 'text'; eyeIcon.innerHTML = '👁️‍🗨️'; } else { passwordInput.type = 'password'; eyeIcon.innerHTML = '👁️'; } } // === OTP फंक्शंस === function requestLoginOtp() { const email = document.getElementById('otpEmpEmail').value; if (!email) { showAlert('कृपया ईमेल दर्ज करें', 'error'); return; } const btn = document.getElementById('sendOtpBtn'); btn.disabled = true; btn.innerHTML = ' OTP भेजा जा रहा है...'; google.script.run.withSuccessHandler(function(result) { if (result.success) { showAlert('✅ OTP आपके ईमेल पर भेज दिया गया है!', 'success'); document.getElementById('otpInputGroup').style.display = 'block'; document.getElementById('verifyOtpBtn').style.display = 'block'; btn.style.display = 'none'; } else { showAlert(result.message, 'error'); btn.disabled = false; btn.innerHTML = 'OTP भेजें'; } }).withFailureHandler(function(error) { showAlert('Error: ' + error, 'error'); btn.disabled = false; btn.innerHTML = 'OTP भेजें'; }).sendLoginOtp(email); } function verifyAndLoginOtp() { const email = document.getElementById('otpEmpEmail').value; const otp = document.getElementById('empOtpCode').value; if (!otp) { showAlert('कृपया OTP दर्ज करें', 'error'); return; } const btn = document.getElementById('verifyOtpBtn'); btn.disabled = true; btn.innerHTML = ' सत्यापन हो रहा है...'; google.script.run.withSuccessHandler(function(result) { if (result.success) { sessionStorage.setItem('currentUser', JSON.stringify(result)); showAlert('✅ लॉगिन सफल!', 'success'); currentUser = result; document.getElementById('loginPage').style.display = 'none'; document.getElementById('dashboardPage').classList.add('active'); initDashboard(); } else { showAlert(result.message, 'error'); btn.disabled = false; btn.innerHTML = 'OTP सत्यापित करें और लॉगिन करें'; } }).withFailureHandler(function(error) { showAlert('Error: ' + error, 'error'); btn.disabled = false; btn.innerHTML = 'OTP सत्यापित करें और लॉगिन करें'; }).verifyLoginOtp(email, otp); } // SUPERVISOR LOGIN function supervisorLoginFn() { const code = document.getElementById('supervisorCode').value; if (!code) { showAlert('कृपया सुपरवाइज़र कोड दर्ज करें', 'error'); return; } const btn = document.getElementById('supLoginBtn'); btn.disabled = true; btn.innerHTML = ' लॉड हो रहा है...'; google.script.run.withSuccessHandler(function(result) { if (result.success) { sessionStorage.setItem('currentUser', JSON.stringify(result)); showAlert('✅ लॉगिन सफल!', 'success'); currentUser = result; document.getElementById('loginPage').style.display = 'none'; document.getElementById('supervisorPage').classList.add('active'); initSupervisorDashboard(); } else { showAlert(result.message, 'error'); btn.disabled = false; btn.innerHTML = 'लॉगिन करें'; } }).withFailureHandler(function(error) { showAlert('Error: ' + error, 'error'); btn.disabled = false; btn.innerHTML = 'लॉगिन करें'; }).supervisorLogin(code); } // ADMIN LOGIN function adminLoginFn() { const code = document.getElementById('adminCode').value || 'ADMIN'; const password = document.getElementById('adminPassword').value.trim(); if (!code || !password) { showAlert('कृपया सभी फील्ड भरें', 'error'); return; } const btn = document.getElementById('adminLoginBtn'); btn.disabled = true; btn.innerHTML = ' लॉड हो रहा है...'; google.script.run.withSuccessHandler(function(result) { if (result.success) { sessionStorage.setItem('currentUser', JSON.stringify(result)); showAlert('✅ लॉगिन सफल!', 'success'); currentUser = result; document.getElementById('loginPage').style.display = 'none'; document.getElementById('adminPage').classList.add('active'); initAdminDashboard(); } else { showAlert(result.message, 'error'); btn.disabled = false; btn.innerHTML = 'लॉगिन करें'; } }).withFailureHandler(function(error) { showAlert('Error: ' + error, 'error'); btn.disabled = false; btn.innerHTML = 'लॉगिन करें'; }).adminLogin(code, password); } // REGISTRATION function goToRegistration() { document.getElementById('loginPage').style.display = 'none'; document.getElementById('registrationPage').style.display = 'block'; } function backToLogin() { document.getElementById('registrationPage').style.display = 'none'; document.getElementById('loginPage').style.display = 'flex'; } function submitRegistration(e) { e.preventDefault(); // Button ko disable karein taaki user baar-baar click na kare const submitBtn = e.target.querySelector('button[type="submit"]'); submitBtn.disabled = true; submitBtn.innerText = "कृपया प्रतीक्षा करें..."; const data = { employeeCode: document.getElementById('reg2EmpCode').value, name: document.getElementById('reg2Name').value, email: document.getElementById('reg2Email').value, phone: document.getElementById('reg2Phone').value, department: document.getElementById('reg2Department').value, designation: document.getElementById('reg2Designation').value, dateOfJoining: document.getElementById('reg2DateOfJoining').value, branchName: document.getElementById('reg2BranchName').value, photoBase64: '' }; const photoInput = document.getElementById('reg2Photo'); const file = photoInput.files && photoInput.files[0]; if (file) { const reader = new FileReader(); reader.onload = function(e2) { data.photoBase64 = e2.target.result; callRegisterEmployee(data, submitBtn); }; reader.onerror = function() { alert("फोटो लोड करने में समस्या हुई"); submitBtn.disabled = false; }; reader.readAsDataURL(file); } else { callRegisterEmployee(data, submitBtn); } } function callRegisterEmployee(data, btn) { google.script.run .withSuccessHandler(function(result) { btn.disabled = false; btn.innerText = "✅ पंजीकरण पूरा करें"; if (result.success) { showAlert('✅ ' + result.message, 'success'); setTimeout(() => { document.getElementById('registrationPage').style.display = 'none'; document.getElementById('loginPage').style.display = 'flex'; }, 2000); } else { showAlert('❌ ' + result.message, 'error'); } }) .withFailureHandler(function(err) { btn.disabled = false; btn.innerText = "✅ पंजीकरण पूरा करें"; showAlert('❌ Error: ' + err.message, 'error'); }) .registerEmployee(data); } google.script.run.withSuccessHandler(function(result) { if (result.success) { showAlert('✅ ' + result.message, 'success'); setTimeout(() => { document.getElementById('registrationPage').style.display = 'none'; document.getElementById('loginPage').style.display = 'flex'; }, 2000); } else { showAlert('❌ ' + result.message, 'error'); } }).registerEmployee(data); // FORGOT PASSWORD function showForgotPassword() { document.getElementById('forgotPasswordModal').classList.add('show'); } function closeForgotPasswordModal() { document.getElementById('forgotPasswordModal').classList.remove('show'); } function submitForgotPassword() { const email = document.getElementById('forgotEmail').value; if (!email) { showAlert('कृपया ईमेल दर्ज करें', 'error'); return; } google.script.run.withSuccessHandler(function(result) { if (result.success) { showAlert(result.message, "success"); closeForgotPasswordModal(); document.getElementById('forgotEmail').value = ''; } else { showAlert(result.message, "error"); } }).forgotPassword(email); } // SIDEBAR TOGGLE function toggleSidebar() { // 1. User type nikaalte hain (default 'admin' rakhte hain agar currentUser na ho) const type = currentUser?.userType || 'admin'; // 2. IDs ko dynamic banate hain // Agar admin hai toh 'adminSidebar', supervisor hai toh 'supervisorSidebar', etc. const sidebarId = type === 'employee' ? 'sidebar' : `${type}Sidebar`; const overlayId = type === 'employee' ? 'sidebarOverlay' : `${type}SidebarOverlay`; const sidebar = document.getElementById(sidebarId); const overlay = document.getElementById(overlayId); // 3. Toggle logic if (sidebar && overlay) { sidebar.classList.toggle('open'); overlay.classList.toggle('show'); } else { console.error("Sidebar ya Overlay element nahi mila:", { sidebarId, overlayId }); } } // DASHBOARD INITIALIZATION function initDashboard() { document.getElementById('userName').textContent = currentUser.name; document.getElementById('userBranch').textContent = currentUser.branch; document.getElementById('userAvatar').textContent = currentUser.name.charAt(0); loadProfile(); closeSidebarOnLoad(); } function closeSidebarOnLoad() { const sidebar = document.getElementById('sidebar'); const overlay = document.getElementById('sidebarOverlay'); sidebar.classList.remove('open'); overlay.classList.remove('show'); } function loadProfile() { const profileDiv = document.getElementById('profileContent'); profileDiv.innerHTML = `

Udgam Portal Loading...

`; let email = (currentUser && currentUser.email) ? currentUser.email : null; if (!email) { const savedUser = sessionStorage.getItem('currentUser'); if (savedUser) { try { email = JSON.parse(savedUser).email; } catch {} } } if (!email) { profileDiv.innerHTML = "
❌ Session Expired. Please Login Again.
"; return; } google.script.run .withSuccessHandler(function(result) { if (result.success && result.profile) { const p = result.profile; profileDiv.innerHTML = `

${p.name}

${p.desig} | ${p.dept}
📧 ${p.email} 📞 ${p.phone}
Basic Employment Info
Status● ${p.empStatus || 'Active'}
Joining Date${p.joiningDate || '-'}
Home Town${p.hometown || '-'}
Earned Leave${p.earnLeave || '0'}
Financial & Security
Security Amount₹ ${p.secAmt || '0'}
Last Month Security${p.secLastMonth || '-'}
Paid Date${p.secPaidDate || '-'}
Cheque Deposited${p.chequeDep || '-'}
EPF Deduction${p.epfDeduct || '-'}
ESI Deduction${p.esiDeduct || '-'}
Documents
Marksheet Deposit Status${p.marksheet || '-'}

© UDGAM MICROFINANCE EMPLOYEE SELF SERVICE

`; } else { profileDiv.innerHTML = "
⚠️ " + (result.message || 'Profile not found.') + "
"; } }) .withFailureHandler(function(err) { profileDiv.innerHTML = "
❌ Error: " + err.message + "
"; }) .getEmployeeProfile(email); } // PAGE SWITCHING function switchPage(page) { currentPage = page; document.querySelectorAll('#dashboardPage .page-section').forEach(el => el.classList.remove('active')); document.querySelectorAll('.sidebar-menu a').forEach(el => el.classList.remove('active')); event.target.closest('a').classList.add('active'); document.getElementById(page + 'Page').classList.add('active'); const titles = { 'profile': '👤 प्रोफाइल', 'attendance': '🕒 हाज़री', 'attendanceHistory': '📅 हाज़री इतिहास', 'halfday': '⏰ Half Day', 'leave': '🗓 छुट्टी', 'odCollection': '💰 OD संग्रह', 'tasks': '📋 कार्य', 'complaint': '📢 शिकायत', 'notification': '🔔 सूचनाएँ', 'salary': '💼 वेतन पर्ची', 'resignation': '📝 इस्तीफ़ा', 'centerVisit': '🏢 Center Visit' }; document.getElementById('pageTitle').textContent = titles[page] || '📄 Page'; if (page === 'tasks') loadTasks(); if (page === 'notification') loadNotifications(); if (page === 'attendanceHistory') { const today = new Date(); const monthYear = today.getFullYear() + '-' + String(today.getMonth() + 1).padStart(2, '0'); document.getElementById('attendanceHistoryMonth').value = monthYear; loadAttendanceHistory(); } if (page === 'resignation') loadResignationForm(); if (page === 'centerVisit') ECV_init(); toggleSidebar(); } // ध्यान दें: 'currentUser' ऑब्जेक्ट में कर्मचारी का कोड होना चाहिए // उदाहरण: const currentUser = { employeeCode: 'EMP101' }; function loadAttendanceHistory() { const monthYear = document.getElementById('attendanceHistoryMonth').value; const calendarBody = document.getElementById('calendarBody'); if (!monthYear) return; calendarBody.innerHTML = '
Loading...
'; google.script.run.withSuccessHandler(function(res) { if (res.success) { // Summary Update document.getElementById('sumPres').innerText = res.summary.pres; document.getElementById('sumAbs').innerText = res.summary.abs; document.getElementById('sumBranch').innerText = res.summary.branch; document.getElementById('sumHalf').innerText = res.summary.half; document.getElementById('sumEL').innerText = res.summary.el; let html = `
M
T
W
T
F
S
S
`; res.days.forEach(d => { let statusClass = "day-empty"; if (d.status === "present") statusClass = "day-present"; else if (d.status === "absent") statusClass = "day-absent"; else if (d.status === "half") statusClass = "day-half"; // ✅ NEW else if (d.status === "on-el") statusClass = "day-el-blue"; html += `
${d.day || ''}
`; }); calendarBody.innerHTML = html; } }).getAttendanceHistory(currentUser.employeeCode, monthYear); } // ATTENDANCE function markAttendance(type) { if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(function(position) { const latitude = position.coords.latitude; const longitude = position.coords.longitude; google.script.run.withSuccessHandler(function(result) { if (result.success) { // MAIN: Set Lock Immediately const now = new Date(); const todayNum = (now.getFullYear() * 10000) + ((now.getMonth() + 1) * 100) + now.getDate(); localStorage.setItem('attendance_locked_date', todayNum.toString()); location.reload(); // ताकि LOCK स्क्रीन तुरंत लगे } else { document.getElementById('attendanceStatus').innerHTML = `
❌ ${result.message}
`; } }).markAttendance(currentUser.employeeCode, type, latitude, longitude); }); } else { showAlert('Geolocation उपलब्ध नहीं है', 'error'); } } // HALF DAY LEAVE function submitHalfDayLeave() { const date = document.getElementById('halfDayDate').value; const period = document.getElementById('halfDayPeriod').value; const reason = document.getElementById('halfDayReason').value; if (!date || !period || !reason) { showAlert('कृपया सभी फील्ड भरें', 'error'); return; } google.script.run.withSuccessHandler(function(result) { if (result.success) { showAlert('✅ ' + result.message, 'success'); document.getElementById('halfDayDate').value = ''; document.getElementById('halfDayPeriod').value = ''; document.getElementById('halfDayReason').value = ''; } else { showAlert('❌ ' + result.message, 'error'); } }).applyHalfDayLeave(currentUser.employeeCode, date, period, reason); } // ============================================ // ============================================ // ============================================ // ============================================ // FRONTEND LEAVE FUNCTIONS - FINAL VERSION (Synced with A-L Columns) // ============================================ /** * 1. Load Balances - Dashboard sync logic */ function loadLeaveBalances() { if (typeof currentUser === 'undefined' || !currentUser.employeeCode) { console.log("Waiting for user session to fetch balances..."); return; } google.script.run.withSuccessHandler(function(res) { if (res.error) { console.error("Balance Error:", res.error); return; } // 1. EL Balance (Registration se Total - Leave Sheet se Approved) const balEL = document.getElementById('balEL'); if(balEL) balEL.innerText = res.elBalance ?? 0; // 2. EL Taken (Sirf Approved count) const takenEL = document.getElementById('takenEL'); if(takenEL) takenEL.innerText = res.elTaken ?? 0; // 3. Total Yearly (Jo AA column me 10 ya 14 likha hai) const totalEL = document.getElementById('totalEL'); if(totalEL) totalEL.innerText = res.totalAllowed ?? 0; // 4. PL Taken const takenPL = document.getElementById('takenPL'); if(takenPL) takenPL.innerText = res.plTaken ?? 0; // 5. SL Taken const slElem = document.getElementById('takenSL'); if (slElem) slElem.innerText = res.slTaken ?? 0; // Save current limit for blocking logic in form window.userEligibleLimit = res.currentLimit; window.userTotalTaken = res.elTaken; window.userMonthLimit = res.eligibleNow; console.log("Balances Synced: Taken=" + res.elTaken + ", Balance=" + res.elBalance); }).getLeaveBalance(currentUser.employeeCode); } /** * 2. Submit Application - With Blocking Alerts */ function submitLeaveApplication() { const type = document.getElementById('selectedLeaveType').value; const from = document.getElementById('leaveFromDate').value; const to = document.getElementById('leaveToDate').value; const reason = document.getElementById('leaveReason').value; if (!type || !from || !to || !reason) { window.showAlert ? showAlert('❌ कृपया सभी जानकारी भरें', 'error') : alert('❌ कृपया सभी जानकारी भरें'); return; } // Calculate Days const start = new Date(from); const end = new Date(to); const daysRequested = Math.ceil((end - start) / (1000 * 60 * 60 * 24)) + 1; // STRICT EL CHECK: Joining se ab tak ke mahine vs Approved count if (type === "EL" && daysRequested > window.userEligibleLimit) { const msg = `❌ बैलेंस कम है!\n\nआपकी अब तक की लिमिट: ${window.userMonthLimit}\nआप ले चुके हैं (Approved): ${window.userTotalTaken}\nअभी बची हुई लिमिट: ${window.userEligibleLimit}\n\nआप ${daysRequested} दिन के लिए अप्लाई नहीं कर सकते।`; window.showAlert ? showAlert(msg, 'error') : alert(msg); return; } const btn = document.querySelector('.btn-submit'); if(btn) { btn.disabled = true; btn.innerText = 'प्रक्रिया जारी है...'; } google.script.run.withSuccessHandler(function(result) { if(btn) { btn.disabled = false; btn.innerText = '✅ आवेदन सबमिट करें'; } if (result.success) { window.showAlert ? showAlert(result.message, 'success') : alert(result.message); // Form reset document.getElementById('leaveFromDate').value = ''; document.getElementById('leaveToDate').value = ''; document.getElementById('leaveReason').value = ''; // ✅ Instant UI Refresh loadLeaveBalances(); searchLeaveHistory(); } else { window.showAlert ? showAlert(result.message, 'error') : alert(result.message); } }).applyLeave(currentUser.employeeCode, type, from, to, reason); } function searchLeaveHistory() { if (typeof currentUser === 'undefined' || !currentUser.employeeCode) return; let fromDate = document.getElementById('searchFromDate')?.value || (new Date().getFullYear() + "-01-01"); let toDate = document.getElementById('searchToDate')?.value || (new Date().toISOString().split('T')[0]); google.script.run.withSuccessHandler(function(result) { const container = document.getElementById('leaveHistoryList'); if (!container) return; if (result.success && result.leaves && result.leaves.length > 0) { let html = ''; result.leaves.forEach(leave => { let statusCheck = (leave.status || "").toLowerCase().trim(); let statusColor = statusCheck === 'approved' ? '#10b981' : (statusCheck === 'rejected' ? '#ef4444' : '#f59e0b'); html += `
${leave.type} Leave ${leave.status.toUpperCase()}
📅 ${leave.fromDate} - ${leave.toDate} (${leave.days} Days) ${leave.approvedDays ? `
✅ Approved: ${leave.approvedDays} Days` : ''}
📝 Reason: ${leave.reason} ${leave.rejectedReason ? `
🚫 Reject Reason: ${leave.rejectedReason}` : ''}
`; }); container.innerHTML = html; } else { container.innerHTML = '
कोई इतिहास नहीं मिला।
'; } }).getLeaveHistory(currentUser.employeeCode, fromDate, toDate); } /** * 4. AUTO-START LOGIC */ function startLeaveApp() { loadLeaveBalances(); searchLeaveHistory(); // Sync balances every 60 seconds (Backend manager approved kare to dashboard update ho jaye) setInterval(function() { loadLeaveBalances(); }, 60000); } // Login session detect karne ke liye loader window.addEventListener('load', function() { let attempts = 0; let checkUser = setInterval(function() { if (typeof currentUser !== 'undefined' && currentUser.employeeCode) { startLeaveApp(); clearInterval(checkUser); } attempts++; if(attempts > 10) clearInterval(checkUser); // Stop after 10s if not logged in }, 1000); }); // OD COLLECTION // 1. SUBMIT OD COLLECTION function submitODCollection() { const paymentMode = document.getElementById('odPaymentMode').value; const txnId = document.getElementById('odTxnId').value; const data = { employeeCode: currentUser.employeeCode, loanType: document.getElementById('odLoanType').value, customerName: document.getElementById('odCustomerName').value, customerId: document.getElementById('odCustomerId').value, loanId: document.getElementById('odLoanId').value, groupId: document.getElementById('odGroupId').value, groupName: document.getElementById('odGroupName').value, husbandName: document.getElementById('odHusbandName').value, contactNumber: document.getElementById('odContactNumber').value, paymentMode: paymentMode, txnId: txnId, // Naya field: Transaction ID odReceivedAmount: document.getElementById('odReceivedAmount').value, branchName: currentUser.branch, receiverName: currentUser.name }; // Validation if (!data.customerName || !data.odReceivedAmount) { showAlert('⚠️ कृपया ग्राहक का नाम और राशि दर्ज करें', 'error'); return; } // Digital payment validation if (paymentMode === 'डिजिटल' && !txnId) { showAlert('⚠️ कृपया Transaction ID दर्ज करें', 'error'); return; } // Submit to Server google.script.run.withSuccessHandler(function(result) { if (result.success) { showAlert('✅ ' + result.message, 'success'); resetODForm(); loadODDashboard(); // Dashboard refresh karega } else { showAlert('❌ ' + result.message, 'error'); } }).submitODCollection(data); } // 2. LOAD DASHBOARD (5 BOXES LOGIC) function loadODDashboard() { // Stats refresh ke liye null dates bhej rahe hain google.script.run.withSuccessHandler(function(result) { if (result.success) { document.getElementById('todayOD').textContent = '₹' + (result.todayOD || 0); document.getElementById('monthlyOD').textContent = '₹' + (result.monthlyOD || 0); document.getElementById('totalOD').textContent = '₹' + (result.totalODReceived || 0); // Naye Approved aur Incentive Boxes document.getElementById('hoApproved').textContent = '₹' + (result.approvedAmt || 0); document.getElementById('incentiveAmt').textContent = '₹' + (result.incentive || 0); } }).getODReport(currentUser.employeeCode, null, null); } // 3. SEARCH REPORT function searchODReport() { const fromDate = document.getElementById('odReportFromDate').value; const toDate = document.getElementById('odReportToDate').value; if (!fromDate || !toDate) { showAlert('📅 कृपया दोनों तारीखें चुनें', 'error'); return; } google.script.run.withSuccessHandler(function(result) { if (result.success) { let html = ''; result.collections.forEach(col => { html += `
${col.customerName} ₹${col.odAmount}
ID: ${col.customerId} | Status: ${col.status}
Date: ${col.date}
`; }); document.getElementById('odReportList').innerHTML = html || '

कोई रिकॉर्ड नहीं मिला

'; } }).getODReport(currentUser.employeeCode, fromDate, toDate); } // 4. RESET FORM function resetODForm() { document.getElementById('odCustomerName').value = ''; document.getElementById('odReceivedAmount').value = ''; document.getElementById('odCustomerId').value = ''; document.getElementById('odTxnId').value = ''; document.getElementById('txnIdGroup').style.display = 'none'; document.getElementById('odPaymentMode').value = 'नकद'; } // TASKS function loadTasks() { const selectedMonth = document.getElementById('taskMonth').value; const compDiv = document.getElementById('completedTasks'); const dueDiv = document.getElementById('dueTasks'); compDiv.innerHTML = "लोड हो रहा है..."; dueDiv.innerHTML = "लोड हो रहा है..."; google.script.run.withSuccessHandler(function(result) { if (result.success) { let completedHtml = ''; let dueHtml = ''; let counts = { comp: 0, pending: 0 }; // सिर्फ सिलेक्टेड महीने का डेटा फ़िल्टर करें const filteredTasks = result.tasks.filter(t => t.month === selectedMonth); filteredTasks.forEach(task => { const percent = task.target > 0 ? Math.min((task.completed / task.target) * 100, 100) : 0; const isDone = task.remaining === 0 && task.target > 0; const taskHtml = `
${task.title} ${task.month}
लक्ष्य: ${task.target} पूरा: ${task.completed} बाकी: ${task.remaining}
${task.description}
`; if (isDone || (task.title === "New Group" && task.completed > 0)) { completedHtml += taskHtml; counts.comp++; } else { dueHtml += taskHtml; counts.pending++; } }); compDiv.innerHTML = completedHtml || '

कोई पूर्ण कार्य नहीं

'; dueDiv.innerHTML = dueHtml || '

सब क्लियर है!

'; document.getElementById('completedCount').innerText = counts.comp; document.getElementById('pendingCount').innerText = counts.pending; document.getElementById('dueCount').innerText = counts.pending; } else { alert("डेटा लोड करने में विफल: " + result.message); } }).getTasks(currentUser.employeeCode); } function submitComplaint() { const type = document.getElementById('complaintType').value; const desc = document.getElementById('complaintDescription').value; const btn = document.getElementById('submitBtn'); if (type === "-- चुनें --" || !desc.trim()) { alert("⚠️ Details bharna zaruri hai!"); return; } btn.disabled = true; btn.innerText = "⏳ Processing..."; const data = { employeeCode: currentUser.employeeCode, type: type, description: desc.trim() }; google.script.run .withSuccessHandler(function(res) { btn.disabled = false; btn.innerText = "✅ शिकायत सबमिट करें"; if (res.success) { alert(res.message); document.getElementById('complaintDescription').value = ""; loadComplaints(); // List refresh } else { alert("Error: " + res.message); } }) .withFailureHandler(function(err) { btn.disabled = false; btn.innerText = "❌ Failed"; alert("System Error: " + err); }) .submitComplaint(data); } function loadComplaints() { const listDiv = document.getElementById('complaintsList'); if(!listDiv) return; listDiv.innerHTML = "Loading..."; google.script.run.withSuccessHandler(function(res) { if (res.success) { document.getElementById('complaintCount').innerText = res.complaints.length; let html = ""; res.complaints.forEach(c => { let sColor = (c.status === "Pending") ? "#f59e0b" : "#10b981"; html += `
ID: ${c.complaintId} ${c.status}
${c.type}

${c.description}

${c.answer ? `
Admin: ${c.answer}
` : ""}
`; }); listDiv.innerHTML = html || "No complaints found."; } }).getAllComplaints(currentUser.employeeCode); } // NOTIFICATION function loadNotifications() { google.script.run.withSuccessHandler(function(result) { if (result.success) { let html = ''; result.notifications.forEach(notif => { let priorityClass = 'low'; if (notif.priority === 'उच्च') priorityClass = 'high'; else if (notif.priority === 'मध्यम') priorityClass = 'medium'; html += `
${notif.title}
${notif.priority}
${notif.message}
${notif.date}
`; }); document.getElementById('notificationsList').innerHTML = html || '

कोई सूचनाएँ नहीं

'; } }).getNotifications(currentUser.employeeCode); } // SALARY SLIP function selectSalaryOption(btn, option) { document.querySelectorAll('.salary-option').forEach(el => el.classList.remove('active')); btn.classList.add('active'); loadSalarySlip(option); } function loadSalarySlip(option) { let html = `
`; document.getElementById('salaryContent').innerHTML = html; setTimeout(() => fetchSalaryData(), 100); } function fetchSalaryData() { const month = document.getElementById('salaryMonth').value; google.script.run.withSuccessHandler(function(result) { if (result.success) { const s = result.salary; let html = `
वेतन पर्ची - ${month}
कर्मचारी कोड: ${s.employeeCode} PF नंबर: ${s.pfNumber}

💰 आय (Earnings)

मूल वेतन ₹${s.basicPay || 0}
ईंधन भत्ता ₹${s.fuel || 0}
बाइक भत्ता ₹${s.fuel || 0}
फ़ोन रिचार्ज ₹${s.fuel || 0}
प्रोत्साहन ₹${s.incentive || 0}
कुल आय ₹${s.grossPay || 0}

💸 कटौती (Deductions)

PF कटौती -₹${s.pfDeduct || 0}
ESI कटौती -₹${s.esiDeduct || 0}
LEAVE कटौती -₹${s.LeaveDeduct || 0}
ADVANCE कटौती -₹${s.advanceDeduct || 0}
SECURITY कटौती -₹${s.advanceDeduct || 0}
✅ नेट वेतन (NET PAY) ₹${s.netPay || 0}
`; document.getElementById('salaryDisplayContent').innerHTML = html; } else { document.getElementById('salaryDisplayContent').innerHTML = '

इस महीने के लिए कोई डेटा उपलब्ध नहीं है।

'; } }).getSalarySlip(currentUser.employeeCode, month); } function loadResignationForm() { // Profile Load Karein google.script.run.withSuccessHandler(function(result) { if (result.success) { const profile = result.profile; let html = `
Name
${profile.name}
Code
${profile.employeeCode}
Branch
${profile.branchName}
DOJ
${profile.dateOfJoining}
`; document.getElementById('resignationInfoGrid').innerHTML = html; } }).getEmployeeProfile(currentUser.employeeCode); // Status History Load Karein checkStatusHistory(); } function checkStatusHistory() { google.script.run.withSuccessHandler(function(result) { if (result.success && result.history.length > 0) { let html = '

🔍 Resignation History

'; result.history.forEach(res => { let sColor = res.status === 'Accepted' ? '#2ecc71' : (res.status === 'Rejected' ? '#e74c3c' : '#f1c40f'); html += `
🆔 ID: ${res.id} ${res.status}
📅 Apply: ${res.applyDate}
Notice: ${res.noticeDate}
🏠 Visit: ${res.visitDate}
Verified: ${res.visitVerify}
💰 Salary Status: ${res.salaryStatus}
`; }); document.getElementById('resignationStatusContainer').innerHTML = html; } }).getResignationStatus(currentUser.employeeCode); } function submitResignation() { const reason = document.getElementById('resignationReason').value; if (!reason) { showAlert('कृपया कारण लिखें', 'error'); return; } const btn = document.getElementById('submitBtn'); btn.disabled = true; btn.innerHTML = "Processing..."; google.script.run.withSuccessHandler(function(result) { btn.disabled = false; btn.innerHTML = "✅ इस्तीफ़ा सबमिट करें"; if (result.success) { showAlert(result.message, 'success'); document.getElementById('resignationReason').value = ''; checkStatusHistory(); // List refresh karein } }).submitResignation(currentUser.employeeCode, reason); } // LOGOUT function employeeLogout() { if (confirm('क्या आप वाकई लॉगआउट करना चाहते हैं?')) { currentUser = null; sessionStorage.clear(); document.getElementById('dashboardPage').classList.remove('active'); document.getElementById('loginPage').style.display = 'flex'; document.getElementById('empEmail').value = ''; document.getElementById('empPassword').value = ''; showAlert('✅ लॉगआउट सफल', 'success'); } } // ========================================================= // EMPLOYEE CENTER VISIT — 300M GEO-FENCE // ========================================================= function ECV_init(){ const now=new Date(); const d=String(now.getDate()).padStart(2,'0'),m=String(now.getMonth()+1).padStart(2,'0'),y=now.getFullYear(); if(document.getElementById('ECV_date')) document.getElementById('ECV_date').value=y+'-'+m+'-'+d; if(document.getElementById('ECV_time')) document.getElementById('ECV_time').value=String(now.getHours()).padStart(2,'0')+':'+String(now.getMinutes()).padStart(2,'0'); if(document.getElementById('ECV_code')) document.getElementById('ECV_code').value=currentUser?.employeeCode||''; if(document.getElementById('ECV_empName')) document.getElementById('ECV_empName').value=currentUser?.name||''; ECV_getLocation(false); } function ECV_status(t,ok){const e=document.getElementById('ECV_status');if(e){e.textContent=t;e.style.color=ok?'#00e676':'#ff5252'}} function ECV_getLocation(showMsg=true){ if(!navigator.geolocation){ECV_status('❌ Browser GPS support नहीं करता।',false);return} if(showMsg) ECV_status('📍 Location verify हो रही है...',true); navigator.geolocation.getCurrentPosition(function(pos){ const lat=pos.coords.latitude,lon=pos.coords.longitude; document.getElementById('ECV_lat').value=lat.toFixed(6);document.getElementById('ECV_lon').value=lon.toFixed(6); google.script.run.withSuccessHandler(function(r){ if(!r?.success){ECV_status('❌ '+(r?.message||'Location verify failed'),false);return} document.getElementById('ECV_branch').value=r.branch||'';document.getElementById('ECV_pin').value=r.pincode||'';document.getElementById('ECV_village').value=r.village||'';document.getElementById('ECV_location').value=r.location||''; ECV_status('✅ Location verified — Branch से '+Math.round(r.distance||0)+' meter. Submit कर सकते हैं।',true); }).withFailureHandler(e=>ECV_status('❌ '+(e.message||e),false)).getEmployeeCenterVisitMeta(currentUser.employeeCode,lat,lon); },function(err){ECV_status('❌ GPS permission/location error: '+(err.message||'Unknown'),false);},{enableHighAccuracy:true,timeout:15000,maximumAge:0}); } function ECV_submit(){ const name=document.getElementById('ECV_personName').value.trim(),phone=document.getElementById('ECV_personNumber').value.trim(); const lat=parseFloat(document.getElementById('ECV_lat').value),lon=parseFloat(document.getElementById('ECV_lon').value); if(!name||!/^\d{10}$/.test(phone)){ECV_status('❌ Person Name और valid 10-digit Number required.',false);return} if(!Number.isFinite(lat)||!Number.isFinite(lon)){ECV_status('❌ पहले location verify करें.',false);return} ECV_status('⏳ Visit submit हो रही है...',true); google.script.run.withSuccessHandler(function(r){if(r?.success){ECV_status('✅ '+r.message,true);document.getElementById('ECV_personName').value='';document.getElementById('ECV_personNumber').value='';}else ECV_status('❌ '+(r?.message||'Submit failed'),false)}).withFailureHandler(e=>ECV_status('❌ '+(e.message||e),false)).submitEmployeeCenterVisit(currentUser.employeeCode,name,phone,lat,lon); } // SUPERVISOR FUNCTIONS function initSupervisorDashboard() { if (!currentUser) return; const nameEl = document.getElementById('supervisorUserName'); const branchEl = document.getElementById('supervisorUserBranch'); const avatarEl = document.getElementById('supervisorUserAvatar'); if(nameEl) nameEl.textContent = currentUser.name || "N/A"; if(branchEl) branchEl.textContent = currentUser.branch || "N/A"; if(avatarEl) avatarEl.textContent = (currentUser.name || "U").charAt(0); // Pehla page load karte waqt null pass karein taaki event error na aaye switchSupervisorPage('profile', null); } function loadSupervisorProfile() { const contentDiv = document.getElementById('supervisorProfileContent'); // Loader dikhane ke liye (Optional but good practice) contentDiv.innerHTML = '
⌛ Loading profile...
'; google.script.run .withSuccessHandler(function(result) { if (result.success) { const profile = result.profile; // Status color logic let statusColor = profile.status === 'Active' ? '#28a745' : '#dc3545'; let html = `
${profile.name}
${profile.designation} | ${profile.status}
🆔 Supervisor Code
${profile.code}
📧 Email ID
${profile.email}
📱 Mobile Number
${profile.phone}
🏢 Designation
${profile.branch}
📍 yesterday's Branch present name
${profile.todayBranch || 'Not Assigned'}
📅 yesterday's Branch present date
${profile.date}
`; contentDiv.innerHTML = html; } else { contentDiv.innerHTML = `
⚠️ ${result.message}
`; } }) .withFailureHandler(function(err) { contentDiv.innerHTML = "Server Error: " + err.message; }) .getSupervisorProfile(currentUser.supervisorCode); } function switchSupervisorPage(page, evt) { try { // Console mein check karne ke liye ki function call hua ya nahi console.log("Switching to page:", page); // 1. Hide All Sections const sections = document.querySelectorAll('#supervisorPage .page-section'); sections.forEach(section => { section.classList.remove('active'); section.style.display = 'none'; }); // 2. Active Class on Sidebar const links = document.querySelectorAll('.sidebar-menu a'); links.forEach(link => link.classList.remove('active')); // 3. Find Target Page ID const pageMap = { 'profile': 'supervisorProfilePage', 'leaveApproval': 'supervisorLeaveApprovalPage', 'attendanceHistory': 'supervisorAttendanceHistoryPage', 'leaveApply': 'supervisorLeaveApplyPage', 'centerVisit': 'supervisorCenterVisitPage', 'branchPresent': 'supervisorBranchPresentPage', 'employeeRating': 'supervisorEmployeeRatingPage', 'complaint': 'supervisorComplaintPage', }; const pageId = pageMap[page]; const target = document.getElementById(pageId); if (target) { target.classList.add('active'); target.style.display = 'block'; // Title Update const titles = { 'profile': '👤 प्रोफाइल', 'leaveApproval': '✅ छुट्टी अनुमोदन', 'attendanceHistory': '📅 हाज़िरी इतिहास', 'leaveApply': '🗓️ छुट्टी आवेदन', 'centerVisit': '🏢 Center Visit', 'branchPresent': '🏪 Branch Present', 'employeeRating': '⭐ कर्मचारी रेटिंग', 'complaint': '⚠️ शिकायत दर्ज करें' }; document.getElementById('supervisorPageTitle').textContent = titles[page]; } else { alert("HTML Element nahi mila: " + pageId); } // 4. Data Loaders if (page === 'profile') loadSupervisorProfile(); if (page === 'leaveApproval') loadSupervisorLeaves(); if (page === 'attendanceHistory') loadSupervisorAttendanceHistory(); if (page === 'employeeRating') loadEmployeeRatingList(); if (page === 'complaint') loadSupervisorComplaint(); // 5. Sidebar Toggle (Safe call) if (typeof toggleSidebar === "function") toggleSidebar(); } catch (err) { console.error("SwitchPage Error:", err); alert("Kuch galti hui hai: " + err.message); } } function loadSupervisorLeaves() { google.script.run.withSuccessHandler(function(result) { if (result.success) { let html = ''; result.leaves.forEach(leave => { html += `
${leave.employeeCode} - ${leave.employeeName}
${leave.type}
${leave.fromDate} से ${leave.toDate} (${leave.days} दिन)
कारण: ${leave.reason}
`; }); document.getElementById('leaveApprovalList').innerHTML = html || '

कोई छुट्टी अनुरोध नहीं

'; } }).getSupervisorLeaves(currentUser.email); } // ===== APPROVE BUTTON FUNCTION ===== function approveLeaveSupervisor(leaveId) { const days = document.getElementById("approveDays_"+leaveId)?.value || ""; google.script.run .withSuccessHandler(function(result){ if(result.success){ alert(result.message); loadSupervisorLeaves(); }else{ alert(result.message); } }) .approveLeave(leaveId,days); } // ===== REJECT BUTTON FUNCTION ===== function rejectLeaveSupervisor(leaveId) { const reason = prompt("कृपया अस्वीकार करने का कारण लिखें"); if(!reason) return; google.script.run .withSuccessHandler(function(result){ if(result.success){ alert(result.message); loadSupervisorLeaves(); }else{ alert(result.message); } }) .rejectLeave(leaveId, reason); } function loadSupervisorAttendanceHistory(){ const month=A_el('supAttMonth')?.value || (new Date().getFullYear()+'-'+String(new Date().getMonth()+1).padStart(2,'0')); if(A_el('supAttMonth'))A_el('supAttMonth').value=month; google.script.run.withSuccessHandler(function(r){const box=A_el('supAttHistory');if(!box)return;if(!r?.success){box.innerHTML='
'+A_esc(r?.message||'Failed')+'
';return;}let h='';(r.rows||[]).forEach(x=>h+='');box.innerHTML=h+'
DateCodeNameBranchTypeStatusINOUT
'+A_esc(x.date)+''+A_esc(x.code)+''+A_esc(x.name)+''+A_esc(x.branch)+''+A_esc(x.type)+''+A_esc(x.status)+''+A_esc(x.timeIn)+''+A_esc(x.timeOut)+'
'||'
No records
';}).withFailureHandler(function(e){A_el('supAttHistory').innerHTML='
'+A_esc(e.message||e)+'
'}).getSupervisorAttendanceHistory(currentUser.supervisorCode,month); } function submitSupervisorLeave(){const type=A_el('supLeaveType').value,from=A_el('supLeaveFrom').value,to=A_el('supLeaveTo').value,reason=A_el('supLeaveReason').value.trim();if(!from||!to||!reason){alert('From, To और Reason required');return;}google.script.run.withSuccessHandler(function(r){alert(r.message);if(r.success)A_el('supLeaveReason').value='';}).applySupervisorLeave(currentUser.supervisorCode,currentUser.name,currentUser.email,type,from,to,reason);} window.onload = function () { // Auto Date const today = new Date(); const yyyy = today.getFullYear(); const mm = String(today.getMonth() + 1).padStart(2, '0'); const dd = String(today.getDate()).padStart(2, '0'); document.getElementById("visitDate").value = yyyy + "-" + mm + "-" + dd; // Auto Time const hh = String(today.getHours()).padStart(2,'0'); const min = String(today.getMinutes()).padStart(2,'0'); document.getElementById("meetingTime").value = hh + ":" + min; }; function submitCenterVisit() { // 1. फोटो फाइल चेक करें const fileInput = document.getElementById("centerPhoto"); const photoFile = fileInput.files[0]; if (!photoFile) { alert("कृपया Photo Upload करें"); return; } // 2. डेटा ऑब्जेक्ट तैयार करें const data = { visitDate: document.getElementById('visitDate').value, meetingTime: document.getElementById('meetingTime').value, meetingType: document.getElementById('meetingType').value, branchName: document.getElementById('branchName').value, centerCode: document.getElementById('centerCode').value, centerName: document.getElementById('centerName').value, fieldOfficer: document.getElementById('fieldOfficerName').value, totalMembers: document.getElementById('totalMembers').value, membersPresent: document.getElementById('membersPresent').value, odMembers: document.getElementById('odMembersCount').value, centerDiscipline: document.getElementById('centerDiscipline').value, cashVerified: document.getElementById('cashVerified').value, centerStatus: document.getElementById('centerStatus').value, staffRating: document.getElementById('staffRating').value, nextMeetingDate: document.getElementById('nextMeetingDate').value, problem: document.getElementById('problemDescription').value, remark: document.getElementById('supervisorRemark').value, type: 'Center Visit' }; // वैलिडेशन if (!data.centerName || !data.centerCode) { alert('कृपया Center Name और Code दर्ज करें'); return; } // बटन को डिसेबल करें (ताकि बार-बार क्लिक न हो) const submitBtn = document.querySelector('button[onclick="submitCenterVisit()"]'); if(submitBtn) submitBtn.disabled = true; // 3. फोटो को Base64 में बदलें const reader = new FileReader(); reader.onload = function(e) { const base64 = e.target.result; // 4. लोकेशन प्राप्त करें if (navigator.geolocation) { navigator.geolocation.getCurrentPosition( function(position) { const lat = position.coords.latitude; const lon = position.coords.longitude; // 5. सर्वर (Apps Script) को डेटा भेजें google.script.run .withSuccessHandler(function(result) { if (submitBtn) submitBtn.disabled = false; // बटन इनेबल करें if (result.success) { alert('✅ ' + result.message); // फॉर्म को साफ़ करें document.querySelectorAll('input, textarea, select').forEach(el => { if(el.type !== 'button' && el.type !== 'submit') el.value = ''; }); } else { alert('❌ ' + result.message); } }) .withFailureHandler(function(err) { if (submitBtn) submitBtn.disabled = false; alert("Error: " + err); }) .processCenterVisit(currentUser.supervisorCode, data, lat, lon, base64); }, function(error) { if (submitBtn) submitBtn.disabled = false; alert("Location Error: कृपया GPS ऑन करें।"); } ); } else { alert("Geolocation इस ब्राउज़र में सपोर्टेड नहीं है।"); } }; reader.readAsDataURL(photoFile); } function markSupervisorBranchPresent() { const now = new Date(); const hr = now.getHours(); const min = now.getMinutes(); if (hr > 7 || (hr === 7 && min >= 30)) { showAlert('❌ Branch Present केवल 7:00 AM तक लग सकता है', 'error'); return; } if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(function(position) { const latitude = position.coords.latitude; const longitude = position.coords.longitude; const data = { type: 'Branch Present' }; google.script.run.withSuccessHandler(function(result) { if (result.success) { document.getElementById('branchPresentStatus').innerHTML = `
✅ ${result.message}
समय: ${result.time}
`; } else { document.getElementById('branchPresentStatus').innerHTML = `
❌ ${result.message}
`; } }).markSupervisorAttendance(currentUser.supervisorCode, latitude, longitude); }); } } function loadEmployeeRatingList() { google.script.run .withSuccessHandler(function(res) { if (res.success) { let html = ""; if (res.employees.length === 0) { html = "

No employees found under your email.

"; } else { res.employees.forEach(emp => { html += `
${emp.employeeName}
Employee Code: ${emp.employeeCode}
Branch: ${emp.branch}

`; }); } document.getElementById("employeeRatingList").innerHTML = html; } else { alert("Error loading list: " + res.message); } }) .getSupervisedEmployees(currentUser.email); } // Renamed local function to avoid conflict with server function function rateEmployeeAction(empCode, rating) { if (!rating) return; google.script.run .withSuccessHandler(function(res) { if(res.success){ alert(res.message); } else { alert("Failed: " + res.message); } }) .rateEmployee(currentUser.email, empCode, rating); } document.addEventListener('DOMContentLoaded', () => { // 1. SELECTING ELEMENTS const branchBtn = document.querySelectorAll('button')[0]; // First button const employeeBtn = document.querySelectorAll('button')[1]; // Second button // Forms select karne ke liye humne unke titles ka sahara liya hai const sections = document.querySelectorAll('.page-section > div'); const branchForm = sections[2]; // Branch Form Container const employeeForm = sections[3]; // Employee Form Container // Initial state: Dono form dikhenge, ya aap kisi ek ko hide kar sakte hain // employeeForm.style.display = 'none'; // 2. TAB SWITCHING LOGIC branchBtn.addEventListener('click', () => { branchForm.style.display = 'block'; employeeForm.style.display = 'none'; console.log("Switched to Branch Complaint"); }); employeeBtn.addEventListener('click', () => { branchForm.style.display = 'none'; employeeForm.style.display = 'block'; console.log("Switched to Employee Complaint"); }); // 3. FORM ACTIONS (SUBMIT, RESOLVE, ETC.) const allButtons = document.querySelectorAll('button'); allButtons.forEach(button => { button.addEventListener('click', (e) => { const btnText = e.target.innerText.trim(); // Search Button Logic if (btnText === 'Search') { const searchInput = e.target.previousElementSibling.value; alert('Searching for: ' + (searchInput || "Nothing entered")); } // Submit/Action Logic if (btnText.includes('Submit') || btnText.includes('Mark Resolved') || btnText.includes('Escalate')) { alert('Action Taken: ' + btnText + '\nData has been processed successfully!'); // Yahan aap apna backend API call add kar sakte hain } }); }); }); function supervisorLogout() { if (confirm('क्या आप वाकई लॉगआउट करना चाहते हैं?')) { currentUser = null; sessionStorage.clear(); document.getElementById('supervisorPage').classList.remove('active'); document.getElementById('loginPage').style.display = 'flex'; showAlert('✅ लॉगआउट सफल', 'success'); } } function submitBranchEmpRequirement(data) { const sheetName = "EmployeeRequirement"; let sheet = ss.getSheetByName(sheetName); if (!sheet) { sheet = ss.insertSheet(sheetName); sheet.appendRow([ "Request ID","Branch Code","Branch Name","Gender Required","Designation","Number Required","Reason","Request Date","Status" ]); } const id = "BRREQ" + Date.now(); const row = [ id, data.branchCode, data.branchName, data.genderRequired, data.designation, data.numberRequired, data.reason, data.requestDate || new Date(), "Pending" ]; sheet.appendRow(row); return {success:true, message:"✅ रिक्वेस्ट सेव हो गई", reqId: id}; } function getEmpRequirements(branchCode) { const sheetName = "EmployeeRequirement"; const sheet = ss.getSheetByName(sheetName); if(!sheet) return {success:true, list:[]}; const data = sheet.getDataRange().getValues(); return {success:true, list:data.filter(r=>r[1]==branchCode).slice(1)}; } function submitBranchComplaint(data) { const sheetName = "BranchComplaint"; let sheet = ss.getSheetByName(sheetName); if(!sheet) { sheet = ss.insertSheet(sheetName); sheet.appendRow([ "Complaint ID", "Emp Code", "Emp Name", "Branch Code", "Category", "Description", "Attachment (link/base64)", "Date", "Status", "Resolution", "Resolved Date" ]); } const id = "CMP"+Date.now(); // Optional: attachment as base64/link, base64 बड़ा होगा तो स्टोरेज पर ध्यान रखें! const row = [ id, data.empCode, data.empName, data.branchCode, data.category, data.desc, data.attach || "", data.date || new Date(), "Pending", "", "" ]; sheet.appendRow(row); return {success:true, message:"✅ शिकायत सेव हो गई!", complaintId:id}; } function getBranchComplaints(branchCode) { const sheet = ss.getSheetByName("BranchComplaint"); if(!sheet) return {success:true, list:[]}; const data = sheet.getDataRange().getValues(); return {success:true, list: data.filter(r=>r[3]==branchCode).slice(1)}; } function submitSoftwareIssue(data) { const sheetName = "SoftwareIssue"; let sheet = ss.getSheetByName(sheetName); if(!sheet) { sheet = ss.insertSheet(sheetName); sheet.appendRow([ "Issue ID","Branch Code","Branch Name","Type","Description","Screenshot (base64/link)", "Date","Status","Resolution","Resolved Date" ]); } const id = "ISSUE"+Date.now(); const row = [ id, data.branchCode, data.branchName, data.problemType, data.desc, data.screenshot || "", data.date || new Date() ,"Pending","","" ]; sheet.appendRow(row); return {success:true, message:"✅ सॉफ्टवेयर समस्या सेव हो गई", issueId:id}; } function getSoftwareIssues(branchCode) { const sheet = ss.getSheetByName("SoftwareIssue"); if(!sheet) return {success:true, list:[]}; const data = sheet.getDataRange().getValues(); return {success:true, list:data.filter(r=>r[1]==branchCode).slice(1)}; } function submitBranchRequirement(data) { const sheetName = "BranchRequirement"; let sheet = ss.getSheetByName(sheetName); if(!sheet) { sheet = ss.insertSheet(sheetName); sheet.appendRow([ "Req ID","Branch Code","Type","Description","Qty","Urgency","Date","Status" ]); } const id = "BRREQ-"+Date.now(); const row = [ id, data.branchCode, data.reqType, data.desc, data.qty, data.urgency, new Date(), "Pending" ]; sheet.appendRow(row); return {success:true, message:"✅ Requirement सेव हो गया", reqId:id}; } function getBranchRequirements(branchCode) { const sheet = ss.getSheetByName("BranchRequirement"); if(!sheet) return {success:true, list:[]}; const data = sheet.getDataRange().getValues(); return {success:true, list:data.filter(r=>r[1]==branchCode).slice(1)}; } function submitOrderSystem(data) { const sheetName = "BranchOrder"; let sheet = ss.getSheetByName(sheetName); if(!sheet) { sheet = ss.insertSheet(sheetName); sheet.appendRow([ "Order ID","Branch Code","Items","Quantity","Delivery Address","Date","Status" ]); } const id = "ORDER-"+Date.now(); const row = [ id, data.branchCode, data.itemType || "", data.qty || "", data.deliveryAddr || "", new Date(), "Requested" ]; sheet.appendRow(row); return {success:true, message:"✅ ऑर्डर सेव हो गया", orderId:id}; } function getOrderSystemHistory(branchCode) { const sheet = ss.getSheetByName("BranchOrder"); if(!sheet) return {success:true, list:[]}; const data = sheet.getDataRange().getValues(); return {success:true, list:data.filter(r=>r[1]==branchCode).slice(1)}; } function getBranchTargets(branchCode, filter, month) { // Suppose sheet: "BranchTarget", columns: Branch Code, Month, Type, Target, Achieved const sheetName = "BranchTarget"; const sheet = ss.getSheetByName(sheetName); if(!sheet) return {success:true, targets:[]}; const data = sheet.getDataRange().getValues(); let filtered = data.filter(r => r[0]==branchCode && (!month || r[1]==month) ).slice(1); const targets = filtered.map(r=>({ type: r[2], target: Number(r[3]), achieved: Number(r[4]) })); return {success:true, targets:targets}; } function getBranchSheetList() { const sheet = ss.getSheetByName("BranchMaster"); if(!sheet) return {success:true, list:[]}; const data = sheet.getDataRange().getValues(); return {success:true, list: data.slice(1)}; // [Name, Code, SheetLink] } // Branch Profile fetch (कोई BranchMaster sheet या EmployeeRegistration "branch" के हिसाब से) function getBranchProfile(branchCode) { const sheet = ss.getSheetByName("BranchMaster"); if(!sheet) return {success:false, message:"No profile found."}; const data = sheet.getDataRange().getValues(); for(let i=1;ir[4]==branchCode).slice(1)}; } function adminLogout() { if (confirm('क्या आप वाकई लॉगआउट करना चाहते हैं?')) { currentUser = null; sessionStorage.clear(); document.getElementById('adminPage').classList.remove('active'); document.getElementById('loginPage').style.display = 'flex'; showAlert('✅ लॉगआउट सफल', 'success'); } } // UTILITY FUNCTIONS function showAlert(message, type = 'info') { const alertDiv = document.createElement('div'); alertDiv.className = `alert ${type}`; alertDiv.innerHTML = ` ${message} `; document.getElementById('alertContainer').insertBefore(alertDiv, document.getElementById('alertContainer').firstChild); setTimeout(() => { alertDiv.style.display = 'none'; }, 5000); } // INITIALIZE ON PAGE LOAD document.addEventListener('DOMContentLoaded', function() { const savedUser = sessionStorage.getItem('currentUser'); if (savedUser) { currentUser = JSON.parse(savedUser); if (currentUser.userType === 'employee') { document.getElementById('loginPage').style.display = 'none'; document.getElementById('dashboardPage').classList.add('active'); initDashboard(); } else if (currentUser.userType === 'supervisor') { document.getElementById('loginPage').style.display = 'none'; document.getElementById('supervisorPage').classList.add('active'); initSupervisorDashboard(); } else if (currentUser.userType === 'admin') { document.getElementById('loginPage').style.display = 'none'; document.getElementById('adminPage').classList.add('active'); initAdminDashboard(); } } }); // Load data after login document.addEventListener('DOMContentLoaded', function() { setTimeout(() => { if (currentUser && currentUser.userType === 'employee') { loadComplaints(); loadODDashboard(); } }, 1000); });