Logout
<script>
const users = {
"fkioko@webergroup":{name:"Fidelis Kioko",password:"fidelis@weber",isAdmin:true},
"fmwangi@webergroup":{name:"Florence Mwangi",password:"florence@weber",isAdmin:false},
"mkyalo@webergroup":{name:"Martin Kyalo",password:"martin@weber",isAdmin:false},
"powen@webergroup":{name:"Philip Owen",password:"philip@weber",isAdmin:false},
"dkipngeno@webergroup":{name:"Duncan Kipngeno",password:"duncan@weber",isAdmin:false}
};
let currentUser=null, sales=[], stock=[], chart;
// Load from localStorage
window.onload = () => {
sales = JSON.parse(localStorage.getItem('salesData') || '[]').map(s => ({...s, date:new Date(s.date)}));
stock = JSON.parse(localStorage.getItem('stockData') || '[]');
};
function save() {
localStorage.setItem('salesData', JSON.stringify(sales));
localStorage.setItem('stockData', JSON.stringify(stock));
}
function login(){
const u=username.value.trim().toLowerCase(), p=password.value;
if(users[u]&&users[u].password===p){
currentUser={username:u,name:users[u].name,isAdmin:users[u].isAdmin};
loginPage.style.display="none";
dashboard.style.display="block";
logoutBtn.style.display="inline-block";
empName.textContent=currentUser.name;
adminPanel.style.display=currentUser.isAdmin?"block":"none";
renderStock();renderSales();
} else {
loginError.textContent="Invalid username or password";
}
}
function logout(){
currentUser=null;
save();
dashboard.style.display="none";
loginPage.style.display="block";
loginError.textContent="";
username.value=password.value="";
if(chart){ chart.destroy(); chart=null; }
}
function addStock(){
const cat=stockCategory.value,it=stockItem.value.trim(),qt=parseInt(stockQty.value);
if(!it||qt<=0) return alert("Invalid stock");
stock.push({category:cat,item:it,quantity:qt});
stockItem.value=stockQty.value="";
save(); renderStock();
}
function renderStock(){
const tb=stockTable.querySelector("tbody");
tb.innerHTML=stock.map(s=>`${s.category}${s.item}${s.quantity}`).join("");
}
function addSale(){
const cat=saleCategory.value,it=saleItem.value.trim(),qt=parseInt(saleQty.value),
pr=parseFloat(salePrice.value),pm=salePayment.value,mp=saleMpesa.value.trim();
if(!it||qt<=0||pr<=0) return alert("Fill valid sale details");
const st=stock.find(s=>s.item.toLowerCase()===it.toLowerCase());
if(st){
if(st.quantity{
if(!currentUser.isAdmin && s.username!==currentUser.username) return false;
if(from&&s.dateto) return false;
return !term||Object.values(s).some(v=>String(v).toLowerCase().includes(term));
});
let total=0;
salesTable.querySelector("tbody").innerHTML=filtered.map((s,i)=>{
total+=s.total;
return `${s.date.toLocaleString()}${s.employee}${s.category}${s.item}${s.qty}${s.price}${s.total}${s.payment}${s.mpesa}Delete`;
}).join("");
totalSales.textContent=total.toFixed(2);
dailyWage.textContent=total>=1300?300:total>=800?250:total>=650?150:total>=350?100:0;
renderChart(filtered);
}
function deleteSale(i){
sales.splice(i,1);
save(); renderSales();
}
function exportToExcel(){
const data = (currentUser.isAdmin? sales : sales.filter(s=>s.username===currentUser.username))
.map(s=>({Date:s.date.toLocaleString(),Employee:s.employee,Category:s.category,Item:s.item,Qty:s.qty,Price:s.price,Total:s.total,Payment:s.payment,MPESA:s.mpesa}));
const ws=XLSX.utils.json_to_sheet(data), wb=XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, "Sales"); XLSX.writeFile(wb, "webertech_sales.xlsx");
}
function renderChart(list){
if(chart){ chart.destroy(); chart=null; }
const daily={}, empTotals={};
list.forEach(s=>{
const d=s.date.toISOString().split("T")[0];
daily[d]=(daily[d]||0)+s.total;
if(currentUser.isAdmin){
empTotals[s.employee]=empTotals[s.employee]||{};
empTotals[s.employee][d]=(empTotals[s.employee][d]||0)+s.total;
}
});
const labels=Object.keys(daily).sort();
const datasets=[{label:currentUser.isAdmin?"Total Sales":"Your Sales",data:labels.map(d=>daily[d]),borderColor:"#007BFF",fill:false}];
if(currentUser.isAdmin){
Object.keys(empTotals).forEach((emp,i)=>{
const color=["#e6194B","#3cb44b","#ffe119","#4363d8","#f58231"][i%5];
datasets.push({label:emp,data:labels.map(d=>empTotals[emp][d]||0),borderColor:color,fill:false});
});
}
const ctx=document.getElementById("chartCanvas").getContext("2d");
chart=new Chart(ctx,{type:"line",data:{labels,datasets},options:{scales:{y:{beginAtZero:true}}}});
}
function print(){ window.print(); }
</script>
<div id="adminPanel" class="card">
<h3>Manage Stock</h3>
<div class="flex">
<select id="stockCategory">
<option>Cyber Services</option><option>Stationery</option><option>Electronics</option>
<option>Gas Refill</option><option>Full Gas Cylinder</option><option>Gas Accessories</option>
</select>
<input id="stockItem" placeholder="New stock item">
<input id="stockQty" type="number" placeholder="Qty">
<button onclick="addStock()">Add Stock</button>
</div>
<table id="stockTable"><thead><tr><th>Category</th><th>Item</th><th>Qty</th></tr></thead><tbody></tbody></table>
</div>
<h3>Record Sale</h3>
<div class="flex">
<select id="saleCategory">
<option>Cyber Services</option><option>Stationery</option><option>Electronics</option>
<option>Gas Refill</option><option>Full Gas Cylinder</option><option>Gas Accessories</option>
</select>
<input id="saleItem" placeholder="Item or Service">
<input id="saleQty" type="number" placeholder="Qty">
<input id="salePrice" type="number" placeholder="Unit Price (KES)">
<select id="salePayment">
<option>Cash</option><option>MPESA Till</option><option>Bank Paybill</option><option>Send Money</option>
</select>
<input id="saleMpesa" placeholder="MPESA Confirmation ID (optional)">
<button onclick="addSale()">Add Sale</button>
</div>
<div class="flex">
<h4>Total Sales: KES <span id="totalSales">0</span></h4>
<h4>Daily Wage: KES <span id="dailyWage">0</span></h4>
</div>
<div class="flex">
<label>From: <input type="date" id="fromDate" onchange="renderSales()"></label>
<label>To: <input type="date" id="toDate" onchange="renderSales()"></label>
<input id="search" placeholder="Search..." oninput="renderSales()">
<button onclick="print()">Print</button>
<button onclick="exportToExcel()">Export to Excel</button>
</div>
<table id="salesTable"><thead><tr>
<th>Date</th><th>Employee</th><th>Category</th><th>Item</th><th>Qty</th><th>Price</th><th>Total</th><th>Payment</th><th>MPESA</th><th>Action</th>
</tr></thead><tbody></tbody></table>
<canvas id="chartCanvas" style="margin-top:30px;"></canvas>
