πŸ“– Study Session Tracker

An afternoon in the library, a warm cup of coffee, and a little progress at a time. β˜•πŸŒΏ

πŸ•―οΈ A Gentle Reminder

You don't have to finish everything today. A little progress is still progress.


🌸 Welcome to Your Study Journal

// ==========================================
// 🌿 STUDY NOOK β€” COZY STUDY DASHBOARD
// ==========================================

// πŸ“‚ Our correct Study Nook folder
const folder = '"study nook/School/Study Sessions"';

const sessions = dv.pages(folder)
  .where(p => p.type === "study-session")
  .array()
  .filter(p => p.date && Number(p.minutes) > 0);

// πŸ•―οΈ Dates
const today = dv.date("today");
const monday = today.minus({
  days: today.weekday - 1
});
const sunday = monday.plus({ days: 6 });

function sessionDate(p) {
  try {
    return dv.date(p.date);
  } catch {
    return null;
  }
}

function minutesTotal(items) {
  return items.reduce(
    (sum, p) => sum + Number(p.minutes), 0
  );
}

function prettyTime(n) {
  const h = Math.floor(n / 60);
  const m = Math.round(n % 60);

  if (h === 0) return `${m} min`;
  if (m === 0) return `${h}h`;
  return `${h}h ${m}m`;
}

// β˜• Study totals
const todaySessions = sessions.filter(p => {
  const d = sessionDate(p);
  return d && d.toISODate() === today.toISODate();
});

const weekSessions = sessions.filter(p => {
  const d = sessionDate(p);
  return d && d >= monday && d <= sunday;
});

const cards = [
  ["β˜• Today", prettyTime(minutesTotal(todaySessions))],
  ["🌿 This Week", prettyTime(minutesTotal(weekSessions))],
  ["πŸ“– Sessions", String(sessions.length)],
  ["πŸ•―οΈ All Time", prettyTime(minutesTotal(sessions))]
];

// 🌸 Create cozy statistic cards
const grid = dv.container.createDiv();

grid.style.display = "grid";
grid.style.gridTemplateColumns =
  "repeat(auto-fit, minmax(145px, 1fr))";
grid.style.gap = "14px";
grid.style.margin = "18px 0 24px";

for (const [label, value] of cards) {
  const card = grid.createDiv();

  card.style.background = "var(--background-secondary)";
  card.style.border =
    "1px solid var(--background-modifier-border)";
  card.style.borderRadius = "14px";
  card.style.padding = "20px 12px";
  card.style.textAlign = "center";
  card.style.boxShadow =
    "0 3px 10px rgba(55, 48, 30, 0.05)";

  const heading = card.createDiv();
  heading.setText(label);
  heading.style.fontSize = "0.9em";
  heading.style.color = "var(--text-muted)";

  const number = card.createDiv();
  number.setText(value);
  number.style.fontSize = "1.65em";
  number.style.fontWeight = "650";
  number.style.color = "var(--text-normal)";
  number.style.marginTop = "8px";
}

// 🌿 Working button
const buttonArea = dv.container.createDiv();
buttonArea.style.textAlign = "center";
buttonArea.style.margin = "18px 0 12px";

const button = buttonArea.createEl("button", {
  text: "🌸 Log a Study Session"
});

button.style.background = "#718a6c";
button.style.color = "#ffffff";
button.style.padding = "12px 25px";
button.style.borderRadius = "12px";
button.style.fontWeight = "600";
button.style.border = "none";
button.style.cursor = "pointer";


 // 🌸 Open our Study Session template directly

button.addEventListener("click", async () => {

  const templatePath =
    "study nook/School/Templates/New Study Session.md";

  const destinationFolder =
    "study nook/School/Study Sessions";

  // Find our specific template
  const templateFile =
    app.vault.getAbstractFileByPath(templatePath);

  if (!templateFile) {
    new Notice("🌿 Study Session template not found!");
    return;
  }

  // Connect to Templater
  const templater =
    app.plugins.plugins["templater-obsidian"]?.templater;

  if (!templater) {
    new Notice("🌿 Please enable Templater.");
    return;
  }

  try {
    // Temporary unique filename.
    // Our template will rename it automatically.
    const temporaryName =
      `Study Session Draft ${Date.now()}`;

    await templater.create_new_note_from_template(
      templateFile,
      destinationFolder,
      temporaryName,
      true
    );

  } catch (error) {
    console.error("Study Nook:", error);
    new Notice("🌿 Could not create study session.");
  }

});


const hint = buttonArea.createDiv();
hint.setText(
  "A few minutes or a whole afternoon β€” every session counts."
);
hint.style.fontStyle = "italic";
hint.style.fontSize = "0.82em";
hint.style.color = "var(--text-muted)";
hint.style.marginTop = "10px";

// 🌷 Gentle encouragement
const message = dv.container.createDiv();
message.style.textAlign = "center";
message.style.margin = "18px 0";
message.style.color = "var(--text-muted)";
message.style.fontStyle = "italic";

if (sessions.length === 0) {
  message.setText(
    "🌱 Your study garden is waiting for its first little seed."
  );
} else if (todaySessions.length === 0) {
  message.setText(
    "πŸ•―οΈ Your journal is here whenever you're ready."
  );
} else {
  message.setText(
    "🌸 Look at the progress you've made today!"
  );
}

πŸ—“οΈ A Week of Little Victories

Seven little days, each with room to grow. 🌱

// ==========================================
// 🌿 STUDY NOOK β€” WEEKLY STUDY CALENDAR
// ==========================================

// πŸ“‚ Our correct study session folder
const sessions = dv.pages('"study nook/School/Study Sessions"')
  .where(p => p.type === "study-session")
  .array()
  .filter(p => p.date && Number(p.minutes) > 0);

// πŸ“… Find the current Monday through Sunday
const today = dv.date("today");
const monday = today.minus({
  days: today.weekday - 1
});

const sunday = monday.plus({ days: 6 });

// 🌸 Collect study minutes by date
const dailyTotals = {};

for (const session of sessions) {
  const date = dv.date(session.date);
  if (!date) continue;

  const key = date.toISODate();

  dailyTotals[key] =
    (dailyTotals[key] || 0) + Number(session.minutes);
}

// β˜• Format study time
function formatTime(minutes) {
  const h = Math.floor(minutes / 60);
  const m = Math.round(minutes % 60);

  if (h === 0) return `${m}m`;
  return m === 0 ? `${h}h` : `${h}h ${m}m`;
}

// πŸ•―οΈ Week title
const weekTitle = dv.container.createDiv();
weekTitle.setText(
  `🌸 ${monday.toFormat("MMMM d")} – ` +
  `${sunday.toFormat("MMMM d, yyyy")}`
);

weekTitle.style.textAlign = "center";
weekTitle.style.fontSize = "1.05em";
weekTitle.style.fontWeight = "600";
weekTitle.style.margin = "16px 0";
weekTitle.style.color = "var(--text-normal)";

// 🌿 Create calendar grid
const calendar = dv.container.createDiv();

calendar.style.display = "grid";
calendar.style.gridTemplateColumns =
  "repeat(7, minmax(0, 1fr))";
calendar.style.gap = "6px";
calendar.style.margin = "15px 0";

// πŸ“œ Day labels
const days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];

let weeklyMinutes = 0;
let studyDays = 0;

for (let i = 0; i < 7; i++) {

  const date = monday.plus({ days: i });
  const key = date.toISODate();

  const minutes = dailyTotals[key] || 0;
  const isToday = key === today.toISODate();
  const hasStudied = minutes > 0;

  weeklyMinutes += minutes;
  if (hasStudied) studyDays++;

  // 🌸 Day card
  const card = calendar.createDiv();

  card.style.display = "flex";
  card.style.flexDirection = "column";
  card.style.alignItems = "center";
  card.style.justifyContent = "center";
  card.style.gap = "5px";
  card.style.padding = "12px 2px";
  card.style.minWidth = "0";
  card.style.borderRadius = "12px";

  card.style.background = hasStudied
    ? "rgba(129, 157, 111, 0.17)"
    : "var(--background-secondary)";

  card.style.border = isToday
    ? "2px solid #819d6f"
    : "1px solid var(--background-modifier-border)";

  // Day of week
  const dayLabel = card.createDiv();
  dayLabel.setText(days[i]);
  dayLabel.style.fontSize = "0.75em";
  dayLabel.style.color = "var(--text-muted)";

  // Calendar date
  const number = card.createDiv();
  number.setText(String(date.day));
  number.style.fontWeight = "650";
  number.style.fontSize = "1.15em";

  // 🌱 Little plant marker
  const flower = card.createDiv();
  flower.setText(hasStudied ? "🌱" : "·");
  flower.style.fontSize = "1.05em";

  // β˜• Minutes studied
  const time = card.createDiv();
  time.setText(
    hasStudied ? formatTime(minutes) : "β€”"
  );
  time.style.fontSize = "0.72em";
  time.style.color = "var(--text-muted)";
  time.style.textAlign = "center";
}

// 🌷 Weekly summary
const summary = dv.container.createDiv();

summary.style.display = "grid";
summary.style.gridTemplateColumns = "1fr 1fr";
summary.style.gap = "12px";
summary.style.margin = "20px 0";

const summaryCards = [
  ["β˜• This Week's Study Time",
    formatTime(weeklyMinutes)],
  ["πŸͺ» Days with Study Sessions",
    `${studyDays} of 7`]
];

for (const [label, value] of summaryCards) {

  const card = summary.createDiv();

  card.style.background = "var(--background-secondary)";
  card.style.border =
    "1px solid var(--background-modifier-border)";
  card.style.borderRadius = "12px";
  card.style.padding = "15px";
  card.style.textAlign = "center";

  const heading = card.createDiv();
  heading.setText(label);
  heading.style.fontSize = "0.8em";
  heading.style.color = "var(--text-muted)";

  const number = card.createDiv();
  number.setText(value);
  number.style.fontWeight = "650";
  number.style.fontSize = "1.3em";
  number.style.marginTop = "8px";
}

// πŸͺ· Closing message
const note = dv.container.createDiv();
note.setText(
  "🌿 Every little leaf represents a moment of learning."
);
note.style.textAlign = "center";
note.style.fontStyle = "italic";
note.style.color = "var(--text-muted)";
note.style.fontSize = "0.85em";
note.style.margin = "16px 0";

🌿 My Study Garden

A little collection of all the time you've spent learning.

const sessions = dv.pages('"study nook/School/Study Sessions"')
  .where(p => p.type === "study-session")
  .array()
  .filter(p => Number(p.minutes) > 0);

const totals = {};

for (const session of sessions) {
  const name = String(session.class || "Other");

  totals[name] =
    (totals[name] || 0) + Number(session.minutes);
}

const entries = Object.entries(totals)
  .sort((a, b) => b[1] - a[1]);

const total = entries.reduce(
  (sum, item) => sum + item[1], 0
);

const colors = [
  "#8a9b74",
  "#b69b79",
  "#ac91a4",
  "#8eaaa5",
  "#c3ae78"
];

function prettyTime(n) {
  const h = Math.floor(n / 60);
  const m = Math.round(n % 60);
  if (h === 0) return `${m} min`;
  return m ? `${h}h ${m}m` : `${h}h`;
}

if (!entries.length) {
  dv.paragraph(
    "🌱 Your subjects will begin blooming here soon."
  );
} else {
  const garden = dv.container.createDiv();
  garden.style.margin = "18px 0";

  entries.forEach(([name, minutes], index) => {
    const item = garden.createDiv();
    item.style.marginBottom = "18px";

    const heading = item.createDiv();
    heading.style.display = "flex";
    heading.style.justifyContent = "space-between";
    heading.style.gap = "12px";
    heading.style.marginBottom = "7px";

    const title = heading.createSpan();
    title.setText("🌱 " + name);

    const time = heading.createSpan();
    time.setText(prettyTime(minutes));
    time.style.color = "var(--text-muted)";

    const track = item.createDiv();
    track.style.height = "12px";
    track.style.borderRadius = "10px";
    track.style.background =
      "var(--background-modifier-border)";
    track.style.overflow = "hidden";

    const fill = track.createDiv();
    fill.style.height = "100%";
    fill.style.width =
      `${(minutes / total) * 100}%`;
    fill.style.borderRadius = "10px";
    fill.style.background =
      colors[index % colors.length];
  });

  const footnote = garden.createDiv();
  footnote.setText(
    "πŸͺ» Each bar shows a class's share of your total study time."
  );
  footnote.style.fontSize = "0.85em";
  footnote.style.fontStyle = "italic";
  footnote.style.color = "var(--text-muted)";
}

πŸ“œ Recent Pages in My Journal

Every study session has its own little story.

const sessions = dv.pages('"study nook/School/Study Sessions"')
  .where(p => p.type === "study-session")
  .sort(p => p.file.ctime, "desc")
  .limit(10);

const rows = sessions.map(p => [
  dv.fileLink(p.file.path, false,
    p.date
      ? dv.date(p.date).toFormat("MMM d, yyyy")
      : p.file.name
  ),
  p.class || "Other",
  `${p.minutes || 0} min`,
  p.accomplishment || "πŸ“œ A little progress!"
]);

if (rows.length) {
  dv.table(
    ["πŸ“… Date", "πŸ“š Class", "β˜• Time", "🌸 Accomplished"],
    rows
  );
} else {
  dv.paragraph(
    "πŸ•―οΈ Your first journal entry is waiting."
  );
}

🌸 A Little Progress Is Still Progress

Whether you studied for five minutes or two hours, you showed up for yourself today. That's something worth remembering.

May your coffee stay warm and your curiosity keep growing. β˜•πŸŒΏπŸ“œ

Built with LogoFlowershow