Skip to content

Feature/supabase auth - #34

Merged
DucCuong159 merged 19 commits into
mainfrom
feature/supabase-auth
Aug 11, 2026
Merged

Feature/supabase auth#34
DucCuong159 merged 19 commits into
mainfrom
feature/supabase-auth

Conversation

@DucCuong159

@DucCuong159 DucCuong159 commented Jan 7, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit
Release Notes
New Features

Added authentication system with login and sign-up functionality.
Protected pages now require authentication with automatic redirects to login.
New header with user profile display and logout option.
Enhanced error handling and recovery for Tarot AR feature.
Style

Improved layout and responsive design throughout the app.
Restructured navigation interface.
Chores

Added Supabase authentication backend support.

- Add supabaseClient.ts for Supabase initialization
- Add authListener.ts to handle auth state changes
- Add authSlice.ts for Redux auth state management
- Integrate authSlice into Redux store
- Add paths.ts with PATHS, LABELS, and MENU_ITEMS constants
- Add requiresAuth flag for protected routes
- Improve maintainability by centralizing route definitions
- Create ProtectedRoute wrapper for protected pages
- Add loading state during auth initialization
- Redirect to login with return URL for unauthenticated users
- Use Ant Design components (Flex, Space, Spin, Typography)
- Create Login component with toggle between sign up and sign in modes
- Integrate Supabase authentication (signUp, signInWithPassword)
- Add form validation using Zod schema
- Implement return URL functionality after login
- Add responsive design with Ant Design components
- Use centralized constants for UI text and configuration
- Create Header component with navigation menu
- Filter menu items based on authentication status
- Add login/logout functionality
- Display user email when authenticated
- Add responsive design with SCSS
- Replace old NavBar with new Header
- Add auth state initialization on app mount
- Setup auth listener for session changes
- Add ProtectedRoute for Todo and Tarot pages
- Add Login route
- Replace NavBar with new Header component
- Update background color to use SCSS variable
- Check authentication before navigating to protected routes
- Redirect to login with return URL if not authenticated
- Prevent flash of protected pages before redirect
- Remove unused Home.scss file
- Add todo-container wrapper with flexbox layout
- Add todo-list-body for better content grouping
- Use gap for consistent spacing between elements
- Update card styling with white background and border-radius
- Add subtle box-shadow to cards
- Clean up unused CSS (legacy grid, sortable, action buttons)
- Use SCSS variables consistently (gray-50 for background)
- Organize responsive styles within component blocks
- Add try-catch for WebGLRenderer initialization
- Add onError callback to TarotSceneCallbacks interface
- Display user-friendly error message when WebGL is not supported
- Add error state handling in TarotAR component
- Show Result component with reload option on WebGL failure
- Fix unused variable lint error
- Add proper typing for form submission handler
- Export FormRef type for external use
- Improve component reusability
- Update BackLink default path from /todo-list to /todo
- Update TodoDetail to use PATHS constant
- Ensure consistency with centralized path configuration
@DucCuong159 DucCuong159 self-assigned this Jan 7, 2026
@coderabbitai

coderabbitai Bot commented Jan 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added sign-up and login flows with session tracking, protected pages, and authentication-aware navigation.
    • Added a responsive header with menu navigation, user status, and logout.
    • Added centralized application routes and improved form reset and submission support.
  • Bug Fixes

    • Improved Tarot AR error handling with recovery guidance and reload support.
    • Improved attachment cleanup when leaving todo forms.
  • Style

    • Refreshed layouts, responsive styling, todo cards, spacing, and visual presentation.

Walkthrough

Adds Supabase authentication, Redux auth state, protected routes, centralized paths, a Header, and a Login page. The change also updates application initialization, form behavior, todo navigation, Tarot error handling, and related layouts and styles.

Changes

Authentication and application structure

Layer / File(s) Summary
Authentication state and routing
.env.example, .gitignore, package.json, src/store/..., src/utils/..., src/constants/paths.ts, src/components/ProtectedRoute/ProtectedRoute.tsx, src/views/App.tsx
Adds the Supabase client, auth listener, Redux auth slice, centralized route constants, protected routing, and session initialization.
Header and login flow
src/views/common/Header/..., src/views/common/NavBar/..., src/views/Page/Login/...
Replaces NavBar with an auth-aware Header and adds sign-up and sign-in flows with validation, error handling, session dispatch, and redirects.
Page navigation and form behavior
src/views/Page/Home/..., src/views/Page/TodoList/..., src/views/Page/TodoDetail/..., src/views/common/Form/Form.tsx, src/views/common/BackLink/BackLink.tsx
Uses centralized paths, adds auth-aware Home navigation, updates todo forms and navigation, adds form reset and compound-item APIs, and changes the BackLink default route.
Tarot error handling
src/views/Page/Tarot/TarotAR.tsx, src/views/Page/Tarot/TarotScene.ts
Propagates Tarot scene initialization errors and displays a reloadable error result.
Layout and visual updates
src/views/App.scss, src/styles/global.scss, src/views/Page/TodoList/TodoList.scss, src/views/Page/Home/Home.scss, src/views/Page/TodoDetail/TodoDetail.scss
Updates header-driven layout, card styling, todo list presentation, responsive rules, and container constraints.

Estimated code review effort: 4 (Complex) | ~60 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 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 (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: adding Supabase authentication.
Description check ✅ Passed The description accurately covers authentication, protected routes, header changes, Tarot error handling, and layout updates.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/supabase-auth

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

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

⚠️ Outside diff range comments (2)
src/views/Page/TodoDetail/TodoDetail.tsx (1)

55-56: Use PATHS constant for route checking.

Line 55 hardcodes the path string "/todo-create" for checking create mode. Consider using the imported PATHS constant for consistency.

♻️ Proposed fix
-const isCreateMode = window.location.pathname === "/todo-create";
+const isCreateMode = window.location.pathname === PATHS.TODO_CREATE;
src/views/Page/TodoList/components/TodoForm/TodoForm.tsx (1)

229-257: Blob URLs are created on every render, causing memory leaks.

URL.createObjectURL(item) is called during the render cycle every time the component re-renders. While you track URLs for cleanup on unmount, new URLs are created each render for the same files, accumulating in memory.

Proposed fix using useMemo or stable URL mapping
+ const blobUrlMap = React.useRef<Map<File, string>>(new Map());

  const fileList: UploadFile[] = value.map(
    (item: any, index: number) => {
      if (item instanceof File) {
-       // Create blob URL for preview
-       const previewUrl = URL.createObjectURL(item);
-       // Track for cleanup
-       if (!createdBlobUrls.current.includes(previewUrl)) {
-         createdBlobUrls.current.push(previewUrl);
-       }
+       // Reuse existing blob URL or create new one
+       let previewUrl = blobUrlMap.current.get(item);
+       if (!previewUrl) {
+         previewUrl = URL.createObjectURL(item);
+         blobUrlMap.current.set(item, previewUrl);
+         createdBlobUrls.current.push(previewUrl);
+       }
        return {
          uid: (item as any).uid || `new-${index}`,
          name: item.name,
          status: "done",
          url: previewUrl,
          thumbUrl: previewUrl,
          originFileObj: item,
        } as UploadFile;
      }
🤖 Fix all issues with AI agents
In @src/components/ProtectedRoute/ProtectedRoute.tsx:
- Line 41: The Ant Design Space usage is passing an invalid prop name
"orientation" on the Space component; replace the "orientation" prop with the
correct "direction" prop on the Space element in ProtectedRoute (i.e., change
Space orientation="vertical" to Space direction="vertical") so the layout
direction is applied correctly.
- Around line 17-27: The useEffect in ProtectedRoute currently uses a hardcoded
100ms timeout (isLoading/setIsLoading) which can cause a race where Supabase
session restoration is slower and authenticated users are redirected; replace
this mechanism by selecting the auth initialization/loading state from Redux
(e.g., useAppSelector(state => state.auth.isLoading or state.auth.initialized)
instead of the timeout), derive isLoading from that selector and only perform
redirect logic after that auth loading flag is false, and remove the artificial
setTimeout and its cleanup so the component waits for real auth readiness (refer
to useAppSelector, state.auth.user, isLoading, setIsLoading and the useEffect
inside ProtectedRoute).

In @src/views/Page/Login/Login.scss:
- Around line 2-3: Add an inline comment in Login.scss beside the existing rules
to document the margin-offset pattern: note that min-height: calc(100vh - 64px)
corresponds to the Header's explicit height (64px) and that margin: -24px
intentionally counteracts the parent .app-content 24px padding to produce an
edge-to-edge, full-viewport layout; keep the comment concise and colocated with
the min-height/margin declarations so future maintainers understand the layout
intent.
🧹 Nitpick comments (10)
src/utils/supabaseClient.ts (1)

6-10: Consider failing fast when credentials are missing.

The client is created with empty strings when env vars are missing, which will cause confusing runtime errors during auth operations (e.g., sign-in, sign-out). Consider throwing an error to fail fast during initialization rather than allowing a non-functional client.

♻️ Suggested improvement
 if (!supabaseUrl || !supabaseAnonKey) {
-  console.error("Missing Supabase URL or Anon Key. Check .env.local");
+  throw new Error("Missing Supabase URL or Anon Key. Check .env.local");
 }

-export const supabase = createClient(supabaseUrl || "", supabaseAnonKey || "");
+export const supabase = createClient(supabaseUrl, supabaseAnonKey);

Alternatively, if you want the app to run in degraded mode without auth, wrap auth-dependent operations with guards.

src/views/common/Header/Header.tsx (2)

27-30: Add error handling for sign-out.

If signOut() fails (e.g., network error), the user is still redirected to HOME while potentially remaining authenticated. This could cause confusion.

♻️ Suggested fix
 const handleLogout = async () => {
-  await supabase.auth.signOut();
-  history.push(PATHS.HOME);
+  const { error } = await supabase.auth.signOut();
+  if (error) {
+    console.error("Sign out failed:", error.message);
+    // Optionally show user notification
+    return;
+  }
+  history.push(PATHS.HOME);
 };

45-51: Menu highlighting won't work for sub-routes.

When on /todo/123, currentPath won't match PATHS.TODO ("/todo"), so the Todo menu item won't be highlighted. Consider matching by prefix for nested routes.

♻️ Possible approach
// Derive selected key by finding the menu item whose path is a prefix of currentPath
const selectedKey = visibleMenuItems.find(
  (item) => currentPath === item.path || currentPath.startsWith(item.path + "/")
)?.key;

// Then use: selectedKeys={selectedKey ? [selectedKey] : []}
src/views/common/Header/Header.scss (1)

62-68: Targeting Ant Design internal class may break on version updates.

Styling .ant-menu-item directly is fragile as Ant Design may change class names between versions. Consider using Ant Design's theming/token system or applying styles via the component's className prop with a more specific selector.

src/views/Page/Tarot/TarotScene.ts (1)

214-226: Code ordering is confusing: matBack referenced before declaration.

The error callback references matBack (lines 223-224) before it's declared (line 232). While this works because the callback executes asynchronously after matBack is initialized, the code order is misleading and could cause issues if refactored.

♻️ Consider reordering for clarity

Declare matBack before the textureLoader.load call, or move the error handler logic after the material declarations.

src/constants/paths.ts (1)

23-29: Consider i18n for menu labels.

The labels are hardcoded in English. Based on learnings, the project enforces Vietnamese (vi-VN) locale. Consider using an i18n library (e.g., react-i18next) for these labels to support localization, or update to Vietnamese if that's the target language.

src/views/App.tsx (1)

24-29: Consider adding error handling for session fetch.

The getSession() call doesn't handle potential errors. If the Supabase client fails to fetch the session (e.g., network issues), the error is silently ignored.

Proposed fix
  useEffect(() => {
-   supabase.auth.getSession().then(({ data: { session } }) => {
-     if (session) {
-       dispatch(setAuthUser({ user: session.user, session }));
-     }
-   });
+   supabase.auth.getSession().then(({ data: { session }, error }) => {
+     if (error) {
+       console.error("Failed to fetch session:", error);
+       return;
+     }
+     if (session) {
+       dispatch(setAuthUser({ user: session.user, session }));
+     }
+   });
src/views/Page/Tarot/TarotAR.tsx (1)

88-99: Control flow is confusing and may cause unintended behavior.

The guard logs an error if sceneManager.current is null, but only returns early when error is truthy. If the scene manager is null for reasons other than an error (e.g., component not yet initialized), startGame() is still called via optional chaining, which silently does nothing.

Proposed fix
  const handleTopicSelect = (topic: TarotTopic) => {
+   if (!sceneManager.current) {
+     console.error("❌ Scene Manager not found during topic select!");
+     return;
+   }
+
    dispatch(setSelectedTopic(topic));
    dispatch(setStep(TarotStep.PICKING));
-   if (!sceneManager.current) {
-     console.error("❌ Scene Manager not found during topic select!");
-     if (error) return;
-   }
-   sceneManager.current?.startGame();
+   sceneManager.current.startGame();

    // Start Audio
    soundManager.playSelectSound();
  };
src/views/Page/Login/Login.tsx (1)

130-131: Avoid as any type cast for onSubmit handler.

The as any cast bypasses type safety. Consider properly typing the Form component's onSubmit prop or adjusting the handler signature.

src/views/common/Form/Form.tsx (1)

54-59: Automatic reset on unmount may not be necessary.

React Hook Form already cleans up its internal state when the component unmounts. This explicit reset could cause unnecessary re-renders before unmount or interfere with transitions where form state should persist.

Consider removing this effect unless there's a specific use case requiring form reset before unmount.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8fd8b21 and 4a087df.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (31)
  • .env.example
  • .gitignore
  • package.json
  • src/components/ProtectedRoute/ProtectedRoute.tsx
  • src/constants/paths.ts
  • src/store/index.ts
  • src/store/slices/authSlice.ts
  • src/utils/authListener.ts
  • src/utils/supabaseClient.ts
  • src/views/App.scss
  • src/views/App.tsx
  • src/views/Page/Home/Home.scss
  • src/views/Page/Home/Home.tsx
  • src/views/Page/Login/Login.scss
  • src/views/Page/Login/Login.tsx
  • src/views/Page/Tarot/TarotAR.tsx
  • src/views/Page/Tarot/TarotScene.ts
  • src/views/Page/TodoDetail/TodoDetail.scss
  • src/views/Page/TodoDetail/TodoDetail.tsx
  • src/views/Page/TodoList/TodoList.scss
  • src/views/Page/TodoList/components/TodoForm/TodoForm.tsx
  • src/views/Page/TodoList/components/TodoListContent/TodoListContent.tsx
  • src/views/Page/TodoList/components/TodoListHeader/TodoListHeader.scss
  • src/views/Page/TodoList/components/TodoListHeader/TodoListHeader.tsx
  • src/views/common/BackLink/BackLink.tsx
  • src/views/common/Form/Form.tsx
  • src/views/common/Header/Header.scss
  • src/views/common/Header/Header.tsx
  • src/views/common/NavBar/NavBar.scss
  • src/views/common/NavBar/NavBar.tsx
  • src/views/common/NavBar/index.ts
💤 Files with no reviewable changes (8)
  • src/views/common/NavBar/index.ts
  • src/views/Page/TodoDetail/TodoDetail.scss
  • src/views/common/NavBar/NavBar.scss
  • .gitignore
  • src/views/common/NavBar/NavBar.tsx
  • .env.example
  • src/views/Page/Home/Home.scss
  • src/views/Page/TodoList/components/TodoListHeader/TodoListHeader.scss
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-12-10T19:29:31.324Z
Learnt from: DucCuong159
Repo: DucCuong159/Reactjs_test PR: 24
File: src/views/Page/TodoList/TodoList.tsx:307-311
Timestamp: 2025-12-10T19:29:31.324Z
Learning: Enforce Vietnamese (vi-VN) locale usage across the project for date formatting, numbers, and localization. In code, apply toLocaleString / Intl APIs with 'vi-VN' or configure i18n libraries to default to 'vi-VN'. Ensure UI components format dates, currencies, and relative times using the locale, and centralize locale configuration to avoid hard-coded formats per file.

Applied to files:

  • src/utils/authListener.ts
  • src/components/ProtectedRoute/ProtectedRoute.tsx
  • src/utils/supabaseClient.ts
  • src/constants/paths.ts
  • src/views/Page/TodoList/components/TodoListContent/TodoListContent.tsx
  • src/views/Page/Login/Login.tsx
  • src/views/Page/Tarot/TarotAR.tsx
  • src/views/common/Header/Header.tsx
  • src/store/slices/authSlice.ts
  • src/views/App.tsx
  • src/views/common/Form/Form.tsx
  • src/views/Page/TodoList/components/TodoListHeader/TodoListHeader.tsx
  • src/views/Page/TodoDetail/TodoDetail.tsx
  • src/views/Page/Home/Home.tsx
  • src/views/Page/Tarot/TarotScene.ts
  • src/views/common/BackLink/BackLink.tsx
  • src/store/index.ts
  • src/views/Page/TodoList/components/TodoForm/TodoForm.tsx
🧬 Code graph analysis (12)
src/utils/authListener.ts (2)
src/utils/supabaseClient.ts (1)
  • supabase (10-10)
src/store/index.ts (1)
  • store (7-14)
src/components/ProtectedRoute/ProtectedRoute.tsx (2)
src/store/hooks.ts (1)
  • useAppSelector (5-5)
src/constants/paths.ts (1)
  • PATHS (6-17)
src/views/Page/TodoList/components/TodoListContent/TodoListContent.tsx (4)
src/views/common/StatusTag/index.ts (1)
  • StatusTag (1-1)
src/views/common/StatusTag/StatusTag.tsx (1)
  • StatusTag (11-30)
src/utils/statusUtils.ts (1)
  • getStatusLabel (7-9)
src/utils/dateUtils.ts (1)
  • formatDate (8-10)
src/views/Page/Login/Login.tsx (4)
src/store/hooks.ts (1)
  • useAppDispatch (4-4)
src/views/common/Form/Form.tsx (2)
  • FormRef (24-27)
  • Form (75-77)
src/utils/supabaseClient.ts (1)
  • supabase (10-10)
src/constants/paths.ts (1)
  • PATHS (6-17)
src/views/Page/Tarot/TarotAR.tsx (1)
src/views/types/tarot.ts (1)
  • TarotTopic (27-30)
src/views/common/Header/Header.tsx (3)
src/store/hooks.ts (1)
  • useAppSelector (5-5)
src/constants/paths.ts (3)
  • PATHS (6-17)
  • MENU_ITEMS (35-54)
  • LABELS (23-29)
src/utils/supabaseClient.ts (1)
  • supabase (10-10)
src/views/App.tsx (5)
src/store/hooks.ts (1)
  • useAppDispatch (4-4)
src/utils/supabaseClient.ts (1)
  • supabase (10-10)
src/utils/authListener.ts (1)
  • setupAuthListener (5-23)
src/views/common/ScrollToTop/ScrollToTop.tsx (1)
  • ScrollToTop (8-16)
src/constants/paths.ts (1)
  • PATHS (6-17)
src/views/Page/TodoList/components/TodoListHeader/TodoListHeader.tsx (1)
src/constants/paths.ts (1)
  • PATHS (6-17)
src/views/Page/TodoDetail/TodoDetail.tsx (1)
src/constants/paths.ts (1)
  • PATHS (6-17)
src/views/Page/Home/Home.tsx (2)
src/store/hooks.ts (1)
  • useAppSelector (5-5)
src/constants/paths.ts (1)
  • PATHS (6-17)
src/store/index.ts (3)
src/store/slices/todoSlice.ts (1)
  • todoSlice (132-143)
src/store/slices/todoDetailSlice.ts (1)
  • todoDetailSlice (30-31)
src/store/slices/authSlice.ts (1)
  • authSlice (47-48)
src/views/Page/TodoList/components/TodoForm/TodoForm.tsx (2)
src/views/common/Form/Form.tsx (1)
  • Form (75-77)
src/views/common/Form/index.ts (1)
  • Form (1-1)
🔇 Additional comments (40)
src/views/App.scss (2)

12-21: LGTM! Layout changes align with the new header-based design.

The flexbox layout with column direction and the updated content styling (auto overflow, flex expansion, and padding) properly support the new authentication-aware header layout introduced in this PR.


18-18: The $gray-50 SCSS variable is properly defined and no issues exist.

The variable is correctly declared in src/styles/_variables.scss with the value #f9fafb; and is accessible to App.scss. No compilation errors will occur.

src/views/Page/TodoList/components/TodoListHeader/TodoListHeader.tsx (2)

4-4: LGTM! Good use of centralized routing constants.

Replacing the hard-coded route with PATHS.TODO_CREATE improves maintainability and consistency across the application.

Also applies to: 33-33


42-43: LGTM! Added input attributes improve accessibility and testability.

Adding id and name attributes to the Search component enhances form semantics and makes the input easier to target in automated tests.

src/views/Page/Login/Login.scss (1)

14-35: LGTM! Responsive design breakpoints are well-structured.

The progressive width adjustments (30% → 40% → 50% → 60% → 70%) provide good responsiveness across device sizes, ensuring the login card remains usable on smaller screens while maintaining a compact appearance on larger displays.

src/views/Page/TodoList/components/TodoListContent/TodoListContent.tsx (1)

43-102: LGTM! Structural reorganization aligns with layout improvements.

Wrapping the results count and todo grid in a .todo-list-body container is a clean refactoring that supports the CSS layout changes introduced in this PR. All existing rendering logic and functionality are preserved.

package.json (1)

13-13: @supabase/supabase-js version specification is appropriate and free from known vulnerabilities.

Version ^2.89.0 is actively maintained by Supabase with no reported security advisories. The caret (^) allows automatic updates to patch and minor versions (e.g., 2.90.0), ensuring the project benefits from bug fixes and improvements while maintaining backward compatibility.

src/store/slices/authSlice.ts (3)

1-9: LGTM!

The imports and AuthState interface are properly structured with appropriate nullable types for user, session, and error states.


18-45: LGTM!

The reducers are well-structured and follow Redux Toolkit best practices. State transitions are handled correctly with proper cleanup of loading and error states.


47-49: LGTM!

Actions and reducer are properly exported following Redux Toolkit conventions.

src/views/Page/TodoDetail/TodoDetail.tsx (4)

15-15: LGTM!

The centralized PATHS constants are correctly imported and consistently used throughout the component, replacing hardcoded route strings. This improves maintainability and aligns with the PR's routing refactor.

Also applies to: 89-89, 119-119, 152-152, 159-159


58-80: LGTM!

The cleanup mechanism properly prevents memory leaks by:

  • Capturing attachments in a ref to avoid stale closures
  • Revoking blob URLs on unmount using the ref
  • Resetting component state on unmount

This is a solid pattern for resource cleanup in React components.


84-94: LGTM!

The 404 Result component is correctly simplified by removing the unnecessary wrapper div, and properly uses the centralized PATHS constant for navigation.


45-45: LGTM!

The refactor to a const arrow function with default export and the removal of the root div wrapper in favor of a fragment are both appropriate. The fragment removes an unnecessary DOM element while preserving the component structure.

Also applies to: 166-166, 333-337

src/views/Page/TodoList/TodoList.scss (3)

4-19: LGTM!

The layout refactor from grid to flexbox column is clean and modern. The use of gap for spacing and the container padding/background settings are appropriate.


21-76: LGTM!

The card styling with proper padding, shadows, and typography is well-structured. The centered pagination container follows good UI patterns.


78-129: LGTM!

The responsive styles appropriately adjust spacing and typography for tablet and mobile viewports. The Ant Design component overrides maintain consistent styling across the form elements.

src/views/common/BackLink/BackLink.tsx (1)

10-10: LGTM!

The default route update from "/todo-list" to "/todo" correctly aligns with the centralized PATHS constants introduced in this PR (PATHS.TODO = "/todo").

src/utils/authListener.ts (1)

5-23: Initial session handling is already in place in App.tsx, making INITIAL_SESSION handling in setupAuthListener unnecessary.

The app correctly handles initial session in App.tsx using supabase.auth.getSession() before calling setupAuthListener(). This two-step approach means setupAuthListener only needs to handle subsequent auth state changes (SIGNED_IN, TOKEN_REFRESHED, USER_UPDATED, SIGNED_OUT), which it does correctly. No changes needed.

src/store/index.ts (1)

1-17: LGTM!

The auth slice is correctly integrated into the Redux store following the same pattern as existing slices. The RootState type will automatically include the new auth field.

src/views/Page/Tarot/TarotScene.ts (2)

62-72: Good addition of error boundary for scene initialization.

The try/catch with onError callback provides proper error propagation to consumers, enabling graceful error UI in TarotAR.tsx.


92-100: Appropriate WebGL detection with clear error message.

Good practice to catch WebGL initialization failures and provide a descriptive error message for debugging.

src/constants/paths.ts (1)

1-58: Well-structured centralized constants.

Good use of as const for literal types and clean separation of paths, labels, and menu configuration. The exported types (PathKey, LabelKey) provide good type safety for consumers.

src/views/Page/Home/Home.tsx (3)

4-5: LGTM!

Clean imports for centralized path constants and typed Redux selector.


7-15: LGTM!

Good practice extracting UI text into a typed constant with as const for literal types.


21-27: LGTM!

The navigateTo helper correctly implements auth-aware navigation by redirecting unauthenticated users to the login page with the return path in state.

src/views/App.tsx (2)

31-35: LGTM!

Proper cleanup of the auth subscription on unmount prevents memory leaks and stale callbacks.


44-58: LGTM!

Routes are well-organized using centralized PATHS constants, with appropriate protection applied to authenticated routes.

src/views/Page/Tarot/TarotAR.tsx (3)

35-35: LGTM!

Good addition of error state for WebGL/AR initialization failures.


71-78: LGTM!

Proper cleanup of the scene manager when an error occurs, preventing resource leaks and allowing clean re-initialization.


114-150: LGTM!

Clean error UI with helpful guidance for users experiencing WebGL issues. The reload button provides a straightforward recovery path.

src/views/Page/Login/Login.tsx (4)

17-20: LGTM!

Clean Zod schema with appropriate validation rules for email format and password minimum length.


47-55: LGTM!

Good UX practice mapping authentication errors to user-friendly messages.


75-108: LGTM!

Well-structured authentication flow with proper error handling, success feedback, and redirect logic.


114-118: No changes needed — orientation is the correct prop for newer versions of Ant Design.

The orientation prop is the modern API for Ant Design's Space component. In antd v4/v5, the prop was named direction, but newer releases replaced it with orientation (supporting the same values: "horizontal" | "vertical"). The code is using the current standard.

Likely an incorrect or invalid review comment.

src/views/Page/TodoList/components/TodoForm/TodoForm.tsx (2)

114-130: LGTM!

Clean migration to the new Form.Item wrapper pattern.


144-145: LGTM!

Good accessibility practice adding explicit id and name attributes to form controls.

src/views/common/Form/Form.tsx (3)

12-13: LGTM!

Clean extension of the FormProps interface with optional style and onSubmit props.


49-51: LGTM!

Exposing the reset method via the imperative handle allows parent components to programmatically reset the form.


74-77: LGTM!

Clean compound component pattern attaching AntdForm.Item as Form.Item for convenient usage.

Comment thread src/components/ProtectedRoute/ProtectedRoute.tsx Outdated
Comment thread src/components/ProtectedRoute/ProtectedRoute.tsx Outdated
Comment thread src/views/Page/Login/Login.scss
DucCuong159 and others added 4 commits January 8, 2026 00:33
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
- Remove artificial 100ms timeout that could cause race condition
- Use auth.loading from Redux to track real auth initialization
- Set loading state in App.tsx before checking session
- Prevents authenticated users from being redirected during slow session restoration
- Fixes race condition where Supabase session loads slower than timeout
- Change initial loading from false to true in authSlice
- Prevents ProtectedRoute from redirecting before session check completes
- Fixes issue where reload on protected pages redirects to login
- Remove redundant setAuthLoading(true) dispatch in App.tsx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @src/views/App.tsx:
- Around line 24-38: The getSession() call in the useEffect lacks error handling
so failures leave the app loading; wrap supabase.auth.getSession() with a catch
(or use try/catch if converted to async) to handle errors, log the error, and
dispatch setAuthLoading(false) (and/or dispatch an auth error action if
available) instead of leaving the app stuck; keep the existing success path that
dispatches setAuthUser({ user: session.user, session }) and ensure the
subscription from setupAuthListener is still unsubscribed in the cleanup.
🧹 Nitpick comments (2)
src/components/ProtectedRoute/ProtectedRoute.tsx (2)

21-21: Consider making the exact prop configurable.

The exact prop is hardcoded to true, which works for the current routes but limits flexibility if you later need non-exact protected routes (e.g., nested paths).

♻️ Proposed refactor to allow configurable exact matching
 <Route
-  exact
   {...rest}
   render={(props) => {

This way, callers can pass exact via ...rest when needed.


29-29: Consider extracting the header height as a constant.

The 64px value appears to be the header height but is hardcoded. If the header height changes, this calculation will be incorrect.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 210697e and d3c3386.

📒 Files selected for processing (3)
  • src/components/ProtectedRoute/ProtectedRoute.tsx
  • src/store/slices/authSlice.ts
  • src/views/App.tsx
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-12-10T19:29:31.324Z
Learnt from: DucCuong159
Repo: DucCuong159/Reactjs_test PR: 24
File: src/views/Page/TodoList/TodoList.tsx:307-311
Timestamp: 2025-12-10T19:29:31.324Z
Learning: Enforce Vietnamese (vi-VN) locale usage across the project for date formatting, numbers, and localization. In code, apply toLocaleString / Intl APIs with 'vi-VN' or configure i18n libraries to default to 'vi-VN'. Ensure UI components format dates, currencies, and relative times using the locale, and centralize locale configuration to avoid hard-coded formats per file.

Applied to files:

  • src/components/ProtectedRoute/ProtectedRoute.tsx
  • src/store/slices/authSlice.ts
  • src/views/App.tsx
🧬 Code graph analysis (2)
src/components/ProtectedRoute/ProtectedRoute.tsx (2)
src/store/hooks.ts (1)
  • useAppSelector (5-5)
src/constants/paths.ts (1)
  • PATHS (6-17)
src/views/App.tsx (5)
src/store/hooks.ts (1)
  • useAppDispatch (4-4)
src/utils/supabaseClient.ts (1)
  • supabase (10-10)
src/utils/authListener.ts (1)
  • setupAuthListener (5-23)
src/views/common/ScrollToTop/ScrollToTop.tsx (1)
  • ScrollToTop (8-16)
src/constants/paths.ts (1)
  • PATHS (6-17)
🔇 Additional comments (4)
src/components/ProtectedRoute/ProtectedRoute.tsx (1)

16-17: LGTM! Race condition resolved correctly.

The component now uses Redux auth loading state instead of the arbitrary timeout, eliminating the race condition where slow session restoration could incorrectly redirect authenticated users.

src/views/App.tsx (1)

46-60: LGTM! Route protection properly implemented.

The routes are correctly configured with PATHS constants for maintainability, and ProtectedRoute properly guards authenticated pages while keeping Home and Login public.

src/store/slices/authSlice.ts (2)

11-16: LGTM! Initial loading state prevents race conditions.

The loading: true initialization (with explanatory comment) ensures ProtectedRoute won't redirect before the session check completes, directly addressing the race condition mentioned in the PR objectives.


18-45: LGTM! Reducers correctly manage auth state lifecycle.

All reducers properly handle the loading flag and state transitions. The implementation is clean, type-safe, and follows Redux Toolkit best practices.

Comment thread src/views/App.tsx
- Add box-shadow override in global.scss for all .ant-card components
- Remove local .ant-card override from TodoList.scss
- Fix Space component prop: orientation -> direction in ProtectedRoute
- Apply consistent shadow (0 2px 8px rgba(0,0,0,0.1)) across all cards

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/styles/global.scss`:
- Around line 3-5: Update the global font-family declaration to remove quotes
only from the single-word names "Roboto", "Oxygen", "Ubuntu", and "Cantarell";
retain quotes around multi-word names such as "Segoe UI", "Helvetica Neue", and
any other names requiring them.

In `@src/views/App.tsx`:
- Around line 25-37: Update the supabase.auth.getSession flow in App so it
inspects the resolved error alongside session, dispatches setAuthError for both
resolved refresh failures and rejected promises, and preserves loading-state
handling. Add an authentication error/retry rendering path before the
unauthenticated redirect so ProtectedRoute is not reached when auth.error is
present; do not treat an errored null session as a normal signed-out state.
🪄 Autofix

✅ Autofix completed


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3250586f-ab3f-4196-9bfc-22e33d3b3e8b

📥 Commits

Reviewing files that changed from the base of the PR and between d3c3386 and f13e005.

📒 Files selected for processing (3)
  • src/styles/global.scss
  • src/views/App.tsx
  • src/views/Page/TodoList/TodoList.scss
💤 Files with no reviewable changes (1)
  • src/views/Page/TodoList/TodoList.scss

Comment thread src/styles/global.scss Outdated
Comment thread src/views/App.tsx
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Fixes Applied Successfully

Fixed 3 file(s) based on 2 unresolved review comments.

Files modified:

  • src/components/ProtectedRoute/ProtectedRoute.tsx
  • src/styles/global.scss
  • src/views/App.tsx

Commit: c281c810f350125b31b620687705c95f33f56cda

The changes have been pushed to the feature/supabase-auth branch.

Time taken: 3m 3s

Fixed 3 file(s) based on 2 unresolved review comments.

Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
@DucCuong159
DucCuong159 merged commit 2209b78 into main Aug 11, 2026
2 checks passed
@DucCuong159
DucCuong159 deleted the feature/supabase-auth branch August 11, 2026 20:04
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.

1 participant