Fix per-user data isolation by passing userId explicitly to all storage operations
- Pass user.id explicitly to all storage function calls instead of relying on global state - Add userId prop to UsageCalendar and UsagePromptDialog components - Fix UserHeader to use user.id when fetching preferences - Add refreshKey to force calendar re-render after logging usage Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
a244e740c9
commit
39a1e858fb
@ -1,6 +1,6 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { User } from '@/lib/session';
|
||||
import {
|
||||
getUsageData,
|
||||
@ -34,14 +34,17 @@ export function Dashboard({ user }: DashboardProps) {
|
||||
const [showSetup, setShowSetup] = useState(false);
|
||||
const [showUsagePrompt, setShowUsagePrompt] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [refreshKey, setRefreshKey] = useState(0);
|
||||
|
||||
const loadData = () => {
|
||||
const prefs = getPreferences();
|
||||
const usage = getUsageData();
|
||||
const loadData = useCallback(() => {
|
||||
// Always pass user.id explicitly to ensure correct data is loaded
|
||||
const prefs = getPreferences(user.id);
|
||||
const usage = getUsageData(user.id);
|
||||
setPreferences(prefs);
|
||||
setUsageData(usage);
|
||||
setRefreshKey(prev => prev + 1);
|
||||
return prefs;
|
||||
};
|
||||
}, [user.id]);
|
||||
|
||||
useEffect(() => {
|
||||
// Set the current user ID for all storage operations
|
||||
@ -56,7 +59,7 @@ export function Dashboard({ user }: DashboardProps) {
|
||||
}
|
||||
|
||||
setIsLoading(false);
|
||||
}, [user.id]);
|
||||
}, [user.id, loadData]);
|
||||
|
||||
const handleSetupComplete = (data: { substance: 'nicotine' | 'weed'; name: string; age: number }) => {
|
||||
const today = new Date().toISOString().split('T')[0];
|
||||
@ -69,35 +72,41 @@ export function Dashboard({ user }: DashboardProps) {
|
||||
userName: data.name,
|
||||
userAge: data.age,
|
||||
};
|
||||
savePreferences(newPrefs);
|
||||
savePreferences(newPrefs, user.id);
|
||||
setPreferences(newPrefs);
|
||||
setShowSetup(false);
|
||||
setShowUsagePrompt(true);
|
||||
setRefreshKey(prev => prev + 1);
|
||||
};
|
||||
|
||||
const handleUsageSubmit = (count: number) => {
|
||||
if (!preferences || count === 0) {
|
||||
if (!preferences) {
|
||||
setShowUsagePrompt(false);
|
||||
loadData();
|
||||
return;
|
||||
}
|
||||
|
||||
const today = new Date().toISOString().split('T')[0];
|
||||
saveUsageEntry({
|
||||
date: today,
|
||||
count,
|
||||
substance: preferences.substance,
|
||||
});
|
||||
if (count > 0) {
|
||||
const today = new Date().toISOString().split('T')[0];
|
||||
saveUsageEntry({
|
||||
date: today,
|
||||
count,
|
||||
substance: preferences.substance,
|
||||
}, user.id);
|
||||
}
|
||||
|
||||
setShowUsagePrompt(false);
|
||||
loadData();
|
||||
// Reload data and force calendar refresh
|
||||
const usage = getUsageData(user.id);
|
||||
setUsageData(usage);
|
||||
setRefreshKey(prev => prev + 1);
|
||||
};
|
||||
|
||||
const handleGeneratePlan = () => {
|
||||
if (!preferences) return;
|
||||
|
||||
const plan = generateQuitPlan(preferences.substance);
|
||||
const plan = generateQuitPlan(preferences.substance, user.id);
|
||||
const updatedPrefs = { ...preferences, quitPlan: plan };
|
||||
savePreferences(updatedPrefs);
|
||||
savePreferences(updatedPrefs, user.id);
|
||||
setPreferences(updatedPrefs);
|
||||
};
|
||||
|
||||
@ -138,9 +147,11 @@ export function Dashboard({ user }: DashboardProps) {
|
||||
<div className="grid gap-6 md:grid-cols-2">
|
||||
<div className="space-y-6">
|
||||
<UsageCalendar
|
||||
key={refreshKey}
|
||||
usageData={usageData}
|
||||
substance={preferences.substance}
|
||||
onDataUpdate={loadData}
|
||||
userId={user.id}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-6">
|
||||
@ -148,9 +159,9 @@ export function Dashboard({ user }: DashboardProps) {
|
||||
<QuitPlanCard
|
||||
plan={preferences.quitPlan}
|
||||
onGeneratePlan={handleGeneratePlan}
|
||||
hasEnoughData={hasOneWeekOfData(preferences.substance)}
|
||||
hasEnoughData={hasOneWeekOfData(preferences.substance, user.id)}
|
||||
daysTracked={getDaysTracked()}
|
||||
currentAverage={calculateWeeklyAverage(preferences.substance)}
|
||||
currentAverage={calculateWeeklyAverage(preferences.substance, user.id)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -166,6 +177,7 @@ export function Dashboard({ user }: DashboardProps) {
|
||||
onClose={() => setShowUsagePrompt(false)}
|
||||
onSubmit={handleUsageSubmit}
|
||||
substance={preferences.substance}
|
||||
userId={user.id}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@ -19,9 +19,10 @@ interface UsageCalendarProps {
|
||||
usageData: UsageEntry[];
|
||||
substance: 'nicotine' | 'weed';
|
||||
onDataUpdate: () => void;
|
||||
userId: string;
|
||||
}
|
||||
|
||||
export function UsageCalendar({ usageData, substance, onDataUpdate }: UsageCalendarProps) {
|
||||
export function UsageCalendar({ usageData, substance, onDataUpdate, userId }: UsageCalendarProps) {
|
||||
const [selectedDate, setSelectedDate] = useState<Date | undefined>(undefined);
|
||||
const [editCount, setEditCount] = useState('');
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
@ -36,7 +37,7 @@ export function UsageCalendar({ usageData, substance, onDataUpdate }: UsageCalen
|
||||
|
||||
setSelectedDate(date);
|
||||
const dateStr = date.toISOString().split('T')[0];
|
||||
const currentCount = getUsageForDate(dateStr, substance);
|
||||
const currentCount = getUsageForDate(dateStr, substance, userId);
|
||||
setEditCount(currentCount.toString());
|
||||
setIsEditing(true);
|
||||
};
|
||||
@ -45,7 +46,7 @@ export function UsageCalendar({ usageData, substance, onDataUpdate }: UsageCalen
|
||||
if (selectedDate) {
|
||||
const dateStr = selectedDate.toISOString().split('T')[0];
|
||||
const newCount = parseInt(editCount, 10) || 0;
|
||||
setUsageForDate(dateStr, newCount, substance);
|
||||
setUsageForDate(dateStr, newCount, substance, userId);
|
||||
onDataUpdate();
|
||||
}
|
||||
setIsEditing(false);
|
||||
@ -62,7 +63,7 @@ export function UsageCalendar({ usageData, substance, onDataUpdate }: UsageCalen
|
||||
const handleClearDay = () => {
|
||||
if (selectedDate) {
|
||||
const dateStr = selectedDate.toISOString().split('T')[0];
|
||||
clearDayData(dateStr, substance);
|
||||
clearDayData(dateStr, substance, userId);
|
||||
onDataUpdate();
|
||||
}
|
||||
setIsEditing(false);
|
||||
|
||||
@ -18,6 +18,7 @@ interface UsagePromptDialogProps {
|
||||
onClose: () => void;
|
||||
onSubmit: (count: number) => void;
|
||||
substance: 'nicotine' | 'weed';
|
||||
userId: string;
|
||||
}
|
||||
|
||||
export function UsagePromptDialog({
|
||||
@ -25,6 +26,7 @@ export function UsagePromptDialog({
|
||||
onClose,
|
||||
onSubmit,
|
||||
substance,
|
||||
userId,
|
||||
}: UsagePromptDialogProps) {
|
||||
const [wantsToLog, setWantsToLog] = useState<boolean | null>(null);
|
||||
const [count, setCount] = useState('1');
|
||||
@ -33,7 +35,7 @@ export function UsagePromptDialog({
|
||||
const substanceLabelPlural = substance === 'nicotine' ? 'puffs/cigarettes' : 'hits';
|
||||
|
||||
const today = new Date().toISOString().split('T')[0];
|
||||
const todayCount = typeof window !== 'undefined' ? getUsageForDate(today, substance) : 0;
|
||||
const todayCount = typeof window !== 'undefined' ? getUsageForDate(today, substance, userId) : 0;
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (wantsToLog === true && count) {
|
||||
|
||||
@ -14,9 +14,9 @@ export function UserHeader({ user }: UserHeaderProps) {
|
||||
const [userName, setUserName] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const prefs = getPreferences();
|
||||
const prefs = getPreferences(user.id);
|
||||
setUserName(prefs.userName);
|
||||
}, []);
|
||||
}, [user.id]);
|
||||
|
||||
const initials = [user.firstName?.[0], user.lastName?.[0]]
|
||||
.filter(Boolean)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user