Skip to content

SSR Settings + Loading UI#147

Merged
carhartlewis merged 6 commits into
mainfrom
lewis/onboarding-workflow
Mar 19, 2025
Merged

SSR Settings + Loading UI#147
carhartlewis merged 6 commits into
mainfrom
lewis/onboarding-workflow

Conversation

@carhartlewis
Copy link
Copy Markdown
Contributor

@carhartlewis carhartlewis commented Mar 19, 2025

Summary by CodeRabbit

  • New Features
    • API key creation and revocation now trigger an automatic refresh of the API keys display, ensuring immediate, up-to-date feedback.
    • New dynamic loading screens have been introduced for API keys, organization settings, and member management, featuring internationalized content and engaging visuals such as an animated spinner.
    • A new LogoSpinner component has been added to enhance loading indicators throughout the application.
  • Refactor
    • The API keys table has been streamlined to present data directly, offering a cleaner and more intuitive user experience.
    • The RealtimeStatus component has been simplified by removing the completed state handling.

- Added a new `Loading` component to display a fallback UI while organization settings are loading.
- Created `SettingsFallback` component with placeholders for organization name, website, and delete confirmation.
- Wrapped organization settings in `Suspense` to handle loading state effectively.
- Updated `createApiKeyAction` and `revokeApiKeyAction` to include path revalidation after successful operations.
- Improved error handling for API key actions with specific messages for unique and foreign key constraints.
- Replaced the `SettingsFallback` component with a more structured loading UI using `Card` components for organization settings.
- Introduced a new `Loading` component for the API keys page, featuring a spinner and descriptive cards.
- Removed the deprecated `SettingsFallback` component to streamline the codebase.
@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 19, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
app ✅ Ready (Inspect) Visit Preview 💬 Add feedback Mar 19, 2025 3:20pm
comp-portal ✅ Ready (Inspect) Visit Preview 💬 Add feedback Mar 19, 2025 3:20pm

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 19, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

This pull request updates API key management and several dashboard pages. The API key creation and revocation actions now trigger a cache revalidation using revalidatePath("/settings/api-keys"). New asynchronous loading components have been added for the API keys, organization settings, and members pages. The API keys page now retrieves keys via a new cached function and passes them to the table component, which has been refactored to receive data as a prop. Additionally, a new animated LogoSpinner component has been introduced, and the organization settings page now uses React’s Suspense for asynchronous rendering.

Changes

File(s) Change Summary
apps/app/src/actions/organization/create-api-key-action.ts
apps/app/src/actions/organization/revoke-api-key-action.ts
Added import and call to revalidatePath("/settings/api-keys") after successful API key creation/revocation; minor formatting changes (indentation).
apps/app/src/app/[locale]/(app)/(dashboard)/settings/api-keys/loading.tsx
apps/app/src/app/[locale]/(app)/(dashboard)/settings/loading.tsx
apps/app/src/app/[locale]/(app)/(dashboard)/settings/members/loading.tsx
Introduced new asynchronous React loading components utilizing internationalization and UI patterns for API keys, settings, and members pages.
apps/app/src/app/[locale]/(app)/(dashboard)/settings/api-keys/page.tsx Added new async function getApiKeys with caching to fetch active API keys and updated the page to pass data to the ApiKeysTable component.
apps/app/src/app/[locale]/(app)/(dashboard)/settings/page.tsx Wrapped the OrganizationSettings component with React’s Suspense for improved handling of asynchronous data.
apps/app/src/components/logo-spinner.tsx Added new LogoSpinner component that renders an animated SVG logo spinner using framer-motion.
apps/app/src/components/tables/api-keys/index.tsx Updated ApiKeysTable to accept an apiKeys prop directly, removing internal data fetching, loading states, and error handling.

Sequence Diagram(s)

sequenceDiagram
  participant User as User
  participant Action as API Key Action
  participant DB as Database
  participant Cache as revalidatePath

  User->>Action: Request create/revoke API key
  Action->>DB: Perform database operation
  DB-->>Action: Return operation result
  Action->>Cache: revalidatePath("/settings/api-keys")
  Action-->>User: Return success response
Loading
sequenceDiagram
  participant User as User
  participant Page as API Keys Page
  participant GK as getApiKeys
  participant Table as ApiKeysTable

  User->>Page: Navigate to API Keys dashboard
  Page->>GK: Fetch active API keys (with caching)
  GK-->>Page: Return API keys data
  Page->>Table: Render table with API keys
Loading
sequenceDiagram
  participant User as User
  participant Settings as Settings Page
  participant Suspense as Suspense Wrapper
  participant Org as OrganizationSettings

  User->>Settings: Visit organization settings
  Settings->>Suspense: Wrap organization settings component
  Suspense->>Org: Load settings components asynchronously
  Org-->>Suspense: Return rendered settings
  Suspense-->>Settings: Display loaded settings
Loading

Possibly related PRs

  • style: homepage updates #62: Introduces similar caching revalidation using revalidatePath in API key operations.
  • Improvements #124: Modifies API key actions to include revalidatePath, closely aligning with these changes.
  • Mariano/stuff #45: Implements cache revalidation in API key operations, matching the approach taken in this PR.

Poem

In fields of code, I hop with glee,
Refreshing paths as swift as can be.
API keys now sparkle and shine,
Loading screens dance in perfect time.
A rhythmic beat in every line,
CodeRabbit cheers—updates are divine! 🐇✨

Tip

⚡🧪 Multi-step agentic review comment chat (experimental)
  • We're introducing multi-step agentic chat in review comments. This experimental feature enhances review discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments.
    - To enable this feature, set early_access to true under in the settings.

📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 593bf30 and 5c13cda.

📒 Files selected for processing (1)
  • apps/app/src/components/forms/create-organization-form.tsx (3 hunks)
✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 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.
  • @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
Copy Markdown

@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)
apps/app/src/app/[locale]/(app)/(dashboard)/settings/page.tsx (1)

29-35: Consider adding a fallback prop to Suspense

While wrapping the components with Suspense enables asynchronous rendering, you might want to specify a fallback UI to show during loading.

-    <Suspense>
+    <Suspense fallback={<Loading />}>
      <div className="space-y-12">
        <UpdateOrganizationName organizationName={organization?.name ?? ""} />
        <UpdateOrganizationWebsite organizationWebsite={organization?.website ?? ""} />
        <DeleteOrganization organizationId={organization?.id ?? ""} />
      </div>
    </Suspense>

This would require importing the Loading component from your loading.tsx file.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between f1fff75 and 593bf30.

📒 Files selected for processing (9)
  • apps/app/src/actions/organization/create-api-key-action.ts (1 hunks)
  • apps/app/src/actions/organization/revoke-api-key-action.ts (1 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/settings/api-keys/loading.tsx (1 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/settings/api-keys/page.tsx (1 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/settings/loading.tsx (1 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/settings/members/loading.tsx (1 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/settings/page.tsx (2 hunks)
  • apps/app/src/components/logo-spinner.tsx (1 hunks)
  • apps/app/src/components/tables/api-keys/index.tsx (1 hunks)
🧰 Additional context used
🧬 Code Definitions (6)
apps/app/src/app/[locale]/(app)/(dashboard)/settings/api-keys/loading.tsx (3)
apps/app/src/app/[locale]/(app)/(dashboard)/settings/members/loading.tsx (1) (1)
  • Loading (8-56)
apps/app/src/app/[locale]/(app)/(dashboard)/settings/loading.tsx (1) (1)
  • Loading (7-64)
apps/app/src/components/logo-spinner.tsx (1) (1)
  • LogoSpinner (14-85)
apps/app/src/app/[locale]/(app)/(dashboard)/settings/loading.tsx (2)
apps/app/src/app/[locale]/(app)/(dashboard)/settings/api-keys/loading.tsx (1) (1)
  • Loading (7-34)
apps/app/src/app/[locale]/(app)/(dashboard)/settings/members/loading.tsx (1) (1)
  • Loading (8-56)
apps/app/src/actions/organization/create-api-key-action.ts (2)
apps/app/src/actions/schema.ts (1) (1)
  • apiKeySchema (318-324)
apps/app/src/lib/api-key.ts (3) (3)
  • generateApiKey (10-15)
  • generateSalt (21-23)
  • hashApiKey (31-40)
apps/app/src/app/[locale]/(app)/(dashboard)/settings/api-keys/page.tsx (1)
apps/app/src/components/tables/api-keys/index.tsx (1) (1)
  • ApiKeysTable (37-217)
apps/app/src/app/[locale]/(app)/(dashboard)/settings/members/loading.tsx (3)
apps/app/src/app/[locale]/(app)/(dashboard)/settings/api-keys/loading.tsx (1) (1)
  • Loading (7-34)
apps/app/src/app/[locale]/(app)/(dashboard)/settings/loading.tsx (1) (1)
  • Loading (7-64)
apps/app/src/components/logo-spinner.tsx (1) (1)
  • LogoSpinner (14-85)
apps/app/src/components/tables/api-keys/index.tsx (2)
apps/app/src/hooks/use-api-keys.ts (1) (1)
  • ApiKey (8-15)
apps/app/src/actions/organization/revoke-api-key-action.ts (1) (1)
  • revokeApiKeyAction (12-55)
🔇 Additional comments (31)
apps/app/src/app/[locale]/(app)/(dashboard)/settings/api-keys/loading.tsx (1)

1-34: Well-implemented loading component for API keys page

This new loading component follows the established pattern in your application for creating consistent loading states. The implementation uses internationalization correctly for text content and includes the new LogoSpinner component to provide visual feedback during loading.

The structure mirrors what users will see in the loaded state, providing a seamless transition when data becomes available.

apps/app/src/actions/organization/create-api-key-action.ts (2)

7-7: Good addition of cache revalidation

Adding the revalidatePath import for cache invalidation is a good practice.


69-69: Cache revalidation ensures UI consistency

Adding revalidatePath("/settings/api-keys") after creating an API key ensures that users immediately see the updated list of keys without requiring a manual refresh. This improves the user experience.

apps/app/src/app/[locale]/(app)/(dashboard)/settings/page.tsx (1)

10-10: Added Suspense for asynchronous rendering

Importing both cache and Suspense from React provides the foundation for the improved loading behavior.

apps/app/src/actions/organization/revoke-api-key-action.ts (2)

6-6: Good addition of cache revalidation

Adding the revalidatePath import for cache invalidation is a good practice.


42-42: Cache revalidation ensures UI consistency

Adding revalidatePath("/settings/api-keys") after revoking an API key ensures that users immediately see the updated list of keys without requiring a manual refresh. This improves the user experience.

apps/app/src/app/[locale]/(app)/(dashboard)/settings/members/loading.tsx (5)

1-7: Well-structured imports.

Clean organization of imports, separating UI components, server utilities, and custom components.


8-10: Good use of async server component.

The component properly fetches i18n translations asynchronously, which aligns with Next.js server component best practices.


11-22: Clean tab implementation.

The tabs implementation is well-structured with appropriate styling and default value. The custom styling for tab list and triggers creates a visually integrated design.


23-33: Good loading state for members tab.

The members tab content displays a clean card with appropriate title and loading spinner.


35-52: Thoughtful loading UI for invite tab.

I like the use of blur effects on certain elements to indicate loading state, while still showing the general structure. This creates a better user experience by maintaining layout continuity.

apps/app/src/app/[locale]/(app)/(dashboard)/settings/loading.tsx (5)

1-6: Well-organized imports.

Imports are logically grouped by their source and purpose.


7-9: Proper async server component implementation.

The Loading component correctly uses the async pattern to fetch i18n translations.


10-26: Well-structured organization name card.

The card follows best practices with:

  • Clear title and description
  • Disabled input with appropriate placeholder
  • Well-styled footer with tip and disabled save button
  • Proper accessibility with aria-label

28-42: Consistent organization website card.

This card maintains the same structure and styling as the organization name card, creating a consistent user experience.


44-61: Appropriate destructive styling for delete card.

The delete organization card correctly uses destructive styling to indicate danger. The AlertDialog is properly implemented with disabled trigger button and appropriate aria-label.

apps/app/src/app/[locale]/(app)/(dashboard)/settings/api-keys/page.tsx (4)

7-8: Added necessary imports for database access and caching.

The new imports enable server-side data fetching with caching capability.


10-24: Improved session handling and authentication check.

The component now properly validates the user session and redirects if the user doesn't have an organization ID.


25-31: Server-side data fetching implementation.

The component now fetches API keys server-side and passes them to the ApiKeysTable component, following the recommended pattern for Next.js server components.


48-73: Well-implemented cached data fetching function.

The getApiKeys function:

  • Uses React's cache for performance optimization
  • Implements proper database query with filtering and ordering
  • Selects only necessary fields
  • Properly formats date fields to ISO strings for client-side consumption

This approach improves performance and separates data fetching from presentation.

apps/app/src/components/logo-spinner.tsx (5)

1-7: Correct client directive and imports.

The "use client" directive is properly placed at the top of the file. Imports are well-organized, including the motion components from framer-motion.


8-12: Clear props interface definition.

The LogoSpinnerProps interface properly extends SVG props and defines additional custom properties with appropriate types.


14-29: Well-structured component with proper hooks usage.

The component:

  • Uses destructuring with default values for props
  • Implements useRef and useState correctly
  • Uses useEffect appropriately to calculate path length on mount

33-54: Clean SVG implementation with motion animations.

The SVG implementation:

  • Is wrapped in a flex container for proper centering
  • Uses motion.svg with scale animation
  • Spreads additional props correctly
  • Provides a clear comment for the path

56-81: Well-implemented animation for the racing line.

The motion.path implementation:

  • References the path for measurement
  • Uses the custom color prop
  • Has appropriate stroke styling
  • Implements smooth animation with infinite repeat
  • Includes appropriate timing and easing

The racing line effect creates a visually appealing loading indicator that matches the application's branding.

apps/app/src/components/tables/api-keys/index.tsx (6)

4-4: Updated import for ApiKey type looks good

The component now only imports the type definition for ApiKey instead of using the hook for fetching data, aligning with the component's new data-receiving approach.


37-37: Well-structured component signature change

The component now accepts API keys as a prop instead of fetching them internally, which is a good architectural change following separation of concerns. This allows the parent component to handle data fetching and caching while this component focuses on presentation.


38-57: Simplified state management and API key revocation

The component no longer manages loading or error states for API key fetching, making the code cleaner. The revocation functionality remains intact with appropriate toast notifications and state resets.


99-103: Improved conditional rendering logic

The rendering logic has been simplified to directly check the apiKeys array length, making the code more straightforward. This approach eliminates the need for separate loading states and simplifies the UI logic.


124-166: Proper rendering of API keys from props

The component now directly maps over the provided apiKeys prop to render the table rows. The responsive design with different displays for mobile and desktop viewports is well-maintained.


182-214: Revoke dialog implementation looks good

The dialog for revoking API keys is well-implemented with appropriate loading states, cancel functionality, and error handling. The responsive design adjustments for different screen sizes are maintained.

- Replaced Loader2 with LogoSpinner for improved loading indication.
- Removed completed status section to streamline the UI.
- Cleaned up unnecessary code and ensured consistent formatting.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant