Skip to content

WEBERTECHSALESPORTAL/Webertechsalesportal.github.io

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 

Repository files navigation

<title>WEBERTECH SALES PORTAL</title> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.17.0/xlsx.full.min.js"></script> <style> body { font-family: Arial; background:#f0f0f0; padding:20px; max-width:1000px; margin:auto; } .card { background:#fff; border-radius:8px; padding:20px; margin-bottom:20px; box-shadow:0 2px 6px rgba(0,0,0,0.1); } input, select, button { padding:8px; margin:8px 0; width:100%; max-width:260px; } button { cursor:pointer; background:#007BFF; color:#fff; border:none; border-radius:4px; } button.logout { background:#dc3545; float:right; } table { width:100%; border-collapse:collapse; margin-top:20px; } th, td { border:1px solid #ccc; padding:8px; text-align:left; } th { background:#eee; } .flex { display:flex; gap:20px; flex-wrap:wrap; margin-bottom:15px; } .error { color:red; margin-top:10px; } #dashboard, #adminPanel, #logoutBtn { display:none; } </style>

WEBERTECH SALES PORTAL

Login

Login
Logout

Welcome,

<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>
<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>

About

index.html

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published