Skip to content

Commit 84d62b6

Browse files
committed
fix: address CLI agent review feedback - typo, nullable name, DRY violation
1 parent f0b5d50 commit 84d62b6

File tree

3 files changed

+74
-55
lines changed

3 files changed

+74
-55
lines changed

web/src/app/api/referrals/route.ts

Lines changed: 18 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,13 @@ import { extractApiKeyFromHeader } from '@/util/auth'
1313
import type { NextRequest } from 'next/server'
1414

1515
type Referral = Pick<typeof schema.user.$inferSelect, 'id' | 'name' | 'email'> &
16-
Pick<typeof schema.referral.$inferSelect, 'credits'>
16+
Pick<typeof schema.referral.$inferSelect, 'credits' | 'is_recurring'>
1717
const ReferralSchema = z.object({
1818
id: z.string(),
19-
name: z.string(),
19+
name: z.string().nullable(),
2020
email: z.string().email(),
2121
credits: z.coerce.number(),
22+
is_recurring: z.boolean(),
2223
})
2324

2425
export type ReferralData = {
@@ -47,45 +48,29 @@ export async function GET() {
4748
)
4849
}
4950

51+
// Shared select fields for referral queries
52+
const referralSelect = {
53+
id: schema.user.id,
54+
name: schema.user.name,
55+
email: schema.user.email,
56+
credits: schema.referral.credits,
57+
is_recurring: schema.referral.is_recurring,
58+
}
59+
5060
// Who did this user refer?
51-
const referralsQuery = db
52-
.select({
53-
id: schema.referral.referred_id,
54-
credits: schema.referral.credits,
55-
})
61+
const referrals = await db
62+
.select(referralSelect)
5663
.from(schema.referral)
64+
.innerJoin(schema.user, eq(schema.user.id, schema.referral.referred_id))
5765
.where(eq(schema.referral.referrer_id, session.user.id))
58-
.as('referralsQuery')
59-
const referrals = await db
60-
.select({
61-
id: schema.user.id,
62-
name: schema.user.name,
63-
email: schema.user.email,
64-
credits: referralsQuery.credits,
65-
})
66-
.from(referralsQuery)
67-
.leftJoin(schema.user, eq(schema.user.id, referralsQuery.id))
6866

6967
// Who referred this user?
70-
const referredByIdQuery = db
71-
.select({
72-
id: schema.referral.referrer_id,
73-
credits: schema.referral.credits,
74-
})
68+
const referredBy = await db
69+
.select(referralSelect)
7570
.from(schema.referral)
71+
.innerJoin(schema.user, eq(schema.user.id, schema.referral.referrer_id))
7672
.where(eq(schema.referral.referred_id, session.user.id))
7773
.limit(1)
78-
.as('referredByIdQuery')
79-
const referredBy = await db
80-
.select({
81-
id: schema.user.id,
82-
name: schema.user.name,
83-
email: schema.user.email,
84-
credits: referredByIdQuery.credits,
85-
})
86-
.from(referredByIdQuery)
87-
.leftJoin(schema.user, eq(schema.user.id, referredByIdQuery.id))
88-
.limit(1)
8974
.then((users) => {
9075
if (users.length !== 1) {
9176
return

web/src/app/profile/components/referrals-section.tsx

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import { ProfileSection } from './profile-section'
1212

1313
import type { ReferralData } from '@/app/api/referrals/route'
1414

15+
import { cn } from '@/lib/utils'
16+
1517
import { Button } from '@/components/ui/button'
1618
import {
1719
Card,
@@ -33,12 +35,26 @@ const copyReferral = (link: string) => {
3335
})
3436
}
3537

36-
const CreditsBadge = (credits: number) => {
38+
const badgeBaseClasses =
39+
'flex-none p-2 rounded-full text-xs font-semibold items-center text-center shadow-sm bg-gradient-to-r'
40+
41+
const CreditsBadge = ({
42+
credits,
43+
isRecurring,
44+
}: {
45+
credits: number
46+
isRecurring: boolean
47+
}) => {
3748
return (
3849
<span
39-
className={`flex-none p-2 rounded-full text-xs bg-gradient-to-r from-green-300 to-emerald-300 dark:from-green-600 dark:to-emerald-600 text-green-800 dark:text-white font-semibold item-center text-center shadow-sm`}
50+
className={cn(
51+
badgeBaseClasses,
52+
isRecurring
53+
? 'from-green-300 to-emerald-300 dark:from-green-600 dark:to-emerald-600 text-green-800 dark:text-white'
54+
: 'from-blue-300 to-sky-300 dark:from-blue-600 dark:to-sky-600 text-blue-800 dark:text-white',
55+
)}
4056
>
41-
+{credits} credits
57+
+{credits} {isRecurring ? 'credits/mo' : 'credits'}
4258
</span>
4359
)
4460
}
@@ -109,9 +125,12 @@ export function ReferralsSection() {
109125
<CardContent className="flex flex-col">
110126
<div className="flex place-content-between">
111127
<div className="text-sm flex items-center">
112-
<p>{data.referredBy.name} referred you. </p>
128+
<p>{data.referredBy.name || data.referredBy.email} referred you. </p>
113129
</div>
114-
{CreditsBadge(data.referredBy.credits)}
130+
<CreditsBadge
131+
credits={data.referredBy.credits}
132+
isRecurring={data.referredBy.is_recurring}
133+
/>
115134
</div>
116135
</CardContent>
117136
</Card>
@@ -203,9 +222,12 @@ export function ReferralsSection() {
203222
className="flex justify-between items-center"
204223
>
205224
<span>
206-
{r.name} ({r.email})
225+
{r.name ? `${r.name} (${r.email})` : r.email}
207226
</span>
208-
{CreditsBadge(r.credits)}
227+
<CreditsBadge
228+
credits={r.credits}
229+
isRecurring={r.is_recurring}
230+
/>
209231
</li>
210232
))}
211233
</ul>

web/src/app/profile/components/usage-display.tsx

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,16 @@ interface UsageDisplayProps {
3333

3434
type FilteredGrantType = Exclude<GrantType, 'organization'>
3535

36-
const grantTypeInfo: Record<
37-
FilteredGrantType,
38-
{
39-
bg: string
40-
text: string
41-
gradient: string
42-
icon: React.ReactNode
43-
label: string
44-
description: string
45-
}
46-
> = {
36+
type GrantTypeInfoItem = {
37+
bg: string
38+
text: string
39+
gradient: string
40+
icon: React.ReactNode
41+
label: string
42+
description: string
43+
}
44+
45+
const grantTypeInfo: Record<FilteredGrantType, GrantTypeInfoItem> = {
4746
free: {
4847
bg: 'bg-blue-500',
4948
text: 'text-blue-600 dark:text-blue-400',
@@ -58,7 +57,7 @@ const grantTypeInfo: Record<
5857
gradient: 'from-green-500/70 to-green-600/70',
5958
icon: <Users className="h-4 w-4" />,
6059
label: 'Referral Bonus',
61-
description: 'Earned by referring others',
60+
description: 'One-time bonus for referring others',
6261
},
6362
purchase: {
6463
bg: 'bg-yellow-500',
@@ -86,6 +85,15 @@ const grantTypeInfo: Record<
8685
},
8786
}
8887

88+
/**
89+
* Override info for renewable referral credits (legacy/grandfathered).
90+
*/
91+
const renewableReferralInfo: GrantTypeInfoItem = {
92+
...grantTypeInfo.referral,
93+
label: 'Referral Bonus (Legacy)',
94+
description: 'Renews monthly from past referrals',
95+
}
96+
8997
/**
9098
* Helper to get grant types with non-zero balance or principal in a bucket.
9199
* Defined at module level to avoid recreation on each render.
@@ -127,6 +135,10 @@ const CreditLeaf = ({
127135
}: CreditLeafProps) => {
128136
const remainingAmount = amount - used
129137

138+
// Use legacy info for renewable referral credits (grandfathered from before the program update)
139+
const info =
140+
type === 'referral' && isRenewable ? renewableReferralInfo : grantTypeInfo[type]
141+
130142
return (
131143
<div className="group relative pl-6">
132144
<div
@@ -141,14 +153,14 @@ const CreditLeaf = ({
141153
<div className="flex flex-col gap-1 w-full sm:w-auto">
142154
<div className="flex items-center gap-3">
143155
<div className="w-4 h-4 flex-shrink-0">
144-
{grantTypeInfo[type].icon}
156+
{info.icon}
145157
</div>
146158
<span className="font-medium text-sm">
147-
{grantTypeInfo[type].label}
159+
{info.label}
148160
</span>
149161
</div>
150162
<span className="text-xs text-muted-foreground pl-7">
151-
{grantTypeInfo[type].description}
163+
{info.description}
152164
</span>
153165
</div>
154166
<div className="flex items-center gap-2 mt-1 sm:mt-0 pl-7 sm:pl-0">

0 commit comments

Comments
 (0)