Atlas-Bounty: Implement Private Earnings Dashboard (/me/earnings)#419
Conversation
|
Someone is attempting to deploy a commit to the Threadflow Team on Vercel. A member of the Team first needs to authorize it. |
|
Caution Review failedThe pull request is closed. ℹ️ Recent review infoConfiguration used: Organization UI Review profile: CHILL Plan: Pro Disabled knowledge base sources:
📒 Files selected for processing (2)
📝 WalkthroughWalkthroughAdds a new client-side Earnings dashboard page, a user-earnings API module (fetch + claim), and a sidebar navigation entry linking to /me/earnings. Changes
Sequence DiagramsequenceDiagram
participant User
participant Page as EarningsPage
participant API as API Layer
participant Backend as Backend
rect rgba(100,150,200,0.5)
Note over User,Backend: Initial data fetch on mount
User->>Page: Open /me/earnings
Page->>API: getUserEarnings()
API->>Backend: GET /user/earnings
Backend-->>API: EarningsData
API-->>Page: GetEarningsResponse
Page->>Page: Store data, stop loading
Page-->>User: Render dashboard
end
rect rgba(150,100,200,0.5)
Note over User,Backend: Claim earning flow
User->>Page: Click Claim button
Page->>Page: Set claimingId (in-flight)
Page->>API: claimEarning(activityId)
API->>Backend: POST /user/earnings/claim
Backend-->>API: ClaimEarningResponse
API-->>Page: Success
Page->>Page: Show toast, clear claimingId
Page->>API: getUserEarnings()
API->>Backend: GET /user/earnings
Backend-->>API: Updated EarningsData
API-->>Page: Updated GetEarningsResponse
Page->>Page: Refresh UI
Page-->>User: Updated dashboard
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~30 minutes Possibly related issues
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 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: 3
🧹 Nitpick comments (4)
lib/api/user/earnings.ts (2)
55-58: Add generic type parameter for type-safe API response.Same issue as
getUserEarnings- pass the expected response type toapi.post<T>().♻️ Proposed fix
export const claimEarning = async (data: ClaimEarningRequest): Promise<ClaimEarningResponse> => { - const res = await api.post('/user/earnings/claim', data); + const res = await api.post<ClaimEarningResponse>('/user/earnings/claim', data); return res.data; };🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/api/user/earnings.ts` around lines 55 - 58, The API call in claimEarning currently uses api.post without a generic result type, so make the request type-safe by passing the expected response type to api.post (use ClaimEarningResponse as the generic) when calling api.post in the claimEarning function; update the call to api.post<ClaimEarningResponse>(' /user/earnings/claim', data) so res.data is correctly typed for ClaimEarningResponse while leaving the function signature intact.
47-50: Add generic type parameter for type-safe API response.The
api.get<T>()method accepts a generic type parameter to properly type the response. Without it,res.datais typed asunknown.♻️ Proposed fix
export const getUserEarnings = async (): Promise<GetEarningsResponse> => { - const res = await api.get('/user/earnings'); + const res = await api.get<EarningsData>('/user/earnings'); return res.data; };🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/api/user/earnings.ts` around lines 47 - 50, The API call in getUserEarnings returns untyped data; call api.get with the generic type parameter so the response is type-safe (use GetEarningsResponse as the generic for api.get), then return res.data which will now be correctly typed; update the api.get call inside function getUserEarnings to api.get<GetEarningsResponse>(...) so res.data is inferred as GetEarningsResponse.app/me/earnings/page.tsx (2)
22-25: Consider using const arrow function per coding guidelines.The coding guidelines prefer const arrow functions with explicit type annotations. However, function declarations for page components are common in Next.js, so this is a minor stylistic preference.
♻️ Optional refactor
-export default function EarningsPage() { - const [loading, setLoading] = useState(true); - const [data, setData] = useState<EarningsData | null>(null); - const [claimingId, setClaimingId] = useState<string | null>(null); +const EarningsPage: React.FC = () => { + const [loading, setLoading] = useState(true); + const [data, setData] = useState<EarningsData | null>(null); + const [claimingId, setClaimingId] = useState<string | null>(null);And at the end of the component:
-} +}; + +export default EarningsPage;As per coding guidelines: "Prefer const arrow functions with explicit type annotations over function declarations".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/me/earnings/page.tsx` around lines 22 - 25, The component is declared as a function declaration (EarningsPage); change it to a const arrow function with an explicit type annotation per guidelines: replace the `export default function EarningsPage()` declaration with a `const`-declared arrow component (e.g., `const EarningsPage: React.FC` or appropriate Next.js page type) and export it as default; keep the existing state hooks (loading, data, claimingId) and implementation intact while updating the declaration and export style.
56-57: Add error logging for consistency withfetchData.The
fetchDatafunction logs errors to console before showing a toast (line 35), buthandleClaimonly shows a toast. Addingconsole.errorwould help with debugging.♻️ Proposed fix
} catch (error) { + console.error('Failed to claim earning:', error); toast.error('An error occurred during claiming'); } finally {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/me/earnings/page.tsx` around lines 56 - 57, In the catch block of handleClaim, add a console.error call to log the caught error (similar to fetchData) before calling toast.error so errors are recorded for debugging; locate the handleClaim function and update its catch(error) handler to console.error(error) (or include context like "handleClaim error") then show the toast.
🤖 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/me/earnings/page.tsx`:
- Around line 51-52: The refresh logic currently sets state based only on
updated.data; update it to mirror the initial fetch by checking both
updated.success and updated.data before calling setData (i.e., replace the
single `if (updated.data)` with a check for `updated.success && updated.data`)
so getUserEarnings results are validated consistently when using setData.
- Around line 180-182: The Badge usage currently passes a non-existent 'success'
variant; update the conditional in the Badge component rendering (see Badge and
activity.status) to use a supported variant such as 'default' for completed
items (e.g., change the ternary that yields 'success' to 'default', keeping
'secondary' for pending and 'default' for the fallback).
In `@lib/api/user/earnings.ts`:
- Around line 1-2: The import is using a default import for api but the module
exports it as a named export; update the import to use a named import (change
the import of api to use curly braces) so the symbol api resolves correctly when
used in this file (the ApiResponse import can remain unchanged).
---
Nitpick comments:
In `@app/me/earnings/page.tsx`:
- Around line 22-25: The component is declared as a function declaration
(EarningsPage); change it to a const arrow function with an explicit type
annotation per guidelines: replace the `export default function EarningsPage()`
declaration with a `const`-declared arrow component (e.g., `const EarningsPage:
React.FC` or appropriate Next.js page type) and export it as default; keep the
existing state hooks (loading, data, claimingId) and implementation intact while
updating the declaration and export style.
- Around line 56-57: In the catch block of handleClaim, add a console.error call
to log the caught error (similar to fetchData) before calling toast.error so
errors are recorded for debugging; locate the handleClaim function and update
its catch(error) handler to console.error(error) (or include context like
"handleClaim error") then show the toast.
In `@lib/api/user/earnings.ts`:
- Around line 55-58: The API call in claimEarning currently uses api.post
without a generic result type, so make the request type-safe by passing the
expected response type to api.post (use ClaimEarningResponse as the generic)
when calling api.post in the claimEarning function; update the call to
api.post<ClaimEarningResponse>(' /user/earnings/claim', data) so res.data is
correctly typed for ClaimEarningResponse while leaving the function signature
intact.
- Around line 47-50: The API call in getUserEarnings returns untyped data; call
api.get with the generic type parameter so the response is type-safe (use
GetEarningsResponse as the generic for api.get), then return res.data which will
now be correctly typed; update the api.get call inside function getUserEarnings
to api.get<GetEarningsResponse>(...) so res.data is inferred as
GetEarningsResponse.
ℹ️ Review info
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (3)
app/me/earnings/page.tsxcomponents/app-sidebar.tsxlib/api/user/earnings.ts
There was a problem hiding this comment.
🧹 Nitpick comments (2)
app/me/earnings/page.tsx (2)
154-167: Prefer const arrow functions with explicit type annotations.The helper components (
SummaryCard,BreakdownItem,ActivityItem,EarningsSkeleton) use function declarations. Per coding guidelines, prefer const arrow functions with explicit type annotations.♻️ Example refactor for SummaryCard
-function SummaryCard({ title, value, icon, description }: { title: string, value: string, icon: React.ReactNode, description: string }) { - return ( +interface SummaryCardProps { + title: string; + value: string; + icon: React.ReactNode; + description: string; +} + +const SummaryCard: React.FC<SummaryCardProps> = ({ title, value, icon, description }) => ( <Card> <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2"> <CardTitle className="text-sm font-medium">{title}</CardTitle> {icon} </CardHeader> <CardContent> <div className="text-2xl font-bold">{value}</div> <p className="text-xs text-muted-foreground mt-1">{description}</p> </CardContent> </Card> - ); -} +);Apply the same pattern to
BreakdownItem,ActivityItem, andEarningsSkeleton. As per coding guidelines: "Prefer const arrow functions with explicit type annotations over function declarations."🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/me/earnings/page.tsx` around lines 154 - 167, Replace the function declarations with const arrow-function components and add explicit type annotations for props: convert SummaryCard, BreakdownItem, ActivityItem, and EarningsSkeleton into const SummaryCard: React.FC<{ title: string; value: string; icon: React.ReactNode; description: string }> = ({ title, value, icon, description }) => { ... } (and similarly define precise prop types for BreakdownItem and ActivityItem and type EarningsSkeleton as React.FC or a specific props type if needed); update the component definitions and exports to use these const arrow functions so they follow the codebase guideline.
76-76: Consider styling the empty state for consistency.The "No data found" fallback is unstyled, while other states (loading skeleton, empty activities list at line 135) have proper styling. Consider matching the styling for a consistent UX.
♻️ Suggested improvement
- if (!data) return <div>No data found.</div>; + if (!data) { + return ( + <div className="container mx-auto py-8"> + <p className="text-center text-muted-foreground py-8">No earnings data found.</p> + </div> + ); + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/me/earnings/page.tsx` at line 76, Replace the unstyled fallback `if (!data) return <div>No data found.</div>;` with the same styled empty-state markup/component used for the activities empty state (the JSX rendered when activities are empty) so the messaging matches loading/empty UI; find the empty activities JSX (the block that displays the empty activities list) and reuse its container, classes or dedicated EmptyState component, replacing the plain "No data found." text so the empty state looks consistent with other states.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@app/me/earnings/page.tsx`:
- Around line 154-167: Replace the function declarations with const
arrow-function components and add explicit type annotations for props: convert
SummaryCard, BreakdownItem, ActivityItem, and EarningsSkeleton into const
SummaryCard: React.FC<{ title: string; value: string; icon: React.ReactNode;
description: string }> = ({ title, value, icon, description }) => { ... } (and
similarly define precise prop types for BreakdownItem and ActivityItem and type
EarningsSkeleton as React.FC or a specific props type if needed); update the
component definitions and exports to use these const arrow functions so they
follow the codebase guideline.
- Line 76: Replace the unstyled fallback `if (!data) return <div>No data
found.</div>;` with the same styled empty-state markup/component used for the
activities empty state (the JSX rendered when activities are empty) so the
messaging matches loading/empty UI; find the empty activities JSX (the block
that displays the empty activities list) and reuse its container, classes or
dedicated EmptyState component, replacing the plain "No data found." text so the
empty state looks consistent with other states.
ℹ️ Review info
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (2)
app/me/earnings/page.tsxlib/api/user/earnings.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- lib/api/user/earnings.ts
|
LGTM 🚀 |
… claim functionality, and update earnings data structure for improved clarity and performance.
Overview
Implemented a comprehensive Private Earnings Dashboard as requested in issue #390. This page allows users to track their platform income, visualize earnings by source, and claim rewards.
Key Deliverables
any), Framer Motion animations, and shadcn/ui adherence.Payout Information
Address: 0xa5F1e2596DC1e878a6a039f41330d9A97c771bE9
Summary by CodeRabbit