Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: Switch to shadcn form in userResetPassword #9708

Open
wants to merge 77 commits into
base: develop
Choose a base branch
from

Conversation

AdityaJ2305
Copy link
Contributor

@AdityaJ2305 AdityaJ2305 commented Jan 3, 2025

Proposed Changes

@ohcnetwork/care-fe-code-reviewers

Merge Checklist

  • Add specs that demonstrate bug / test a new feature.
  • Update product documentation.
  • Ensure that UI text is kept in I18n files.
  • Prep screenshot or demo video for changelog entry, and attach it to issue.
  • Request for Peer Reviews
  • Completion of QA

Summary by CodeRabbit

Release Notes

  • Removed Components

    • Removed Form component and related context management
    • Removed ExtendPatientRegisterFormComponentType
  • New Features

    • Enhanced password reset form with improved validation using Zod and react-hook-form
    • Added password visibility toggle feature to the input component
    • Improved error handling for structured HTTP errors
  • Localization

    • Updated password-related terminology in English localization file
  • Improvements

    • Streamlined form management and validation processes
    • Upgraded UI components for form rendering
    • Updated response structure for password update API endpoint

Copy link
Contributor

coderabbitai bot commented Jan 3, 2025

Walkthrough

This pull request involves a significant refactoring of form management in the application. The primary changes include removing the custom Form component and FormContext, migrating the UserResetPassword component to use shadcn form components with react-hook-form and zod validation, and updating related type definitions. Additionally, password-related terminology in the localization file has been updated. The changes streamline form handling by adopting a more modern, library-based approach to form management and validation.

Changes

File Change Summary
src/components/Form/Form.tsx Entire component removed
src/components/Form/FormContext.ts Removed form context and related type definitions
src/components/Users/UserResetPassword.tsx Migrated to react-hook-form with zod validation, updated form components
public/locale/en.json Updated password-related key from current_password to old_password and added confirmation prompt
src/pluginTypes.ts Removed ExtendPatientRegisterFormComponentType and related type references
src/Utils/request/errorHandler.ts Added two new error handling functions for structured errors
src/Utils/request/api.tsx Updated response type for updatePassword route
src/Utils/request/types.ts Introduced StructuredError type and updated HTTPErrorCause type
src/components/ui/input.tsx Added password visibility toggle feature

Assessment against linked issues

Objective Addressed Explanation
Migrate UserResetPassword.tsx to shadcn's form
Delete old custom Form component
Delete FormContext.ts
Add eye toggle functionality to Input component

Possibly related PRs

Suggested labels

needs review, tested, P1

Suggested reviewers

  • rithviknishad
  • Jacobjeevan

Poem

🐰 Hop, hop, form farewell!
Old components bid goodbye
Shadcn's magic spell
Brings validation's sweet sigh
Code dances, clean and bright! 🌟


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

netlify bot commented Jan 3, 2025

Deploy Preview for care-ohc ready!

Name Link
🔨 Latest commit 5055633
🔍 Latest deploy log https://app.netlify.com/sites/care-ohc/deploys/677b2a28478cf600085212cc
😎 Deploy Preview https://deploy-preview-9708--care-ohc.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 site configuration.

@AdityaJ2305 AdityaJ2305 marked this pull request as ready for review January 3, 2025 14:58
@AdityaJ2305 AdityaJ2305 requested a review from a team as a code owner January 3, 2025 14:58
Copy link
Member

@rithviknishad rithviknishad left a comment

Choose a reason for hiding this comment

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

you missed one step, one more file was said to be deleted in the issue

src/components/Users/UserResetPassword.tsx Outdated Show resolved Hide resolved
src/components/Users/UserResetPassword.tsx Show resolved Hide resolved
src/components/Users/UserResetPassword.tsx Outdated Show resolved Hide resolved
Copy link
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

🧹 Nitpick comments (3)
src/components/Users/UserResetPassword.tsx (3)

28-50: Use i18n for user-facing error messages
The validation messages within the PasswordSchema (e.g., "Please enter current password", "New password must be at least 8 characters long", etc.) are hardcoded. To maintain consistency with the rest of the application and support localization, consider using t() or otherwise integrating them into your i18n workflow.


136-160: Avoid duplicate validations
You are using both zod to validate passwords and the validateRule function to check password requirements on focus. This might create unnecessary duplication and potential maintenance overhead. Consider consolidating all password checks in one place (preferably zod) and displaying those error messages consistently.


95-197: Consider adding a “show/hide password” toggle
The current form effectively captures password input and provides helpful validation. However, offering a “show/hide password” toggle can enhance user experience and reduce entry errors.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ed05fc0 and d2cfca6.

📒 Files selected for processing (2)
  • src/components/Form/Form.tsx (0 hunks)
  • src/components/Users/UserResetPassword.tsx (3 hunks)
💤 Files with no reviewable changes (1)
  • src/components/Form/Form.tsx
🔇 Additional comments (1)
src/components/Users/UserResetPassword.tsx (1)

200-208: Good approach to toggling edit mode
Toggling the password edit state with setIsEditing is a clean, straightforward approach and helps keep the UI clear. No issues found here.

src/components/Users/UserResetPassword.tsx Outdated Show resolved Hide resolved
Copy link
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: 2

🧹 Nitpick comments (3)
src/components/Users/UserResetPassword.tsx (3)

29-51: Add i18n support for validation messages

The validation messages in the schema are hardcoded in English. Consider using the translation function to support internationalization.

const PasswordSchema = z
  .object({
    current_password: z
      .string()
-      .min(1, { message: "Please enter current password" }),
+      .min(1, { message: t("please_enter_current_password") }),
    new_password_1: z
      .string()
-      .min(8, { message: "New password must be at least 8 characters long" })
+      .min(8, { message: t("password_length_validation") })
-      .regex(/\d/, { message: "Password must contain at least one number" })
+      .regex(/\d/, { message: t("password_number_validation") })
      .regex(/[a-z]/, {
-        message: "Password must contain at least one lowercase letter",
+        message: t("password_lowercase_validation"),
      })
      .regex(/[A-Z]/, {
-        message: "Password must contain at least one uppercase letter",
+        message: t("password_uppercase_validation"),
      }),
    new_password_2: z
      .string()
-      .min(1, { message: "Please confirm your new password" }),
+      .min(1, { message: t("please_confirm_password") }),
  })

70-90: Enhance mutation implementation and error handling

A few suggestions to improve the mutation implementation:

  1. Use isPending from useMutation instead of managing loading state manually
  2. Consider not resetting the form on error to allow users to fix mistakes
  3. Add type safety for the error response
- const { mutate: resetUserPasswordMutate } = useMutation({
+ const { mutate: resetUserPasswordMutate, isPending } = useMutation({
    mutationFn: async (formData: UpdatePasswordForm) => {
      const response = await mutate(routes.updatePassword, { silent: true })(
        formData,
      );
      if ("errors" in response) {
        throw response;
      }
      return response;
    },
    onSuccess: (data: any) => {
      Notification.Success({ msg: data?.message as string });
      resetPasswordForm.reset();
    },
    onError: (error: any) => {
+     type ErrorResponse = {
+       response?: {
+         data?: {
+           message?: string;
+         };
+       };
+     };
+     const typedError = error as ErrorResponse;
      const errorMessage =
-       error?.response?.data?.message || t("password_update_error");
+       typedError?.response?.data?.message || t("password_update_error");
      Notification.Error({ msg: errorMessage });
-     resetPasswordForm.reset();
    },
  });

212-220: Use shadcn's button variants for consistent styling

Instead of custom styling, consider using shadcn's button variants for consistent styling across the application.

  <Button
    onClick={() => setIsEditing(!isEditing)}
    type="button"
    id="change-edit-password-button"
-   className="flex items-center gap-2 rounded-sm border border-gray-100 bg-white px-3 py-1.5 text-sm text-[#009D48] shadow-sm hover:bg-gray-50"
+   variant="outline"
+   className="flex items-center gap-2"
  >
    <CareIcon icon={isEditing ? "l-times" : "l-edit"} className="h-4 w-4" />
    {isEditing ? t("cancel") : t("change_password")}
  </Button>
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d2cfca6 and c170f70.

📒 Files selected for processing (1)
  • src/components/Users/UserResetPassword.tsx (1 hunks)
🔇 Additional comments (1)
src/components/Users/UserResetPassword.tsx (1)

92-100: Unify password field naming convention

The form uses current_password while the API expects old_password. This creates unnecessary mapping and potential confusion.

Consider unifying the naming convention throughout the codebase:

  1. Update the API to use current_password, or
  2. Update the form to use old_password

src/components/Users/UserResetPassword.tsx Outdated Show resolved Hide resolved
src/components/Users/UserResetPassword.tsx Outdated Show resolved Hide resolved
Copy link
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

♻️ Duplicate comments (1)
src/components/Users/UserResetPassword.tsx (1)

136-161: 🛠️ Refactor suggestion

Remove duplicate password validation logic.

The password requirements are already defined in the zod schema. The manual validation here duplicates that logic and could become inconsistent.

Use the form's built-in error display instead:

- {isPasswordFieldFocused && (
-   <div
-     className="text-small mt-2 pl-2 text-secondary-500"
-     aria-live="polite"
-   >
-     {validateRule(
-       field.value.length >= 8,
-       t("password_length_validation"),
-       !field.value,
-     )}
-     {validateRule(
-       /[a-z]/.test(field.value),
-       t("password_lowercase_validation"),
-       !field.value,
-     )}
-     {validateRule(
-       /[A-Z]/.test(field.value),
-       t("password_uppercase_validation"),
-       !field.value,
-     )}
-     {validateRule(
-       /\d/.test(field.value),
-       t("password_number_validation"),
-       !field.value,
-     )}
-   </div>
- )}
+ <FormMessage />
🧹 Nitpick comments (1)
src/components/Users/UserResetPassword.tsx (1)

29-51: LGTM! Well-structured password validation schema.

The zod schema implementation is clean and includes all necessary validation rules. The error messages are clear and user-friendly.

Consider using t() for internationalization in error messages to maintain consistency with the rest of the application:

    old_password: z
      .string()
-     .min(1, { message: "Please enter current password" }),
+     .min(1, { message: t("please_enter_current_password") }),
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c170f70 and 0da92f6.

📒 Files selected for processing (2)
  • public/locale/en.json (1 hunks)
  • src/components/Users/UserResetPassword.tsx (1 hunks)
🔇 Additional comments (2)
src/components/Users/UserResetPassword.tsx (1)

189-196: LGTM! Proper button state handling.

The submit button correctly uses:

  • isDirty for the disabled state
  • isPending for the loading state
public/locale/en.json (1)

1266-1266: Verify the terminology change impact.

The change from "current_password" to "old_password" should be verified across the application to ensure consistency.

Run this script to check for any remaining usages of "current_password":

✅ Verification successful

The previous search might have missed some occurrences. Let's try a broader search pattern to catch variations in naming and also look at the AST to find password-related fields. This will help us better understand the password terminology usage across the codebase.


Terminology change is consistent with implementation

The search results confirm that the change from "current_password" to "old_password" is actually consistent with the codebase implementation. The form component UserResetPassword.tsx already uses old_password in:

  • Form schema validation
  • Form field definitions
  • API request model (UpdatePasswordForm)
  • Form field rendering

The change in the locale file from "current_password" to "old_password" aligns with the existing implementation, making the terminology consistent between the code and the UI.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for remaining "current_password" occurrences
echo "Searching for 'current_password' in code..."
rg "current_password" -g "!*.json"

echo "Searching for CurrentPassword in code..."
rg "CurrentPassword" -g "!*.json"

Length of output: 262


Script:

#!/bin/bash
# Let's try a more comprehensive search for password-related terms
echo "Searching for password-related terms in code files..."
rg -i "(?:old|current)[\s_-]?password" --type-not json -A 2 -B 2

echo -e "\nSearching for password form field references..."
ast-grep --pattern 'password'

Length of output: 4163

src/components/Users/UserResetPassword.tsx Outdated Show resolved Hide resolved
Copy link
Member

@rithviknishad rithviknishad left a comment

Choose a reason for hiding this comment

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

repeating the second time, do delete the other file that was mentioned in the issue

src/components/Users/UserResetPassword.tsx Outdated Show resolved Hide resolved
src/components/Users/UserResetPassword.tsx Outdated Show resolved Hide resolved
src/components/Users/UserResetPassword.tsx Outdated Show resolved Hide resolved
@AdityaJ2305
Copy link
Contributor Author

repeating the second time, do delete the other file that was mentioned in the issue

the context file is used by other file like pluginTypes.ts

@rithviknishad
Copy link
Member

delete those usages 🙂 we don't need it. let's get rid of weird things.

@AdityaJ2305
Copy link
Contributor Author

delete those usages 🙂 we don't need it. let's get rid of weird things.

field: FormContextValue<PatientForm>;

@rithviknishad
Copy link
Member

rithviknishad commented Jan 3, 2025

yup, you can remove that patient register form extension thing....

export type ExtendPatientRegisterFormComponentType = React.FC<{
facilityId: string;
patientId?: string;
state: {
form: {
[key: string]: any;
};
errors: {
[key: string]: string;
};
};
dispatch: React.Dispatch<any>;
field: FormContextValue<PatientForm>;
}>;

cc @gigincg

abhimanyurajeesh and others added 8 commits January 5, 2025 22:30
- Introduced a new PermissionContext to manage user permissions and super admin status across the application.
- Updated AppRouter to utilize PermissionProvider for managing permissions.
- Changed UserModel to store permissions as strings instead of objects.
- Refactored OrganizationFacilities and OrganizationPatients components to use updated permission checks and organization identifiers.
- Enhanced OrganizationLayout to conditionally render navigation items based on user permissions.

This commit improves the permission management system and ensures consistent handling of user permissions throughout the application.
Copy link
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: 0

🧹 Nitpick comments (1)
src/components/Users/UserResetPassword.tsx (1)

150-153: Simplify nested optional chaining.

The error message check can be simplified using optional chaining.

- {form.formState.errors?.new_password_1?.message &&
-   form.formState.errors?.new_password_1?.message.includes(
-     t("new_password_same_as_old"),
-   )}
+ {form.formState.errors?.new_password_1?.message?.includes(
+   t("new_password_same_as_old")
+ )}
🧰 Tools
🪛 Biome (1.9.4)

[error] 150-153: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2e5be57 and 2464dca.

📒 Files selected for processing (3)
  • public/locale/en.json (3 hunks)
  • src/components/Form/Form.tsx (1 hunks)
  • src/components/Users/UserResetPassword.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • public/locale/en.json
🧰 Additional context used
🪛 Biome (1.9.4)
src/components/Users/UserResetPassword.tsx

[error] 150-153: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🪛 GitHub Check: lint
src/components/Users/UserResetPassword.tsx

[failure] 21-21:
Insert

src/components/Form/Form.tsx

[failure] 170-170:
Delete

🪛 eslint
src/components/Users/UserResetPassword.tsx

[error] 21-21: Insert

(prettier/prettier)

src/components/Form/Form.tsx

[error] 170-171: Delete

(prettier/prettier)

🪛 GitHub Actions: Lint Code Base
src/components/Form/Form.tsx

[error] 170-170: Prettier formatting error: Invalid line break detected

🪛 GitHub Actions: Cypress Tests
src/components/Form/Form.tsx

[error] 9-9: Cannot find module '@/components/Form/FormContext' or its corresponding type declarations.

🪛 GitHub Actions: Deploy Care Fe
src/components/Form/Form.tsx

[error] 9-9: Cannot find module '@/components/Form/FormContext' or its corresponding type declarations

🔇 Additional comments (5)
src/components/Form/Form.tsx (1)

Line range hint 1-170: Verify the impact of Form component removal across the codebase.

The removal of this generic Form component in favor of shadcn forms is a good architectural decision. However, we should ensure all usages are migrated.

✅ Verification successful

Let me verify the usage patterns to better understand the impact.


Let me try another search to properly check the Form-related imports and their usage.


Let me try one more time with corrected syntax:


Let me try one final search without file type specifications:


The Form component being removed appears to be already replaced

Based on the search results, I can see that the Form component usages in the codebase are already using the new shadcn Form component, as evidenced by the usage patterns like <Form {...form}> which is typical of React Hook Form with shadcn/ui components. The imports from "@/components/Form/Form" were not found in the current codebase, suggesting the migration has already been completed.

Key observations:

  • All Form usages follow the pattern <Form {...form}> which is consistent with shadcn/ui form implementation
  • No direct imports from '@/components/Form/Form' were found
  • The Form component is being used in various features like PatientLogin, UserResetPassword, CreateFacilityForm, etc., but all appear to be using the new implementation
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any remaining imports or usages of the Form component
echo "Searching for Form component imports..."
rg -l "import.*Form.*from.*@/components/Form/Form"

echo "Searching for Form component usage..."
ast-grep --pattern 'Form $props={$_}'

Length of output: 1521


Script:

#!/bin/bash
# Check a sample of files to understand usage patterns
echo "Checking sample usage patterns..."
echo "=== PatientLogin.tsx ==="
rg -A 5 "import.*Form.*from.*@/components/Form/Form" src/pages/Appoinments/auth/PatientLogin.tsx

echo -e "\n=== ResourceCreate.tsx ==="
rg -A 5 "import.*Form.*from.*@/components/Form/Form" src/components/Resource/ResourceCreate.tsx

echo -e "\n=== FileUpload.tsx ==="
rg -A 5 "import.*Form.*from.*@/components/Form/Form" src/components/Files/FileUpload.tsx

# Check if there are any other Form-related imports that might be affected
echo -e "\nChecking other Form-related imports..."
rg "import.*from.*@/components/Form/" --type ts --type tsx

Length of output: 1800


Script:

#!/bin/bash
# Search for Form-related imports with proper file type handling
echo "Checking Form-related imports..."
rg "import.*from.*@/components/Form/" --type typescript --type tsx

# Check for actual Form component usage
echo -e "\nChecking Form component usage patterns..."
rg "<Form\b" --type typescript --type tsx -B 2 -A 2

# Check for other potential Form component references
echo -e "\nChecking Form component references..."
rg "\bForm\b.*=.*{" --type typescript --type tsx -B 2 -A 2

Length of output: 610


Script:

#!/bin/bash
# Search for actual Form component usage with fixed patterns
echo "Checking Form component usage..."
rg -t ts -t tsx "<Form" -B 2 -A 2

# Check imports from Form directory
echo -e "\nChecking Form directory imports..."
rg -t ts -t tsx "from ['\"]@/components/Form/" -B 1

# Check Form component assignments
echo -e "\nChecking Form component assignments..."
rg -t ts -t tsx "const Form" -B 1 -A 3

Length of output: 469


Script:

#!/bin/bash
# Search for Form component usage in the codebase
echo "Checking direct Form component usage..."
rg "<Form\s" -B 2 -A 2

# Check Form-related imports and dependencies
echo -e "\nChecking Form component imports and dependencies..."
rg "from '@/components/Form/Form'" -B 1

# Check for Form component exports and re-exports
echo -e "\nChecking Form exports..."
rg "export.*Form.*from '@/components/Form/Form'"

Length of output: 4095

🧰 Tools
🪛 GitHub Check: lint

[failure] 170-170:
Delete

🪛 GitHub Actions: Lint Code Base

[error] 170-170: Prettier formatting error: Invalid line break detected

src/components/Users/UserResetPassword.tsx (4)

205-212: LGTM! Button implementation follows best practices.

The button correctly:

  • Uses isPending for loading state
  • Disables when form is not dirty
  • Shows appropriate loading text

74-80: 🛠️ Refactor suggestion

Simplify mutation implementation.

Based on the established patterns:

  1. Use the inferred types from the routes schema instead of any
  2. Let the global error handler manage error notifications
- const { mutate: resetPassword, isPending } = useMutation({
-   mutationFn: mutate(routes.updatePassword),
-   onSuccess: () => {
-     toast.success(t("password_updated"));
-     form.reset();
-   },
- });
+ const { mutate: resetPassword, isPending } = useMutation({
+   mutationFn: mutate(routes.updatePassword),
+   onSuccess: (data) => {
+     toast.success(data.message);
+     form.reset();
+   }
+ });

Likely invalid or redundant comment.


29-55: 🛠️ Refactor suggestion

Extract translation calls from schema definition.

The current implementation evaluates translations only once when the schema is defined, which won't update if the language changes at runtime.

Extract the messages to constants:

+ const passwordMessages = {
+   current: t("please_enter_current_password"),
+   length: t("password_length_validation"),
+   number: t("password_number_validation"),
+   lowercase: t("password_lowercase_validation"),
+   uppercase: t("password_uppercase_validation"),
+   confirm: t("please_enter_confirm_password"),
+   mismatch: t("password_mismatch"),
+   sameAsOld: t("new_password_same_as_old"),
+ };

const PasswordSchema = z
  .object({
    old_password: z
      .string()
-     .min(1, { message: t("please_enter_current_password") }),
+     .min(1, { message: passwordMessages.current }),
    // Apply similar changes to other validation messages
  })

Likely invalid or redundant comment.


154-180: 🛠️ Refactor suggestion

Remove duplicate validation logic.

The password requirements are already defined in the zod schema. The manual validation here duplicates that logic and could become inconsistent.

- {isPasswordFieldFocused && (
-   <div
-     className="text-small mt-2 pl-2 text-secondary-500"
-     aria-live="polite"
-   >
-     {validateRule(
-       field.value.length >= 8,
-       t("password_length_validation"),
-       !field.value,
-     )}
-     {validateRule(
-       /[a-z]/.test(field.value),
-       t("password_lowercase_validation"),
-       !field.value,
-     )}
-     {validateRule(
-       /[A-Z]/.test(field.value),
-       t("password_uppercase_validation"),
-       !field.value,
-     )}
-     {validateRule(
-       /\d/.test(field.value),
-       t("password_number_validation"),
-       !field.value,
-     )}
-   </div>
- )}
+ <FormMessage />

Likely invalid or redundant comment.

@AdityaJ2305
Copy link
Contributor Author

do clear conflicts

@rithviknishad done

@rithviknishad
Copy link
Member

rithviknishad commented Jan 5, 2025

it doesn't inform the user what the error is when i click submit.

  1. do a self test of all the cases after making the changes and then request for review.

  2. let's keep it as grid with two columns (in desktop view) itself like how it was before. New and Confirm password can be in second row though however.

  3. let's not keep the submit button w-full. looks super weird on desktop.

  4. ensure all i18n texts are present. most of it are missing in en.json. do a self review please.

image image

@rithviknishad rithviknishad removed Deploy-Failed Deplyment is not showing preview merge conflict pull requests with merge conflict labels Jan 5, 2025
Copy link
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

🧹 Nitpick comments (4)
src/components/Users/UserResetPassword.tsx (4)

27-27: Remove unnecessary import

The mutate import is redundant since you're using useMutation from @tanstack/react-query. The mutation function can be defined inline.

-import mutate from "@/Utils/request/mutate";

65-65: Remove redundant state

The isPasswordFieldFocused state is used for manual validation display, which is redundant since we're using zod schema validation. The validation messages should be handled by FormMessage component.


75-81: Simplify mutation setup

The mutation can be simplified by defining the mutation function inline:

  const { mutate: resetPassword, isPending } = useMutation({
-   mutationFn: mutate(routes.updatePassword),
+   mutationFn: (data: UpdatePasswordForm) => 
+     routes.updatePassword(data),
    onSuccess: () => {
      toast.success(t("password_updated"));
      form.reset();
    },
  });

151-154: Simplify error message check

Use optional chaining to simplify the error message check:

- {form.formState.errors?.new_password_1?.message &&
-  form.formState.errors?.new_password_1?.message.includes(
-    t("new_password_same_as_old"),
-  ) && <FormMessage />}
+ {form.formState.errors.new_password_1?.message?.includes(
+   t("new_password_same_as_old")
+ ) && <FormMessage />}
🧰 Tools
🪛 Biome (1.9.4)

[error] 151-154: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2464dca and 9b6359b.

📒 Files selected for processing (3)
  • public/locale/en.json (3 hunks)
  • src/components/Form/Form.tsx (0 hunks)
  • src/components/Users/UserResetPassword.tsx (1 hunks)
💤 Files with no reviewable changes (1)
  • src/components/Form/Form.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • public/locale/en.json
🧰 Additional context used
🪛 Biome (1.9.4)
src/components/Users/UserResetPassword.tsx

[error] 151-154: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (2)
src/components/Users/UserResetPassword.tsx (2)

83-91: LGTM!

The form submission handler is well-implemented with proper typing and data transformation.


155-181: 🛠️ Refactor suggestion

Remove duplicate validation display

The manual validation display using validateRule duplicates the validation logic already defined in the zod schema. Remove this section and rely on FormMessage to display validation errors.

- {isPasswordFieldFocused && (
-   <div
-     className="text-small mt-2 pl-2 text-secondary-500"
-     aria-live="polite"
-   >
-     {validateRule(
-       field.value.length >= 8,
-       t("password_length_validation"),
-       !field.value,
-     )}
-     {validateRule(
-       /[a-z]/.test(field.value),
-       t("password_lowercase_validation"),
-       !field.value,
-     )}
-     {validateRule(
-       /[A-Z]/.test(field.value),
-       t("password_uppercase_validation"),
-       !field.value,
-     )}
-     {validateRule(
-       /\d/.test(field.value),
-       t("password_number_validation"),
-       !field.value,
-     )}
-   </div>
- )}

Likely invalid or redundant comment.

src/components/Users/UserResetPassword.tsx Outdated Show resolved Hide resolved
Copy link
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

🧹 Nitpick comments (6)
src/components/ui/input.tsx (3)

11-13: Simplify conditional type retrieval.
Although this function is quite short, consider inlining this logic (e.g., (type === "password" ? (showPassword ? "text" : "password") : type)) if you prefer brevity. This is optional and mostly a stylistic choice.


16-17: Consider adding an accessible label for the input.
Since the Input component is generic, you might include an aria-label or alternative text for screen readers if it's used for password inputs. This ensures robust accessibility if the consumer does not provide its own label.

Also applies to: 18-34


35-42: Add ARIA attributes to the toggle button for accessibility.
Example: aria-pressed={showPassword} or aria-label="Toggle password visibility". This helps screen readers clarify the toggle’s purpose.

<button
  type="button"
+ aria-label="Toggle password visibility"
  ...
>
  <CareIcon icon={showPassword ? "l-eye" : "l-eye-slash"} />
</button>
src/components/Users/UserResetPassword.tsx (3)

30-56: Consider moving t() calls outside schema definitions.
If the language changes at runtime, these translations may not re-evaluate, leading to stale strings. Storing the messages in constants or passing them in as parameters can future-proof your localization.

- ... .min(1, { message: t("please_enter_current_password") }) ...
+ const messages = {
+   pleaseEnterCurrentPassword: t("please_enter_current_password"),
+   ...
+ };

const PasswordSchema = z.object({
  old_password: z
    .string()
-   .min(1, { message: t("please_enter_current_password") }),
+   .min(1, { message: messages.pleaseEnterCurrentPassword }),
  ...
})

75-81: Leverage global error handling for failures.
You are using onSuccess with a success toast here. For errors, react-query’s global error handler can suffice to reduce duplication, though the success toast usage is conventional.


186-214: Properly disable the submit button.
Disabling the button when the form is pristine (!form.formState.isDirty) is a valid approach. If you want to track actual validation readiness, consider isValid from form state.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9b6359b and fb72841.

📒 Files selected for processing (2)
  • src/components/Users/UserResetPassword.tsx (1 hunks)
  • src/components/ui/input.tsx (1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
src/components/Users/UserResetPassword.tsx

[error] 151-154: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (8)
src/components/ui/input.tsx (2)

5-5: Import looks good!
No issues with introducing CareIcon here.


9-10: Stateful toggle approach is valid.
Using showPassword to manage password visibility is a clean, intuitive solution.

src/components/Users/UserResetPassword.tsx (6)

1-2: Imports and initial setup confirmed.
All newly introduced imports (zodResolver, useMutation, z, as well as the updated references to react-hook-form and new UI components) align well with the shift to schema-based validation and modern form libraries.

Also applies to: 5-5, 7-8, 13-21, 27-27


65-66: Avoid maintaining extra focus states.
isPasswordFieldFocused is used only to toggle manual validations. This partially duplicates the Zod validations. Consider removing the manual validations and relying fully on the form state.


67-74: Initial form setup looks good.
Assigning default values and applying the zodResolver(PasswordSchema) is consistent with best practices.


83-85: Submission logic is concise.
The approach correctly merges old_password, username, and the new password. Ensure that the backend route expects these fields exactly.

Also applies to: 91-91


94-107: Toggle logic for password changes is clean.
Unifying the isEditing state to show/hide the form is straightforward. The new fields and the structure introduced by the Form and FormField components help maintain clarity.

Also applies to: 108-132, 133-154


155-181: Avoid duplicating Zod validations in UI.
Zod schema validations already cover length, lowercase, uppercase, and numeric checks. This manual check may drift out of sync.

src/components/Users/UserResetPassword.tsx Outdated Show resolved Hide resolved
Copy link
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: 0

🧹 Nitpick comments (1)
src/components/Users/UserResetPassword.tsx (1)

67-81: Simplify form name and use response message

  1. Since this is the only form in the file, the form name can be simplified
  2. Use the success message from the API response
- const form = useForm({
+ const form = useForm<z.infer<typeof PasswordSchema>>({
   resolver: zodResolver(PasswordSchema),
   defaultValues: {
     old_password: "",
     new_password_1: "",
     new_password_2: "",
   },
 });

 const { mutate: resetPassword, isPending } = useMutation({
   mutationFn: mutate(routes.updatePassword),
-  onSuccess: () => {
-    toast.success(t("password_updated"));
+  onSuccess: (data) => {
+    toast.success(data?.message ?? t("password_updated"));
     form.reset();
   },
 });
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fb72841 and 5055633.

📒 Files selected for processing (2)
  • public/locale/en.json (4 hunks)
  • src/components/Users/UserResetPassword.tsx (1 hunks)
🔇 Additional comments (4)
src/components/Users/UserResetPassword.tsx (3)

207-214: LGTM! Button implementation is correct

The button correctly:

  • Uses isPending for loading state
  • Shows appropriate text based on submission state
  • Disables when form is not dirty

151-182: 🛠️ Refactor suggestion

Remove duplicate validation logic

The password requirements are already defined in the zod schema. The manual validation here duplicates that logic and could become inconsistent.

Use the form's error state instead:

- {isPasswordFieldFocused && (
-   <div
-     className="text-small mt-2 pl-2 text-secondary-500"
-     aria-live="polite"
-   >
-     {validateRule(
-       field.value.length >= 8,
-       t("password_length_validation"),
-       !field.value,
-     )}
-     {validateRule(
-       /[a-z]/.test(field.value),
-       t("password_lowercase_validation"),
-       !field.value,
-     )}
-     {validateRule(
-       /[A-Z]/.test(field.value),
-       t("password_uppercase_validation"),
-       !field.value,
-     )}
-     {validateRule(
-       /\d/.test(field.value),
-       t("password_number_validation"),
-       !field.value,
-     )}
-     {validateRule(
-       field.value !== form.watch("old_password"),
-       t("new_password_same_as_old"),
-       !field.value,
-     )}
-   </div>
- )}
+ <FormMessage />

Likely invalid or redundant comment.


30-56: 🛠️ Refactor suggestion

Extract translation calls from schema definition

The t() function calls within the schema definition might not work correctly with dynamic language changes since they're evaluated only once when the schema is defined.

Extract the messages to constants:

+ const messages = {
+   currentPassword: t("please_enter_current_password"),
+   passwordLength: t("password_length_validation"),
+   passwordNumber: t("password_number_validation"),
+   passwordLowercase: t("password_lowercase_validation"),
+   passwordUppercase: t("password_uppercase_validation"),
+   confirmPassword: t("please_enter_confirm_password"),
+   passwordMismatch: t("password_mismatch"),
+   passwordSameAsOld: t("new_password_same_as_old"),
+ };

const PasswordSchema = z
  .object({
    old_password: z
      .string()
-     .min(1, { message: t("please_enter_current_password") }),
+     .min(1, { message: messages.currentPassword }),
    // Apply similar changes to other validation messages
  })

Likely invalid or redundant comment.

public/locale/en.json (1)

1203-1203: LGTM! Translation changes are consistent

The changes to the translation keys align with the form implementation and provide clear user feedback.

Also applies to: 1286-1286, 1326-1326, 1402-1402

Copy link
Member

Choose a reason for hiding this comment

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

do not modify shadcn's input component. you may extend it by creating a new component instead.

Copy link
Member

Choose a reason for hiding this comment

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

also why was the login page not updated like mentioned in the issue?

also update in the user create form

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
7 participants