OABP2 INTERNAL DESK

Guest Mode

System Access Sign In

New Leave Allocation Booking

Active Leave Allocations

User IDDateCategoryTimestamp

Logistics Provision Request Form

Distribution Logs

ItemQtyStatus

Mass Upload System Accounts Database

// Replace this string placeholder with your real Cloudflare Worker Live URL const workerUrl = "YOUR_CLOUDFLARE_WORKER_URL_HERE"; let currentUser = null; function showPanel(id) { document.querySelectorAll('.panel').forEach(p => p.classList.remove('active')); document.querySelectorAll('.tabs button').forEach(b => b.classList.remove('active')); const targetedPanel = document.getElementById('panel-' + id); const targetedTab = document.getElementById('tab-' + id); if (targetedPanel) targetedPanel.classList.add('active'); if (targetedTab) targetedTab.classList.add('active'); } async function login() { const userId = document.getElementById('uid').value; const employeeNumber = document.getElementById('pass').value; if(userId === 'ADMIN_SYS' && employeeNumber === 'ADMIN123456789') { currentUser = { user_id: 'ADMIN_SYS', name: 'Universal Admin', role: 'Admin', shift: 'ADMINSYS' }; activateUserWorkspace(); return; } try { const res = await fetch(`${workerUrl}/api/auth/login`, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ userId, employeeNumber }) }); if(!res.ok) throw new Error("Invalid runtime validation mapping criteria matching profiles."); const data = await res.json(); currentUser = data.user; activateUserWorkspace(); } catch(e) { alert(e.message); } } function activateUserWorkspace() { document.getElementById('panel-login').classList.remove('active'); document.getElementById('navTabs').style.display = 'flex'; document.getElementById('userDisplay').innerText = `${currentUser.name} [${currentUser.role}]`; if(currentUser.role === 'Admin') { document.getElementById('tab-admin').style.display = 'inline-block'; } showPanel('leave'); renderItemSelection(); } async function indexMatchLookup(val, nameFieldId, shiftFieldId) { if(val.length < 3) return; try { const res = await fetch(`${workerUrl}/api/users/lookup/${val}`); if(res.ok) { const profile = await res.json(); document.getElementById(nameFieldId).value = profile.name; document.getElementById(shiftFieldId).value = profile.shift; } } catch(err) { console.error("Database structural network index mismatch processing trace:", err); } } function renderItemSelection() { const stream = document.getElementById('e_cat').value; const itemMenu = document.getElementById('e_item'); if(!itemMenu) return; itemMenu.innerHTML = ''; const items = { 'Uniform': ['Jumpsuit'], 'PPE': ['Safety Shoe White', 'Safety Shoe HD', 'Ear Muff', 'Ear Plug', 'Reflective Vest'], 'Tool & Stationery': ['Eye-Piece', 'N/A Stamp', 'Pen', 'Permanent Marker Pen'] }; items[stream].forEach(i => { let node = document.createElement('option'); node.value = i; node.innerText = i; itemMenu.appendChild(node); }); } async function bookLeave() { const payload = { employeeNumber: document.getElementById('l_emp').value, name: document.getElementById('l_name').value, shift: document.getElementById('l_shift').value, targetDate: document.getElementById('l_date').value, category: document.getElementById('l_cat').value, userId: currentUser.user_id }; const res = await fetch(`${workerUrl}/api/leave/book`, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(payload) }); if(res.ok) alert("Leave window reservation saved successfully!"); else { const err = await res.json(); alert(err.error); } } async function uploadCSVData() { const raw = document.getElementById('csvInput').value.trim().split('\n'); const usersList = raw.map(line => { const chunks = line.split(','); return { user_id: chunks[0], name: chunks[1], employee_number: chunks[2], shift: chunks[3], role: chunks[4] }; }); const res = await fetch(`${workerUrl}/api/admin/mass-upload`, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ usersList }) }); if(res.ok) alert("Data matrix transaction successfully parsed!"); } function logout() { currentUser = null; location.reload(); } export default { async fetch(request, env) { const url = new URL(request.url); const path = url.pathname; const headers = { "Content-Type": "application/json", "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS", "Access-Control-Allow-Headers": "Content-Type" }; if (request.method === "OPTIONS") return new Response(null, { headers, status: 204 }); try { if (path === "/api/auth/login" && request.method === "POST") { const { userId, employeeNumber } = await request.json(); const user = await env.DB.prepare("SELECT * FROM users WHERE user_id = ? AND employee_number = ?").bind(userId, employeeNumber).first(); if (!user) return new Response(JSON.stringify({ error: "Access Denied" }), { status: 401, headers }); return new Response(JSON.stringify({ user }), { status: 200, headers }); } if (path.startsWith("/api/users/lookup/") && request.method === "GET") { const empNum = path.split("/").pop(); const user = await env.DB.prepare("SELECT name, shift FROM users WHERE employee_number = ?").bind(empNum).first(); if (!user) return new Response(JSON.stringify({ error: "No matching record trace" }), { status: 404, headers }); return new Response(JSON.stringify(user), { status: 200, headers }); } if (path === "/api/leave/book" && request.method === "POST") { const { employeeNumber, name, shift, targetDate, category, userId } = await request.json(); const quotaKey = category === 'Morning/Normal' ? 'morning_quota' : 'night_quota'; const maxQuota = await env.DB.prepare("SELECT value FROM system_settings WHERE key = ?").bind(quotaKey).first(); const currentCount = await env.DB.prepare("SELECT COUNT(*) as total FROM leave_bookings WHERE booking_date = ? AND category = ?").bind(targetDate, category).first(); if (currentCount.total >= parseInt(maxQuota.value)) { return new Response(JSON.stringify({ error: "Selected operational category capacity tier is full." }), { status: 400, headers }); } const id = crypto.randomUUID(); const localTime = new Date().toLocaleString(); await env.DB.prepare("INSERT INTO leave_bookings VALUES (?, ?, ?, ?, ?, ?, ?, ?)") .bind(id, userId, employeeNumber, name, shift, targetDate, category, localTime).run(); return new Response(JSON.stringify({ success: true }), { status: 200, headers }); } if (path === "/api/admin/mass-upload" && request.method === "POST") { const { usersList } = await request.json(); const statements = usersList.map(u => env.DB.prepare("INSERT OR REPLACE INTO users VALUES (?, ?, ?, ?, ?)") .bind(u.user_id, u.name, u.employee_number, u.shift, u.role) ); await env.DB.batch(statements); return new Response(JSON.stringify({ success: true }), { status: 200, headers }); } return new Response(JSON.stringify({ error: "Endpoint route mismatch mapping trace error" }), { status: 404, headers }); } catch (e) { return new Response(JSON.stringify({ error: e.message }), { status: 500, headers }); } } };