Repository navigation
Expand file tree
/
Copy pathdata_visualization_carousel.html
More file actions
99 lines (84 loc) · 2.1 KB
/
Copy pathdata_visualization_carousel.html
File metadata and controls
99 lines (84 loc) · 2.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
<script>
const BASE = "https://cholobot-data-production.up.railway.app";
const ENDPOINTS = [
{ name: "weekly", url: BASE + "/weekly_target" },
{ name: "debt", url: BASE + "/debt_snowball" },
{ name: "job", url: BASE + "/job_costing" },
{ name: "estimate", url: BASE + "/estimate_actuals" },
{ name: "materials", url: BASE + "/materials_reality" },
{ name: "patterns", url: BASE + "/business_patterns" }
];
let cache = {};
let index = 0;
async function fetchData() {
for (let ep of ENDPOINTS) {
try {
const res = await fetch(ep.url);
cache[ep.name] = await res.json();
} catch {
cache[ep.name] = null;
}
}
}
function render(name) {
const el = document.getElementById("view");
const data = cache[name];
if (!data) {
el.innerText = "No data";
return;
}
// --- WEEKLY TARGET ---
if (name === "weekly") {
el.innerText =
`$${data.collected || 0} / $${data.weekly_target || 0}\n` +
`Remaining: $${data.remaining || 0}`;
}
// --- DEBT ---
else if (name === "debt") {
el.innerText =
`Debt: $${data.debt_total || 0}\n` +
`Next: $${data.next_payment_target || 0}`;
}
// --- JOB COSTING ---
else if (name === "job") {
const job = data.recent_jobs?.[0];
if (!job) {
el.innerText = "No jobs yet";
return;
}
el.innerText =
`${job.job_name}\n` +
`Profit: $${job.profit}`;
}
// --- ESTIMATE ---
else if (name === "estimate") {
const e = data.estimate_actuals?.[0];
if (!e) {
el.innerText = "No estimate data";
return;
}
el.innerText =
`${e.job_type}\n` +
`$${e.avg_charged_per_unit}/${e.unit}`;
}
// --- MATERIALS ---
else if (name === "materials") {
el.innerText =
`Used: ${data.recent_items?.length || 0} items`;
}
// --- PATTERNS ---
else if (name === "patterns") {
const p = data.top_patterns?.[0];
el.innerText =
p ? p : "No patterns yet";
}
}
async function loop() {
await fetchData();
const name = ENDPOINTS[index % ENDPOINTS.length].name;
render(name);
index++;
}
loop();
setInterval(loop, 5000);
</script>