From cfecfa5116a503853e936504b290fd7a88d7345d Mon Sep 17 00:00:00 2001 From: Jeet Debnath Date: Tue, 31 Mar 2026 10:23:49 +0530 Subject: [PATCH] fixes --- backend/__pycache__/models.cpython-312.pyc | Bin 7820 -> 7923 bytes backend/models.py | 2 ++ backend/routers/users.py | 2 ++ src/contexts/AuthContext.tsx | 4 ++-- src/hooks/useOnboardingTour.ts | 13 ------------- src/lib/api.ts | 2 +- src/pages/HomePage.tsx | 19 +++++++++++++------ src/pages/LoginPage.tsx | 2 +- 8 files changed, 21 insertions(+), 23 deletions(-) diff --git a/backend/__pycache__/models.cpython-312.pyc b/backend/__pycache__/models.cpython-312.pyc index bff9712fbbbd55017647ea3af79da1b73c36743d..1b1cfe70ec925c97d91b5a1fecddba87de9360bc 100644 GIT binary patch delta 1663 zcmb`HUuau(6vuPR%}si9lWa|zq|Ki$)~sF^H#=r&yCy5M>mR$tPFuHSMcaBa8k#oU zFG)x1(19CvAQ*RECW4@-pnH;nPcq;3GC{^bG%xxf_#%Q@5%k6L{iQ6XxHm7{&+qp; zzdz@Ef9Kr$X6pBp`>xxq+xWS0`fk4Rnfr515p>a;9x${59!E^CIm?xDQRL?fbk7LTZC{)&JIeM0yy^h`;n=VB za?dmjB7T!<%)*GT~|(Q_E(?2p1QAgecRQ2 zWqfn7TE4z=U+t#%osTOY(^t;dl9oMdq+)um@)O;qGH%4PmywvFyRAmR9&4ui7s%C!rr6Gq>N?NTS6>9?nw?K7V$hV!KkU1 ziejmzU6^0a7uH9`F}9g@F^l=Lz&RiboM$wJ`yw0GXnF6*f=q#LceF2Hmj=ifWwd87 zln2W@lczgilP;tx_z`wMMj`dc#OX6I0!#E{+cjkd(&+29FR1GCYx00uX}awj>Phml z4fo8dHDAtI`=;~dLQWuoW{Z$4yEWH;fYY;8c{9(lsFQGdJG$&ll z!?wWSWYhUz7}kv=SgVzSI!%C z&`|Qw?Eh!t7jYnPlRgODR2F5Hr#t@UlAh`e1d5nm1ug=D(UjUU8}86Mok@=GPG>@s zWmYe#6>I>$Bu}_kS=ky68_Hwy9xIqy1MtJ07MGY@J+HuWnbG9pRW^J>Z%2;6MP%O| z8F2zjrH8t+4UB<%2xGWMWx_*S*9Ku8Z@G|~#4lNh0 kN+FjPuhS3F!H}Wo)sAf&H`}qGqHhjt+ql^tq{Ff7KZzMbwEzGB delta 1722 zcma)+UuaWT9LMjex%qR`Yp6-vWH$-cuF9=V7o*GiCso(gl(t%(M!U7Nvzp9xYgau@ z9k*i?M8_T!#2?!fpT^ij83-cm#Xl(c=EElVF#06E3BG6xiZa;md$QTBw84;k&dKk0 z?(h8m-i3~{9p*jLG&KIaJTNzwxN83979(`Ws;5^0t3i*jqTtTEGQ3u3-CABht>xXn zR^S0m8}vEC_E5VgPIm$|R~$U+YnYZE7_*`+GeGr+iU5Hub2Mv4T#M&TN|YlMo2W#w?=DSE3A6tR$k-=pdNS| zcn@fyhsJh#^j65g{j!~rp^SfLRJmhH3(_bM16)9wF8VjstMg&}uK@x;>R;f#sr~fC z-&ghAW$MN=jZr$7qC=IZQy<`D7qAP+0^Ptei=B`Gd#Td2MJL?~M6T^MI|N61Zf&M* z53A-}vKPntfZaepqhB^-yUd>QdLJuBXicDrGo1`rEqHp~b!2jKTsGjDAOIV3r67Bt z00!t(pk4G_yA?PKclxTDhT)F<5I`{VuCFHL7xV5R{oviF&nXStq=m&t0fRBMe zMj4NXSzV+DRb8dJ1ee$4AZ)nlr*LqeGOW_3tb3qQSM0|Q_edR3UZ_}B3NnWyz!?3w z?u^JG@01SSaN#C;8mtyWO5}LzC>yf6HnVufJa{}mS}f$(=f;ZT1&JEl6;k;Iugb(% zVD&lrCA6^=U)AdIWy{A`KB}X9jReln&gzrms0!ha>V-}MtR2)3U9|L+NT7_w1DsUK!SsbnghNN!Ce-_31F zwI!4M9khL=k^KyZSL>Ih>-*()9Q;qOs}@#;{hT#F^KWVoz3;E3YP6}v<8AmjgfkV491r%F_%jI{ z2Tm}`w9yo+?_RJl*9ohkUUmFR-8}(Yz)hOAwulMk#cgY0mnvWp+G#*}Ay4v_`*;SD zuNh?=_=eRF=tXoJJczANsCZQ-)s-vx;=nBMJI%zJg+p_(0b9LDRT)&a)tF)$Rr5+^ nRT*^1j>p6)>W;UC{lYjOS=4x0jMfO_yVgaGm&F#k6d(K>lBPSQ diff --git a/backend/models.py b/backend/models.py index 2908e2f..02529e2 100644 --- a/backend/models.py +++ b/backend/models.py @@ -38,6 +38,7 @@ class UserUpdate(BaseModel): displayName: Optional[str] = None photoURL: Optional[str] = None theme: Optional[str] = None + tutorial: Optional[bool] = None class Config: json_schema_extra = { @@ -56,6 +57,7 @@ class User(BaseModel): createdAt: datetime updatedAt: datetime theme: str = "light" + tutorial: Optional[bool] = None class Config: from_attributes = True diff --git a/backend/routers/users.py b/backend/routers/users.py index 7240909..c6a6d3b 100644 --- a/backend/routers/users.py +++ b/backend/routers/users.py @@ -79,6 +79,7 @@ async def get_user_by_email(email: str): "displayName": user.get("displayName"), "photoURL": user.get("photoURL"), "theme": user.get("theme", "light"), + "tutorial": user.get("tutorial"), "createdAt": user["createdAt"].isoformat(), "updatedAt": user["updatedAt"].isoformat() } @@ -151,6 +152,7 @@ async def update_user(user_id: str, user_data: UserUpdate): "displayName": user.get("displayName"), "photoURL": user.get("photoURL"), "theme": user.get("theme", "light"), + "tutorial": user.get("tutorial"), "createdAt": user["createdAt"].isoformat(), "updatedAt": user["updatedAt"].isoformat(), "message": "User updated successfully" diff --git a/src/contexts/AuthContext.tsx b/src/contexts/AuthContext.tsx index 2cb0ccb..0d94513 100644 --- a/src/contexts/AuthContext.tsx +++ b/src/contexts/AuthContext.tsx @@ -37,6 +37,7 @@ type MongoUser = { displayName?: string photoURL?: string theme?: string + tutorial?: boolean } type AuthContextValue = { @@ -211,8 +212,7 @@ export function AuthProvider({ children }: { children: ReactNode }) { // Clear secret key from memory setSecretKey(null) setMongoUser(null) - // Reset onboarding so tour shows again on next login - localStorage.removeItem('gj-onboarding-done') + // Clear pending tour step (session state) localStorage.removeItem('gj-tour-pending-step') // Keep device key and encrypted key for next login // Do NOT clear localStorage or IndexedDB diff --git a/src/hooks/useOnboardingTour.ts b/src/hooks/useOnboardingTour.ts index f0ccad0..17a17e6 100644 --- a/src/hooks/useOnboardingTour.ts +++ b/src/hooks/useOnboardingTour.ts @@ -3,17 +3,8 @@ import { useNavigate } from 'react-router-dom' import { driver, type DriveStep } from 'driver.js' import 'driver.js/dist/driver.css' -const ONBOARDING_KEY = 'gj-onboarding-done' const TOUR_PENDING_KEY = 'gj-tour-pending-step' -export function hasSeenOnboarding(): boolean { - return localStorage.getItem(ONBOARDING_KEY) === 'true' -} - -export function markOnboardingDone(): void { - localStorage.setItem(ONBOARDING_KEY, 'true') -} - export function hasPendingTourStep(): string | null { return localStorage.getItem(TOUR_PENDING_KEY) } @@ -144,7 +135,6 @@ export function useOnboardingTour() { const driverObj = driver({ ...driverDefaults(), onDestroyStarted: () => { - markOnboardingDone() clearPendingTourStep() driverObj.destroy() }, @@ -175,7 +165,6 @@ export function useOnboardingTour() { const driverObj = driver({ ...driverDefaults(), onDestroyStarted: () => { - markOnboardingDone() clearPendingTourStep() driverObj.destroy() }, @@ -206,7 +195,6 @@ export function useOnboardingTour() { const driverObj = driver({ ...driverDefaults(), onDestroyStarted: () => { - markOnboardingDone() clearPendingTourStep() driverObj.destroy() }, @@ -216,7 +204,6 @@ export function useOnboardingTour() { // Last settings step → navigate to / if (activeIndex === steps.length - 1) { - markOnboardingDone() clearPendingTourStep() driverObj.destroy() navigate('/') diff --git a/src/lib/api.ts b/src/lib/api.ts index 43a24ba..c31e139 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -70,7 +70,7 @@ export async function getUserByEmail(email: string, token: string) { export async function updateUserProfile( userId: string, - updates: { displayName?: string; photoURL?: string; theme?: string }, + updates: { displayName?: string; photoURL?: string; theme?: string; tutorial?: boolean }, token: string ) { return apiCall(`/users/${userId}`, { diff --git a/src/pages/HomePage.tsx b/src/pages/HomePage.tsx index 8b331fa..8f1b651 100644 --- a/src/pages/HomePage.tsx +++ b/src/pages/HomePage.tsx @@ -1,12 +1,12 @@ import { useAuth } from '../contexts/AuthContext' import { Link, useNavigate } from 'react-router-dom' import { useState, useRef, useEffect } from 'react' -import { createEntry } from '../lib/api' +import { createEntry, updateUserProfile } from '../lib/api' import { encryptEntry } from '../lib/crypto' import BottomNav from '../components/BottomNav' import WelcomeModal from '../components/WelcomeModal' import { SaveBookAnimation } from '../components/SaveBookAnimation' -import { useOnboardingTour, hasSeenOnboarding, markOnboardingDone } from '../hooks/useOnboardingTour' +import { useOnboardingTour } from '../hooks/useOnboardingTour' import { PageLoader } from '../components/PageLoader' const AFFIRMATIONS = [ @@ -31,7 +31,7 @@ const SAVE_LEAVES = [ ] export default function HomePage() { - const { user, userId, secretKey, loading } = useAuth() + const { user, userId, mongoUser, secretKey, loading } = useAuth() const navigate = useNavigate() const [entry, setEntry] = useState('') const [title, setTitle] = useState('') @@ -47,19 +47,26 @@ export default function HomePage() { // Check if onboarding should be shown after login useEffect(() => { - if (!loading && user && userId && !hasSeenOnboarding()) { + if (!loading && user && userId && mongoUser && !mongoUser.tutorial) { setShowWelcome(true) } - }, [loading, user, userId]) + }, [loading, user, userId, mongoUser]) + + async function markTutorialDone() { + if (!user || !userId) return + const token = await user.getIdToken() + updateUserProfile(userId, { tutorial: true }, token).catch(console.error) + } const handleStartTour = () => { setShowWelcome(false) + markTutorialDone() startTour() } const handleSkipTour = () => { setShowWelcome(false) - markOnboardingDone() + markTutorialDone() } if (loading) { diff --git a/src/pages/LoginPage.tsx b/src/pages/LoginPage.tsx index 7324662..1ebbef3 100644 --- a/src/pages/LoginPage.tsx +++ b/src/pages/LoginPage.tsx @@ -28,7 +28,7 @@ export default function LoginPage() { } } - if (loading) { + if (loading || signingIn) { return }