Avery Felts a244e740c9 Store data per-user using unique account ID
- Add user ID prefix to all localStorage keys
- Each user now has isolated data storage
- New users see fresh setup wizard
- Switching accounts loads that user's specific data

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 21:52:00 -07:00

227 lines
7.1 KiB
TypeScript

// Client-side storage utilities for tracking data
// All data is stored per-user using their unique ID as a prefix
export interface UsageEntry {
date: string; // ISO date string YYYY-MM-DD
count: number;
substance: 'nicotine' | 'weed';
}
export interface UserPreferences {
substance: 'nicotine' | 'weed';
trackingStartDate: string | null;
hasCompletedSetup: boolean;
dailyGoal: number | null;
quitPlan: QuitPlan | null;
userName: string | null;
userAge: number | null;
}
export interface QuitPlan {
startDate: string;
endDate: string;
weeklyTargets: number[];
baselineAverage: number;
}
const CURRENT_USER_KEY = 'quit_smoking_current_user';
function getStorageKey(baseKey: string, userId?: string): string {
const uid = userId || getCurrentUserId();
if (!uid) return baseKey;
return `${baseKey}_${uid}`;
}
export function setCurrentUserId(userId: string): void {
if (typeof window === 'undefined') return;
localStorage.setItem(CURRENT_USER_KEY, userId);
}
export function getCurrentUserId(): string | null {
if (typeof window === 'undefined') return null;
return localStorage.getItem(CURRENT_USER_KEY);
}
export function getUsageData(userId?: string): UsageEntry[] {
if (typeof window === 'undefined') return [];
const key = getStorageKey('quit_smoking_usage', userId);
const data = localStorage.getItem(key);
return data ? JSON.parse(data) : [];
}
export function saveUsageEntry(entry: UsageEntry, userId?: string): void {
if (typeof window === 'undefined') return;
const key = getStorageKey('quit_smoking_usage', userId);
const data = getUsageData(userId);
const existingIndex = data.findIndex(
(e) => e.date === entry.date && e.substance === entry.substance
);
if (existingIndex >= 0) {
data[existingIndex].count += entry.count;
} else {
data.push(entry);
}
localStorage.setItem(key, JSON.stringify(data));
}
export function setUsageForDate(date: string, count: number, substance: 'nicotine' | 'weed', userId?: string): void {
if (typeof window === 'undefined') return;
const key = getStorageKey('quit_smoking_usage', userId);
const data = getUsageData(userId);
const existingIndex = data.findIndex(
(e) => e.date === date && e.substance === substance
);
if (existingIndex >= 0) {
data[existingIndex].count = count;
} else {
data.push({ date, count, substance });
}
localStorage.setItem(key, JSON.stringify(data));
}
export function getUsageForDate(date: string, substance: 'nicotine' | 'weed', userId?: string): number {
const data = getUsageData(userId);
const entry = data.find((e) => e.date === date && e.substance === substance);
return entry?.count ?? 0;
}
export function getPreferences(userId?: string): UserPreferences {
const defaultPrefs: UserPreferences = {
substance: 'nicotine',
trackingStartDate: null,
hasCompletedSetup: false,
dailyGoal: null,
quitPlan: null,
userName: null,
userAge: null,
};
if (typeof window === 'undefined') {
return defaultPrefs;
}
const key = getStorageKey('quit_smoking_preferences', userId);
const data = localStorage.getItem(key);
if (!data) {
return defaultPrefs;
}
return { ...defaultPrefs, ...JSON.parse(data) };
}
export function savePreferences(preferences: UserPreferences, userId?: string): void {
if (typeof window === 'undefined') return;
const key = getStorageKey('quit_smoking_preferences', userId);
localStorage.setItem(key, JSON.stringify(preferences));
}
export function getLastPromptDate(userId?: string): string | null {
if (typeof window === 'undefined') return null;
const key = getStorageKey('quit_smoking_last_prompt', userId);
return localStorage.getItem(key);
}
export function setLastPromptDate(date: string, userId?: string): void {
if (typeof window === 'undefined') return;
const key = getStorageKey('quit_smoking_last_prompt', userId);
localStorage.setItem(key, date);
}
export function shouldShowUsagePrompt(): boolean {
// Always show the prompt - users can log multiple times throughout the day
return true;
}
export function getWeeklyData(substance: 'nicotine' | 'weed', userId?: string): UsageEntry[] {
const data = getUsageData(userId);
const today = new Date();
const weekAgo = new Date(today);
weekAgo.setDate(weekAgo.getDate() - 7);
return data.filter((entry) => {
const entryDate = new Date(entry.date);
return entry.substance === substance && entryDate >= weekAgo && entryDate <= today;
});
}
export function calculateWeeklyAverage(substance: 'nicotine' | 'weed', userId?: string): number {
const weeklyData = getWeeklyData(substance, userId);
if (weeklyData.length === 0) return 0;
const total = weeklyData.reduce((sum, entry) => sum + entry.count, 0);
return Math.round(total / weeklyData.length);
}
export function hasOneWeekOfData(substance: 'nicotine' | 'weed', userId?: string): boolean {
const prefs = getPreferences(userId);
if (!prefs.trackingStartDate) return false;
const startDate = new Date(prefs.trackingStartDate);
const today = new Date();
const daysDiff = Math.floor((today.getTime() - startDate.getTime()) / (1000 * 60 * 60 * 24));
return daysDiff >= 7;
}
export function generateQuitPlan(substance: 'nicotine' | 'weed', userId?: string): QuitPlan {
const baseline = calculateWeeklyAverage(substance, userId);
const today = new Date();
const startDate = today.toISOString().split('T')[0];
// 6-week reduction plan
const endDate = new Date(today);
endDate.setDate(endDate.getDate() + 42);
// Gradual reduction: each week reduce by ~15-20%
const weeklyTargets: number[] = [];
let current = baseline;
for (let i = 0; i < 6; i++) {
current = Math.max(0, Math.round(current * 0.8));
weeklyTargets.push(current);
}
return {
startDate,
endDate: endDate.toISOString().split('T')[0],
weeklyTargets,
baselineAverage: baseline,
};
}
export function getCurrentWeekTarget(userId?: string): number | null {
const prefs = getPreferences(userId);
if (!prefs.quitPlan) return null;
const startDate = new Date(prefs.quitPlan.startDate);
const today = new Date();
const weekNumber = Math.floor((today.getTime() - startDate.getTime()) / (1000 * 60 * 60 * 24 * 7));
if (weekNumber >= prefs.quitPlan.weeklyTargets.length) {
return 0; // Goal achieved
}
return prefs.quitPlan.weeklyTargets[weekNumber];
}
export function clearDayData(date: string, substance: 'nicotine' | 'weed', userId?: string): void {
if (typeof window === 'undefined') return;
const key = getStorageKey('quit_smoking_usage', userId);
const data = getUsageData(userId);
const filtered = data.filter((e) => !(e.date === date && e.substance === substance));
localStorage.setItem(key, JSON.stringify(filtered));
}
export function clearAllData(userId?: string): void {
if (typeof window === 'undefined') return;
const usageKey = getStorageKey('quit_smoking_usage', userId);
const prefsKey = getStorageKey('quit_smoking_preferences', userId);
const promptKey = getStorageKey('quit_smoking_last_prompt', userId);
localStorage.removeItem(usageKey);
localStorage.removeItem(prefsKey);
localStorage.removeItem(promptKey);
}