<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Computer Service Receipt</title>
<style>
*{box-sizing:border-box}
:root{--blue:#174b87;--light:#eaf3ff;--line:#b8cbe0;--text:#172033;--muted:#5d6b7d}
body{margin:0;background:#eef2f7;color:var(--text);font-family:Arial,Segoe UI,sans-serif}
.appbar{background:linear-gradient(135deg,#12345d,#2165a8);color:white;padding:18px 24px;display:flex;justify-content:space-between;align-items:center}
.appbar h1{margin:0;font-size:22px}.appbar p{margin:4px 0 0;font-size:12px;color:#dbeafe}
.wrap{max-width:1120px;margin:20px auto;padding:0 15px}
.form-card{background:#fff;border:1px solid #d8e0ea;border-radius:12px;padding:18px;margin-bottom:15px;box-shadow:0 5px 18px #17203310}
.form-title{font-size:16px;font-weight:700;color:var(--blue);margin:0 0 14px}
.grid{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}
.field label{display:block;font-size:11px;font-weight:700;color:var(--muted);margin-bottom:5px}
input,textarea,select{width:100%;border:1px solid #ccd6e2;border-radius:7px;padding:9px;font:inherit;color:var(--text);background:#fbfdff}
textarea{min-height:65px;resize:vertical}
.full{grid-column:1/-1}
.bill-preview{background:#fff;border:1px solid #c8d4e2;padding:18px;margin-top:15px}
.bill-head{border-bottom:3px solid var(--blue);padding-bottom:9px;display:flex;justify-content:space-between;gap:15px}
.company h2{margin:0;color:#163f70;font-size:22px}.company p{margin:3px 0;font-size:11px;color:#4b5b70}
.receipt-title{background:var(--blue);color:white;padding:8px 20px;border-radius:5px;font-weight:bold;font-size:18px;white-space:nowrap;align-self:center}
.meta{font-size:11px;line-height:1.7;text-align:right}
.section{border:1px solid var(--line);border-radius:5px;margin-top:9px;overflow:hidden}
.section-head{background:var(--light);color:#174b87;font-weight:bold;padding:5px 8px;font-size:12px}
.section-body{padding:7px 8px;font-size:11px}
.info-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.info-grid.three{grid-template-columns:1fr 1fr 1fr}
.info-row{display:flex;gap:8px;line-height:1.45}
.info-row b{min-width:105px}
.bill-table{width:100%;border-collapse:collapse;font-size:9.5px}
.bill-table th,.bill-table td{border:1px solid #b9cbe0;padding:4px;text-align:left;vertical-align:top}
.bill-table th{background:#edf5ff;color:#173f70}
.bill-bottom{display:grid;grid-template-columns:1.35fr .9fr;gap:9px}
.amount{display:flex;justify-content:space-between;padding:3px 0}.amount.total{border-top:2px solid #173f70;margin-top:3px;padding-top:6px;font-weight:bold;font-size:13px}
.signature{display:flex;justify-content:space-between;margin-top:25px;text-align:center;font-size:10px}
.sig{width:190px;border-top:1px solid #555;padding-top:4px}
.actions{display:flex;gap:8px;justify-content:flex-end;flex-wrap:wrap}
button{border:0;border-radius:7px;padding:10px 14px;font-weight:bold;cursor:pointer}
.primary{background:#2165d1;color:#fff}.secondary{background:#e8eef6;color:#172033}.danger{background:#fee2e2;color:#a11}
.add{margin-top:8px;background:#eaf3ff;color:#174b87;border:1px dashed #80a9d4}
.remove{background:#fee2e2;color:#a11;padding:5px 8px}
.table-wrap{overflow:auto}
#partsInput,#softwareInput{min-width:900px}
.note{font-size:10px;color:#6b7280;margin-top:6px}
@media(max-width:760px){.grid,.info-grid,.info-grid.three,.bill-bottom{grid-template-columns:1fr}.bill-head{display:block}.receipt-title{display:inline-block;margin-top:8px}.meta{text-align:left;margin-top:6px}}
@media print{
body{background:#fff}
.appbar,.form-card,.actions,.screen-only{display:none!important}
.wrap{max-width:none;margin:0;padding:0}
.bill-preview{border:0;padding:0;margin:0;box-shadow:none}
.bill-head{break-inside:avoid}.section{break-inside:avoid}
@page{size:A4;margin:10mm}
body.print58{width:58mm;font-size:8px}
body.print80{width:80mm;font-size:9px}
body.print58 .bill-preview,body.print80 .bill-preview{width:100%;padding:0}
body.print58 .bill-head,body.print80 .bill-head{display:block;border-bottom:1px dashed #000}
body.print58 .company h2{font-size:13px}.print80 .company h2{font-size:15px}
body.print58 .receipt-title,body.print80 .receipt-title{display:inline-block;background:#fff;color:#000;border:1px solid #000;padding:3px 7px;font-size:10px;margin:4px 0}
body.print58 .meta,body.print80 .meta{text-align:left;font-size:8px}
body.print58 .section,body.print80 .section{border:0;border-bottom:1px dashed #000;border-radius:0;margin-top:4px}
body.print58 .section-head,body.print80 .section-head{background:#fff;color:#000;border-bottom:1px solid #000;padding:2px 0}
body.print58 .section-body,body.print80 .section-body{padding:3px 0;font-size:8px}
body.print58 .bill-table,body.print80 .bill-table{font-size:7px}
body.print58 .bill-table th,body.print58 .bill-table td,body.print80 .bill-table th,body.print80 .bill-table td{padding:2px}
body.print58 .info-grid,body.print80 .info-grid,body.print58 .info-grid.three,body.print80 .info-grid.three,body.print58 .bill-bottom,body.print80 .bill-bottom{display:block}
body.print58 .sig,body.print80 .sig{width:100px}
body.print58 .signature,body.print80 .signature{margin-top:12px}
body.print58 .software-section,body.print80 .software-section{display:none}
body.print58 .notes-section,body.print80 .notes-section{display:none}
body.print58 .bill-bottom .section:first-child,body.print80 .bill-bottom .section:first-child{display:none}
}
</style>
</head>
<body>
<header class="appbar">
<div><h1>Computer Service Job Card</h1><p>Service Receipt & Customer Copy</p></div>
<div>TECHNICAL SERVICE</div>
</header>
<div class="wrap">
<form id="jobForm" class="screen-only">
<div class="form-card">
<h3 class="form-title">Company & Receipt</h3>
<div class="grid">
<div class="field"><label>Company Name</label><input id="companyName" value="The Computer Service Center"></div>
<div class="field"><label>Company Address</label><input id="companyAddress" value="Aluva, Ernakulam, Kerala - 683101"></div>
<div class="field"><label>Company Phone</label><input id="companyPhone" value=""></div>
<div class="field"><label>Receipt / Job No.</label><input id="jobNo" placeholder="TC-2026-0001"></div>
<div class="field"><label>Date</label><input id="date" type="date"></div>
<div class="field"><label>Service Time</label><input id="receiptTime" type="time"></div>
</div>
</div>
<div class="form-card">
<h3 class="form-title">Customer / Received From</h3>
<div class="grid">
<div class="field"><label>Customer Name</label><input id="customerName"></div>
<div class="field"><label>Received From / Contact Person</label><input id="receivedFrom"></div>
<div class="field"><label>Phone Number</label><input id="customerPhone"></div>
<div class="field full"><label>Customer Address</label><textarea id="customerAddress"></textarea></div>
</div>
</div>
<div class="form-card">
<h3 class="form-title">Item & Complaint</h3>
<div class="grid">
<div class="field"><label>Item Received</label><input id="itemReceived" placeholder="Laptop / Desktop / Printer"></div>
<div class="field"><label>Brand</label><input id="itemBrand"></div>
<div class="field"><label>Model Number</label><input id="itemModel"></div>
<div class="field"><label>Serial Number</label><input id="itemSerial"></div>
<div class="field"><label>Service Start</label><input id="startTime" type="time"></div>
<div class="field"><label>Service Completed</label><input id="endTime" type="time"></div>
<div class="field full"><label>Customer Complaint</label><textarea id="complaint"></textarea></div>
<div class="field full"><label>Service / Work Done</label><textarea id="workDone" placeholder="Changed parts, repaired, cleaned, configured, etc."></textarea></div>
</div>
</div>
<div class="form-card">
<h3 class="form-title">Software Installed / Configured</h3>
<div class="table-wrap">
<table class="bill-table" id="softwareInput">
<thead><tr><th>Software Name</th><th>Version</th><th>Remarks</th><th></th></tr></thead>
<tbody></tbody>
</table>
</div>
<button type="button" class="add" onclick="addSoftware()">+ Add Software</button>
</div>
<div class="form-card">
<h3 class="form-title">Changed / Purchased Parts & Items</h3>
<div class="grid">
<div class="field"><label>Vendor / Company / Shop Name</label><input id="vendorName"></div>
<div class="field"><label>Purchase Date</label><input id="purchaseDate" type="date"></div>
<div class="field full"><label>Vendor Address</label><input id="vendorAddress"></div>
</div>
<div class="table-wrap" style="margin-top:12px">
<table class="bill-table" id="partsInput">
<thead><tr><th>Item / Part</th><th>Brand</th><th>Model</th><th>Serial / Part No.</th><th>Qty</th><th>Amount</th><th>Total</th><th></th></tr></thead>
<tbody></tbody>
</table>
</div>
<button type="button" class="add" onclick="addPart()">+ Add Part / Item</button>
</div>
<div class="form-card">
<h3 class="form-title">Payment & Notes</h3>
<div class="grid">
<div class="field"><label>Service Charge</label><input id="serviceCharge" type="number" value="0" min="0" oninput="calculate()"></div>
<div class="field"><label>Other Charges</label><input id="otherCharge" type="number" value="0" min="0" oninput="calculate()"></div>
<div class="field"><label>Amount Paid</label><input id="paid" type="number" value="0" min="0" oninput="calculate()"></div>
<div class="field full"><label>Notes / Warranty / Remarks</label><textarea id="notes"></textarea></div>
</div>
</div>
<div class="form-card">
<div class="actions">
<select id="printMode">
<option value="a4">A4 One Page</option>
<option value="58">Thermal 58mm</option>
<option value="80">Thermal 80mm</option>
</select>
<button type="button" class="secondary" onclick="printBill()">🖨 Print</button>
<button type="button" class="secondary" onclick="saveData()">💾 Save</button>
<button type="button" class="secondary" onclick="exportExcel()">📊 Export Excel</button>
<button type="button" class="secondary" onclick="document.getElementById('importFile').click()">📥 Import Excel</button>
<input id="importFile" type="file" accept=".csv,.xlsx,.xls" style="display:none" onchange="importExcel(event)">
<button type="button" class="danger" onclick="newJob()">↻ New</button>
</div>
</div>
</form>
<div class="bill-preview" id="bill">
<div class="bill-head">
<div class="company">
<h2 id="pCompany">The Computer Service Center</h2>
<p id="pAddress">Aluva, Ernakulam, Kerala - 683101</p>
<p id="pPhone"></p>
</div>
<div>
<div class="receipt-title">SERVICE RECEIPT / JOB CARD</div>
<div class="meta">
Receipt No.: <b id="pJobNo">—</b><br>
Date: <b id="pDate">—</b><br>
Time: <b id="pReceiptTime">—</b>
</div>
</div>
</div>
<div class="section">
<div class="section-head">CUSTOMER / RECEIVED FROM</div>
<div class="section-body info-grid">
<div class="info-row"><b>Customer Name</b><span id="pCustomer">—</span></div>
<div class="info-row"><b>Received From</b><span id="pReceived">—</span></div>
<div class="info-row"><b>Address</b><span id="pCustomerAddress">—</span></div>
<div class="info-row"><b>Phone</b><span id="pCustomerPhone">—</span></div>
</div>
</div>
<div class="section">
<div class="section-head">ITEM RECEIVED</div>
<div class="section-body info-grid three">
<div class="info-row"><b>Item</b><span id="pItem">—</span></div>
<div class="info-row"><b>Brand</b><span id="pBrand">—</span></div>
<div class="info-row"><b>Model</b><span id="pModel">—</span></div>
<div class="info-row"><b>Serial No.</b><span id="pSerial">—</span></div>
<div class="info-row"><b>Start</b><span id="pStart">—</span></div>
<div class="info-row"><b>Completed</b><span id="pEnd">—</span></div>
</div>
</div>
<div class="section">
<div class="section-head">CUSTOMER COMPLAINT</div>
<div class="section-body" id="pComplaint">—</div>
</div>
<div class="section">
<div class="section-head">SERVICE / WORK DONE</div>
<div class="section-body" id="pWork">—</div>
</div>
<div class="section software-section">
<div class="section-head">SOFTWARE INSTALLED / CONFIGURED</div>
<div class="section-body">
<table class="bill-table" id="softwareOutput">
<thead><tr><th>Sl.</th><th>Software Name</th><th>Version</th><th>Remarks</th></tr></thead><tbody></tbody>
</table>
</div>
</div>
<div class="section">
<div class="section-head">CHANGED / PURCHASED PARTS & ITEMS</div>
<div class="section-body">
<table class="bill-table" id="partsOutput">
<thead><tr><th>Sl.</th><th>Vendor</th><th>Date</th><th>Item</th><th>Brand</th><th>Model</th><th>Serial / Part No.</th><th>Qty</th><th>Amount</th><th>Total</th></tr></thead>
<tbody></tbody>
</table>
</div>
</div>
<div class="bill-bottom">
<div>
<div class="section notes-section">
<div class="section-head">NOTES / WARRANTY / REMARKS</div>
<div class="section-body" id="pNotes">—</div>
</div>
</div>
<div class="section">
<div class="section-head">PAYMENT DETAILS</div>
<div class="section-body">
<div class="amount"><span>Parts Total</span><b id="pParts">₹0.00</b></div>
<div class="amount"><span>Service Charge</span><b id="pService">₹0.00</b></div>
<div class="amount"><span>Other Charges</span><b id="pOther">₹0.00</b></div>
<div class="amount total"><span>Total Amount</span><b id="pGrand">₹0.00</b></div>
<div class="amount"><span>Amount Paid</span><b id="pPaid">₹0.00</b></div>
<div class="amount"><span>Balance</span><b id="pBalance">₹0.00</b></div>
</div>
</div>
</div>
<div class="signature">
<div class="sig">Customer Signature<br><span>Received in Good Condition</span></div>
<div><b>Thank You</b><br>For your support</div>
<div class="sig">Technician Signature<br><span id="pTechnician">Technician</span></div>
</div>
</div>
</div>
<script>
const $=id=>document.getElementById(id);
const money=n=>"₹"+Number(n||0).toLocaleString("en-IN",{minimumFractionDigits:2,maximumFractionDigits:2});
const val=id=>$(id).value||"—";
function esc(v){return String(v??"").replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">")}
function addSoftware(d={}){
const tr=document.createElement("tr");
tr.innerHTML=`<td><input class="sname" value="${esc(d.name||"")}"></td><td><input class="sversion" value="${esc(d.version||"")}"></td><td><input class="sremarks" value="${esc(d.remarks||"")}"></td><td><button type="button" class="remove" onclick="this.closest('tr').remove();render()">×</button></td>`;
$("softwareInput").querySelector("tbody").appendChild(tr);render();
}
function addPart(d={}){
const tr=document.createElement("tr");
tr.innerHTML=`<td><input class="pname" value="${esc(d.name||"")}"></td>
<td><input class="pbrand" value="${esc(d.brand||"")}"></td>
<td><input class="pmodel" value="${esc(d.model||"")}"></td>
<td><input class="pserial" value="${esc(d.serial||"")}"></td>
<td><input class="pqty" type="number" min="0" value="${d.qty||1}" oninput="calculate()"></td>
<td><input class="pamount" type="number" min="0" step="0.01" value="${d.amount||0}" oninput="calculate()"></td>
<td class="ptotal">₹0.00</td><td><button type="button" class="remove" onclick="this.closest('tr').remove();calculate()">×</button></td>`;
$("partsInput").querySelector("tbody").appendChild(tr);calculate();
}
function getParts(){
return [...$("partsInput").querySelectorAll("tbody tr")].map(tr=>({
name:tr.querySelector(".pname").value,brand:tr.querySelector(".pbrand").value,
model:tr.querySelector(".pmodel").value,serial:tr.querySelector(".pserial").value,
qty:tr.querySelector(".pqty").value,amount:tr.querySelector(".pamount").value,
total:(Number(tr.querySelector(".pqty").value)||0)*(Number(tr.querySelector(".pamount").value)||0)
}));
}
function getSoftware(){
return [...$("softwareInput").querySelectorAll("tbody tr")].map(tr=>({
name:tr.querySelector(".sname").value,version:tr.querySelector(".sversion").value,remarks:tr.querySelector(".sremarks").value
}));
}
function getData(){
const ids=["companyName","companyAddress","companyPhone","jobNo","date","receiptTime","customerName","receivedFrom","customerPhone","customerAddress","itemReceived","itemBrand","itemModel","itemSerial","startTime","endTime","complaint","workDone","vendorName","purchaseDate","vendorAddress","serviceCharge","otherCharge","paid","notes"];
const d={};ids.forEach(i=>d[i]=$(i).value);d.parts=getParts();d.software=getSoftware();return d;
}
function calculate(){
let parts=0;
document.querySelectorAll("#partsInput tbody tr").forEach(tr=>{
const t=(Number(tr.querySelector(".pqty").value)||0)*(Number(tr.querySelector(".pamount").value)||0);
parts+=t;tr.querySelector(".ptotal").textContent=money(t);
});
const service=Number($("serviceCharge").value)||0,other=Number($("otherCharge").value)||0,paid=Number($("paid").value)||0;
$("pParts").textContent=money(parts);$("pService").textContent=money(service);$("pOther").textContent=money(other);
$("pGrand").textContent=money(parts+service+other);$("pPaid").textContent=money(paid);$("pBalance").textContent=money(Math.max(parts+service+other-paid,0));
render();
}
function render(){
const d=getData();
$("pCompany").textContent=d.companyName||"—";$("pAddress").textContent=d.companyAddress||"—";$("pPhone").textContent=d.companyPhone?"Phone: "+d.companyPhone:"";
$("pJobNo").textContent=d.jobNo||"—";$("pDate").textContent=d.date||"—";$("pReceiptTime").textContent=d.receiptTime||"—";
$("pCustomer").textContent=d.customerName||"—";$("pReceived").textContent=d.receivedFrom||"—";$("pCustomerAddress").textContent=d.customerAddress||"—";$("pCustomerPhone").textContent=d.customerPhone||"—";
$("pItem").textContent=d.itemReceived||"—";$("pBrand").textContent=d.itemBrand||"—";$("pModel").textContent=d.itemModel||"—";$("pSerial").textContent=d.itemSerial||"—";$("pStart").textContent=d.startTime||"—";$("pEnd").textContent=d.endTime||"—";
$("pComplaint").textContent=d.complaint||"—";$("pWork").textContent=d.workDone||"—";$("pNotes").textContent=d.notes||"—";
const so=$("softwareOutput").querySelector("tbody");so.innerHTML="";d.software.forEach((x,i)=>so.innerHTML+=`<tr><td>${i+1}</td><td>${esc(x.name)}</td><td>${esc(x.version)}</td><td>${esc(x.remarks)}</td></tr>`);
const po=$("partsOutput").querySelector("tbody");po.innerHTML="";d.parts.forEach((x,i)=>po.innerHTML+=`<tr><td>${i+1}</td><td>${esc(d.vendorName)}</td><td>${esc(d.purchaseDate)}</td><td>${esc(x.name)}</td><td>${esc(x.brand)}</td><td>${esc(x.model)}</td><td>${esc(x.serial)}</td><td>${esc(x.qty)}</td><td>${money(x.amount)}</td><td>${money(x.total)}</td></tr>`);
}
function saveData(){localStorage.setItem("computerServiceJobV3",JSON.stringify(getData()));alert("Job card saved in this browser.");}
function loadData(){
const raw=localStorage.getItem("computerServiceJobV3");if(!raw)return;
try{const d=JSON.parse(raw);Object.keys(d).forEach(k=>{if(!["parts","software"].includes(k)&&$(k))$(k).value=d[k]||""});
$("partsInput").querySelector("tbody").innerHTML="";$("softwareInput").querySelector("tbody").innerHTML="";
(d.parts||[]).forEach(addPart);(d.software||[]).forEach(addSoftware);calculate();
}catch(e){}
}
function exportExcel(){
const d=getData(),rows=[];
rows.push(["COMPUTER SERVICE RECEIPT / JOB CARD"]);
rows.push(["Company",d.companyName,"Address",d.companyAddress,"Phone",d.companyPhone]);
rows.push(["Receipt No.",d.jobNo,"Date",d.date,"Receipt Time",d.receiptTime]);
rows.push(["Customer",d.customerName,"Received From",d.receivedFrom,"Phone",d.customerPhone]);
rows.push(["Customer Address",d.customerAddress]);
rows.push(["Item",d.itemReceived,"Brand",d.itemBrand,"Model",d.itemModel,"Serial",d.itemSerial]);
rows.push(["Service Start",d.startTime,"Service Completed",d.endTime]);
rows.push(["Complaint",d.complaint]);rows.push(["Work Done",d.workDone]);rows.push([]);
rows.push(["SOFTWARE INSTALLED"]);rows.push(["Software","Version","Remarks"]);d.software.forEach(x=>rows.push([x.name,x.version,x.remarks]));rows.push([]);
rows.push(["PARTS / ITEMS PURCHASED OR REPLACED"]);rows.push(["Vendor",d.vendorName,"Purchase Date",d.purchaseDate,"Vendor Address",d.vendorAddress]);
rows.push(["Item","Brand","Model","Serial / Part No.","Qty","Amount","Total"]);d.parts.forEach(x=>rows.push([x.name,x.brand,x.model,x.serial,x.qty,x.amount,x.total]));
const pt=d.parts.reduce((s,x)=>s+Number(x.total||0),0),grand=pt+Number(d.serviceCharge||0)+Number(d.otherCharge||0);
rows.push([]);rows.push(["PAYMENT"]);rows.push(["Parts Total",pt],["Service Charge",d.serviceCharge],["Other Charges",d.otherCharge],["Grand Total",grand],["Amount Paid",d.paid],["Balance",Math.max(grand-Number(d.paid||0),0)]);
rows.push(["Notes",d.notes]);
const csv="\ufeff"+rows.map(r=>r.map(x=>`"${String(x??"").replace(/"/g,'""')}"`).join(",")).join("\r\n");
const a=document.createElement("a"),url=URL.createObjectURL(new Blob([csv],{type:"text/csv;charset=utf-8"}));
a.href=url;a.download=(d.jobNo||"service_receipt")+".csv";a.click();URL.revokeObjectURL(url);
}
function parseCSV(text){
const rows=[];let row=[],cell="",quoted=false;
for(let i=0;i<text.length;i++){
const c=text[i],n=text[i+1];
if(c=='"' && quoted && n=='"'){cell+='"';i++;continue}
if(c=='"'){quoted=!quoted;continue}
if(c==',' && !quoted){row.push(cell);cell="";continue}
if((c=='\n'||c=='\r') && !quoted){
if(c=='\r' && n=='\n')i++;
row.push(cell);cell="";
if(row.some(v=>v!==""))rows.push(row);
row=[];continue;
}
cell+=c;
}
if(cell!==""||row.length){row.push(cell);if(row.some(v=>v!==""))rows.push(row)}
return rows;
}
function importExcel(event){
const file=event.target.files[0];
if(!file)return;
const name=file.name.toLowerCase();
if(name.endsWith(".xlsx")||name.endsWith(".xls")){
alert("The current Export Excel button creates an Excel-compatible CSV file. Please import that exported .csv file. XLSX/XLS direct import can be added with an Excel library if required.");
event.target.value="";return;
}
const reader=new FileReader();
reader.onload=function(e){
try{
const rows=parseCSV(e.target.result.replace(/^\uFEFF/,""));
importRows(rows);
alert("Job card data imported successfully.");
}catch(err){
console.error(err);
alert("Could not import this file. Please select a CSV file exported from this Job Card.");
}
event.target.value="";
};
reader.readAsText(file,"UTF-8");
}
function importRows(rows){
const findValue=(label)=>{
for(const r of rows){
for(let i=0;i<r.length;i++){
if(String(r[i]).trim().toLowerCase()===label.toLowerCase()) return r[i+1]??"";
}
}
return "";
};
const set=(id,label)=>{
if($(id)) $(id).value=findValue(label);
};
set("companyName","Company");
set("companyAddress","Address");
set("companyPhone","Phone");
set("jobNo","Receipt No.");
set("date","Date");
set("receiptTime","Receipt Time");
set("customerName","Customer");
set("receivedFrom","Received From");
set("customerPhone","Phone");
set("customerAddress","Customer Address");
set("itemReceived","Item");
set("itemBrand","Brand");
set("itemModel","Model");
set("itemSerial","Serial");
set("startTime","Service Start");
set("endTime","Service Completed");
set("complaint","Complaint");
set("workDone","Work Done");
set("vendorName","Vendor");
set("purchaseDate","Purchase Date");
set("vendorAddress","Vendor Address");
set("notes","Notes");
set("serviceCharge","Service Charge");
set("otherCharge","Other Charges");
set("paid","Amount Paid");
// Locate the software section and rebuild it.
$("softwareInput").querySelector("tbody").innerHTML="";
let softwareHeader=-1;
for(let i=0;i<rows.length;i++){
if(String(rows[i][0]).trim().toUpperCase()==="SOFTWARE INSTALLED"){softwareHeader=i;break}
}
if(softwareHeader>=0){
for(let i=softwareHeader+2;i<rows.length;i++){
const r=rows[i];
if(!r.length || String(r[0]).trim().toUpperCase()==="PARTS / ITEMS PURCHASED OR REPLACED")break;
if(r[0]||r[1]||r[2])addSoftware({name:r[0],version:r[1],remarks:r[2]});
}
}
// Locate parts table and rebuild it.
$("partsInput").querySelector("tbody").innerHTML="";
let partsHeader=-1;
for(let i=0;i<rows.length;i++){
if(String(rows[i][0]).trim().toUpperCase()==="PARTS / ITEMS PURCHASED OR REPLACED"){partsHeader=i;break}
}
if(partsHeader>=0){
let dataHeader=-1;
for(let i=partsHeader+1;i<Math.min(partsHeader+4,rows.length);i++){
if(String(rows[i][0]).trim().toLowerCase()==="item"){dataHeader=i;break}
}
if(dataHeader>=0){
for(let i=dataHeader+1;i<rows.length;i++){
const r=rows[i];
if(!r.length || String(r[0]).trim().toUpperCase()==="PAYMENT")break;
// Exported row: Item, Brand, Model, Serial / Part No., Qty, Amount, Total
if(r[0]||r[1]||r[2]||r[3]) addPart({
name:r[0],brand:r[1],model:r[2],serial:r[3],qty:r[4]||1,amount:r[5]||0
});
}
}
}
calculate();
saveData();
}
function printBill(){
document.body.classList.remove("print58","print80");
const m=$("printMode").value;if(m==="58"||m==="80")document.body.classList.add("print"+m);
window.print();setTimeout(()=>document.body.classList.remove("print58","print80"),800);
}
function newJob(){if(confirm("Clear current job and start a new one?")){localStorage.removeItem("computerServiceJobV3");location.reload()}}
document.querySelectorAll("input,textarea,select").forEach(e=>e.addEventListener("input",render));
$("date").valueAsDate=new Date();$("purchaseDate").valueAsDate=new Date();
addPart();loadData();render();calculate();
</script>
</body>
</html>