mirror of
https://github.com/nagaoo0/HabbitGrid.git
synced 2026-01-11 23:44:55 +00:00
CountersUpdate
This commit is contained in:
@@ -23,6 +23,7 @@ function ensureUUIDs(habits) {
|
||||
});
|
||||
}
|
||||
import { supabase, isSupabaseConfigured } from './supabase';
|
||||
import { calculateStreaks } from './utils-habit';
|
||||
import * as local from './storage';
|
||||
|
||||
const SYNC_FLAG = 'habitgrid_remote_synced_at';
|
||||
@@ -172,7 +173,10 @@ export async function toggleCompletion(habitId, dateStr) {
|
||||
const completions = Array.isArray(target.completions) ? [...target.completions] : [];
|
||||
const idx = completions.indexOf(dateStr);
|
||||
if (idx > -1) completions.splice(idx, 1); else completions.push(dateStr);
|
||||
return updateHabit(habitId, { completions });
|
||||
// Calculate streaks and preserve personal record (do not decrease longest)
|
||||
const { currentStreak, longestStreak } = calculateStreaks(completions);
|
||||
const nextLongest = Math.max(longestStreak, target.longestStreak || 0);
|
||||
return updateHabit(habitId, { completions, currentStreak, longestStreak: nextLongest });
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -126,65 +126,7 @@ export const toggleCompletion = (habitId, dateStr) => {
|
||||
});
|
||||
};
|
||||
|
||||
import { getFrozenDays } from './utils-habit.js';
|
||||
const calculateStreaks = (completions) => {
|
||||
if (completions.length === 0) {
|
||||
return { currentStreak: 0, longestStreak: 0 };
|
||||
}
|
||||
// Only use frozen days for streak calculation
|
||||
const frozenDays = getFrozenDays(completions);
|
||||
const allValid = Array.from(new Set([...completions, ...frozenDays]));
|
||||
const sortedDates = allValid
|
||||
.map(d => new Date(d))
|
||||
.sort((a, b) => b - a);
|
||||
|
||||
let currentStreak = 0;
|
||||
let longestStreak = 0;
|
||||
let tempStreak = 1;
|
||||
|
||||
const today = new Date();
|
||||
today.setHours(0, 0, 0, 0);
|
||||
const yesterday = new Date(today);
|
||||
yesterday.setDate(yesterday.getDate() - 1);
|
||||
|
||||
const mostRecent = sortedDates[0];
|
||||
mostRecent.setHours(0, 0, 0, 0);
|
||||
|
||||
if (mostRecent.getTime() === today.getTime() || mostRecent.getTime() === yesterday.getTime()) {
|
||||
currentStreak = 1;
|
||||
for (let i = 1; i < sortedDates.length; i++) {
|
||||
const current = new Date(sortedDates[i]);
|
||||
current.setHours(0, 0, 0, 0);
|
||||
const previous = new Date(sortedDates[i - 1]);
|
||||
previous.setHours(0, 0, 0, 0);
|
||||
const diffDays = Math.floor((previous - current) / (1000 * 60 * 60 * 24));
|
||||
if (diffDays === 1) {
|
||||
currentStreak++;
|
||||
tempStreak++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tempStreak = 1;
|
||||
for (let i = 1; i < sortedDates.length; i++) {
|
||||
const current = new Date(sortedDates[i]);
|
||||
current.setHours(0, 0, 0, 0);
|
||||
const previous = new Date(sortedDates[i - 1]);
|
||||
previous.setHours(0, 0, 0, 0);
|
||||
const diffDays = Math.floor((previous - current) / (1000 * 60 * 60 * 24));
|
||||
if (diffDays === 1) {
|
||||
tempStreak++;
|
||||
longestStreak = Math.max(longestStreak, tempStreak);
|
||||
} else {
|
||||
tempStreak = 1;
|
||||
}
|
||||
}
|
||||
|
||||
longestStreak = Math.max(longestStreak, currentStreak, 1);
|
||||
return { currentStreak, longestStreak };
|
||||
}
|
||||
import { calculateStreaks } from './utils-habit.js';
|
||||
|
||||
export const exportData = () => {
|
||||
const habits = getHabits();
|
||||
|
||||
@@ -40,6 +40,71 @@ export const getWeekdayLabel = (dayIndex) => {
|
||||
const labels = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
||||
return labels[dayIndex];
|
||||
};
|
||||
|
||||
// Calculate current and longest streaks from a list of completion date strings (YYYY-MM-DD)
|
||||
// Rules:
|
||||
// - Streaks count consecutive days
|
||||
// - Today or yesterday must be present to have a non-zero current streak
|
||||
// - We also include "frozen" days (one missed day per month sandwiched by completions)
|
||||
// - Longest streak is at least 1 if there is at least one completion
|
||||
export function calculateStreaks(completions) {
|
||||
if (!Array.isArray(completions) || completions.length === 0) {
|
||||
return { currentStreak: 0, longestStreak: 0 };
|
||||
}
|
||||
// Only use frozen days for streak calculation
|
||||
const frozenDays = getFrozenDays(completions);
|
||||
const allValid = Array.from(new Set([...(completions || []), ...frozenDays]));
|
||||
const sortedDates = allValid
|
||||
.map(d => new Date(d))
|
||||
.sort((a, b) => b - a);
|
||||
|
||||
let currentStreak = 0;
|
||||
let longestStreak = 0;
|
||||
let tempStreak = 1;
|
||||
|
||||
const today = new Date();
|
||||
today.setHours(0, 0, 0, 0);
|
||||
const yesterday = new Date(today);
|
||||
yesterday.setDate(yesterday.getDate() - 1);
|
||||
|
||||
const mostRecent = sortedDates[0];
|
||||
mostRecent.setHours(0, 0, 0, 0);
|
||||
|
||||
if (mostRecent.getTime() === today.getTime() || mostRecent.getTime() === yesterday.getTime()) {
|
||||
currentStreak = 1;
|
||||
for (let i = 1; i < sortedDates.length; i++) {
|
||||
const current = new Date(sortedDates[i]);
|
||||
current.setHours(0, 0, 0, 0);
|
||||
const previous = new Date(sortedDates[i - 1]);
|
||||
previous.setHours(0, 0, 0, 0);
|
||||
const diffDays = Math.floor((previous - current) / (1000 * 60 * 60 * 24));
|
||||
if (diffDays === 1) {
|
||||
currentStreak++;
|
||||
tempStreak++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tempStreak = 1;
|
||||
for (let i = 1; i < sortedDates.length; i++) {
|
||||
const current = new Date(sortedDates[i]);
|
||||
current.setHours(0, 0, 0, 0);
|
||||
const previous = new Date(sortedDates[i - 1]);
|
||||
previous.setHours(0, 0, 0, 0);
|
||||
const diffDays = Math.floor((previous - current) / (1000 * 60 * 60 * 24));
|
||||
if (diffDays === 1) {
|
||||
tempStreak++;
|
||||
longestStreak = Math.max(longestStreak, tempStreak);
|
||||
} else {
|
||||
tempStreak = 1;
|
||||
}
|
||||
}
|
||||
|
||||
longestStreak = Math.max(longestStreak, currentStreak, 1);
|
||||
return { currentStreak, longestStreak };
|
||||
}
|
||||
// Returns array of frozen days (date strings) for a given completions array
|
||||
export function getFrozenDays(completions) {
|
||||
// Map: month string -> frozen day string
|
||||
|
||||
Reference in New Issue
Block a user