Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughThe changes consolidate Prisma client usage into a shared instance across API routes and auth modules, expand API endpoints to return related contact and payment destination data, restructure form components to group payment destinations by their owning contacts, refactor UI styling with simplified iconography and initials-based avatars, and remove redundant per-item API detail fetches. Changes
Estimated Code Review Effort🎯 3 (Moderate) | ⏱️ ~30 minutes Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (4)
app/api/prisms/route.ts (1)
19-25: Minor inconsistency: GET includesThe GET handler selects
Proposed fix to align POST response with GET
contact: { select: { id: true, firstName: true, lastName: true, screenName: true, + email: true, }, },Also applies to: 102-107
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/api/prisms/route.ts` around lines 19 - 25, GET's contact select includes email but the POST response's contact select (in the create/prism response) omits it, causing inconsistent shapes; update the POST handler's response selection (the contact select used when returning the newly created prism in route.ts) to include email alongside id, firstName, lastName, and screenName so the POST and GET return the same contact fields.app/contacts/page.tsx (1)
9-17: Consider consolidating duplicateContactinterface.The
Contactinterface is defined both here and inapp/components/ContactCard.tsx. Consider extracting to a shared types file (e.g.,@/types/contact.ts) to avoid drift and duplication.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/contacts/page.tsx` around lines 9 - 17, The Contact interface is duplicated; extract the interface Contact into a single shared type module and export it, then replace the local Contact definitions in the page and the ContactCard component with an import of the shared Contact type, removing the duplicate declarations and ensuring all usages (firstName, lastName, screenName, email, nostrPubkey, metadata, id) match the exported shape so the app compiles and types remain consistent.app/prisms/new/page.tsx (1)
36-186: Significant code duplication withPrismForm.tsx.This page duplicates most of the form logic from
app/components/PrismForm.tsx:
- Same
ContactandPaymentDestinationinterfaces- Same
fetchContactsimplementation- Same
getContactNamehelper- Same form state management (
handleInputChange,handleAddSplit,handleRemoveSplit,handleSplitChange)- Same validation logic
Since
PrismFormalready exists as a reusable component, consider using it here instead of duplicating the implementation.Example refactor to use PrismForm
'use client'; import { useState } from 'react'; import { useRouter } from 'next/navigation'; import PrismForm, { PrismFormData } from '@/app/components/PrismForm'; export default function NewPrismPage() { const router = useRouter(); const [loading, setLoading] = useState(false); const [error, setError] = useState<string | null>(null); const handleSubmit = async (data: PrismFormData) => { setLoading(true); setError(null); try { const response = await fetch('/api/prisms', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data), }); if (!response.ok) { const result = await response.json(); throw new Error(result.error || 'Failed to create prism'); } router.push('/prisms'); } catch (err) { setError(err instanceof Error ? err.message : 'An error occurred'); } finally { setLoading(false); } }; return ( <PrismForm title="Create New Prism" onSubmit={handleSubmit} isLoading={loading} error={error} /> ); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/prisms/new/page.tsx` around lines 36 - 186, The NewPrismPage component duplicates much of the form logic already implemented in PrismForm.tsx, leading to unnecessary code duplication. Refactor NewPrismPage to remove the local state management, fetchContacts, form handlers, validation, and getContactName, and instead use the existing PrismForm component by importing it and passing required props like title, onSubmit, isLoading, and error. Move the fetch and submit logic into a handleSubmit function that accepts the form data and handles the POST request and routing, then render PrismForm in NewPrismPage with this handler to simplify and reuse the form functionality.package.json (1)
27-27: Verify necessity ofdotenvdependency.Next.js has built-in support for loading
.env*files automatically since version 9.4. Thedotenvpackage is typically redundant for standard Next.js runtime usage. However, it may be necessary if you're loading environment files outside the Next.js runtime (e.g., in Prisma seed scripts, custom config files, or ORM setup). If needed for non-runtime scenarios, consider using@next/envwithloadEnvConfiginstead, which is the recommended approach.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@package.json` at line 27, The package lists "dotenv" as a dependency which is likely redundant for Next.js apps; inspect usages of "dotenv" in the repo (search for require('dotenv'), import 'dotenv', or dotenv.config()) and either remove the dependency from package.json if it's unused, or if it's only used in non-Next runtime contexts (e.g., Prisma seed scripts, custom config or ORM setup) replace those usages with the Next.js recommended approach using `@next/env`'s loadEnvConfig or keep "dotenv" as a dev-only dependency and document why it's required; update package.json (remove or move "dotenv" to devDependencies or add "@next/env"), adjust any scripts that call dotenv to use loadEnvConfig where appropriate, and run the test/build to ensure no missing env loading.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@app/components/PrismCard.tsx`:
- Around line 60-67: getInitials currently returns '?' when primaryAccount only
has an email, causing inconsistent fallback with getPrimaryAccountName; update
getInitials to check primaryAccount.email and use the first character of the
email's local-part (text before '@') as the initial (uppercased) when firstName
and screenName are absent. Ensure you reference the primaryAccount.email value,
safely handle missing/empty email, and keep existing behaviors for firstName and
screenName in the getInitials function.
In `@app/components/PrismForm.tsx`:
- Around line 264-270: The "No contacts found" warning in PrismForm.tsx is shown
even when a contacts-loading error exists; update the conditional that renders
the warning to also check that there is no error (i.e., change the render guard
from contacts.length === 0 to contacts.length === 0 && !error), so the message
only appears when contacts are empty and there is no error; locate the JSX block
that references contacts and the existing error variable in the PrismForm
component and add the !error check to that condition.
In `@app/prisms/page.tsx`:
- Around line 69-70: The code currently assigns the raw API payload to state via
setPrisms and setFilteredPrisms without validation; update the logic that
handles the /api/prisms response (where response.json() is used and
setPrisms/setFilteredPrisms are called) to validate the payload shape is an
array (Array.isArray) before storing it; if it is not an array, log or surface
the error and fall back to an empty array (or abort setting state) so downstream
list operations on prisms/filtering won’t throw.
In `@lib/auth.ts`:
- Line 22: The baseURL in the server-side auth configuration uses a fallback
chain with BETTER_AUTH_URL prioritized over NEXT_PUBLIC_APP_URL, while
lib/auth-client.ts uses only NEXT_PUBLIC_APP_URL. To fix this mismatch, align
the baseURL fallback logic in lib/auth.ts with that in lib/auth-client.ts by
either using only NEXT_PUBLIC_APP_URL or documenting clearly that
BETTER_AUTH_URL and NEXT_PUBLIC_APP_URL must match when both are set. This will
ensure the server and client use the same baseURL and prevent auth issues.
---
Nitpick comments:
In `@app/api/prisms/route.ts`:
- Around line 19-25: GET's contact select includes email but the POST response's
contact select (in the create/prism response) omits it, causing inconsistent
shapes; update the POST handler's response selection (the contact select used
when returning the newly created prism in route.ts) to include email alongside
id, firstName, lastName, and screenName so the POST and GET return the same
contact fields.
In `@app/contacts/page.tsx`:
- Around line 9-17: The Contact interface is duplicated; extract the interface
Contact into a single shared type module and export it, then replace the local
Contact definitions in the page and the ContactCard component with an import of
the shared Contact type, removing the duplicate declarations and ensuring all
usages (firstName, lastName, screenName, email, nostrPubkey, metadata, id) match
the exported shape so the app compiles and types remain consistent.
In `@app/prisms/new/page.tsx`:
- Around line 36-186: The NewPrismPage component duplicates much of the form
logic already implemented in PrismForm.tsx, leading to unnecessary code
duplication. Refactor NewPrismPage to remove the local state management,
fetchContacts, form handlers, validation, and getContactName, and instead use
the existing PrismForm component by importing it and passing required props like
title, onSubmit, isLoading, and error. Move the fetch and submit logic into a
handleSubmit function that accepts the form data and handles the POST request
and routing, then render PrismForm in NewPrismPage with this handler to simplify
and reuse the form functionality.
In `@package.json`:
- Line 27: The package lists "dotenv" as a dependency which is likely redundant
for Next.js apps; inspect usages of "dotenv" in the repo (search for
require('dotenv'), import 'dotenv', or dotenv.config()) and either remove the
dependency from package.json if it's unused, or if it's only used in non-Next
runtime contexts (e.g., Prisma seed scripts, custom config or ORM setup) replace
those usages with the Next.js recommended approach using `@next/env`'s
loadEnvConfig or keep "dotenv" as a dev-only dependency and document why it's
required; update package.json (remove or move "dotenv" to devDependencies or add
"@next/env"), adjust any scripts that call dotenv to use loadEnvConfig where
appropriate, and run the test/build to ensure no missing env loading.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: daaae448-d62c-42a9-b4bc-cd6b9b130996
⛔ Files ignored due to path filters (2)
package-lock.jsonis excluded by!**/package-lock.jsonyarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (10)
app/api/contacts/[id]/route.tsapp/api/contacts/route.tsapp/api/prisms/route.tsapp/components/PrismCard.tsxapp/components/PrismForm.tsxapp/contacts/page.tsxapp/prisms/new/page.tsxapp/prisms/page.tsxlib/auth.tspackage.json
| const getInitials = (): string => { | ||
| if (!primaryAccount) return '?'; | ||
| if (primaryAccount.firstName) { | ||
| return (primaryAccount.firstName[0] + (primaryAccount.lastName?.[0] || '')).toUpperCase(); | ||
| } | ||
| if (primaryAccount.screenName) return primaryAccount.screenName[0].toUpperCase(); | ||
| return '?'; | ||
| }; |
There was a problem hiding this comment.
Handle email-only contacts in initials fallback.
On Line 65–66, getInitials() returns ? when only email is present, even though getPrimaryAccountName() can show that email. This creates inconsistent identity rendering for valid contact shapes.
Suggested fix
const getInitials = (): string => {
if (!primaryAccount) return '?';
if (primaryAccount.firstName) {
return (primaryAccount.firstName[0] + (primaryAccount.lastName?.[0] || '')).toUpperCase();
}
if (primaryAccount.screenName) return primaryAccount.screenName[0].toUpperCase();
+ if (primaryAccount.email?.trim()) return primaryAccount.email.trim()[0].toUpperCase();
return '?';
};📝 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.
| const getInitials = (): string => { | |
| if (!primaryAccount) return '?'; | |
| if (primaryAccount.firstName) { | |
| return (primaryAccount.firstName[0] + (primaryAccount.lastName?.[0] || '')).toUpperCase(); | |
| } | |
| if (primaryAccount.screenName) return primaryAccount.screenName[0].toUpperCase(); | |
| return '?'; | |
| }; | |
| const getInitials = (): string => { | |
| if (!primaryAccount) return '?'; | |
| if (primaryAccount.firstName) { | |
| return (primaryAccount.firstName[0] + (primaryAccount.lastName?.[0] || '')).toUpperCase(); | |
| } | |
| if (primaryAccount.screenName) return primaryAccount.screenName[0].toUpperCase(); | |
| if (primaryAccount.email?.trim()) return primaryAccount.email.trim()[0].toUpperCase(); | |
| return '?'; | |
| }; |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@app/components/PrismCard.tsx` around lines 60 - 67, getInitials currently
returns '?' when primaryAccount only has an email, causing inconsistent fallback
with getPrimaryAccountName; update getInitials to check primaryAccount.email and
use the first character of the email's local-part (text before '@') as the
initial (uppercased) when firstName and screenName are absent. Ensure you
reference the primaryAccount.email value, safely handle missing/empty email, and
keep existing behaviors for firstName and screenName in the getInitials
function.
| {contacts.length === 0 && ( | ||
| <div className="bg-yellow-900/30 border border-yellow-800/50 rounded-lg p-4"> | ||
| <p className="text-yellow-300 text-sm"> | ||
| No contacts found. <a href="/contacts/add" className="underline hover:text-yellow-200">Create a contact</a> with a payment destination first. | ||
| </p> | ||
| </div> | ||
| )} |
There was a problem hiding this comment.
Missing !error check in "no contacts" warning condition.
Unlike app/prisms/new/page.tsx (line 272), this warning displays even when an error exists, which could show redundant UI messages.
Proposed fix
- {contacts.length === 0 && (
+ {contacts.length === 0 && !error && (
<div className="bg-yellow-900/30 border border-yellow-800/50 rounded-lg p-4">📝 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.
| {contacts.length === 0 && ( | |
| <div className="bg-yellow-900/30 border border-yellow-800/50 rounded-lg p-4"> | |
| <p className="text-yellow-300 text-sm"> | |
| No contacts found. <a href="/contacts/add" className="underline hover:text-yellow-200">Create a contact</a> with a payment destination first. | |
| </p> | |
| </div> | |
| )} | |
| {contacts.length === 0 && !error && ( | |
| <div className="bg-yellow-900/30 border border-yellow-800/50 rounded-lg p-4"> | |
| <p className="text-yellow-300 text-sm"> | |
| No contacts found. <a href="/contacts/add" className="underline hover:text-yellow-200">Create a contact</a> with a payment destination first. | |
| </p> | |
| </div> | |
| )} |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@app/components/PrismForm.tsx` around lines 264 - 270, The "No contacts found"
warning in PrismForm.tsx is shown even when a contacts-loading error exists;
update the conditional that renders the warning to also check that there is no
error (i.e., change the render guard from contacts.length === 0 to
contacts.length === 0 && !error), so the message only appears when contacts are
empty and there is no error; locate the JSX block that references contacts and
the existing error variable in the PrismForm component and add the !error check
to that condition.
| setPrisms(data); | ||
| setFilteredPrisms(data); |
There was a problem hiding this comment.
Validate /api/prisms payload shape before storing state.
On Line 69–70, raw response.json() is assigned directly to array state. If the API returns a non-array payload (e.g., transient error object), later list operations can fail at runtime.
Suggested fix
- const data = await response.json();
- setPrisms(data);
- setFilteredPrisms(data);
+ const data: unknown = await response.json();
+ if (!Array.isArray(data)) {
+ throw new Error('Invalid prisms payload');
+ }
+ setPrisms(data as Prism[]);
+ setFilteredPrisms(data as Prism[]);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@app/prisms/page.tsx` around lines 69 - 70, The code currently assigns the raw
API payload to state via setPrisms and setFilteredPrisms without validation;
update the logic that handles the /api/prisms response (where response.json() is
used and setPrisms/setFilteredPrisms are called) to validate the payload shape
is an array (Array.isArray) before storing it; if it is not an array, log or
surface the error and fall back to an empty array (or abort setting state) so
downstream list operations on prisms/filtering won’t throw.
| } | ||
|
|
||
| export const auth = betterAuth({ | ||
| baseURL: process.env.BETTER_AUTH_URL || process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000", |
There was a problem hiding this comment.
Potential baseURL mismatch between server and client auth.
Server-side auth prioritizes BETTER_AUTH_URL while lib/auth-client.ts uses only NEXT_PUBLIC_APP_URL. If these environment variables differ, the server and client will target different base URLs, potentially causing authentication failures or redirect issues.
Consider aligning the fallback chain or documenting that BETTER_AUTH_URL should equal NEXT_PUBLIC_APP_URL when both are set.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@lib/auth.ts` at line 22, The baseURL in the server-side auth configuration
uses a fallback chain with BETTER_AUTH_URL prioritized over NEXT_PUBLIC_APP_URL,
while lib/auth-client.ts uses only NEXT_PUBLIC_APP_URL. To fix this mismatch,
align the baseURL fallback logic in lib/auth.ts with that in lib/auth-client.ts
by either using only NEXT_PUBLIC_APP_URL or documenting clearly that
BETTER_AUTH_URL and NEXT_PUBLIC_APP_URL must match when both are set. This will
ensure the server and client use the same baseURL and prevent auth issues.
Summary by CodeRabbit
New Features
Improvements
Chores