Skip to content

Conversation

@devdezzies
Copy link
Owner

@devdezzies devdezzies commented Jun 30, 2025

Summary by CodeRabbit

  • New Features

    • Introduced a split-view project interface with resizable panels, featuring a messages area and a placeholder for web preview.
    • Added a message container displaying project-specific messages with automatic scrolling and support for interactive message fragments.
    • Implemented a message form with validation, auto-resizing textarea, keyboard shortcuts, and real-time updates after sending.
    • Enhanced message display with distinct styling for user and assistant roles, including clickable fragments.
  • Improvements

    • Improved data loading and UI responsiveness with data prefetching and hydration.
    • Added project detail fetching with error handling for missing projects.
  • Bug Fixes

    • Ensured messages are properly filtered and displayed per project.
  • Chores

    • Updated dependencies to include auto-resizing textarea support.

@coderabbitai
Copy link

coderabbitai bot commented Jun 30, 2025

Walkthrough

This update introduces a comprehensive project messaging interface. It adds new backend procedures for fetching projects and project-specific messages, and implements frontend components for displaying messages, submitting new ones, and rendering a split-panel project view. Data fetching is optimized using React Query with TRPC integration, including prefetching and hydration.

Changes

File(s) Change Summary
package.json Added react-textarea-autosize dependency.
src/app/projects/[projectId]/page.tsx Refactored to prefetch project and message data using React Query and TRPC; added hydration and suspense boundaries.
src/modules/messages/server/procedures.ts Updated getMany to require projectId input and return messages with fragments.
src/modules/projects/server/procedures.ts Added getOne procedure to fetch a single project by ID; minor refactor to getMany.
src/modules/projects/ui/components/message-card.tsx Introduced MessageCard component for rendering user and assistant messages with fragment interaction.
src/modules/projects/ui/components/message-form.tsx Added MessageForm for submitting new messages, with validation and mutation logic.
src/modules/projects/ui/components/messages-container.tsx Added MessagesContainer to fetch, display, and auto-scroll messages; integrates MessageCard and MessageForm.
src/modules/projects/ui/views/project-view.tsx Introduced ProjectView with a resizable split-panel layout for messages and a placeholder for web preview.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ProjectPage
    participant ReactQuery/TRPC
    participant Backend

    User->>ProjectPage: Navigates to /projects/[projectId]
    ProjectPage->>ReactQuery/TRPC: Prefetch project and messages
    ReactQuery/TRPC->>Backend: getOne(projectId), getMany({ projectId })
    Backend-->>ReactQuery/TRPC: Project data, Messages data
    ReactQuery/TRPC-->>ProjectPage: Hydrated data
    ProjectPage->>ProjectView: Render with projectId
    ProjectView->>MessagesContainer: Render messages panel
    MessagesContainer->>ReactQuery/TRPC: Fetch messages (suspense)
    User->>MessageForm: Submit new message
    MessageForm->>ReactQuery/TRPC: createMessage mutation
    ReactQuery/TRPC->>Backend: Create message in DB
    Backend-->>ReactQuery/TRPC: New message confirmation
    ReactQuery/TRPC->>MessagesContainer: Invalidate and refetch messages
Loading

Possibly related PRs

Poem

A bunny hops with nimble flair,
New messages and panels pair.
Projects fetched and fragments shown,
Cards and forms, the UI’s grown!
With queries quick and panels wide,
The code and chat now coincide.
🐇✨

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

npm error Exit handler never called!
npm error This is an error with npm itself. Please report this error at:
npm error https://github.com/npm/cli/issues
npm error A complete log of this run can be found in: /.npm/_logs/2025-06-30T18_09_53_345Z-debug-0.log


📜 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 3ed4fdb and 81d87b0.

📒 Files selected for processing (1)
  • src/modules/projects/ui/components/messages-container.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/modules/projects/ui/components/messages-container.tsx
✨ 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.
    • Explain this complex logic.
    • 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 explain this code block.
    • @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 explain its main purpose.
    • @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.

Support

Need 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)

  • @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 generate sequence diagram to generate a sequence diagram of the changes in 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

@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: 4

🧹 Nitpick comments (7)
src/modules/projects/server/procedures.ts (1)

26-35: Minor formatting inconsistency in procedure structure.

The getMany procedure has inconsistent formatting compared to the new getOne procedure. Consider aligning the formatting for consistency.

-    getMany: baseProcedure 
+    getMany: baseProcedure
         .query(async () => {
             const results = await prisma.project.findMany({
                 orderBy: {
                     updatedAt: "desc"
                 }
-            }); 
+            });
 
             return results;
         }),
src/modules/projects/ui/views/project-view.tsx (3)

35-35: Fix incorrect fallback text for the web preview panel.

The fallback text says "Loading messages" but this panel is for the web preview, not messages.

-                    <Suspense fallback={<p>Loading messages</p>}>
+                    <Suspense fallback={<p>Loading preview...</p>}>

36-36: TODO comment indicates incomplete implementation.

The right panel currently shows a placeholder. This suggests the web preview functionality is not yet implemented.

Would you like me to help implement the web preview functionality or create an issue to track this TODO item?


19-19: Consider making height more flexible.

The hardcoded h-screen class assumes the component will always occupy the full viewport height. Consider making this configurable or using h-full if the parent container manages the height.

-        <div className="h-screen">
+        <div className="h-full">
src/modules/projects/ui/components/message-form.tsx (3)

58-58: Remove unused variable.

The showUsage variable is defined but never set to true, making the conditional styling unreachable.

Apply this diff to remove the unused variable:

-    const showUsage = false;

And remove the related conditional styling:

                className={cn(
                    "relative border p-4 pt-1 rounded-xl bg-sidebar dark:bg-sidebar transtion-all", 
-                    isFocused && "shadow-xs", 
-                    showUsage && "rounded-t-none"
+                    isFocused && "shadow-xs"
                )}

65-65: Fix typo in CSS class name.

There's a typo in the className: "transtion-all" should be "transition-all".

Apply this diff to fix the typo:

-                    "relative border p-4 pt-1 rounded-xl bg-sidebar dark:bg-sidebar transtion-all", 
+                    "relative border p-4 pt-1 rounded-xl bg-sidebar dark:bg-sidebar transition-all", 

48-53: Consider improving error handling in form submission.

The current implementation doesn't handle potential validation errors that might occur during mutation.

Consider wrapping the mutation call in a try-catch block:

    const onSubmit = async (values: z.infer<typeof formSchema>) => {
+        try {
            await createMessage.mutateAsync({
                value: values.value, 
                projectId: projectId,
            });
+        } catch (error) {
+            // Error is already handled by onError callback, but we can add additional logic here if needed
+        }
    };
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 9e56e5d and 3ed4fdb.

⛔ Files ignored due to path filters (2)
  • package-lock.json is excluded by !**/package-lock.json
  • public/logo.svg is excluded by !**/*.svg
📒 Files selected for processing (8)
  • package.json (1 hunks)
  • src/app/projects/[projectId]/page.tsx (1 hunks)
  • src/modules/messages/server/procedures.ts (1 hunks)
  • src/modules/projects/server/procedures.ts (1 hunks)
  • src/modules/projects/ui/components/message-card.tsx (1 hunks)
  • src/modules/projects/ui/components/message-form.tsx (1 hunks)
  • src/modules/projects/ui/components/messages-container.tsx (1 hunks)
  • src/modules/projects/ui/views/project-view.tsx (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (5)
src/modules/projects/server/procedures.ts (2)
src/trpc/init.ts (2)
  • createTRPCRouter (21-21)
  • baseProcedure (23-23)
src/lib/db.ts (1)
  • prisma (7-7)
src/modules/messages/server/procedures.ts (1)
src/lib/db.ts (1)
  • prisma (7-7)
src/modules/projects/ui/views/project-view.tsx (2)
src/components/ui/resizable.tsx (3)
  • ResizablePanelGroup (56-56)
  • ResizablePanel (56-56)
  • ResizableHandle (56-56)
src/modules/projects/ui/components/messages-container.tsx (1)
  • MessagesContainer (9-56)
src/modules/projects/ui/components/message-form.tsx (4)
src/trpc/server.tsx (1)
  • trpc (10-14)
src/components/ui/form.tsx (2)
  • Form (160-160)
  • FormField (166-166)
src/lib/utils.ts (1)
  • cn (4-6)
src/components/ui/button.tsx (1)
  • Button (60-60)
src/modules/projects/ui/components/message-card.tsx (2)
src/lib/utils.ts (1)
  • cn (4-6)
src/components/ui/card.tsx (1)
  • Card (85-85)
🔇 Additional comments (9)
package.json (1)

63-63: Dependency update validated: react-textarea-autosize@8.5.9 is up-to-date and secure

  • 8.5.9 is the latest published version as of March 30, 2025.
  • No known security advisories or vulnerabilities are reported against this release.

This addition can be safely merged.

src/modules/projects/server/procedures.ts (1)

9-25: LGTM! Well-implemented procedure with proper error handling.

The getOne procedure follows good practices:

  • Proper input validation with meaningful error messages
  • Appropriate database query using findUnique
  • Correct error handling with TRPCError and NOT_FOUND code
  • Clean return of the found project
src/modules/messages/server/procedures.ts (1)

8-26: All messages.getMany calls now include projectId – breaking change impact addressed

I searched the entire codebase and confirmed every trpc.messages.getMany invocation passes a projectId:

  • src/modules/projects/ui/components/messages-container.tsx
  • src/modules/projects/ui/components/message-form.tsx
  • src/app/projects/[projectId]/page.tsx

No missing usages remain. The API change is fully supported by the calling code.

src/app/projects/[projectId]/page.tsx (2)

12-21: LGTM! Well-implemented data prefetching strategy.

The prefetching implementation follows Next.js best practices:

  • Properly awaits params before using them
  • Correctly prefetches both required queries (messages and project data)
  • Uses void appropriately for fire-and-forget prefetch operations
  • Integrates well with the updated backend procedures

24-28: Excellent use of React Query hydration.

The HydrationBoundary setup correctly passes the dehydrated query state to enable client-side hydration, and the Suspense wrapper provides a good loading experience.

src/modules/projects/ui/components/messages-container.tsx (1)

30-55: Component structure and data flow look good.

The component properly handles data fetching, rendering, and provides a clean interface for the messaging functionality.

src/modules/projects/ui/components/message-form.tsx (1)

20-24: Form validation and implementation look solid.

The zod schema provides appropriate validation, form setup is correct, and the textarea integration with keyboard shortcuts works well.

Also applies to: 41-46, 70-91

src/modules/projects/ui/components/message-card.tsx (2)

10-18: Component architecture and TypeScript interfaces are well-designed.

The component properly separates concerns with dedicated subcomponents, uses comprehensive TypeScript interfaces, and implements clean conditional rendering based on message roles.

Also applies to: 30-37, 65-103, 115-134


105-113: UserMessage component is clean and functional.

Simple, focused component that handles user message display with proper styling and responsive design.

Comment on lines +44 to +62
return (
<button className={cn(
"flex items-start text-start gap-2 border rounded-lg bg-muted w-fit p-3 hover:bg-secondary transition-colors cursor-pointer",
isActiveFragment && "bg-primary text-primary-foreground border-primary hover:bg-primary"
)}>
<Code2Icon className="size-4 mt-0.5" />
<div className="flex flex-col flex-1">
<span className="text-sm font-medium line-clamp-1">
{fragment.title}
</span>
<span className="text-sm">
Preview
</span>
</div>
<div className="flex items-center justify-center mt-0.5">
<ChevronRightIcon className="size-4" />
</div>
</button>
)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

FragmentCard component missing onClick handler.

The FragmentCard button doesn't call the onFragmentClick handler that was passed as a prop.

Apply this diff to fix the missing click handler:

        <button className={cn(
            "flex items-start text-start gap-2 border rounded-lg bg-muted w-fit p-3 hover:bg-secondary transition-colors cursor-pointer",
            isActiveFragment && "bg-primary text-primary-foreground border-primary hover:bg-primary"
-        )}>
+        )}
+        onClick={() => onFragmentClick(fragment)}>
📝 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
return (
<button className={cn(
"flex items-start text-start gap-2 border rounded-lg bg-muted w-fit p-3 hover:bg-secondary transition-colors cursor-pointer",
isActiveFragment && "bg-primary text-primary-foreground border-primary hover:bg-primary"
)}>
<Code2Icon className="size-4 mt-0.5" />
<div className="flex flex-col flex-1">
<span className="text-sm font-medium line-clamp-1">
{fragment.title}
</span>
<span className="text-sm">
Preview
</span>
</div>
<div className="flex items-center justify-center mt-0.5">
<ChevronRightIcon className="size-4" />
</div>
</button>
)
return (
<button
className={cn(
"flex items-start text-start gap-2 border rounded-lg bg-muted w-fit p-3 hover:bg-secondary transition-colors cursor-pointer",
isActiveFragment && "bg-primary text-primary-foreground border-primary hover:bg-primary"
)}
onClick={() => onFragmentClick(fragment)}
>
<Code2Icon className="size-4 mt-0.5" />
<div className="flex flex-col flex-1">
<span className="text-sm font-medium line-clamp-1">
{fragment.title}
</span>
<span className="text-sm">
Preview
</span>
</div>
<div className="flex items-center justify-center mt-0.5">
<ChevronRightIcon className="size-4" />
</div>
</button>
)
🤖 Prompt for AI Agents
In src/modules/projects/ui/components/message-card.tsx around lines 44 to 62,
the button element representing the FragmentCard is missing an onClick handler
to call the onFragmentClick prop. To fix this, add an onClick attribute to the
button element that invokes the onFragmentClick function passed as a prop,
ensuring the component responds to user clicks as intended.

<FragmentCard
fragment={fragment}
isActiveFragment={isActiveFragment}
onFragmentClick={() => { }}
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Fragment click handlers are not implemented.

The onFragmentClick handlers are defined as empty functions, which means the fragment interaction functionality is incomplete.

The onFragmentClick prop is passed down but never called. Verify if this is intentional placeholder code or if the implementation is missing.

Also applies to: 125-125


🏁 Script executed:

#!/bin/bash
# Search for fragment click handler implementations or usage
rg -A 5 -B 5 "onFragmentClick"

Length of output: 7382


Implement real onFragmentClick handlers for fragment clicks

The onFragmentClick props in both messages-container.tsx and message-card.tsx are currently no-op placeholders (() => {}), so clicking a fragment does nothing. You need to propagate and invoke the actual handler with the clicked fragment.

• In src/modules/projects/ui/components/messages-container.tsx, replace:

- onFragmentClick={() => {}}
+ onFragmentClick={onFragmentClick}

so that the container’s callback is passed down.

• In src/modules/projects/ui/components/message-card.tsx, forward the prop instead of re-defining an empty handler:

// When rendering AssistantMessage
- onFragmentClick={() => {}}
+ onFragmentClick={onFragmentClick}

• Inside FragmentCard, invoke the handler with the fragment:

- <button className="…" /* no click handler */>
+ <button
+   className="…"
+   onClick={() => onFragmentClick(fragment)}
+>

This ensures that clicking a fragment actually calls your handler with the selected fragment.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/modules/projects/ui/components/message-card.tsx at line 97, the
onFragmentClick prop is currently set to an empty function, preventing fragment
clicks from triggering any action. To fix this, modify message-card.tsx to
accept onFragmentClick as a prop and forward it without redefining it as a
no-op. Then, in messages-container.tsx, pass the actual onFragmentClick handler
down to message-card. Finally, ensure that inside FragmentCard, the
onFragmentClick handler is called with the clicked fragment as an argument to
propagate the click event properly.

@devdezzies devdezzies merged commit a927db3 into main Jun 30, 2025
1 check passed
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.

2 participants