-
Notifications
You must be signed in to change notification settings - Fork 6
10: added ui messages #9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughThis 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
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
Possibly related PRs
Poem
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
npm error Exit handler never called! 📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
✨ Finishing Touches
🪧 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.
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
getManyprocedure has inconsistent formatting compared to the newgetOneprocedure. 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-screenclass assumes the component will always occupy the full viewport height. Consider making this configurable or usingh-fullif 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
showUsagevariable is defined but never set totrue, 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
⛔ Files ignored due to path filters (2)
package-lock.jsonis excluded by!**/package-lock.jsonpublic/logo.svgis 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
getOneprocedure follows good practices:
- Proper input validation with meaningful error messages
- Appropriate database query using
findUnique- Correct error handling with
TRPCErrorandNOT_FOUNDcode- 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 addressedI searched the entire codebase and confirmed every
trpc.messages.getManyinvocation passes aprojectId:
- 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
voidappropriately for fire-and-forget prefetch operations- Integrates well with the updated backend procedures
24-28: Excellent use of React Query hydration.The
HydrationBoundarysetup correctly passes the dehydrated query state to enable client-side hydration, and theSuspensewrapper 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.
| 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> | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| 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={() => { }} |
There was a problem hiding this comment.
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.
Summary by CodeRabbit
New Features
Improvements
Bug Fixes
Chores