Uh, I completed two pathology lesson and two microbiology lesson. Totally, I have around 57-- uh, 54 to 55 lessons in total. So, in pathology, today, I thought I will complete around the small, small lessons, around seven I have. I will complete all those seven today. And I'm planning to complete pathology pa-- full paper, like paper one and paper two by, uh, July 17, so that I will have ample time for revision. And, uh, I thought of completing pathology and microbiology paper one before July 17. And after that, before 26th of July, I should complete all lessons. Is that reasonable? Can I complete it? Is that a good plan?
Create a visual study timeline tracker for your goals
ls /home/daytona/workspace/ 2>/dev/null || mkdir -p /home/daytona/workspace/stud…
mkdir -p /home/daytona/workspace/study-tracker
~/study-tracker/timeline.js
const pptxgen = require("pptxgenjs");
const pres = new pptxgen();
pres.layout = "LAYOUT_WIDE"; // 13.3" x 7.5"
// ─── Palette ───────────────────────────────────────────────────────────────
const BG = "0D1B2A"; // deep navy
const CARD = "162032"; // slightly lighter navy for cards
const ACCENT1 = "F4A261"; // warm orange – Pathology
const ACCENT2 = "2EC4B6"; // teal – Microbiology
const ACCENT3 = "E94560"; // coral-red – deadline marker
const WHITE = "FFFFFF";
const MUTED = "8899AA";
const GREEN = "06D6A0"; // progress fill
const YELLOW = "FFD166"; // milestone star
// ─── Helper: rounded rect shorthand ───────────────────────────────────────
function card(slide, x, y, w, h, color, rounding = 0.08) {
slide.addShape(pres.ShapeType.roundRect, {
x, y, w, h,
fill: { color },
line: { color, width: 0 },
rectRadius: rounding,
});
}
function pill(slide, x, y, w, h, color) {
slide.addShape(pres.ShapeType.roundRect, {
x, y, w, h,
fill: { color },
line: { color, width: 0 },
rectRadius: 0.15,
});
}
// ─── SLIDE 1 – OVERVIEW DASHBOARD ─────────────────────────────────────────
{
const s = pres.addSlide();
// Background
s.addShape(pres.ShapeType.rect, { x:0, y:0, w:13.3, h:7.5, fill:{ color:BG }, line:{ color:BG } });
// Top bar
s.addShape(pres.ShapeType.rect, { x:0, y:0, w:13.3, h:0.85, fill:{ color:"0A1520" }, line:{ color:"0A1520" } });
s.addText("📚 STUDY TIMELINE TRACKER", {
x:0.4, y:0.1, w:7, h:0.6,
fontSize:22, bold:true, color:WHITE, fontFace:"Calibri", margin:0
});
s.addText("July 13 – July 26, 2026", {
x:9.8, y:0.18, w:3.1, h:0.45,
fontSize:13, color:MUTED, fontFace:"Calibri", align:"right", margin:0
});
// ── Stat cards row ──────────────────────────────────────────────────────
const stats = [
{ label:"Total Lessons", value:"54–55", sub:"entire course", col: ACCENT1 },
{ label:"Completed", value:"4", sub:"2 Path + 2 Micro", col: GREEN },
{ label:"Remaining", value:"~51", sub:"lessons to go", col: ACCENT2 },
{ label:"Days Left", value:"13", sub:"until July 26", col: ACCENT3 },
];
stats.forEach((st, i) => {
const x = 0.35 + i * 3.15;
card(s, x, 1.05, 2.9, 1.6, CARD);
// left accent bar
s.addShape(pres.ShapeType.rect, { x, y:1.05, w:0.06, h:1.6, fill:{ color:st.col }, line:{ color:st.col } });
s.addText(st.value, {
x: x+0.2, y:1.12, w:2.65, h:0.75,
fontSize:34, bold:true, color:st.col, fontFace:"Calibri", margin:0
});
s.addText(st.label, {
x: x+0.2, y:1.85, w:2.65, h:0.3,
fontSize:11, bold:true, color:WHITE, fontFace:"Calibri", margin:0
});
s.addText(st.sub, {
x: x+0.2, y:2.12, w:2.65, h:0.3,
fontSize:9, color:MUTED, fontFace:"Calibri", margin:0
});
});
// ── Progress bar – overall ──────────────────────────────────────────────
card(s, 0.35, 3.0, 12.6, 0.85, CARD);
s.addText("OVERALL PROGRESS", {
x:0.6, y:3.08, w:4, h:0.3,
fontSize:10, bold:true, color:MUTED, fontFace:"Calibri", charSpacing:2, margin:0
});
// track
s.addShape(pres.ShapeType.roundRect, { x:0.6, y:3.47, w:12.1, h:0.25, fill:{ color:"253345" }, line:{ color:"253345" }, rectRadius:0.05 });
// fill 4/54 ≈ 7.4%
const fillW = 12.1 * (4/54);
s.addShape(pres.ShapeType.roundRect, { x:0.6, y:3.47, w:fillW, h:0.25, fill:{ color:GREEN }, line:{ color:GREEN }, rectRadius:0.05 });
s.addText("7% complete (4 of 54 lessons)", {
x:0.6, y:3.74, w:12.1, h:0.25,
fontSize:9, color:MUTED, fontFace:"Calibri", margin:0
});
// ── Phase breakdown ────────────────────────────────────────────────────
// Phase boxes
const phases = [
{
title:"PHASE 1 – INTENSIVE",
date:"Jul 13 – 17",
color:ACCENT1,
goals:[
"✅ 2 Pathology done",
"🎯 7 small Pathology lessons (today)",
"📖 Pathology Paper 1 complete",
"📖 Pathology Paper 2 complete",
"📖 Microbiology Paper 1 complete",
],
x: 0.35, w: 5.95
},
{
title:"PHASE 2 – COMPLETION",
date:"Jul 18 – 26",
color:ACCENT2,
goals:[
"📖 Microbiology Paper 2",
"📖 All remaining subjects",
"🏁 All 54–55 lessons done",
"🔄 Buffer: 2–3 days spare",
"",
],
x: 6.7, w: 5.95
}
];
phases.forEach(ph => {
card(s, ph.x, 4.05, ph.w, 3.1, CARD);
// header stripe
s.addShape(pres.ShapeType.rect, { x:ph.x, y:4.05, w:ph.w, h:0.55, fill:{ color:ph.color+"33" }, line:{ color:ph.color+"33" } });
s.addText(ph.title, {
x:ph.x+0.2, y:4.1, w:ph.w-1.2, h:0.42,
fontSize:12, bold:true, color:ph.color, fontFace:"Calibri", margin:0
});
s.addText(ph.date, {
x:ph.x+ph.w-1.4, y:4.1, w:1.2, h:0.42,
fontSize:10, bold:true, color:WHITE, fontFace:"Calibri", align:"right", margin:0
});
ph.goals.forEach((g, i) => {
s.addText(g, {
x:ph.x+0.25, y:4.75+i*0.44, w:ph.w-0.4, h:0.38,
fontSize:11, color:g.startsWith("✅") ? GREEN : WHITE,
fontFace:"Calibri", margin:0
});
});
});
// Deadline badge
card(s, 6.05, 4.05, 0.6, 3.1, ACCENT3+"22");
s.addText("D\nE\nA\nD\nL\nI\nN\nE", {
x:6.05, y:4.2, w:0.6, h:2.8,
fontSize:8, bold:true, color:ACCENT3, fontFace:"Calibri", align:"center", margin:0
});
}
// ─── SLIDE 2 – GANTT / DAY-BY-DAY TIMELINE ────────────────────────────────
{
const s = pres.addSlide();
s.addShape(pres.ShapeType.rect, { x:0, y:0, w:13.3, h:7.5, fill:{ color:BG }, line:{ color:BG } });
// Header
s.addShape(pres.ShapeType.rect, { x:0, y:0, w:13.3, h:0.85, fill:{ color:"0A1520" }, line:{ color:"0A1520" } });
s.addText("📅 DAY-BY-DAY GANTT TIMELINE", {
x:0.4, y:0.15, w:8, h:0.55,
fontSize:20, bold:true, color:WHITE, fontFace:"Calibri", margin:0
});
s.addText("Jul 13 → Jul 26, 2026", {
x:9.8, y:0.2, w:3.1, h:0.42,
fontSize:13, color:MUTED, fontFace:"Calibri", align:"right", margin:0
});
// Day columns: Jul 13-26 = 14 days
const days = [];
const dayNames = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"];
// Jul 13, 2026 is a Sunday (day 0 = index 0)
// Jul 13 = Sunday
const startDow = 0; // Sunday
for (let d = 0; d < 14; d++) {
const date = 13 + d;
const dow = (startDow + d) % 7;
days.push({ date: `Jul ${date}`, day: dayNames[dow] });
}
const colW = (13.3 - 1.2) / 14; // ~0.864 per day
const startX = 0.6;
const headerY = 1.0;
const rowH = 0.72;
// Day header cells
days.forEach((d, i) => {
const x = startX + i * colW;
const isWeekend = (d.day === "Sat" || d.day === "Sun");
const isToday = i === 0; // Jul 13
const isDeadline1 = i === 4; // Jul 17
const isDeadline2 = i === 13; // Jul 26
// cell background
s.addShape(pres.ShapeType.roundRect, {
x, y: headerY, w: colW - 0.04, h: 0.7,
fill: { color: isToday ? ACCENT1+"55" : isDeadline1 ? ACCENT3+"55" : isDeadline2 ? ACCENT3+"55" : isWeekend ? "1E2E3E" : "1A2A3A" },
line: { color: isToday ? ACCENT1 : isDeadline1||isDeadline2 ? ACCENT3 : "253345", width: isToday||isDeadline1||isDeadline2 ? 1.5 : 0.5 },
rectRadius: 0.04,
});
s.addText(d.day, {
x, y: headerY + 0.04, w: colW - 0.04, h: 0.28,
fontSize: 8, bold: true,
color: isToday ? ACCENT1 : isDeadline1||isDeadline2 ? ACCENT3 : isWeekend ? MUTED : WHITE,
fontFace:"Calibri", align:"center", margin:0
});
s.addText(d.date.replace("Jul ",""), {
x, y: headerY + 0.33, w: colW - 0.04, h: 0.3,
fontSize: 10, bold: true,
color: isToday ? ACCENT1 : isDeadline1||isDeadline2 ? ACCENT3 : WHITE,
fontFace:"Calibri", align:"center", margin:0
});
});
// Subject rows ──────────────────────────────────────────────────────────
const subjects = [
{
label:"Pathology P1",
color: ACCENT1,
start: 0, // Jul 13
end: 3, // Jul 16 (spans 4 days, target done by Jul 17)
done: true,
note: "Target: Jul 17"
},
{
label:"Pathology P2",
color: ACCENT1+"BB",
start: 1,
end: 4, // Jul 17
done: false,
note: "Target: Jul 17"
},
{
label:"Microbiology P1",
color: ACCENT2,
start: 1,
end: 4, // Jul 17
done: false,
note: "Target: Jul 17"
},
{
label:"Microbiology P2",
color: ACCENT2+"BB",
start: 5,
end: 11, // Jul 18-24
done: false,
note: "Target: Jul 25"
},
{
label:"All Remaining",
color: YELLOW,
start: 5,
end: 12, // Jul 18-25
done: false,
note: "Final push"
},
];
subjects.forEach((sub, ri) => {
const y = headerY + 0.75 + ri * (rowH + 0.08);
// Row label
card(s, 0, y, 0.58, rowH - 0.02, CARD);
s.addText(sub.label, {
x: 0.02, y, w: 0.56, h: rowH - 0.02,
fontSize: 7.5, bold: true, color: sub.color,
fontFace: "Calibri", align: "center", valign: "middle", margin: 0, wrap: true
});
// Empty cells
days.forEach((_, i) => {
const x = startX + i * colW;
s.addShape(pres.ShapeType.roundRect, {
x, y, w: colW - 0.04, h: rowH - 0.02,
fill: { color: "162032" },
line: { color: "253345", width: 0.5 },
rectRadius: 0.03,
});
});
// Gantt bar
const barX = startX + sub.start * colW + 0.04;
const barW = (sub.end - sub.start + 1) * colW - 0.1;
s.addShape(pres.ShapeType.roundRect, {
x: barX, y: y + 0.12, w: barW, h: rowH - 0.28,
fill: { color: sub.color },
line: { color: sub.color, width: 0 },
rectRadius: 0.06,
});
s.addText(sub.note, {
x: barX + 0.05, y: y + 0.12, w: barW - 0.08, h: rowH - 0.28,
fontSize: 8, bold: true, color: "0D1B2A",
fontFace: "Calibri", align: "center", valign: "middle", margin: 0
});
});
// Milestone markers ─────────────────────────────────────────────────────
const milestones = [
{ day: 0, label: "TODAY\nStart" },
{ day: 4, label: "🎯 Jul 17\nDeadline 1" },
{ day: 13, label: "🏁 Jul 26\nAll Done!" },
];
milestones.forEach(m => {
const x = startX + m.day * colW + (colW - 0.04)/2 - 0.01;
// vertical line
s.addShape(pres.ShapeType.line, {
x, y: 1.72, w: 0, h: 5.4,
line: { color: m.day === 0 ? ACCENT1 : ACCENT3, width: 1.5, dashType: "dash" }
});
// label at bottom
s.addText(m.label, {
x: x - 0.35, y: 7.0, w: 0.72, h: 0.45,
fontSize: 7, bold: true,
color: m.day === 0 ? ACCENT1 : ACCENT3,
fontFace:"Calibri", align:"center", margin:0
});
});
// Legend
const legend = [
{ color: ACCENT1, label: "Pathology" },
{ color: ACCENT2, label: "Microbiology" },
{ color: YELLOW, label: "All Remaining" },
{ color: ACCENT3, label: "Deadline" },
{ color: GREEN, label: "Completed" },
];
legend.forEach((l, i) => {
const lx = 0.5 + i * 2.5;
pill(s, lx, 6.82, 0.22, 0.22, l.color);
s.addText(l.label, {
x: lx + 0.27, y: 6.82, w: 2.0, h: 0.22,
fontSize: 9, color: WHITE, fontFace:"Calibri", margin:0
});
});
}
// ─── SLIDE 3 – DAILY TARGET TRACKER ───────────────────────────────────────
{
const s = pres.addSlide();
s.addShape(pres.ShapeType.rect, { x:0, y:0, w:13.3, h:7.5, fill:{ color:BG }, line:{ color:BG } });
// Header
s.addShape(pres.ShapeType.rect, { x:0, y:0, w:13.3, h:0.85, fill:{ color:"0A1520" }, line:{ color:"0A1520" } });
s.addText("🎯 DAILY LESSON TARGET TRACKER", {
x:0.4, y:0.15, w:8, h:0.55,
fontSize:20, bold:true, color:WHITE, fontFace:"Calibri", margin:0
});
s.addText("Fill in checkboxes as you complete lessons each day", {
x:6, y:0.22, w:6.9, h:0.42,
fontSize:11, color:MUTED, fontFace:"Calibri", align:"right", margin:0
});
// Daily plan table ──────────────────────────────────────────────────────
// Phase 1: Jul 13-17 (5 days) Phase 2: Jul 18-26 (9 days)
const phase1Days = [
{ date:"Jul 13 (Mon)", target:7, subject:"Pathology – 7 small lessons", color:ACCENT1 },
{ date:"Jul 14 (Tue)", target:6, subject:"Pathology Paper 1 cont.", color:ACCENT1 },
{ date:"Jul 15 (Wed)", target:6, subject:"Pathology Paper 2 start", color:ACCENT1+"BB" },
{ date:"Jul 16 (Thu)", target:6, subject:"Pathology P2 + Micro P1 start", color:ACCENT2 },
{ date:"Jul 17 (Fri)", target:5, subject:"🎯 DEADLINE – Finish Path + Micro P1", color:ACCENT3 },
];
const phase2Days = [
{ date:"Jul 18 (Sat)", target:5, subject:"Microbiology P2 start", color:ACCENT2 },
{ date:"Jul 19 (Sun)", target:5, subject:"Microbiology P2 cont.", color:ACCENT2 },
{ date:"Jul 20 (Mon)", target:5, subject:"Remaining subjects", color:YELLOW },
{ date:"Jul 21 (Tue)", target:4, subject:"Remaining subjects", color:YELLOW },
{ date:"Jul 22 (Wed)", target:4, subject:"Remaining subjects", color:YELLOW },
{ date:"Jul 23 (Thu)", target:4, subject:"Remaining subjects", color:YELLOW },
{ date:"Jul 24 (Fri)", target:4, subject:"Remaining subjects", color:YELLOW },
{ date:"Jul 25 (Sat)", target:3, subject:"Final lessons + buffer", color:GREEN },
{ date:"Jul 26 (Sun)", target:0, subject:"🏁 ALL LESSONS COMPLETE – Begin Revision", color:GREEN },
];
// Column headers
const cols = [
{ label:"DATE", x:0.3, w:1.8 },
{ label:"SUBJECT FOCUS", x:2.15, w:4.0 },
{ label:"TARGET", x:6.2, w:1.0 },
{ label:"DONE", x:7.25, w:0.8 },
{ label:"LESSONS COMPLETED (check off)", x:8.1, w:4.9 },
];
// header row
cols.forEach(c => {
s.addText(c.label, {
x:c.x, y:1.0, w:c.w, h:0.32,
fontSize:9, bold:true, color:MUTED, fontFace:"Calibri",
charSpacing:1.5, margin:0
});
});
// divider
s.addShape(pres.ShapeType.line, { x:0.3, y:1.33, w:12.9, h:0, line:{ color:"253345", width:1 } });
const allDays = [...phase1Days, ...phase2Days];
const rowH2 = 0.43;
allDays.forEach((row, i) => {
const y = 1.38 + i * rowH2;
const isPhase1 = i < 5;
const isLast = i === allDays.length - 1;
// Row background (alternate)
if (i % 2 === 0) {
s.addShape(pres.ShapeType.rect, { x:0.3, y, w:12.9, h:rowH2 - 0.03, fill:{ color:"152030" }, line:{ color:"152030" } });
}
// Phase separator label
if (i === 0 || i === 5) {
const phLabel = i === 0 ? "◀ PHASE 1 ▶" : "◀ PHASE 2 ▶";
const phColor = i === 0 ? ACCENT1 : ACCENT2;
pill(s, 0.3, y + 0.04, 1.05, 0.32, phColor + "33");
s.addText(phLabel, { x:0.3, y:y+0.06, w:1.05, h:0.28, fontSize:7, bold:true, color:phColor, fontFace:"Calibri", align:"center", margin:0 });
}
// Date
s.addText(row.date, {
x:0.3, y:y+0.06, w:1.8, h:0.3,
fontSize: row.color === ACCENT3 ? 10 : 9,
bold: row.color === ACCENT3,
color: row.color === ACCENT3 ? ACCENT3 : row.color === GREEN ? GREEN : WHITE,
fontFace:"Calibri", margin:0
});
// Subject
s.addText(row.subject, {
x:2.15, y:y+0.06, w:4.0, h:0.3,
fontSize:9, color:WHITE, fontFace:"Calibri", margin:0
});
// Target count pill
if (row.target > 0) {
pill(s, 6.2, y+0.07, 0.55, 0.27, row.color + "44");
s.addText(`${row.target}`, {
x:6.2, y:y+0.07, w:0.55, h:0.27,
fontSize:11, bold:true, color:row.color, fontFace:"Calibri", align:"center", margin:0
});
}
// Done checkbox area (empty square to tick manually)
s.addShape(pres.ShapeType.roundRect, {
x:7.35, y:y+0.08, w:0.28, h:0.27,
fill:{ color:"0D1B2A" },
line:{ color: i === 0 ? GREEN : MUTED, width: i === 0 ? 2 : 1 },
rectRadius: 0.03,
});
// tick for day 0 (already started)
if (i === 0) {
s.addText("✓", { x:7.35, y:y+0.07, w:0.28, h:0.28, fontSize:12, bold:true, color:GREEN, fontFace:"Calibri", align:"center", margin:0 });
}
// Lesson tick boxes (6 small boxes for manual fill)
const boxCount = row.target > 0 ? Math.min(row.target, 8) : 0;
for (let b = 0; b < boxCount; b++) {
s.addShape(pres.ShapeType.roundRect, {
x: 8.1 + b * 0.56, y: y + 0.09, w: 0.42, h: 0.24,
fill:{ color: b < 2 && i === 0 ? GREEN+"44" : "0D1B2A" },
line:{ color: b < 2 && i === 0 ? GREEN : "253345", width: 1 },
rectRadius: 0.03,
});
if (b < 2 && i === 0) {
s.addText("✓", { x:8.1+b*0.56, y:y+0.08, w:0.42, h:0.26, fontSize:9, bold:true, color:GREEN, fontFace:"Calibri", align:"center", margin:0 });
}
}
if (isLast) {
s.addText("REVISION BEGINS 🚀", {
x:8.1, y:y+0.07, w:4.9, h:0.28,
fontSize:11, bold:true, color:GREEN, fontFace:"Calibri", margin:0
});
}
});
// Footer note
s.addShape(pres.ShapeType.line, { x:0.3, y:7.15, w:12.9, h:0, line:{ color:"253345", width:1 } });
s.addText("💡 Adjust daily targets if lessons run long. Completing all by Jul 25 gives you a full day buffer before revision.", {
x:0.3, y:7.2, w:12.9, h:0.28,
fontSize:9, color:MUTED, fontFace:"Calibri", margin:0
});
}
// ─── SLIDE 4 – MOTIVATION / CHECKLIST ─────────────────────────────────────
{
const s = pres.addSlide();
s.addShape(pres.ShapeType.rect, { x:0, y:0, w:13.3, h:7.5, fill:{ color:BG }, line:{ color:BG } });
// bg accent circle (decorative)
s.addShape(pres.ShapeType.ellipse, { x:8.5, y:-1.5, w:7, h:7, fill:{ color:ACCENT1+"0D" }, line:{ color:ACCENT1+"0D" } });
s.addShape(pres.ShapeType.ellipse, { x:-2, y:3, w:6, h:6, fill:{ color:ACCENT2+"0D" }, line:{ color:ACCENT2+"0D" } });
// Header
s.addShape(pres.ShapeType.rect, { x:0, y:0, w:13.3, h:0.85, fill:{ color:"0A1520" }, line:{ color:"0A1520" } });
s.addText("🏆 MILESTONE CHECKLIST & TIPS", {
x:0.4, y:0.15, w:10, h:0.55,
fontSize:20, bold:true, color:WHITE, fontFace:"Calibri", margin:0
});
// Milestones ─────────────────────────────────────────────────────────
const milestones = [
{ done:true, date:"Jul 13 – Morning", label:"Pathology: 2 lessons complete", color:GREEN },
{ done:true, date:"Jul 13 – Morning", label:"Microbiology: 2 lessons complete", color:GREEN },
{ done:false, date:"Jul 13 – End of Day", label:"Pathology: 7 small lessons complete (TODAY'S GOAL)", color:ACCENT1 },
{ done:false, date:"Jul 17", label:"Pathology Paper 1 – FULLY COMPLETE", color:ACCENT1 },
{ done:false, date:"Jul 17", label:"Pathology Paper 2 – FULLY COMPLETE", color:ACCENT1 },
{ done:false, date:"Jul 17", label:"Microbiology Paper 1 – FULLY COMPLETE", color:ACCENT2 },
{ done:false, date:"Jul 25", label:"All 54-55 lessons – FULLY COMPLETE", color:YELLOW },
{ done:false, date:"Jul 26", label:"🚀 Revision begins – You're READY!", color:GREEN },
];
s.addText("MILESTONES", {
x:0.5, y:1.0, w:6, h:0.32,
fontSize:10, bold:true, color:MUTED, fontFace:"Calibri", charSpacing:2, margin:0
});
milestones.forEach((m, i) => {
const y = 1.38 + i * 0.64;
// connector line
if (i < milestones.length - 1) {
s.addShape(pres.ShapeType.line, {
x:0.73, y:y+0.35, w:0, h:0.3,
line:{ color: m.done ? GREEN : "253345", width:1.5 }
});
}
// dot
s.addShape(pres.ShapeType.ellipse, {
x:0.55, y:y+0.06, w:0.32, h:0.32,
fill:{ color: m.done ? GREEN : CARD },
line:{ color: m.color, width: 2 }
});
if (m.done) {
s.addText("✓", { x:0.55, y:y+0.04, w:0.32, h:0.34, fontSize:11, bold:true, color:"0D1B2A", fontFace:"Calibri", align:"center", margin:0 });
}
s.addText(m.date, {
x:1.05, y:y+0.03, w:2.2, h:0.26,
fontSize:8, color:MUTED, fontFace:"Calibri", margin:0
});
s.addText(m.label, {
x:1.05, y:y+0.25, w:5.4, h:0.28,
fontSize:11, bold:!m.done, color: m.done ? GREEN : WHITE,
fontFace:"Calibri", margin:0
});
});
// Tips ──────────────────────────────────────────────────────────────────
const tips = [
{ icon:"⏰", tip:"Set a fixed start time. Consistency beats motivation." },
{ icon:"📊", tip:"Count lessons in each paper TONIGHT to confirm July 17 is realistic." },
{ icon:"🔋", tip:"Phase 1 is intense (6-7/day). Schedule short breaks every 90 min." },
{ icon:"📝", tip:"After each lesson, tick the box. Visual progress keeps momentum." },
{ icon:"🛡️", tip:"July 25 buffer: if you fall 1-2 days behind, you still finish on time." },
];
card(s, 7.2, 1.0, 5.7, 6.1, CARD);
s.addShape(pres.ShapeType.rect, { x:7.2, y:1.0, w:5.7, h:0.5, fill:{ color:ACCENT2+"33" }, line:{ color:ACCENT2+"33" } });
s.addText("STUDY TIPS", {
x:7.4, y:1.05, w:5.2, h:0.38,
fontSize:12, bold:true, color:ACCENT2, fontFace:"Calibri", charSpacing:2, margin:0
});
tips.forEach((t, i) => {
const ty = 1.65 + i * 1.0;
s.addText(t.icon, { x:7.4, y:ty, w:0.5, h:0.5, fontSize:20, fontFace:"Segoe UI Emoji", margin:0 });
s.addText(t.tip, {
x:7.95, y:ty+0.05, w:4.7, h:0.6,
fontSize:11, color:WHITE, fontFace:"Calibri", margin:0, wrap:true
});
});
}
// ─── Write file ────────────────────────────────────────────────────────────
pres.writeFile({ fileName: "/home/daytona/workspace/study-tracker/Study_Timeline_Tracker.pptx" })
.then(() => console.log("✅ Saved: Study_Timeline_Tracker.pptx"))
.catch(e => console.error("❌", e));
cd /home/daytona/workspace/study-tracker && node timeline.js
~/study-tracker/timeline.js
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/study-tracker/timeline.js'
~/study-tracker/timeline.js
const pptxgen = require("pptxgenjs");
const pres = new pptxgen();
pres.layout = "LAYOUT_WIDE"; // 13.3" x 7.5"
// ─── Palette (6-digit hex only) ────────────────────────────────────────────
const BG = "0D1B2A";
const CARD = "162032";
const CARD2 = "1A2840";
const NAV = "0A1520";
const TRACK = "253345";
const A1 = "F4A261"; // orange – Pathology
const A1D = "7A5130"; // dark orange
const A1L = "3D2818"; // very dark orange
const A2 = "2EC4B6"; // teal – Microbiology
const A2D = "176860"; // dark teal
const A2L = "0D3330"; // very dark teal
const A3 = "E94560"; // coral-red – deadline
const A3D = "6B1F2B"; // dark red
const GREEN = "06D6A0";
const GREEND = "03523D";
const YELLOW = "FFD166";
const YELLOWD = "7A6330";
const WHITE = "FFFFFF";
const MUTED = "8899AA";
function card(slide, x, y, w, h, color, rounding = 0.08) {
slide.addShape(pres.ShapeType.roundRect, {
x, y, w, h,
fill: { color },
line: { color, width: 0 },
rectRadius: rounding,
});
}
function pill(slide, x, y, w, h, color) {
slide.addShape(pres.ShapeType.roundRect, {
x, y, w, h,
fill: { color },
line: { color, width: 0 },
rectRadius: 0.15,
});
}
// ══════════════════════════════════════════════════════════════════
// SLIDE 1 – OVERVIEW DASHBOARD
// ══════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
s.addShape(pres.ShapeType.rect, { x:0, y:0, w:13.3, h:7.5, fill:{ color:BG }, line:{ color:BG } });
// Top bar
s.addShape(pres.ShapeType.rect, { x:0, y:0, w:13.3, h:0.85, fill:{ color:NAV }, line:{ color:NAV } });
s.addText("STUDY TIMELINE TRACKER", {
x:0.4, y:0.14, w:8, h:0.55,
fontSize:22, bold:true, color:WHITE, fontFace:"Calibri", margin:0
});
s.addText("July 13 - July 26, 2026", {
x:9.8, y:0.22, w:3.1, h:0.4,
fontSize:13, color:MUTED, fontFace:"Calibri", align:"right", margin:0
});
// ── Stat cards row ──────────────────────────────────────────────
const stats = [
{ label:"Total Lessons", value:"54-55", sub:"entire course", col:A1 },
{ label:"Completed", value:"4", sub:"2 Path + 2 Micro", col:GREEN },
{ label:"Remaining", value:"~51", sub:"lessons to go", col:A2 },
{ label:"Days Left", value:"13", sub:"until July 26", col:A3 },
];
stats.forEach((st, i) => {
const x = 0.35 + i * 3.15;
card(s, x, 1.05, 2.9, 1.6, CARD);
s.addShape(pres.ShapeType.rect, { x, y:1.05, w:0.06, h:1.6, fill:{ color:st.col }, line:{ color:st.col } });
s.addText(st.value, {
x: x+0.2, y:1.12, w:2.65, h:0.75,
fontSize:34, bold:true, color:st.col, fontFace:"Calibri", margin:0
});
s.addText(st.label, {
x: x+0.2, y:1.87, w:2.65, h:0.28,
fontSize:11, bold:true, color:WHITE, fontFace:"Calibri", margin:0
});
s.addText(st.sub, {
x: x+0.2, y:2.15, w:2.65, h:0.26,
fontSize:9, color:MUTED, fontFace:"Calibri", margin:0
});
});
// ── Overall progress bar ────────────────────────────────────────
card(s, 0.35, 3.0, 12.6, 0.85, CARD);
s.addText("OVERALL PROGRESS", {
x:0.6, y:3.08, w:4, h:0.28,
fontSize:10, bold:true, color:MUTED, fontFace:"Calibri", charSpacing:2, margin:0
});
s.addShape(pres.ShapeType.roundRect, { x:0.6, y:3.47, w:12.1, h:0.24, fill:{ color:TRACK }, line:{ color:TRACK }, rectRadius:0.05 });
const fillW = 12.1 * (4/54);
s.addShape(pres.ShapeType.roundRect, { x:0.6, y:3.47, w:fillW, h:0.24, fill:{ color:GREEN }, line:{ color:GREEN }, rectRadius:0.05 });
s.addText("7% complete (4 of 54 lessons done)", {
x:0.6, y:3.74, w:12.1, h:0.22,
fontSize:9, color:MUTED, fontFace:"Calibri", margin:0
});
// ── Phase boxes ─────────────────────────────────────────────────
const phases = [
{
title:"PHASE 1 - INTENSIVE",
date:"Jul 13 - 17",
hdr: A1D,
col: A1,
goals:[
"2 Pathology lessons done",
"7 small Pathology lessons today",
"Pathology Paper 1 complete",
"Pathology Paper 2 complete",
"Microbiology Paper 1 complete",
],
done: [true, false, false, false, false],
x: 0.35, w: 5.95,
},
{
title:"PHASE 2 - COMPLETION",
date:"Jul 18 - 26",
hdr: A2D,
col: A2,
goals:[
"Microbiology Paper 2",
"All remaining subjects done",
"All 54-55 lessons complete",
"2-3 buffer days spare",
"",
],
done: [false, false, false, false, false],
x: 6.7, w: 5.95,
}
];
phases.forEach(ph => {
card(s, ph.x, 4.05, ph.w, 3.1, CARD);
s.addShape(pres.ShapeType.rect, { x:ph.x, y:4.05, w:ph.w, h:0.55, fill:{ color:ph.hdr }, line:{ color:ph.hdr } });
s.addText(ph.title, {
x:ph.x+0.2, y:4.1, w:ph.w-1.5, h:0.42,
fontSize:12, bold:true, color:ph.col, fontFace:"Calibri", margin:0
});
s.addText(ph.date, {
x:ph.x+ph.w-1.4, y:4.1, w:1.2, h:0.42,
fontSize:10, bold:true, color:WHITE, fontFace:"Calibri", align:"right", margin:0
});
ph.goals.forEach((g, i) => {
if (!g) return;
const prefix = ph.done[i] ? "checkmark " : "circle ";
s.addText((ph.done[i] ? "[DONE] " : "[ ] ") + g, {
x:ph.x+0.25, y:4.75+i*0.44, w:ph.w-0.4, h:0.38,
fontSize:11,
color: ph.done[i] ? GREEN : WHITE,
fontFace:"Calibri", margin:0
});
});
});
// Deadline divider bar
card(s, 6.05, 4.05, 0.6, 3.1, A3D);
s.addText("D\nE\nA\nD\nL\nI\nN\nE", {
x:6.05, y:4.25, w:0.6, h:2.7,
fontSize:8, bold:true, color:A3, fontFace:"Calibri", align:"center", margin:0
});
}
// ══════════════════════════════════════════════════════════════════
// SLIDE 2 – GANTT / DAY-BY-DAY TIMELINE
// ══════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
s.addShape(pres.ShapeType.rect, { x:0, y:0, w:13.3, h:7.5, fill:{ color:BG }, line:{ color:BG } });
s.addShape(pres.ShapeType.rect, { x:0, y:0, w:13.3, h:0.85, fill:{ color:NAV }, line:{ color:NAV } });
s.addText("DAY-BY-DAY GANTT TIMELINE", {
x:0.4, y:0.18, w:8, h:0.52,
fontSize:20, bold:true, color:WHITE, fontFace:"Calibri", margin:0
});
s.addText("Jul 13 -> Jul 26, 2026", {
x:9.8, y:0.22, w:3.1, h:0.4,
fontSize:13, color:MUTED, fontFace:"Calibri", align:"right", margin:0
});
// Days Jul 13-26, Jul 13=Sunday
const dayNames = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"];
const days = [];
for (let d = 0; d < 14; d++) {
days.push({ date: String(13+d), day: dayNames[(0+d)%7] });
}
const colW = (13.3 - 1.2) / 14;
const startX = 0.6;
const headerY = 1.0;
const rowH = 0.68;
days.forEach((d, i) => {
const x = startX + i * colW;
const isWeekend = d.day === "Sat" || d.day === "Sun";
const isToday = i === 0;
const isDead1 = i === 4;
const isDead2 = i === 13;
const bgColor = isToday ? A1D : isDead1||isDead2 ? A3D : isWeekend ? "1E2E3E" : "1A2A3A";
const lineColor = isToday ? A1 : isDead1||isDead2 ? A3 : TRACK;
const lineW = isToday||isDead1||isDead2 ? 1.5 : 0.5;
const txColor = isToday ? A1 : isDead1||isDead2 ? A3 : isWeekend ? MUTED : WHITE;
s.addShape(pres.ShapeType.roundRect, {
x, y:headerY, w:colW-0.04, h:0.68,
fill:{ color:bgColor },
line:{ color:lineColor, width:lineW },
rectRadius:0.04,
});
s.addText(d.day, {
x, y:headerY+0.04, w:colW-0.04, h:0.26,
fontSize:8, bold:true, color:txColor, fontFace:"Calibri", align:"center", margin:0
});
s.addText(d.date, {
x, y:headerY+0.32, w:colW-0.04, h:0.3,
fontSize:11, bold:true, color:txColor, fontFace:"Calibri", align:"center", margin:0
});
});
// Subject Gantt rows
const subjects = [
{ label:"Path P1", color:A1, bgRow:A1L, start:0, end:3, note:"Target Jul 17" },
{ label:"Path P2", color:A1D, bgRow:A1L, start:1, end:4, note:"Target Jul 17" },
{ label:"Micro P1", color:A2, bgRow:A2L, start:1, end:4, note:"Target Jul 17" },
{ label:"Micro P2", color:A2D, bgRow:A2L, start:5, end:11, note:"Jul 18-24" },
{ label:"All Remaining", color:YELLOW, bgRow:YELLOWD, start:5, end:12, note:"Final push" },
];
subjects.forEach((sub, ri) => {
const y = headerY + 0.73 + ri * (rowH + 0.08);
card(s, 0, y, 0.58, rowH-0.02, CARD2);
s.addText(sub.label, {
x:0.02, y, w:0.56, h:rowH-0.02,
fontSize:7, bold:true, color:sub.color,
fontFace:"Calibri", align:"center", valign:"middle", margin:0, wrap:true
});
// Empty cells
days.forEach((_, i) => {
const x = startX + i * colW;
s.addShape(pres.ShapeType.roundRect, {
x, y, w:colW-0.04, h:rowH-0.02,
fill:{ color:"162032" },
line:{ color:TRACK, width:0.5 },
rectRadius:0.03,
});
});
// Gantt bar
const barX = startX + sub.start*colW + 0.04;
const barW = (sub.end - sub.start + 1)*colW - 0.1;
s.addShape(pres.ShapeType.roundRect, {
x:barX, y:y+0.1, w:barW, h:rowH-0.26,
fill:{ color:sub.color },
line:{ color:sub.color, width:0 },
rectRadius:0.06,
});
s.addText(sub.note, {
x:barX+0.05, y:y+0.1, w:barW-0.08, h:rowH-0.26,
fontSize:8, bold:true, color:"0D1B2A",
fontFace:"Calibri", align:"center", valign:"middle", margin:0
});
});
// Milestone vertical lines
const milestones = [
{ day:0, label:"TODAY" },
{ day:4, label:"Jul 17 DEADLINE 1" },
{ day:13, label:"Jul 26 ALL DONE" },
];
milestones.forEach(m => {
const x = startX + m.day*colW + (colW-0.04)/2;
s.addShape(pres.ShapeType.line, {
x, y:1.7, w:0, h:5.3,
line:{ color: m.day===0 ? A1 : A3, width:1.5, dashType:"dash" }
});
s.addText(m.label, {
x:x-0.4, y:7.05, w:0.82, h:0.38,
fontSize:7, bold:true,
color: m.day===0 ? A1 : A3,
fontFace:"Calibri", align:"center", margin:0
});
});
// Legend
const legend = [
{ color:A1, label:"Pathology" },
{ color:A2, label:"Microbiology" },
{ color:YELLOW, label:"All Remaining" },
{ color:A3, label:"Deadline" },
{ color:GREEN, label:"Completed" },
];
legend.forEach((l, i) => {
const lx = 0.5 + i*2.5;
pill(s, lx, 6.88, 0.22, 0.22, l.color);
s.addText(l.label, {
x:lx+0.28, y:6.88, w:2.0, h:0.22,
fontSize:9, color:WHITE, fontFace:"Calibri", margin:0
});
});
}
// ══════════════════════════════════════════════════════════════════
// SLIDE 3 – DAILY TARGET TRACKER
// ══════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
s.addShape(pres.ShapeType.rect, { x:0, y:0, w:13.3, h:7.5, fill:{ color:BG }, line:{ color:BG } });
s.addShape(pres.ShapeType.rect, { x:0, y:0, w:13.3, h:0.85, fill:{ color:NAV }, line:{ color:NAV } });
s.addText("DAILY LESSON TARGET TRACKER", {
x:0.4, y:0.18, w:7, h:0.52,
fontSize:20, bold:true, color:WHITE, fontFace:"Calibri", margin:0
});
s.addText("Fill in checkboxes as you complete lessons each day", {
x:6.5, y:0.24, w:6.5, h:0.38,
fontSize:10, color:MUTED, fontFace:"Calibri", align:"right", margin:0
});
const allDays = [
{ date:"Jul 13 (Mon)", target:7, subject:"Pathology - 7 small lessons", color:A1, phase:1 },
{ date:"Jul 14 (Tue)", target:6, subject:"Pathology Paper 1 cont.", color:A1, phase:1 },
{ date:"Jul 15 (Wed)", target:6, subject:"Pathology Paper 2 start", color:A1D, phase:1 },
{ date:"Jul 16 (Thu)", target:6, subject:"Pathology P2 + Micro P1 start", color:A2, phase:1 },
{ date:"Jul 17 (Fri)", target:5, subject:"DEADLINE - Finish Path P1+P2 + Micro P1",color:A3, phase:1 },
{ date:"Jul 18 (Sat)", target:5, subject:"Microbiology Paper 2 start", color:A2, phase:2 },
{ date:"Jul 19 (Sun)", target:5, subject:"Microbiology Paper 2 cont.", color:A2, phase:2 },
{ date:"Jul 20 (Mon)", target:5, subject:"Remaining subjects", color:YELLOW, phase:2 },
{ date:"Jul 21 (Tue)", target:4, subject:"Remaining subjects", color:YELLOW, phase:2 },
{ date:"Jul 22 (Wed)", target:4, subject:"Remaining subjects", color:YELLOW, phase:2 },
{ date:"Jul 23 (Thu)", target:4, subject:"Remaining subjects", color:YELLOW, phase:2 },
{ date:"Jul 24 (Fri)", target:4, subject:"Remaining subjects", color:YELLOW, phase:2 },
{ date:"Jul 25 (Sat)", target:3, subject:"Final lessons + buffer day", color:GREEN, phase:2 },
{ date:"Jul 26 (Sun)", target:0, subject:"ALL LESSONS COMPLETE - Begin Revision", color:GREEN, phase:2 },
];
// Column headers
const cols = [
{ label:"DATE", x:0.3, w:1.8 },
{ label:"SUBJECT FOCUS", x:2.15, w:4.0 },
{ label:"TARGET", x:6.2, w:0.9 },
{ label:"DONE", x:7.2, w:0.75},
{ label:"LESSON BOXES (tick as done)", x:8.0, w:5.0 },
];
cols.forEach(c => {
s.addText(c.label, {
x:c.x, y:0.98, w:c.w, h:0.3,
fontSize:9, bold:true, color:MUTED, fontFace:"Calibri", charSpacing:1.5, margin:0
});
});
s.addShape(pres.ShapeType.line, { x:0.3, y:1.3, w:12.9, h:0, line:{ color:TRACK, width:1 } });
const rowH2 = 0.43;
allDays.forEach((row, i) => {
const y = 1.35 + i * rowH2;
const isLast = i === allDays.length - 1;
if (i % 2 === 0) {
s.addShape(pres.ShapeType.rect, { x:0.3, y, w:12.9, h:rowH2-0.03, fill:{ color:"152030" }, line:{ color:"152030" } });
}
// Phase tag (first row of each phase)
if (i === 0 || i === 5) {
const phColor = i === 0 ? A1 : A2;
const phBg = i === 0 ? A1D : A2D;
pill(s, 0.3, y+0.05, 0.95, 0.28, phBg);
s.addText(i === 0 ? "PHASE 1" : "PHASE 2", {
x:0.3, y:y+0.06, w:0.95, h:0.26,
fontSize:7, bold:true, color:phColor, fontFace:"Calibri", align:"center", margin:0
});
}
s.addText(row.date, {
x:0.3, y:y+0.08, w:1.8, h:0.27,
fontSize: row.color===A3 ? 10 : 9,
bold: row.color===A3,
color: row.color===A3 ? A3 : row.color===GREEN ? GREEN : WHITE,
fontFace:"Calibri", margin:0
});
s.addText(row.subject, {
x:2.15, y:y+0.08, w:4.0, h:0.27,
fontSize:9, color:WHITE, fontFace:"Calibri", margin:0
});
if (row.target > 0) {
pill(s, 6.25, y+0.08, 0.52, 0.25, CARD2);
s.addText(String(row.target), {
x:6.25, y:y+0.08, w:0.52, h:0.25,
fontSize:11, bold:true, color:row.color, fontFace:"Calibri", align:"center", margin:0
});
}
// Done checkbox
s.addShape(pres.ShapeType.roundRect, {
x:7.28, y:y+0.1, w:0.26, h:0.24,
fill:{ color:"0D1B2A" },
line:{ color: i===0 ? GREEN : MUTED, width: i===0 ? 2 : 1 },
rectRadius:0.03,
});
if (i===0) {
s.addText("v", { x:7.28, y:y+0.08, w:0.26, h:0.26, fontSize:10, bold:true, color:GREEN, fontFace:"Calibri", align:"center", margin:0 });
}
// Lesson tick boxes
const boxCount = row.target > 0 ? Math.min(row.target, 8) : 0;
for (let b = 0; b < boxCount; b++) {
const alreadyDone = b < 2 && i === 0; // show 2 done for day 1 (pathology + micro already started)
s.addShape(pres.ShapeType.roundRect, {
x:8.0+b*0.56, y:y+0.1, w:0.42, h:0.24,
fill:{ color: alreadyDone ? GREEND : "0D1B2A" },
line:{ color: alreadyDone ? GREEN : TRACK, width:1 },
rectRadius:0.03,
});
if (alreadyDone) {
s.addText("v", { x:8.0+b*0.56, y:y+0.09, w:0.42, h:0.26, fontSize:9, bold:true, color:GREEN, fontFace:"Calibri", align:"center", margin:0 });
}
}
if (isLast) {
s.addText("REVISION BEGINS!", {
x:8.0, y:y+0.08, w:4.9, h:0.28,
fontSize:11, bold:true, color:GREEN, fontFace:"Calibri", margin:0
});
}
});
s.addShape(pres.ShapeType.line, { x:0.3, y:7.38, w:12.9, h:0, line:{ color:TRACK, width:1 } });
s.addText("TIP: Adjust daily targets if lessons run long. Finishing by Jul 25 gives 1 full buffer day before revision starts.", {
x:0.3, y:7.41, w:12.9, h:0.26,
fontSize:9, color:MUTED, fontFace:"Calibri", margin:0
});
}
// ══════════════════════════════════════════════════════════════════
// SLIDE 4 – MILESTONES & TIPS
// ══════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
s.addShape(pres.ShapeType.rect, { x:0, y:0, w:13.3, h:7.5, fill:{ color:BG }, line:{ color:BG } });
// decorative circles
s.addShape(pres.ShapeType.ellipse, { x:8.5, y:-1.5, w:7, h:7, fill:{ color:A1L }, line:{ color:A1L } });
s.addShape(pres.ShapeType.ellipse, { x:-2, y:3, w:6, h:6, fill:{ color:A2L }, line:{ color:A2L } });
s.addShape(pres.ShapeType.rect, { x:0, y:0, w:13.3, h:0.85, fill:{ color:NAV }, line:{ color:NAV } });
s.addText("MILESTONE CHECKLIST & STUDY TIPS", {
x:0.4, y:0.18, w:10, h:0.52,
fontSize:20, bold:true, color:WHITE, fontFace:"Calibri", margin:0
});
// Milestones
const milestones = [
{ done:true, date:"Jul 13 - Morning", label:"Pathology: 2 lessons COMPLETE", color:GREEN },
{ done:true, date:"Jul 13 - Morning", label:"Microbiology: 2 lessons COMPLETE", color:GREEN },
{ done:false, date:"Jul 13 - Today", label:"Pathology: 7 small lessons (TODAY'S GOAL)", color:A1 },
{ done:false, date:"Jul 17", label:"Pathology Paper 1 - COMPLETE", color:A1 },
{ done:false, date:"Jul 17", label:"Pathology Paper 2 - COMPLETE", color:A1 },
{ done:false, date:"Jul 17", label:"Microbiology Paper 1 - COMPLETE", color:A2 },
{ done:false, date:"Jul 25", label:"All 54-55 lessons - FULLY COMPLETE", color:YELLOW},
{ done:false, date:"Jul 26", label:"REVISION BEGINS - You are READY!", color:GREEN },
];
s.addText("MILESTONES", {
x:0.5, y:1.0, w:5.5, h:0.3,
fontSize:10, bold:true, color:MUTED, fontFace:"Calibri", charSpacing:2, margin:0
});
milestones.forEach((m, i) => {
const y = 1.38 + i * 0.64;
if (i < milestones.length - 1) {
s.addShape(pres.ShapeType.line, {
x:0.73, y:y+0.35, w:0, h:0.3,
line:{ color: m.done ? GREEN : TRACK, width:1.5 }
});
}
s.addShape(pres.ShapeType.ellipse, {
x:0.55, y:y+0.06, w:0.32, h:0.32,
fill:{ color: m.done ? GREEN : CARD },
line:{ color:m.color, width:2 }
});
if (m.done) {
s.addText("v", { x:0.55, y:y+0.05, w:0.32, h:0.32, fontSize:11, bold:true, color:NAV, fontFace:"Calibri", align:"center", margin:0 });
}
s.addText(m.date, {
x:1.05, y:y+0.03, w:2.2, h:0.24,
fontSize:8, color:MUTED, fontFace:"Calibri", margin:0
});
s.addText(m.label, {
x:1.05, y:y+0.26, w:5.4, h:0.28,
fontSize:11, bold:!m.done, color: m.done ? GREEN : WHITE,
fontFace:"Calibri", margin:0
});
});
// Tips panel
card(s, 7.2, 1.0, 5.7, 6.15, CARD);
s.addShape(pres.ShapeType.rect, { x:7.2, y:1.0, w:5.7, h:0.5, fill:{ color:A2D }, line:{ color:A2D } });
s.addText("STUDY TIPS", {
x:7.4, y:1.07, w:5.2, h:0.36,
fontSize:12, bold:true, color:A2, fontFace:"Calibri", charSpacing:2, margin:0
});
const tips = [
{ icon:"1.", tip:"Set a fixed start time every day. Consistency beats motivation." },
{ icon:"2.", tip:"COUNT the lessons in each paper TONIGHT to confirm July 17 is achievable." },
{ icon:"3.", tip:"Phase 1 is intense (6-7 lessons/day). Schedule a 15-min break every 90 min." },
{ icon:"4.", tip:"After each lesson, tick the box. Visual progress builds momentum." },
{ icon:"5.", tip:"July 25 buffer: if you fall 1-2 days behind, you still finish on time." },
];
tips.forEach((t, i) => {
const ty = 1.65 + i * 0.98;
pill(s, 7.4, ty, 0.32, 0.32, A2D);
s.addText(t.icon, {
x:7.4, y:ty, w:0.32, h:0.32,
fontSize:11, bold:true, color:A2, fontFace:"Calibri", align:"center", margin:0
});
s.addText(t.tip, {
x:7.8, y:ty+0.03, w:4.85, h:0.7,
fontSize:11, color:WHITE, fontFace:"Calibri", margin:0, wrap:true
});
});
}
// ─── Write ─────────────────────────────────────────────────────────────────
pres.writeFile({ fileName: "/home/daytona/workspace/study-tracker/Study_Timeline_Tracker.pptx" })
.then(() => console.log("Saved."))
.catch(e => console.error(e));
cat > /home/daytona/workspace/study-tracker/timeline.js << 'JSEOF' const pptxgen…
cd /home/daytona/workspace/study-tracker && node timeline.js 2>&1
Study Timeline Tracker
Presentation · PPTX