CarDentIQ / static /js /report.js
parthmax24's picture
added the latest updates
81b4246
Raw
History Blame Contribute Delete
5.06 kB
// Developer: Saksham Pathak (github.com/parthmax2)
const emptyState = document.getElementById("emptyState");
const reportContainer = document.getElementById("reportContainer");
const severityBanner = document.getElementById("severityBanner");
const severityPill = document.getElementById("severityPill");
const severityFilename = document.getElementById("severityFilename");
const statDefects = document.getElementById("statDefects");
const statTypes = document.getElementById("statTypes");
const statScore = document.getElementById("statScore");
const findingsEl = document.getElementById("findings");
const outputImage = document.getElementById("outputImage");
const imageMetaEl = document.getElementById("imageMeta");
const detectionsListEl = document.getElementById("detectionsList");
const resultsTableBody = document.querySelector("#resultsTable tbody");
const downloadCsvBtn = document.getElementById("downloadCsv");
const downloadTxtBtn = document.getElementById("downloadTxt");
const scanAnotherBtn = document.getElementById("scanAnotherBtn");
const SEVERITY_CLASS = {
"No Damage Detected": "none",
"Minor": "minor",
"Moderate": "moderate",
"Severe": "severe",
};
function formatBytes(bytes) {
if (bytes < 1024) return `${bytes} B`;
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)} KB`;
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
}
function downloadText(filename, text) {
const blob = new Blob([text], { type: "text/plain" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = filename;
a.click();
URL.revokeObjectURL(url);
}
function renderSummary(summary) {
severityPill.textContent = summary.severity_label;
severityPill.className = `severity-pill ${SEVERITY_CLASS[summary.severity_label] || "none"}`;
severityBanner.className = `severity-banner glass-card ${SEVERITY_CLASS[summary.severity_label] || "none"}`;
statDefects.textContent = summary.total_defects;
statTypes.textContent = summary.by_class.length;
statScore.textContent = summary.severity_score;
if (summary.by_class.length === 0) {
findingsEl.innerHTML = `<p class="empty-note">No damage detected above the current confidence thresholds.</p>`;
return;
}
findingsEl.innerHTML = summary.by_class.map((c) => `
<div class="finding-chip">
<span class="swatch" style="background: rgb(${c.color.join(",")})"></span>
<span class="count">${c.count}</span>
<span>${c.class_name}</span>
</div>
`).join("");
}
function renderDetections(detections, classColorById) {
const issues = detections
.filter((d) => d.class_id !== 0)
.sort((a, b) => b.confidence - a.confidence);
if (issues.length === 0) {
detectionsListEl.innerHTML = `<p class="empty-note">No damage detected above the current confidence thresholds.</p>`;
return;
}
detectionsListEl.innerHTML = issues.map((d) => {
const color = classColorById[d.class_id] || [102, 112, 133];
const pct = Math.round(d.confidence * 100);
return `
<div class="detection-item">
<span class="swatch" style="background: rgb(${color.join(",")})"></span>
<span class="detection-name">${d.class_name}</span>
<div class="confidence-track">
<div class="confidence-fill" style="width: ${pct}%; background: rgb(${color.join(",")})"></div>
</div>
<span class="confidence-value mono">${pct}%</span>
</div>
`;
}).join("");
}
async function render() {
const raw = sessionStorage.getItem("cardentiq_result");
if (!raw) {
emptyState.hidden = false;
return;
}
let data;
try {
data = JSON.parse(raw);
} catch {
emptyState.hidden = false;
return;
}
reportContainer.hidden = false;
let classColorById = {};
try {
const res = await fetch("/api/classes");
const classData = await res.json();
classColorById = Object.fromEntries(classData.classes.map((c) => [c.id, c.color]));
} catch {
// fall back to default colors already handled per-item
}
severityFilename.textContent = data.image_info?.filename || "";
outputImage.src = data.annotated_image;
imageMetaEl.textContent = data.image_info
? `${data.image_info.width} × ${data.image_info.height} px · ${formatBytes(data.image_info.size_bytes)}`
: "";
renderSummary(data.summary);
renderDetections(data.detections, classColorById);
resultsTableBody.innerHTML = data.detections.map((d) => `
<tr>
<td>${d.class_name}</td>
<td>${d.confidence}</td>
<td>[${d.box_yolo.join(", ")}]</td>
</tr>
`).join("");
downloadCsvBtn.disabled = data.detections.length === 0;
downloadTxtBtn.disabled = data.detections.length === 0;
downloadCsvBtn.addEventListener("click", () => downloadText("detections.csv", data.csv));
downloadTxtBtn.addEventListener("click", () => downloadText("labels.txt", data.yolo_txt));
}
scanAnotherBtn.addEventListener("click", () => sessionStorage.removeItem("cardentiq_result"));
render();