Skip to content

(SP: 2) [Frontend][Backend] Sync guest quiz results after authentication across all login methods#147

Merged
ViktorSvertoka merged 2 commits into
developfrom
feat/post-auth-guest-quiz-sync
Jan 18, 2026
Merged

(SP: 2) [Frontend][Backend] Sync guest quiz results after authentication across all login methods#147
ViktorSvertoka merged 2 commits into
developfrom
feat/post-auth-guest-quiz-sync

Conversation

@kryvosheyin
Copy link
Copy Markdown
Collaborator

@kryvosheyin kryvosheyin commented Jan 15, 2026

This pull request introduces a refactor and improvement to the way guest quiz results are synchronized with user accounts after authentication. The main change is the extraction of guest quiz result synchronization logic from the login page into a new reusable client component, improving maintainability and user experience. There are also minor updates to the project structure documentation and a redirect fix for Google auth.

Guest Quiz Result Synchronization Improvements:

Authentication and Routing:

  • Changed the Google OAuth callback to redirect users to /dashboard instead of the home page after successful authentication, improving user flow.

Related Issue

Issue: #<146>

Database Changes (if applicable)

  • Schema migration required
  • Seed data updated
  • Breaking changes to existing queries
  • Transaction-safe migration
  • Migration tested locally on Neon

How Has This Been Tested?

  • Tested locally
  • Verified in development environment
  • Checked responsive layout (if UI-related)
  • Tested accessibility (keyboard / screen reader)

Screenshots (if applicable)


Checklist

Before submitting

  • Code has been self-reviewed
  • No TypeScript or console errors
  • Code follows project conventions
  • Scope is limited to this feature/fix
  • No unrelated refactors included
  • English used in code, commits, and docs
  • New dependencies discussed with team
  • Database migration tested locally (if applicable)
  • GitHub Projects card moved to In Review

Reviewers

Summary by CodeRabbit

  • New Features

    • Automatic synchronization of pending guest quiz results after sign-in (client-side sync runs post-auth).
  • Bug Fixes

    • Quiz score calculation precision improved (no premature rounding).
    • Google sign-in now redirects users to the dashboard.
  • Chores

    • Various frontend structure and documentation updates; added locale-aware pages and auth components.

✏️ Tip: You can customize this high-level summary in your review settings.

@netlify
Copy link
Copy Markdown

netlify Bot commented Jan 15, 2026

Deploy Preview for develop-devlovers ready!

Name Link
🔨 Latest commit b6a41ee
🔍 Latest deploy log https://app.netlify.com/projects/develop-devlovers/deploys/696cf83d51f87400086cf327
😎 Deploy Preview https://deploy-preview-147--develop-devlovers.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 15, 2026

📝 Walkthrough

Walkthrough

This PR moves guest-quiz post-login sync into a new PostAuthQuizSync client component mounted on the dashboard, converts guest-result API to session-authenticated, adds comprehensive validation and persistence for quiz attempts, changes Google OAuth callback to redirect to /dashboard, and removes rounding from average score display.

Changes

Cohort / File(s) Summary
Post-auth sync component
frontend/components/auth/PostAuthQuizSync.tsx
New client component that posts any pending guest quiz from localStorage to /api/quiz/guest-result, writes a sessionStorage summary on success, clears pending data, and triggers a router refresh.
Dashboard integration
frontend/app/[locale]/dashboard/page.tsx
Mounted <PostAuthQuizSync /> in dashboard layout; removed Math.round around average score calculation.
Login / OAuth redirect
frontend/app/[locale]/login/page.tsx, frontend/app/api/auth/google/callback/route.ts
Removed inline post-login guest-result save from login page; changed Google callback redirect target from / to /dashboard.
Guest-result API (session-auth + validation)
frontend/app/api/quiz/guest-result/route.ts
Switched to session-derived userId, added session auth (401 on missing), quiz existence check (404), answers length/mapping/duplicate validation, integrity/timing/points computation, inserts for quizAttempts and quizAttemptAnswers, award points call, error handling, and export const runtime = "nodejs".
Project structure & docs
frontend/project-structure.txt, new README and component files under frontend/components/auth
Large structural/doc updates and added auth UI components (OAuthButtons, ProviderButton) documented; review for unrelated file moves.

Sequence Diagram

sequenceDiagram
    participant Browser
    participant Dashboard
    participant PostAuthQuizSync
    participant LocalStorage
    participant API as /api/quiz/guest-result
    participant DB as Database
    participant SessionStorage

    Browser->>Dashboard: Navigate to /dashboard (post-auth)
    Dashboard->>PostAuthQuizSync: Mount component
    PostAuthQuizSync->>LocalStorage: Read pending quiz result
    LocalStorage-->>PostAuthQuizSync: Return pending result
    alt pending result exists
        PostAuthQuizSync->>API: POST quizId, answers, violations, timeSpentSeconds
        API->>DB: Validate quiz, questions, answer mappings
        DB-->>API: Validation result
        alt valid
            API->>DB: Insert quizAttempt and quizAttemptAnswers
            DB-->>API: Confirm insertion
            API->>DB: Award points (awardQuizPoints)
            DB-->>API: Points confirmed
            API-->>PostAuthQuizSync: Return success
            PostAuthQuizSync->>SessionStorage: Write quiz_just_saved summary
            PostAuthQuizSync->>LocalStorage: Clear pending result
            PostAuthQuizSync->>Dashboard: Trigger router.refresh()
        else invalid
            API-->>PostAuthQuizSync: Return 4xx error
        end
    else no pending result
        PostAuthQuizSync-->>PostAuthQuizSync: Exit silently
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers

  • AM1007
  • ViktorSvertoka

Poem

🐰 I hopped from login to dashboard bright,

Pending quizzes sent in post-auth light,
Answers checked, points scored true,
Session saved a little victory too,
Hooray — the quiz is safely through! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and specifically describes the main objective: syncing guest quiz results after authentication across all login methods, which aligns with the core changes in the PR.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/app/api/quiz/guest-result/route.ts (1)

147-178: Wrap attempt/answers/points in a transaction to avoid partial writes — but note driver limitation.

The concern about partial writes is valid: if awardQuizPoints fails after inserting the attempt and answers, the API returns 500 while persisting incomplete data, and a client retry creates duplicate attempts.

However, the suggested .transaction() approach has a critical issue: the production database uses the Neon HTTP driver (drizzle-orm/neon-http), which does not support interactive transactions. Transactions require the Neon WebSocket driver or a full TCP pg driver.

Recommended alternatives:

  • Make awardQuizPoints idempotent using a unique constraint on sourceId in pointTransactions, so retries don't duplicate points.
  • Add compensating logic in the catch block to delete the attempt and answers if awardQuizPoints fails, ensuring atomicity at the application level.
  • Switch the production database driver to Neon WebSocket/serverless if transaction support is critical.
🤖 Fix all issues with AI agents
In `@frontend/components/auth/PostAuthQuizSync.tsx`:
- Around line 13-65: The current flow sets sessionStorage key
"guest_quiz_sync_done" before the POST finishes, which can permanently block
future syncs; change the logic in PostAuthQuizSync (around
useEffect/getPendingQuizResult/clearPendingQuizResult) to stop setting the
global flag early — either remove the "guest_quiz_sync_done" flag entirely or
replace it with a result-scoped key (e.g., include pendingResult.quizId or
savedAt in the key) and only write that key after the POST returns success, keep
removing/clearing it on any failure or catch, and ensure
clearPendingQuizResult() and router.refresh() still run after a confirmed
successful save.
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0109871 and d0590fe.

📒 Files selected for processing (6)
  • frontend/app/[locale]/dashboard/page.tsx
  • frontend/app/[locale]/login/page.tsx
  • frontend/app/api/auth/google/callback/route.ts
  • frontend/app/api/quiz/guest-result/route.ts
  • frontend/components/auth/PostAuthQuizSync.tsx
  • frontend/project-structure.txt
💤 Files with no reviewable changes (1)
  • frontend/app/[locale]/login/page.tsx
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-12-30T16:01:02.523Z
Learnt from: kryvosheyin
Repo: DevLoversTeam/devlovers.net PR: 88
File: frontend/drizzle/schema.ts:153-153
Timestamp: 2025-12-30T16:01:02.523Z
Learning: The file frontend/drizzle/schema.ts is a legacy file not used by Drizzle or the runtime. The canonical schemas live in frontend/db/schema/* as configured in drizzle-config.ts, and that's what migrations and runtime use.

Applied to files:

  • frontend/project-structure.txt
🧬 Code graph analysis (3)
frontend/components/auth/PostAuthQuizSync.tsx (1)
frontend/lib/quiz/guest-quiz.ts (2)
  • getPendingQuizResult (27-49)
  • clearPendingQuizResult (51-54)
frontend/app/[locale]/dashboard/page.tsx (1)
frontend/components/auth/PostAuthQuizSync.tsx (1)
  • PostAuthQuizSync (10-70)
frontend/app/api/quiz/guest-result/route.ts (2)
frontend/lib/auth.ts (1)
  • getCurrentUser (95-116)
frontend/db/queries/points.ts (1)
  • calculateQuizPoints (7-12)
🔇 Additional comments (3)
frontend/app/api/auth/google/callback/route.ts (1)

155-155: Redirect update looks good.

Matches the new post-auth sync flow on the dashboard.

frontend/app/api/quiz/guest-result/route.ts (1)

2-146: Session-based userId + validation flow looks solid.

Good tightening of input checks and server-side user identity.

frontend/app/[locale]/dashboard/page.tsx (1)

10-61: Dashboard integration looks good.

PostAuthQuizSync placement is appropriate and average score calculation still reads clearly.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment thread frontend/components/auth/PostAuthQuizSync.tsx
@kryvosheyin kryvosheyin force-pushed the feat/post-auth-guest-quiz-sync branch from d0590fe to b6a41ee Compare January 18, 2026 15:11
@ViktorSvertoka ViktorSvertoka merged commit 16fe42e into develop Jan 18, 2026
8 checks passed
@ViktorSvertoka ViktorSvertoka deleted the feat/post-auth-guest-quiz-sync branch January 18, 2026 15:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants