JSFiddle - React, Tailwind, and code Playground
by velo_ninja
HTML
<div class="presentation">
<header class="header">
<div class="logo">BBM</div>
<div class="progress-info" id="progressText"></div>
</header>
<div class="progress-container">
<div class="progress-bar" id="progress"></div>
</div>
<div class="slide active">
<h1>Graduation Project Proposal</h1>
<h2>Process & Waste Optimization at BBM</h2>
<p class="meta">
Fadi Almadanat<br>
B.Sc. Industrial Engineering<br>
December 2025
</p>
</div>
<div class="slide">
<h1>Problem Definition</h1>
<ul>
<li>Ø 18–25 min/day lost per employee due to search activities</li>
<li>High inventory levels with simultaneous stockouts</li>
<li>Reactive logistics instead of data-driven planning</li>
</ul>
</div>
<div class="slide">
<h1>Methodological Framework</h1>
<ul>
<li>Lean Manufacturing (Motion & Waiting Waste)</li>
<li>Time Study & Cost–Benefit Analysis</li>
<li>ABC Analysis & Quantitative Forecasting</li>
</ul>
</div>
<div class="slide">
<h1>Case Study 1</h1>
<h2>Paternoster ROI (€/Year)</h2>
<canvas id="roiChart" width="650" height="320"></canvas>
</div>
<div class="slide">
<h1>Case Study 1 – Assumptions</h1>
<ul>
<li>15 operators × 20 min/day search time</li>
<li>Labor cost: 28 €/hour (fully burdened)</li>
<li>Annual waste cost ≈ 35,000 €</li>
<li>Paternoster investment: 85,000 €</li>
<li>Payback Period ≈ 2.4 years</li>
</ul>
</div>
<div class="slide">
<h1>Case Study 2</h1>
<h2>Inventory Cost Reduction (€/Year)</h2>
<canvas id="inventoryChart" width="650" height="320"></canvas>
</div>
<div class="slide">
<h1>Case Study 2 – Assumptions</h1>
<ul>
<li>Average inventory value: 600,000 €</li>
<li>Carrying cost rate: 18 %</li>
<li>Optimized reduction: −22 % inventory</li>
<li>Annual...
CSS
body {
margin: 0;
font-family: "Segoe UI", Arial, sans-serif;
background: #f2f4f7;
color: #1c1f23;
overflow: hidden;
}
.header {
position: absolute;
top: 10px;
left: 20px;
right: 20px;
display: flex;
justify-content: space-between;
align-items: center;
}
.logo {
font-weight: 700;
font-size: 1.4em;
color: #004b8d;
border: 2px solid #004b8d;
padding: 4px 10px;
}
.progress-container {
position: absolute;
top: 0;
height: 6px;
width: 100%;
background: #d6dbe1;
}
.progress-bar {
height: 100%;
width: 0%;
background: #004b8d;
}
.slide {
position: absolute;
inset: 0;
padding: 90px 140px;
opacity: 0;
transform: translateX(30px);
transition: all 0.45s ease;
}
.slide.active {
opacity: 1;
transform: translateX(0);
}
h1 {
font-size: 2.6em;
color: #004b8d;
}
h2 {
font-size: 1.5em;
color: #006fcf;
margin-bottom: 25px;
}
ul {
font-size: 1.3em;
line-height: 1.7;
}
.meta {
margin-top: 50px;
font-size: 1.1em;
}
.controls {
position: absolute;
bottom: 30px;
right: 40px;
}
button {
background: #004b8d;
color: #fff;
border: none;
padding: 10px 18px;
margin-left: 10px;
font-size: 1em;
border-radius: 4px;
cursor: pointer;
}
JavaScript
const slides = document.querySelectorAll(".slide");
const progress = document.getElementById("progress");
const progressText = document.getElementById("progressText");
let current = 0;
function update() {
slides.forEach((s, i) => s.classList.toggle("active", i === current));
const percent = ((current + 1) / slides.length) * 100;
progress.style.width = percent + "%";
progressText.textContent = `Slide ${current + 1} / ${slides.length}`;
if (slides[current].querySelector("#roiChart")) drawROI();
if (slides[current].querySelector("#inventoryChart")) drawInventory();
}
document.getElementById("next").onclick = () => {
if (current < slides.length - 1) current++;
update();
};
document.getElementById("prev").onclick = () => {
if (current > 0) current--;
update();
};
document.addEventListener("keydown", e => {
if (e.key === "ArrowRight") document.getElementById("next").click();
if (e.key === "ArrowLeft") document.getElementById("prev").click();
});
function animate(ctx, values, labels, color) {
let h = 0;
const max = Math.max(...values);
function draw() {
ctx.clearRect(0, 0, 650, 320);
values.forEach((v, i) => {
const bar = (v / max) * h;
ctx.fillStyle = color;
ctx.fillRect(120 + i * 220, 260 - bar, 100, bar);
ctx.fillStyle = "#000";
ctx.fillText(labels[i], 140 + i * 220, 290);
ctx.fillText(v + " €", 135 + i * 220, 245 - bar);
});
h += 4;
if (h <= 200) requestAnimationFrame(draw);
}
draw();
}
function drawROI() {
const c = document.getElementById("roiChart");
animate(c.getContext("2d"),
[35000, 59000],
["Labor Waste", "Total Savings"],
"#004b8d"
);
}
function drawInventory() {
const c = document.getElementById("inventoryChart");
animate(c.getContext("2d"),
[108000, 84000],
["Current Cost", "Optimized Cost"],
"#006fcf"
);
}
update();