- {HEALTH_MILESTONES.map((milestone, index) => {
- const isAchieved = minutesSinceQuit >= milestone.timeMinutes;
- const isCurrent = index === currentMilestoneIndex;
- const Icon = iconMap[milestone.icon] || Heart;
-
- return (
-
- {/* Icon */}
-
- {isAchieved ? (
-
- ) : (
-
- )}
-
-
- {/* Content */}
-
-
-
- {milestone.title}
-
- {isCurrent && (
-
- Current
-
- )}
-
-
- {milestone.description}
-
-
-
-
- {formatDuration(milestone.timeMinutes)}
-
-
-
-
- );
- })}
+
+
+
+
-
+
);
}
diff --git a/src/lib/storage.ts b/src/lib/storage.ts
index 1db105a..9dfb58d 100644
--- a/src/lib/storage.ts
+++ b/src/lib/storage.ts
@@ -16,6 +16,8 @@ export interface UserPreferences {
userName: string | null;
userAge: number | null;
religion: 'christian' | 'muslim' | 'jewish' | 'secular' | null;
+ lastNicotineUsageTime?: string | null; // ISO timestamp of last usage
+ lastWeedUsageTime?: string | null; // ISO timestamp of last usage
}
export interface QuitPlan {
@@ -395,8 +397,51 @@ export function calculateTotalSaved(
export function getMinutesSinceQuit(
usageData: UsageEntry[],
- substance: 'nicotine' | 'weed'
+ substance: 'nicotine' | 'weed',
+ precise: boolean = false,
+ preferences?: UserPreferences | null
): number {
+ // Try to use precise timestamp from preferences first
+ if (preferences) {
+ const lastUsageTimeStr = substance === 'nicotine'
+ ? preferences.lastNicotineUsageTime
+ : preferences.lastWeedUsageTime;
+
+ if (lastUsageTimeStr) {
+ const now = new Date();
+ const lastUsageTime = new Date(lastUsageTimeStr);
+ const diffMs = now.getTime() - lastUsageTime.getTime();
+ const minutes = Math.max(0, diffMs / (1000 * 60));
+
+ // Sanity check: if the timestamp is OLDER than the last recorded date in usageData,
+ // it might mean the user manually added a later date in the calendar without a timestamp.
+ // In that case, we should fall back to the date-based logic.
+
+ const substanceData = usageData
+ .filter((e) => e.substance === substance && e.count > 0)
+ .sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
+
+ if (substanceData.length > 0) {
+ const lastDateStr = substanceData[0].date;
+ const lastDate = new Date(lastDateStr);
+ // Set lastDate to end of day to compare with timestamp
+ lastDate.setHours(23, 59, 59, 999);
+
+ // If the timestamp is essentially on the same day or later than the last recorded date, rely on the timestamp
+ // (We allow the timestamp to be earlier in the same day, that's the whole point)
+ const lastDateStart = new Date(lastDateStr);
+ lastDateStart.setHours(0, 0, 0, 0);
+
+ if (lastUsageTime >= lastDateStart) {
+ return precise ? minutes : Math.floor(minutes);
+ }
+ } else {
+ // No usage data but we have a timestamp? Trust the timestamp.
+ return precise ? minutes : Math.floor(minutes);
+ }
+ }
+ }
+
// Find the last usage date for this substance
const substanceData = usageData
.filter((e) => e.substance === substance && e.count > 0)
@@ -411,7 +456,7 @@ export function getMinutesSinceQuit(
const todayStr = now.toISOString().split('T')[0];
const lastUsageDateStr = substanceData[0].date;
- // If the last usage was today, reset to 0 (just used)
+ // If the last usage was today, reset to 0 (just used, unknown time)
if (lastUsageDateStr === todayStr) {
return 0;
}
@@ -421,7 +466,9 @@ export function getMinutesSinceQuit(
lastUsageDate.setHours(23, 59, 59, 999);
const diffMs = now.getTime() - lastUsageDate.getTime();
- return Math.max(0, Math.floor(diffMs / (1000 * 60)));
+ const minutes = Math.max(0, diffMs / (1000 * 60));
+
+ return precise ? minutes : Math.floor(minutes);
}
export function checkBadgeEligibility(