Conversation
WalkthroughThe changes introduce new UI components for example text and alerts, refactor example and button components for modularity and styling, and update test cases and layout to use these new components. Several files are updated to simplify conditional rendering, enforce user session checks, and improve button and pagination UI consistency, with associated style and type improvements. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Layout
participant DiscoverWorksAlert
participant Session
Layout->>DiscoverWorksAlert: Render inside layout
DiscoverWorksAlert->>Session: Get current user session
alt User is signed in
DiscoverWorksAlert->>User: Show toast with action buttons
User->>DiscoverWorksAlert: Click action button (e.g., search works)
DiscoverWorksAlert->>User: Navigate to selected page
else User not signed in
DiscoverWorksAlert-->>Layout: Render nothing
end
sequenceDiagram
participant PageComponent
participant ExampleTextComponent
PageComponent->>PageComponent: Check if query is empty
alt Query is empty
PageComponent->>ExampleTextComponent: Render example text (specialized component)
else Query exists
PageComponent->>PageComponent: Render search results
end
Suggested reviewers
Note ⚡️ AI Code Reviews for VS Code, Cursor, WindsurfCodeRabbit now has a plugin for VS Code, Cursor and Windsurf. This brings AI code reviews directly in the code editor. Each commit is reviewed immediately, finding bugs before the PR is raised. Seamless context handoff to your AI code agent ensures that you can easily incorporate review feedback. Note ⚡️ Faster reviews with cachingCodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure 📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms (7)
✨ Finishing Touches
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. 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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (18)
src/components/ForceDirectedGraph/ForceDirectedGraph.tsx (1)
46-46: Suppressing TypeScript errors should be justified
The@ts-expect-errordirective silences the TypeScript error on the<Vega>component but bypasses compile-time checks and may mask real issues. Consider importing or declaring the correct prop types forreact-vega(e.g. extending theVegacomponent’sspecanddatainterfaces) or adding a clear comment referencing the upstream type mismatch for future maintainability.src/components/SankeyGraph/SankeyGraph.tsx (1)
91-91: Suppressing TypeScript errors should be justified
As inForceDirectedGraph, the@ts-expect-errordirective hides the TS error on the<Vega>component. To maintain type safety, consider defining or importing accurate types for thesankeySpecoutput and component props, or document the suppression rationale with a reference to a tracking issue.src/data/constants.ts (1)
46-48: Ensure consistent theming and usage of accent color constant.The new
ACCENT_COLORconstant provides a central definition for the blue accent used across the project—great for maintainability. Please verify:
- That this constant is used in all relevant places (e.g., the new button and alert SCSS modules) instead of hardcoding
#00B1E2.- Consider grouping it with other color constants (e.g., in a
COLORSobject) to align with potential theming strategies.src/components/FacetList/FacetListGroup.module.scss (1)
2-13: Reevaluate use of!importantflags.Applying
!importantto all CSS custom properties can lead to maintenance challenges and conflicts later. Consider removing!importantfor properties that do not collide with other styles or increasing selector specificity instead. For example:--bs-accordion-border-width: 0 !important;could be
--bs-accordion-border-width: 0;and rely on the module-scoped selector.
src/styles.css (1)
645-649: Encapsulate.secondaryin a CSS module if possible.Adding a global
.secondaryclass may lead to style clashes. Since we have scoped styles inDataCiteButton.module.scss, consider moving this into the button component’s module and exposing it as a variant prop, rather than a global class.cypress/e2e/searchOrganization.test.ts (1)
74-74: Remove unnecessary export from test file.The export statement is flagged by static analysis and is unnecessary in a test file. Test files typically don't need to export anything.
-export { }🧰 Tools
🪛 Biome (1.9.4)
[error] 73-74: Do not export from a test file.
(lint/suspicious/noExportsInTest)
cypress/e2e/searchWork.test.ts (1)
159-159: Remove unnecessary export from test file.This export statement is flagged by static analysis and is unnecessary in a test file. Test files typically don't need to export anything.
-export { }🧰 Tools
🪛 Biome (1.9.4)
[error] 158-159: Do not export from a test file.
(lint/suspicious/noExportsInTest)
src/components/Header/ServerButtons.tsx (1)
116-117: Improved SignInButton implementation with consistent stylingThe refactoring simplifies the SignInButton by leveraging the DataCiteButton component, which provides consistent styling across the application. This change aligns with modern React patterns by composing components rather than using custom CSS.
However, the original implementation likely included a sign-in icon which has been removed. Consider whether this icon should be preserved for visual consistency.
- <NavLink id="sign-in" href={href} as={DataCiteButton} className="text-nowrap" variant="secondary" outline> - Sign In + <NavLink id="sign-in" href={href} as={DataCiteButton} className="text-nowrap" variant="secondary" outline icon={faSignInAlt}> + Sign Insrc/components/DiscoverWorksAlert/DiscoverWorksAlert.module.scss (4)
1-4: Toast container styling looks good, but consider avoiding !importantThe toast container styling provides appropriate visual treatment with box-shadow and border, but the use of
!importantflags suggests potential style conflicts that should be resolved through proper CSS specificity instead..toast-container { - box-shadow: 0px 28px 36px -10px rgba(13, 96, 212, 0.08) !important; - border: 1px solid rgba(36, 59, 84, 0.08) !important; + box-shadow: 0px 28px 36px -10px rgba(13, 96, 212, 0.08); + border: 1px solid rgba(36, 59, 84, 0.08); }
6-13: Consider using CSS variables for consistent stylingThe primary button styling uses hardcoded color values and multiple
!importantflags. For better maintainability and consistency, consider using CSS variables for colors and avoiding!importantwhere possible.+:root { + --primary-color: #037AAD; + --primary-text-color: #FFF; +} .primary { - color: #FFF !important; - background-color: #037AAD !important; + color: var(--primary-text-color); + background-color: var(--primary-color); border-width: 0 !important; font-size: 1em !important; padding: .5em 2em !important; white-space: nowrap; }
15-22: Secondary button styling should be consistent with primarySimilar to the primary button, the secondary button uses hardcoded colors and
!importantflags. For consistency, use the same CSS variables approach recommended for the primary button..secondary, .secondary:hover { - color: #037AAD !important; + color: var(--primary-color); background-color: transparent !important; - border: 2px solid #037AAD !important; + border: 2px solid var(--primary-color); font-size: 1em !important; padding: .5em 2em !important; white-space: nowrap; }
24-30: Use standard flex-end instead of end for better compatibilityThe
justify-content: endproperty might not be widely supported across all browsers. Useflex-endfor better compatibility..button-container { display: flex; flex-direction: row; flex-wrap: wrap; - justify-content: end; + justify-content: flex-end; gap: 10px; }src/components/DataCiteButton/DataCiteButton.module.scss (1)
7-14: Consider removing!importantdeclarationsThe stylesheet makes extensive use of
!importantflags, which can lead to CSS specificity issues and make future styling changes more difficult to implement..button { - color: $color !important; - font-size: 1em !important; - padding: .5em 2em !important; - border-width: 1.5px !important; - border-style: solid !important; - border-radius: 100px !important; + color: $color; + font-size: 1em; + padding: .5em 2em; + border-width: 1.5px; + border-style: solid; + border-radius: 100px; }If specificity issues arise, consider using more specific selectors or restructuring your CSS hierarchy instead of using
!important.src/components/DiscoverWorksAlert/DiscoverWorksAlert.tsx (2)
27-37: Consider adjusting column layout for better centeringThe column offset (md={{ span: 8, offset: 3 }}) doesn't properly center the content in a 12-column grid. For proper centering with a span of 8, an offset of 2 would be more appropriate.
- <Col xs={12} md={{ span: 8, offset: 3 }} className="d-flex justify-content-center"> + <Col xs={12} md={{ span: 8, offset: 2 }} className="d-flex justify-content-center">
19-19: Consider persisting the alert's dismissed stateCurrently, the alert will reappear on page refresh even if the user dismissed it. Consider storing the dismissed state in localStorage or similar to respect the user's preference across sessions.
- const [show, setShow] = useState(true); + const [show, setShow] = useState(() => { + // Check if running in browser environment + if (typeof window !== 'undefined') { + const storedValue = localStorage.getItem('discoverWorksAlertDismissed'); + return storedValue ? false : true; + } + return true; + });And update the onClose handler:
- <Toast show={show} onClose={() => setShow(false)} className={`${styles["toast-container"]} w-auto my-4 p-2 rounded-0`}> + <Toast show={show} onClose={() => { + setShow(false); + localStorage.setItem('discoverWorksAlertDismissed', 'true'); + }} className={`${styles["toast-container"]} w-auto my-4 p-2 rounded-0`}>src/components/DataCiteButton/DataCiteButton.tsx (1)
29-32: Consider simplifying Next.js Link usage.While the WrapLink helper component works correctly, the use of both
passHrefandlegacyBehaviormay be redundant aspassHrefis implied when usinglegacyBehaviorin Next.js.- return <Link href={props.href} passHref legacyBehavior>{props.children}</Link> + return <Link href={props.href} legacyBehavior>{props.children}</Link>src/components/ExampleText/ExampleText.tsx (2)
50-59: Base ExampleText component implemented with good layout structure.The component uses Bootstrap's grid system appropriately for responsive layout. However, consider improving the documentation link's accessibility.
- <a href="https://support.datacite.org/docs/datacite-commons" target="_blank" rel="noreferrer">DataCite Support.</a> + <a href="https://support.datacite.org/docs/datacite-commons" target="_blank" rel="noreferrer" aria-label="DataCite Support documentation (opens in new tab)">DataCite Support.</a>
62-66: Consider adding accessibility attributes to the Search component icon.The search icon could benefit from aria attributes to improve accessibility if it's meant to be decorative.
- <FontAwesomeIcon icon={faSearch} className="me-1" />{props.children} + <FontAwesomeIcon icon={faSearch} className="me-1" aria-hidden="true" />{props.children}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (26)
cypress/e2e/searchOrganization.test.ts(1 hunks)cypress/e2e/searchPerson.test.ts(0 hunks)cypress/e2e/searchWork.test.ts(1 hunks)src/app/doi.org/page.tsx(3 hunks)src/app/layout.tsx(2 hunks)src/app/orcid.org/page.tsx(1 hunks)src/app/page.tsx(2 hunks)src/app/repositories/page.tsx(2 hunks)src/app/ror.org/page.tsx(2 hunks)src/components/DataCiteButton/DataCiteButton.module.scss(1 hunks)src/components/DataCiteButton/DataCiteButton.tsx(1 hunks)src/components/DiscoverWorksAlert/DiscoverWorksAlert.module.scss(1 hunks)src/components/DiscoverWorksAlert/DiscoverWorksAlert.tsx(1 hunks)src/components/DownloadMetadata/DownloadMetadata.tsx(2 hunks)src/components/ExampleText/ExampleText.tsx(1 hunks)src/components/FacetList/FacetListGroup.module.scss(1 hunks)src/components/ForceDirectedGraph/ForceDirectedGraph.tsx(1 hunks)src/components/Header/ClientButtons.tsx(2 hunks)src/components/Header/Dropdown.tsx(1 hunks)src/components/Header/Header.tsx(2 hunks)src/components/Header/ServerButtons.tsx(2 hunks)src/components/Pager/Pager.tsx(2 hunks)src/components/SankeyGraph/SankeyGraph.tsx(4 hunks)src/data/constants.ts(1 hunks)src/styles.css(1 hunks)src/utils/session.ts(1 hunks)
💤 Files with no reviewable changes (1)
- cypress/e2e/searchPerson.test.ts
🧰 Additional context used
🧬 Code Graph Analysis (9)
src/app/repositories/page.tsx (1)
src/components/ExampleText/ExampleText.tsx (1)
RepositoriesExampleText(39-46)
src/components/DownloadMetadata/DownloadMetadata.tsx (1)
src/components/DataCiteButton/DataCiteButton.tsx (1)
DataCiteButton(16-26)
src/app/page.tsx (1)
src/components/ExampleText/ExampleText.tsx (1)
WorksExampleText(9-16)
src/components/Header/Header.tsx (1)
src/components/ReactBootstrap.tsx (1)
Collapse(17-17)
src/app/doi.org/page.tsx (1)
src/components/ExampleText/ExampleText.tsx (1)
WorksExampleText(9-16)
src/app/ror.org/page.tsx (1)
src/components/ExampleText/ExampleText.tsx (1)
OrganizationsExampleText(19-26)
src/components/Header/ServerButtons.tsx (2)
src/components/ReactBootstrap.tsx (1)
NavLink(14-14)src/components/DataCiteButton/DataCiteButton.tsx (1)
DataCiteButton(16-26)
src/components/DiscoverWorksAlert/DiscoverWorksAlert.tsx (3)
src/utils/session.ts (1)
session(5-27)src/data/constants.ts (1)
PROFILES_URL(33-33)src/components/DataCiteButton/DataCiteButton.tsx (1)
DataCiteButton(16-26)
src/components/Pager/Pager.tsx (1)
src/components/DataCiteButton/DataCiteButton.tsx (1)
DataCiteButton(16-26)
🪛 Biome (1.9.4)
cypress/e2e/searchOrganization.test.ts
[error] 73-74: Do not export from a test file.
(lint/suspicious/noExportsInTest)
cypress/e2e/searchWork.test.ts
[error] 158-159: Do not export from a test file.
(lint/suspicious/noExportsInTest)
⏰ Context from checks skipped due to timeout of 90000ms (6)
- GitHub Check: test / cypress (5)
- GitHub Check: test / cypress (4)
- GitHub Check: test / cypress (3)
- GitHub Check: test / cypress (2)
- GitHub Check: test / cypress (1)
- GitHub Check: CodeQL-Build
🔇 Additional comments (34)
src/components/SankeyGraph/SankeyGraph.tsx (1)
78-79: Formatting adjustments improve readability
The added spaces around the==operator and consistent JSX tag spacing for the<EmptyChart>conditional render align with the repository’s style conventions and enhance readability.src/styles.css (1)
643-649:Details
✅ Verification successful
Validate removal of
.btn.sign-inand pagination styles.Global CSS for
.btn.sign-in, pagination selectors, and other removed rules are no longer present. Please verify no residual usage remains in the codebase:This ensures we won’t introduce missing styles or broken UI elements.
🏁 Script executed:
rg --fixed-strings ".btn.sign-in" -n . rg "pagination a" -n .Length of output: 63
.btn.sign-in and pagination styles removal verified
- Searched for
.btn.sign-inwithrg --fixed-strings ".btn.sign-in"→ no matches- Searched for
pagination awithrg "pagination a"→ no matchesNo residual references found; it’s safe to remove these styles.
src/app/layout.tsx (1)
59-60: Ensure alert displays only for authenticated users.The banner should only appear for signed-in users. Verify that
DiscoverWorksAlertinternally checks the user session and rendersnullor nothing when no user is present. If not, wrap the component with a conditional:{session() && <DiscoverWorksAlert />}src/components/Header/Header.tsx (2)
31-31: Improved spacing between navigation elements.Adding the
gap-5class to the Collapse component enhances the spacing between child elements, creating a more visually balanced header layout.
45-45: Removed unnecessary top margin from navigation.Removing the
mt-3class from the Nav component eliminates excess vertical spacing, creating a cleaner alignment with other header elements.src/components/Header/Dropdown.tsx (2)
9-9: Good defensive programming with explicit error for unauthenticated users.Adding an explicit error when no user is signed in prevents potential rendering issues and ensures this component is only used in authenticated contexts, aligning with the PR's focus on signed-in user features.
11-11: Consistent vertical spacing for dropdown.Adding the
my-4class provides consistent margin spacing around the dropdown, improving the visual hierarchy in the header.src/components/DownloadMetadata/DownloadMetadata.tsx (2)
4-4: Good use of the new DataCiteButton component for consistency.The replacement of the generic Button with the custom DataCiteButton component contributes to UI consistency across the application. The added props (
outlineandclassName='w-100') enhance the button's appearance appropriately.Also applies to: 15-23
28-35: Successful migration to DataCiteButton in modal footer.The modal footer button has been properly updated to use the DataCiteButton component with appropriate variant styling.
src/components/Header/ClientButtons.tsx (2)
14-14: Good defensive programming with user session check.Adding this explicit check for the user's existence prevents potential runtime errors when accessing
user.uidif the user is not signed in. The clear error message makes debugging easier.
25-25: Consistent user session validation.This check mirrors the one added to UserCommonsPageButton, ensuring consistent validation across components that require an authenticated user.
src/app/repositories/page.tsx (1)
3-3: Good refactoring to use specialized example text component.Replacing inline JSX with the
RepositoriesExampleTextcomponent improves code organization and maintainability while ensuring UI consistency across search pages. This approach centralizes example text styling and structure, making future updates easier.Also applies to: 15-16
src/app/orcid.org/page.tsx (1)
3-3: Clean implementation of example text component.Similar to the repositories page, this refactoring improves code organization by using the specialized
PeopleExampleTextcomponent. The conditional logic is clear and maintains the same behavior while improving the component structure.Also applies to: 11-15
src/components/Header/ServerButtons.tsx (1)
5-5: Good addition of the DataCiteButton componentThe addition of this import enables the refactoring of the SignInButton to use a more consistent styling approach.
src/app/page.tsx (2)
3-3: Good refactoring of example text importThe import change correctly uses the specialized WorksExampleText component instead of the generic ExampleText.
18-20: Improved code with encapsulated example text componentThe replacement of inline JSX with the WorksExampleText component improves code maintainability and consistency across search pages. This change aligns with the broader refactoring effort to standardize example text rendering throughout the application.
src/app/doi.org/page.tsx (2)
5-5: Good addition of specialized example text componentThe import of WorksExampleText is appropriate for this DOI search page.
26-28: Improved code organization with standardized example textThe replacement of inline JSX with the WorksExampleText component enhances code consistency and maintainability. This change is consistent with similar refactoring in other search pages, creating a uniform approach to rendering example text.
src/components/DiscoverWorksAlert/DiscoverWorksAlert.module.scss (1)
32-37: Good responsive design considerationThe media query for smaller screens is a good practice to ensure the buttons are usable on mobile devices. Consider aligning the breakpoint with other breakpoints in the application for consistency.
src/app/ror.org/page.tsx (2)
3-3: Nice module refactoring!The change from importing a generic
ExampleTextto the specificOrganizationsExampleTextcomponent improves code modularity and makes the component's purpose clearer.
18-20: Clean simplification of conditional renderingReplacing the inline JSX with a dedicated component improves readability and maintainability. This change also ensures consistent user experience across different search pages.
src/components/DataCiteButton/DataCiteButton.module.scss (2)
1-5: Good use of color variablesDefining color variables at the top of the stylesheet promotes consistency and makes future theming changes easier to implement.
41-45: Good responsive design considerationThe media query for small screens ensures buttons are full-width on mobile devices, improving usability on smaller screens.
src/components/DiscoverWorksAlert/DiscoverWorksAlert.tsx (2)
16-22: Good user session checkThe component correctly checks for user session before rendering content, aligning with the PR objective to show the alert only to signed-in users.
23-25: Well-constructed URL parametersThe URLs for searching works by ID and name are appropriately constructed, making it easy for users to find their works.
src/components/Pager/Pager.tsx (3)
6-6: Good component refactoringThe refactoring to use the new DataCiteButton component and the change from a const to a named function export improves code consistency and readability.
Also applies to: 15-15
19-24: Cleaner URL construction logicThe simplified logic for determining and constructing page URLs is more readable and maintainable than the previous implementation.
27-33: Improved pagination UI consistencyUsing DataCiteButton for pagination controls helps maintain UI consistency across the application. The justify-content-between class appropriately spaces the buttons.
src/components/DataCiteButton/DataCiteButton.tsx (2)
1-14: Well-structured component setup with appropriate imports and props interface.The component setup follows good practices with the 'use client' directive, necessary imports, and a clear props interface that extends ButtonProps with additional properties for an outline style and icon support.
16-26: Good implementation of conditional styling and icon rendering.The component correctly applies styling based on variant and outline props, and conditionally renders a FontAwesome icon with appropriate spacing.
src/components/ExampleText/ExampleText.tsx (4)
9-16: Clean implementation of WorksExampleText component.The component is well-structured with clear URL definitions and appropriate use of the base ExampleText component.
19-26: Good implementation of OrganizationsExampleText component.Similar to WorksExampleText, this component follows a consistent pattern with clearly defined URLs and appropriate heading.
29-36: Well-structured PeopleExampleText component.The component follows the established pattern with appropriate example searches for people.
39-46: Clean implementation of RepositoriesExampleText component.Consistent with the other example text components, providing appropriate repository search examples.
| // verify asymmetric token, using RSA with SHA-256 hash algorithm | ||
| JsonWebToken.verify(token, JWT_KEY, { algorithms: ['RS256'] }, setUser) | ||
|
|
||
| return user | ||
| return user as { uid: string, name: string } | ||
| } |
There was a problem hiding this comment.
Fix async JWT verification logic.
JsonWebToken.verify with a callback is asynchronous: the return user as { uid: string, name: string } executes before the callback runs, so user is always null. This breaks session retrieval. Please refactor to use the synchronous return form or Promises:
Example synchronous approach:
export const session = (): { uid: string; name: string } | null => {
if (!JWT_KEY) return null;
const sessionCookie = Cookies.getJSON('_datacite');
const token = sessionCookie?.authenticated?.access_token;
if (!token) return null;
try {
const payload = JsonWebToken.verify(token, JWT_KEY, { algorithms: ['RS256'] }) as any;
return { uid: payload.uid, name: payload.name };
} catch (err) {
console.error('JWT verification error:', err);
return null;
}
};🤖 Prompt for AI Agents
In src/utils/session.ts around lines 23 to 27, the JWT verification uses an
asynchronous callback but immediately returns the user, causing it to always
return null. Refactor the code to use the synchronous form of
JsonWebToken.verify without a callback, wrapping it in a try-catch block to
handle errors. Extract the user info from the returned payload and return it
directly, ensuring the function returns the user only after successful
verification.
There was a problem hiding this comment.
Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!
There was a problem hiding this comment.
Personally no, it's been working this far I see no reason to mess with it. I just added the basic typing for clarity when working with the user object
akita
|
||||||||||||||||||||||||||||
| Project |
akita
|
| Branch Review |
discover-works-alert
|
| Run status |
|
| Run duration | 01m 37s |
| Commit |
|
| Committer | Bryceson Laing |
| View all properties for this run ↗︎ | |
| Test results | |
|---|---|
|
|
0
|
|
|
0
|
|
|
3
|
|
|
0
|
|
|
46
|
| View all changes introduced in this branch ↗︎ | |
akita
|
||||||||||||||||||||||||||||
| Project |
akita
|
| Branch Review |
1.37.0
|
| Run status |
|
| Run duration | 01m 26s |
| Commit |
|
| Committer | Bryceson Laing |
| View all properties for this run ↗︎ | |
| Test results | |
|---|---|
|
|
0
|
|
|
0
|
|
|
3
|
|
|
0
|
|
|
46
|
| View all changes introduced in this branch ↗︎ | |
Purpose
Adds an alert banner to the top of all pages when a User is signed in.
closes: https://github.com/datacite/product-backlog/issues/267
Approach
Open Questions and Pre-Merge TODOs
Learning
Types of changes
Bug fix (non-breaking change which fixes an issue)
New feature (non-breaking change which adds functionality)
Breaking change (fix or feature that would cause existing functionality to change)
Reviewer, please remember our guidelines:
Summary by CodeRabbit
New Features
Refactor
Style
Bug Fixes
Chores