JSFiddle - React, Tailwind, and code Playground

by Josh Pullen

JavaScript

// User data
const goal = {
	days: ["mon", "tue"],
  startDate: new Date("May 22, 2020").getTime()
};
const logs = [
  { date: new Date("May 25, 2020").getTime() },
  { date: new Date("May 26, 2020").getTime() },
  { date: new Date("May 27, 2020").getTime() },
  { date: new Date("May 28, 2020").getTime() }
];

const today = new Date("May 28, 2020");

// Functions
function completedDay(day) {
  const sameDay = (dateA, dateB) => (
    dateA.getFullYear() === dateB.getFullYear() &&
    dateA.getMonth() === dateB.getMonth() &&
    dateA.getDate() === dateB.getDate()
  );

  return logs.some(log => sameDay(new Date(log.date), day));
}

function isDayOff(day) {
	const dayNames = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"];
  const dayName = dayNames[day.getDay()];

  return !goal.days.includes(dayName);
}

function getStreak(beforeDay) {
  let day = new Date(beforeDay); // Copy so we don't modify the original
  day.setDate(day.getDate() - 1);

  let streakType = null;
  let streakDays = 0;

  while (day.getTime() >= goal.startDate) {
  	if (!isDayOff(day)) {
    	if (streakType === null) {
      	streakType = completedDay(day) ? "good" : "bad";
      }
    
    	if (completedDay(day) === (streakType === "good")) {
        // This day matches the streak!
        streakDays++;
      } else {
        // This day doesn't match. We've hit the end of the streak.
        break;
      }
    }

    day.setDate(day.getDate() - 1);
  }

  // If it's a bad streak and you haven't done anything today,
  // that doesn't count against you (because the outcome of today
  // is still undecided). But if you have a good streak going and
  // you succeed today, that should add to your streak.
  if (streakType === "good" && completedDay(today) && !isDayOff(today)) {
    streakDays++;
  }

  return {
    type: streakType,
    days: streakDays
  }
}

// Code
console.log("Completed today?", completedDay(today));

const streak = getStreak(today);
console.log("Streak:", streak.days,...