Skip to content

Conversation

@leslyclopez11
Copy link
Contributor

✨ Codu Pull Request 💻

Fixes #1009

Pull Request details

  • I added code to _client.tsx modifying slideThree (including the dropdown)
  • Defined yearsOfExperience in additionalUserDetails.tsx
  • Defined yearsOfExperience in page.tsx
  • Defined yearsOfExperience in schema.ts
  • I added validation based on coderabbitai suggestions
  • Attempted to create the Drizzle migration
  • I cherry-picked from the develop branch the commits, but I'm confused if I'm doing this right.

Any Breaking changes

  • 'None'

Associated Screenshots

  • 'None'

@leslyclopez11 leslyclopez11 requested a review from a team as a code owner October 14, 2024 15:29
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 14, 2024

Walkthrough

The pull request introduces a new "Years of experience" field in the onboarding form within the AdditionalSignUpDetails component. This includes the addition of a new constant and type for experience options, updates to the UserDetails type, and modifications to the form's validation logic. The database schema is also updated to include a new column for yearsOfExperience, with associated migrations and constraints. These changes enhance user data collection during onboarding and ensure proper validation and storage of the new field.

Changes

File Path Change Summary
app/(app)/alpha/additional-details/_client.tsx Added yearsOfExperienceOptions constant, YearsOfExperience type, updated UserDetails type, modified form logic to include yearsOfExperience.
app/(app)/alpha/additional-details/page.tsx Added import for YearsOfExperience, included yearsOfExperience in database query and details object.
drizzle/0010_gorgeous_living_tribunal.sql Added yearsOfExperience column to user table with default value and NOT NULL constraint.
drizzle/0011_yearsOfExperience Added yearsOfExperience column to User table with exception handling and a new check constraint.
schema/additionalUserDetails.ts Introduced yearsOfExperienceOptions constant, added yearsOfExperience field in slideThreeSchema with validation.
server/db/schema.ts Added yearsOfExperience field in user table, added indexes for username and userId, updated relations.

Assessment against linked issues

Objective Addressed Explanation
Add "Years of experience" field to onboarding form (1009)
Include Zod schema for validation of a reasonable number (1009)
New field required on the user table (1009)

Possibly related PRs

Poem

🐇 In the meadow where we play,
A new field comes to stay,
"Years of experience," we cheer,
To guide our friends, both far and near.
With forms now bright and true,
Onboarding's fun for me and you! 🎉


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 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.

@vercel
Copy link

vercel bot commented Oct 14, 2024

@leslycatota1 is attempting to deploy a commit to the Codú Team on Vercel.

A member of the Team first needs to authorize it.

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: 3

🧹 Outside diff range and nitpick comments (8)
drizzle/0011_yearsOfExperience (3)

1-5: Consider adding a NOT NULL constraint to the "yearsOfExperience" column.

The migration script correctly adds the "yearsOfExperience" column to the "User" table with proper exception handling. However, based on the PR objectives, this field is required in the onboarding form. Consider adding a NOT NULL constraint to ensure data integrity at the database level.

You can modify the ALTER TABLE statement as follows:

- ALTER TABLE "User" ADD COLUMN "yearsOfExperience" text;
+ ALTER TABLE "User" ADD COLUMN "yearsOfExperience" text NOT NULL;

Note: If you add the NOT NULL constraint, ensure that you have a strategy to handle existing rows in the table, such as setting a default value or updating them before applying the constraint.


7-12: LGTM! Consider using ANY for better performance.

The constraint is correctly implemented and aligns with the PR objectives. It ensures that only valid values can be inserted into the "yearsOfExperience" column.

For potentially better performance, especially with larger datasets, you might consider using the ANY operator instead of IN. Here's the suggested modification:

- CHECK ("yearsOfExperience" IN ('0-1', '1-3', '3-5', '5-8', '8-12', '12+'));
+ CHECK ("yearsOfExperience" = ANY(ARRAY['0-1', '1-3', '3-5', '5-8', '8-12', '12+']));

This change is optional and might not have a significant impact for small to medium-sized tables, but it's worth considering for future scalability.


1-12: Overall, the migration script is well-implemented and meets the requirements.

The script successfully adds the "yearsOfExperience" column to the "User" table and implements a constraint to ensure data integrity. The use of DO blocks and exception handling for both operations ensures idempotency, which is a best practice for database migrations.

To further improve the robustness of your database schema:

  1. Consider adding a default value for the "yearsOfExperience" column if you decide to make it NOT NULL.
  2. Ensure that your application code (form validation, API endpoints, etc.) aligns with these database constraints to provide a consistent user experience.
  3. If you haven't already, consider creating a corresponding down migration script to revert these changes if needed.
app/(app)/alpha/additional-details/page.tsx (2)

43-46: Approved with suggestions: Addition of yearsOfExperience to detailsWithNullsRemoved

The implementation correctly handles undefined or invalid yearsOfExperience values and ensures type safety. However, consider the following improvements:

  1. Move the array of valid values to a constant or configuration file for easier maintenance.
  2. Reconsider the default value approach. Setting "0-1" for invalid or undefined cases might not be appropriate for all users.

Consider refactoring the code as follows:

import { YEARS_OF_EXPERIENCE_OPTIONS } from '@/constants';

// ...

yearsOfExperience: YEARS_OF_EXPERIENCE_OPTIONS.includes(details?.yearsOfExperience)
  ? (details.yearsOfExperience as YearsOfExperience)
  : undefined,

This approach allows for easier updates to valid options and doesn't assume a default value when the input is invalid or undefined.


Line range hint 1-50: Overall assessment: Implementation aligns with PR objectives

The changes successfully implement the "Years of experience" field as per the PR objectives. The field is correctly added to the database query and the details object. The implementation handles invalid cases and ensures type safety.

However, consider the suggestions for improvement in the previous comment to enhance maintainability and flexibility of the code.

To further improve the implementation:

  1. Consider creating a separate type file for YearsOfExperience and other related types.
  2. If this pattern of retrieving user details is used in multiple places, consider extracting it into a reusable function in a separate file.
server/db/schema.ts (3)

221-221: LGTM! Consider adding a check constraint for valid values.

The addition of the yearsOfExperience field aligns well with the PR objectives. The use of varchar with a default value is appropriate for this use case.

Consider adding a check constraint to ensure only valid values are inserted. For example:

CHECK (yearsOfExperience IN ('0-1', '1-3', '3-5', '5-10', '10+'))

This would prevent invalid data from being inserted into the database.


Line range hint 228-228: Remove redundant index on username.

The addition of usernameIndex is redundant as there's already a unique index usernameKey on the username column. Having multiple indexes on the same column can negatively impact insert and update performance without providing additional query optimization benefits.

Remove the redundant index:

- usernameIndex: index("User_username_index").on(table.username), // Add this line

The existing usernameKey unique index is sufficient for optimizing queries on the username column.


Line range hint 254-254: LGTM! Consider clarifying the comment.

The update to the sessions relation in userRelations is correct and ensures proper relationship definition between users and their sessions.

Consider updating the comment to provide more context:

- sessions: many(session), // This should now be correctly inferred
+ sessions: many(session), // Defines the one-to-many relationship between users and their sessions

This change would make the purpose of the relation more explicit and helpful for future developers.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between cbd9a06 and 793e524.

📒 Files selected for processing (6)
  • app/(app)/alpha/additional-details/_client.tsx (7 hunks)
  • app/(app)/alpha/additional-details/page.tsx (3 hunks)
  • drizzle/0010_gorgeous_living_tribunal.sql (1 hunks)
  • drizzle/0011_yearsOfExperience (1 hunks)
  • schema/additionalUserDetails.ts (2 hunks)
  • server/db/schema.ts (1 hunks)
🧰 Additional context used
🔇 Additional comments (12)
app/(app)/alpha/additional-details/page.tsx (2)

5-5: LGTM: Import statement for YearsOfExperience

The import statement for YearsOfExperience is correctly added and follows the existing import style in the file.


27-27: LGTM: Addition of yearsOfExperience to database query

The yearsOfExperience field is correctly added to the columns object in the database query. This ensures that the years of experience data is retrieved from the database, aligning with the PR objectives.

schema/additionalUserDetails.ts (2)

2-2: LGTM: Well-defined constant for years of experience options.

The yearsOfExperienceOptions constant is well-defined and aligns with the PR objective. The use of as const ensures type safety, which is a good practice.


Line range hint 1-39: Verify implementation of status dropdown and additional questions.

The PR objectives mention a dropdown for selecting status (Working professional, Current student, None of the above) and additional questions for "Working professional". These elements are not visible in this file.

Please confirm that these features are implemented in other files. If not, they should be added to fully meet the PR objectives. Run the following script to check for their implementation:

✅ Verification successful

✅ Status Dropdown and Additional Questions Implemented Successfully

The status dropdown and additional questions for "Working professional" are properly implemented across the codebase:

  • Status Dropdown Options:

    • schema/additionalUserDetails.ts
    • app/(app)/alpha/additional-details/selectOptions.ts
  • Additional Questions for "Working professional":

    • app/(app)/alpha/additional-details/_client.tsx
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for implementation of status dropdown and additional questions

# Test 1: Search for status dropdown options
echo "Searching for status dropdown options..."
rg -i "working professional|current student|none of the above" --type typescript --type tsx

# Test 2: Search for additional questions for "Working professional"
echo "Searching for additional questions..."
rg -i "where are you working|what is your job title" --type typescript --type tsx

Length of output: 423


Script:

#!/bin/bash
# Description: Re-check implementation of status dropdown and additional questions with correct file types

# Test 1: Search for status dropdown options
echo "Searching for status dropdown options..."
rg -i "working professional|current student|none of the above" --type ts --type tsx

# Test 2: Search for additional questions for "Working professional"
echo "Searching for additional questions..."
rg -i "where are you working|what is your job title" --type ts --type tsx

Length of output: 393


Script:

#!/bin/bash
# Description: Re-check implementation of status dropdown and additional questions using file extension patterns

# Test 1: Search for status dropdown options
echo "Searching for status dropdown options..."
rg -i "working professional|current student|none of the above" -g "*.ts" -g "*.tsx"

# Test 2: Search for additional questions for "Working professional"
echo "Searching for additional questions..."
rg -i "where are you working|what is your job title" -g "*.ts" -g "*.tsx"

Length of output: 1631

server/db/schema.ts (2)

Line range hint 93-93: LGTM! Good performance optimization.

The addition of the userIdIndex on the userId column in the post table is a good performance optimization. This index will improve query performance for operations that filter or join posts based on the user who created them, which is likely a common operation in a blog or social media-like application.


Line range hint 1-624: Overall, good changes with minor improvements suggested.

The changes to the schema align well with the PR objectives and generally improve the database structure. Key points:

  1. The addition of the yearsOfExperience field fulfills the requirement for capturing user experience.
  2. New indexes have been added to improve query performance, but be cautious of redundant indexes.
  3. The userRelations update clarifies the relationship between users and sessions.

Please address the suggestions in the previous comments, particularly removing the redundant usernameIndex and considering a check constraint for yearsOfExperience.

app/(app)/alpha/additional-details/_client.tsx (6)

43-44: Definition of yearsOfExperienceOptions and YearsOfExperience type looks good

The constants are correctly defined and exported for use throughout the application.


56-56: Added yearsOfExperience to UserDetails type

Including yearsOfExperience in the UserDetails type ensures proper typing and data handling.


74-74: Destructured yearsOfExperience from details

This allows the component to access and utilize the yearsOfExperience property.


406-406: Destructured yearsOfExperience in SlideThree component

Accessing yearsOfExperience ensures it can be used within the form logic.


424-424: Included yearsOfExperience in form default values

This ensures that the form pre-fills the yearsOfExperience field if the data is already available.


435-435: Updated validation to include yearsOfExperience

Triggering validation for yearsOfExperience when the user is a working professional is appropriate.

@@ -0,0 +1 @@
ALTER TABLE "user" ADD COLUMN "yearsOfExperience" varchar DEFAULT '0-1' NOT NULL; No newline at end of file
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

⚠️ Potential issue

Add constraints to the yearsOfExperience column for data integrity

The frontend implementation restricts yearsOfExperience to predefined options, ensuring valid user input. However, the current database schema does not enforce these constraints, which could allow invalid data entries if bypassed.

To align the database schema with the application's validation logic and enhance data integrity, consider updating the column definition as follows:

ALTER TABLE "user" 
  ADD COLUMN "yearsOfExperience" varchar(20) 
  CHECK ("yearsOfExperience" IN ('0-1', '1-3', '3-5', '5-8', '8-12', '12+', 'Student', 'None')) 
  DEFAULT 'None' 
  NOT NULL;

This modification introduces a length limit and enforces that only the specified values can be stored in the yearsOfExperience column, ensuring consistency between the frontend and backend.

🔗 Analysis chain

Consider refining the yearsOfExperience column definition

The addition of the yearsOfExperience column aligns with the PR objectives. However, there are a few points to consider:

  1. The varchar type allows for any string input, which might not be ideal if we're using a dropdown with predefined options. Consider using an enum type if your database supports it, or add a CHECK constraint to limit the possible values.

  2. The default value '0-1' might not cover all scenarios mentioned in the PR objectives, such as "Current student" or "None of the above". Consider if a different default value or making the column nullable would be more appropriate.

  3. There's no explicit length limit on the varchar field. It's generally a good practice to set a reasonable maximum length to prevent potential issues with very long strings.

Here's a suggested refinement:

ALTER TABLE "user" ADD COLUMN "yearsOfExperience" varchar(20) CHECK ("yearsOfExperience" IN ('0-1', '1-3', '3-5', '5-10', '10+', 'Student', 'None')) NOT NULL DEFAULT 'None';

This suggestion adds a length limit, includes a CHECK constraint for predefined options, and uses 'None' as the default value. Adjust the options and default value as needed to match your specific requirements.

To ensure this change aligns with the frontend implementation, let's check the related React components:

Please review the script output to ensure the backend and frontend implementations are consistent.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check the implementation of yearsOfExperience in React components

# Test: Search for yearsOfExperience in TypeScript/JavaScript files
rg --type-add 'web:*.{ts,tsx,js,jsx}' -t web 'yearsOfExperience'

# Test: Look for dropdown or select components related to years of experience
rg --type-add 'web:*.{ts,tsx,js,jsx}' -t web -i 'dropdown|select.*years.*experience'

Length of output: 4236

Comment on lines +34 to +39
yearsOfExperience: z
.string()
.optional()
.refine((val) => val === undefined || yearsOfExperienceOptions.includes(val as typeof yearsOfExperienceOptions[number]), {
message: "Please select a valid years of experience.",
}),
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Consider making yearsOfExperience a required field.

The implementation of yearsOfExperience is well done, using Zod for schema validation as required. The refinement ensures only valid options are accepted, which is great. However, the PR objectives state that this field should be required, but it's currently defined as optional.

Consider updating the schema to make yearsOfExperience a required field:

-    yearsOfExperience: z
-      .string()
-      .optional()
+    yearsOfExperience: z
+      .string()
      .refine((val) => val === undefined || yearsOfExperienceOptions.includes(val as typeof yearsOfExperienceOptions[number]), {
        message: "Please select a valid years of experience.",
      }),

This change will ensure the field aligns fully with the PR objectives.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
yearsOfExperience: z
.string()
.optional()
.refine((val) => val === undefined || yearsOfExperienceOptions.includes(val as typeof yearsOfExperienceOptions[number]), {
message: "Please select a valid years of experience.",
}),
yearsOfExperience: z
.string()
.refine((val) => val === undefined || yearsOfExperienceOptions.includes(val as typeof yearsOfExperienceOptions[number]), {
message: "Please select a valid years of experience.",
}),

Comment on lines +520 to +542

<Field className="mx-4 my-4 ">
<Label>Years of experience:</Label>
<Select
id="years-of-experience"
{...register('yearsOfExperience')}
>
<option value="" disabled>
Select range
</option>
<option value="0-1">0-1 years</option>
<option value="1-3">1-3 years</option>
<option value="3-5">3-5 years</option>
<option value="5-8">5-8 years</option>
<option value="8-12">8-12 years</option>
<option value="12+">12+ years</option>
</Select>
{errors.yearsOfExperience && (
<ErrorMessage className="text-red-500">
{errors.yearsOfExperience.message}
</ErrorMessage>
)}
</Field>
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Refactor to use yearsOfExperienceOptions in Select component

Currently, the options in the Select component for "Years of experience" are hardcoded, which duplicates data and can lead to inconsistencies. Refactor to map over the yearsOfExperienceOptions array for better maintainability.

Apply this change:

<Field className="mx-4 my-4 ">
  <Label>Years of experience:</Label>
  <Select
    id="years-of-experience"
    {...register('yearsOfExperience')}
  >
    <option value="" disabled>
      Select range
    </option>
-   <option value="0-1">0-1 years</option>
-   <option value="1-3">1-3 years</option>
-   <option value="3-5">3-5 years</option>
-   <option value="5-8">5-8 years</option>
-   <option value="8-12">8-12 years</option>
-   <option value="12+">12+ years</option>
+   {yearsOfExperienceOptions.map((range) => (
+     <option key={range} value={range}>
+       {range} years
+     </option>
+   ))}
  </Select>
  {errors.yearsOfExperience && (
    <ErrorMessage className="text-red-500">
      {errors.yearsOfExperience.message}
    </ErrorMessage>
  )}
</Field>

Committable suggestion was skipped due to low confidence.

@John-Paul-Larkin
Copy link
Member

Hey @leslyclopez11
Great to see you back! I am sure you learned loads about Git 🤣
I see you have two PRs open now.
Test/years of experience #1121 and Feature/years of experience #1120

Which one of these can be closed?

@leslyclopez11
Copy link
Contributor Author

@John-Paul-Larkin oh, I fear I did learn a lot of git. Hopefully, I did the PR correct now but let me know if that's not the case. I feel more confident with this one: Test/years of experience #1121

@John-Paul-Larkin
Copy link
Member

@John-Paul-Larkin oh, I fear I did learn a lot of git. Hopefully, I did the PR correct now but let me know if that's not the case. I feel more confident with this one: Test/years of experience #1121

Great, so I will close the other PR and review this one.
PS. Git is complicated and very powerful, but it will all start to make sense to you soon!

@John-Paul-Larkin
Copy link
Member

John-Paul-Larkin commented Oct 15, 2024

Hey @leslyclopez11
This is great work. Thanks very much.
You are nearly there with this PR, but there are a few small things we should fix first.

The value '0-1' is defaulted to for every record.
The database is not actually being update with the entered value.
You can search for the function "slideThreeSubmitAction", which is in the _actions file in the additional-details directory.
This is a Next.js server action and is invoked to update the database.
You can follow the pattern to update the database with the yearsOfExperience value.

On the same subject, we actually dont want a default value for this. The field should be null until the user inputs something in the form.

If you run "npx drizzle-kit studio" it will connect to your database and spin up proxy server for Drizzle Studio which you can use for viewing the database.

I hope this all makes sense?

@NiallJoeMaher
Copy link
Contributor

Is this still being worked on? Just so I know if I should keep it open or close?

@leslyclopez11
Copy link
Contributor Author

@NiallJoeMaher I'm still working on this!

Copy link
Contributor

Choose a reason for hiding this comment

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

There should be only one migration file for the updates. Let me know if you still want to take this on or else we can take it over.

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.

Add "Years of experience" field to onboarding form

4 participants