Feature: Add an onboarding page and redirect users to that page if the user is not logged in. Have 3 sample latest question an... - #103
Open
lazydev-issue-resolver[bot] wants to merge 1 commit into
Conversation
Generated autonomously by LazyDev.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Resolves #102
Generated autonomously by LazyDev.
Implementation Plan
I have gathered all the context I need. Here's my implementation plan.
Implementation Plan: Onboarding Page + Auth Redirect
Context / Findings
AuthProvider(components/auth-provider.tsx) stores a"auth"flag insessionStorageand exposesisAuthenticated,isAdmin,password,login,logoutviauseAuth(). Because auth lives insessionStorage, a Next.jsmiddleware.tscannot read it — the redirect must be done client-side in a page effect.app/page.tsx(HomePage) currently renders for everyone with no auth check. There is no onboarding page today.GET /api/questions?scope=public&limit=N&page=N(seeapp/api/questions/route.ts), which supportsscope=publicandlimit— usable to fetch 3 sample questions.QuestionCard(components/question-card.tsx) hides answers behind a "Show Answer" button (useState(false)). For onboarding we want the Q&A visible, so we add an optional prop.app/login/page.tsx) callslogin(password), which pushes to/admin— unchanged by this feature.isAuthenticatedstartsfalseand is only set totruein auseEffectinAuthProvider. A naive redirect on!isAuthenticatedwould bounce logged-in users too. We fix this by exposing anauthLoadingflag from the provider.Step 1 — Expose
authLoadingincomponents/auth-provider.tsxSymbols:
AuthContextType(interface),AuthProvider(function).authLoading: boolean;to theAuthContextTypeinterface.AuthProvider, add state:const [authLoading, setAuthLoading] = React.useState(true);useEffectsosetAuthLoading(false)runs on every exit path:if (!auth) return;toif (!auth) { setAuthLoading(false); return; }try/catchwith afinally { setAuthLoading(false); }(keep the existingsessionStorage.removeItem("auth")calls in thecatch/else branches as-is).authLoadingto the context value object passed toAuthContext.Provider.This is the single source of truth for "auth is still being determined" and prevents redirect races.
Step 2 — Redirect unauthenticated users from the home page
File:
app/page.tsx— symbol:HomePage(default export function).const { isAdmin, logout } = useAuth();to also pullisAuthenticatedandauthLoading:const { isAdmin, logout, isAuthenticated, authLoading } = useAuth();(therouterfromuseRouter()already exists).useEffects, e.g. right after theuseEffectthat restores the exam type):if (authLoading) return null;just before the mainreturn (JSX to avoid flashing the page content for a frame (all hooks are above it, so this is safe).Step 3 — Let
QuestionCardshow the answer initiallyFile:
components/question-card.tsx— symbols:QuestionCardProps(interface),QuestionCard(function).QuestionCardProps:showAnswerInitially?: boolean;export function QuestionCard({ question, showAnswerInitially = false }: QuestionCardProps)and change the state initializer toReact.useState(showAnswerInitially).app/page.tsx,components/admin/admin-question-list.tsxuses its ownAdminQuestionListItem, notQuestionCard) are unaffected since the prop defaults tofalse.Step 4 — Create
app/onboarding/page.tsxNew file,
"use client", default-exported functionOnboardingPage. Follow the existing page patterns (seeapp/login/page.tsxfor theThemeToggleplacement andapp/page.tsxfor fetch + loading/empty/error rendering).Structure:
React,useRouterfromnext/navigation,QuestionCard,ThemeToggle,Buttonfrom@/components/ui/button,useAuth, typesQuestionandPaginatedResponsefrom@/lib/types, optional lucide icons (e.g.ArrowRight,Sparkles).sampleQuestions: Question[],loading: boolean(inittrue)./(mirrors Step 2's pattern):if (authLoading) return; if (isAuthenticated) router.replace("/");with deps[authLoading, isAuthenticated, router].fetch("/api/questions?scope=public&limit=3"), parsePaginatedResponse<Question>,setSampleQuestions(data.data); setloadingfalse infinally; use a cancelled flag for cleanup (match the fetch/error-handling pattern inHomePage'sfetchQuestions).ThemeToggle(matchapp/login/page.tsx).new Date().getHours()) plus a welcome headline such as "Welcome to AWS Developer Q&A" and a short subheading ("Practice the latest AWS Developer questions and answers."), all with Tailwind classes consistent with the app (text-center,space-y-4,text-muted-foreground, etc.).<Button size="lg" onClick={() => router.push("/login")}>Get Started</Button>linking to the existing/loginpage.<QuestionCard question={q} showAnswerInitially />(keyed byq._id ?? q.id ?? index, same as home page). Include loading state (Loading sample questions...) and empty state (No questions available yet.), matching the home page's conditional-render pattern.Step 5 — Sanity / no other changes needed
app/admin/page.tsxalready gates itself with an inline password form, so no redirect is needed there.app/api/questions/route.tsalready supportsscope=public+limit=3; no API change required.login()→/admin); the onboarding CTA routes through/login.pnpm format(Prettier is checked bypnpm build) after the changes.Files touched (summary)
components/auth-provider.tsxauthLoadingstate + context fieldapp/page.tsx!isAuthenticated→/onboardingafterauthLoadingresolvescomponents/question-card.tsxshowAnswerInitiallypropapp/onboarding/page.tsx