00:00:00 AM
LOADING SECURE DATA...
SECURE SERVER TELEMETRY: ACTIVE
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 काउंट होगा।
📅 महीना चुनें (वार्षिक रिपोर्ट):
जनवरी
फरवरी
मार्च
अप्रैल
मई
जून
जुलाई
अगस्त
सितंबर
अक्टूबर
नवंबर
दिसंबर
⏳ बाकी कार्य और पिछला बकाया
GEO VERIFIED VISIT
🏢 Center Visit
Branch location से 300 मीटर के अंदर ही form submit होगा।
📍 Get Location
Location लेने के लिए ऊपर button दबाएँ।
✅ Submit Center Visit
इस्तीफ़े का कारण *
✅ इस्तीफ़ा सबमिट करें
🏪 Branch Present (7:00 AM तक)
⚠️ नोट: यह ऑप्शन केवल 7:00 AM तक सक्रिय है।
🏪 Branch Present लगाएं
⚠️ Complaint Management System
🏢 Branch Complaint Form
👤 Employee Complaint Form
Results
ID
Date
Category
Status
Action
WELCOME ADMIN All Over Control Dashboard Staff, Supervisor, Attendance, Complaints, Notifications और complete sheet data.
🔄 Load Latest
⚡ Quick Control 👥 Manage Employees / Block-Unblock 🕒 Monthly Attendance 👨💼 Create Supervisor 🔔 Publish Staff Notification 📢 Review Complaints ⬆️ Upload Data
📌 System Status Loading...
EMPLOYEE CONTROL 👥 Employee Registration Employee data, approval status और Block / Unblock.
✅ Unblock All ⛔ Block All
ATTENDANCE CONTROL 🕒 Attendance / Half Day Screenshot-style monthly matrix — Code, Name और हर दिन का status एक साथ.
All Employees All Branches 🔍 Show
LIVE SHEET DATA Sheet Data A to Z rows और columns — password/OTP जैसे sensitive columns hide रहेंगे.
Clear
STAFF SUPPORT 📢 Complaint Control Employee / Branch complaint records देखें और resolve करें.
↻ Refresh
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.
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 = `
`;
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.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 = `
कर्मचारी कोड:
${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}
✅ Approve
❌ Reject
`;
});
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='
Date Code Name Branch Type Status IN OUT ';(r.rows||[]).forEach(x=>h+=''+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)+' ');box.innerHTML=h+'
'||'
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}
Select Rating
⭐ 1
⭐⭐ 2
⭐⭐⭐ 3
⭐⭐⭐⭐ 4
⭐⭐⭐⭐⭐ 5
`;
});
}
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;i
r[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);
});