Skip to content

Commit 93174a5

Browse files
authored
Show networkStatus badge in PartnerRowItem (#3988)
1 parent 1e65ea2 commit 93174a5

10 files changed

Lines changed: 114 additions & 138 deletions

File tree

apps/web/app/(ee)/api/partners/route.ts

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { getPartners } from "@/lib/api/partners/get-partners";
33
import { getDefaultProgramIdOrThrow } from "@/lib/api/programs/get-default-program-id-or-throw";
44
import { getProgramOrThrow } from "@/lib/api/programs/get-program-or-throw";
55
import { parseRequestBody } from "@/lib/api/utils";
6-
import { applicationEventSchema } from "@/lib/application-events/schema";
76
import { withWorkspace } from "@/lib/auth";
87
import { throwIfPartnersLimitExceeded } from "@/lib/partners/throw-if-partners-limit-exceeded";
98
import { polyfillSocialMediaFields } from "@/lib/social-utils";
@@ -102,16 +101,11 @@ export const GET = withWorkspace(
102101
saleAmount: z.number().default(0),
103102
});
104103

105-
const responseSchema =
106-
parsedParams.includeApplicationEvent ||
107-
parsedParams.includePartnerPlatforms
108-
? baseSchema.extend({
109-
platforms: z.array(partnerPlatformSchema),
110-
applicationEvent: applicationEventSchema
111-
.pick({ referralSource: true })
112-
.nullish(),
113-
})
114-
: baseSchema;
104+
const responseSchema = parsedParams.includePartnerPlatforms
105+
? baseSchema.extend({
106+
platforms: z.array(partnerPlatformSchema),
107+
})
108+
: baseSchema;
115109

116110
return NextResponse.json(
117111
z.array(responseSchema).parse(

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/analytics/applications/application-referral-source-icon.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,19 @@ import { Globe, Shop, UserArrowRight } from "@dub/ui/icons";
33

44
export function ApplicationReferralSourceIcon({
55
referralSource,
6+
className,
67
}: {
78
referralSource: string;
9+
className?: string;
810
}) {
911
switch (referralSource) {
1012
case "marketplace":
11-
return <Shop />;
13+
return <Shop className={className} />;
1214
case "direct":
13-
return <Globe />;
15+
return <Globe className={className} />;
1416
case "manual":
15-
return <UserArrowRight />;
17+
return <UserArrowRight className={className} />;
1618
default:
17-
return <ReferrerIcon display={referralSource} />;
19+
return <ReferrerIcon display={referralSource} className={className} />;
1820
}
1921
}

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/applications/page-client.tsx

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,6 @@ export function ProgramPartnersApplicationsPageClient() {
103103
status: "pending",
104104
sortBy,
105105
sortOrder,
106-
includeApplicationEvent: true,
107106
includePartnerPlatforms: true,
108107
},
109108
{ exclude: ["partnerId"] },
@@ -196,17 +195,6 @@ export function ProgramPartnersApplicationsPageClient() {
196195
header: "Applied",
197196
accessorFn: (d) => formatDate(d.createdAt, { month: "short" }),
198197
},
199-
// TODO: add source column back once we fix application source display
200-
// {
201-
// id: "source",
202-
// header: "Source",
203-
// minSize: 170,
204-
// cell: ({ row }) => (
205-
// <PartnerApplicationSource
206-
// referralSource={row.original.applicationEvent?.referralSource}
207-
// />
208-
// ),
209-
// },
210198
{
211199
id: "group",
212200
header: "Group",

apps/web/lib/api/partners/get-partners.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ export async function getPartners(filters: PartnerFilters) {
1919
sortBy,
2020
sortOrder,
2121
programId,
22-
includeApplicationEvent,
2322
includePartnerPlatforms: _includePartnerPlatforms,
2423
includeGroup = false,
2524
...enrollmentRest
@@ -45,7 +44,6 @@ export async function getPartners(filters: PartnerFilters) {
4544
},
4645
},
4746
links: true,
48-
...(includeApplicationEvent ? { applicationEvent: true } : {}),
4947
...(includeGroup
5048
? {
5149
partnerGroup: {

apps/web/lib/zod/schemas/partners.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,6 @@ export const getPartnersQuerySchemaExtended = getPartnersQuerySchema.extend({
212212
country: z.union([z.string(), z.array(z.string())]).optional(),
213213
referredByPartnerId: z.string().optional(),
214214
includePartnerPlatforms: booleanQuerySchema.optional(),
215-
includeApplicationEvent: booleanQuerySchema.optional(),
216215
// metric range query fields (TODO: Add to public API once we finalize the syntax)
217216
totalClicksMin: z.coerce
218217
.number()
@@ -593,11 +592,6 @@ export const EnrolledPartnerSchemaExtended = EnrolledPartnerSchema.extend({
593592
customerDataSharingEnabledAt: z.date().nullish(),
594593
groupMoveDisabledAt: z.date().nullish(),
595594
platforms: z.array(partnerPlatformSchema).nullable(),
596-
applicationEvent: z
597-
.object({
598-
referralSource: z.string(),
599-
})
600-
.nullish(),
601595
discount: DiscountSchema.pick({
602596
id: true,
603597
provider: true,

apps/web/ui/partners/partner-application-source.tsx

Lines changed: 0 additions & 59 deletions
This file was deleted.

apps/web/ui/partners/partner-info-cards.tsx

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import {
4747
import { PartnerFraudIndicator } from "./fraud-risks/partner-fraud-indicator";
4848
import { PartnerAvatar } from "./partner-avatar";
4949
import { PartnerInfoGroup } from "./partner-info-group";
50+
import { PartnerNetworkStatusBadge } from "./partner-network/partner-network-status-badge";
5051
import { PartnerStarButton } from "./partner-star-button";
5152
import { PartnerStatusBadgeWithTooltip } from "./partner-status-badge-with-tooltip";
5253
import { PartnerTagsList } from "./partner-tags-list";
@@ -55,7 +56,6 @@ import {
5556
getPayoutMethodLabel,
5657
} from "./payouts/payout-method-config";
5758
import { ProgramRewardList } from "./program-reward-list";
58-
import { TrustedPartnerBadge } from "./trusted-partner-badge";
5959
import {
6060
UpdatePartnerTagsModal,
6161
useUpdatePartnerTagsModal,
@@ -154,8 +154,6 @@ export function PartnerInfoCards({
154154
if ((isEnrolled || isAdmin) && partner) {
155155
const isPendingApplication =
156156
"status" in partner && partner.status === "pending";
157-
const applicationReferralSource =
158-
isEnrolled && partner.applicationEvent?.referralSource;
159157

160158
basicFields = basicFields.concat([
161159
{
@@ -175,24 +173,11 @@ export function PartnerInfoCards({
175173
>
176174
<span>Applied {formatDate(partner.createdAt)}</span>
177175
</TimestampTooltip>
178-
{/* TODO: add source column back once we fix application source display */}
179-
{/* {applicationReferralSource && (
180-
<>
181-
<span>via</span>
182-
<PartnerApplicationSource
183-
referralSource={applicationReferralSource}
184-
variant="inline"
185-
/>
186-
</>
187-
)} */}
188176
</span>
189177
) : (
190178
`${isPendingApplication ? "Applied" : "Partner since"} ${formatDate(partner.createdAt)}`
191179
),
192-
timestamp:
193-
isPendingApplication && applicationReferralSource
194-
? undefined
195-
: partner.createdAt,
180+
timestamp: isPendingApplication ? undefined : partner.createdAt,
196181
},
197182
{
198183
id: "payoutMethod" as const,
@@ -279,9 +264,6 @@ export function PartnerInfoCards({
279264
) : (
280265
<div className="size-20 animate-pulse rounded-full bg-neutral-200" />
281266
)}
282-
{partner?.networkStatus === "trusted" && (
283-
<TrustedPartnerBadge />
284-
)}
285267
</div>
286268

287269
<div className="flex items-center gap-2">
@@ -306,6 +288,13 @@ export function PartnerInfoCards({
306288
{partner.name}
307289
</span>
308290

291+
{"networkStatus" in partner && partner.networkStatus && (
292+
<PartnerNetworkStatusBadge
293+
networkStatus={partner.networkStatus}
294+
size="large"
295+
/>
296+
)}
297+
309298
{showFraudIndicator && (
310299
<PartnerFraudIndicator partnerId={partner.id} />
311300
)}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { PartnerNetworkStatus } from "@dub/prisma/client";
2+
import { BadgeCheck2Fill, Tooltip } from "@dub/ui";
3+
import { cn } from "@dub/utils";
4+
import { TrustedPartnerBadge } from "../trusted-partner-badge";
5+
6+
export function PartnerNetworkStatusBadge({
7+
networkStatus,
8+
size = "small",
9+
}: {
10+
networkStatus: PartnerNetworkStatus;
11+
size?: "small" | "large";
12+
}) {
13+
if (networkStatus === "trusted") {
14+
return <TrustedPartnerBadge variant="inline" size={size} />;
15+
}
16+
17+
if (networkStatus === "approved") {
18+
return (
19+
<Tooltip
20+
content={
21+
<div className="flex max-w-xs items-start gap-1.5 p-3">
22+
<BadgeCheck2Fill className="mt-0.5 size-5 shrink-0 text-blue-500" />
23+
<div className="flex flex-col gap-1">
24+
<span className="text-sm font-semibold text-neutral-900">
25+
Approved Partner
26+
</span>
27+
<span className="text-sm font-normal text-neutral-600">
28+
This partner is approved in the Dub Partner Network.
29+
</span>
30+
</div>
31+
</div>
32+
}
33+
>
34+
<BadgeCheck2Fill
35+
className={cn(
36+
"shrink-0 text-blue-500",
37+
size === "small" ? "size-3.5" : "size-5",
38+
)}
39+
/>
40+
</Tooltip>
41+
);
42+
}
43+
44+
return null;
45+
}

apps/web/ui/partners/partner-row-item.tsx

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import useProgram from "@/lib/swr/use-program";
2-
import { PartnerPayoutMethod } from "@dub/prisma/client";
2+
import { PartnerNetworkStatus, PartnerPayoutMethod } from "@dub/prisma/client";
33
import { CircleArrowRight, DynamicTooltipWrapper, GreekTemple } from "@dub/ui";
44
import { cn, formatDateTimeSmart } from "@dub/utils";
55
import { CircleMinus } from "lucide-react";
66
import Link from "next/link";
77
import { useParams } from "next/navigation";
88
import type { ReactNode } from "react";
99
import { PartnerFraudIndicator } from "./fraud-risks/partner-fraud-indicator";
10+
import { PartnerNetworkStatusBadge } from "./partner-network/partner-network-status-badge";
1011
import { PartnerAvatar } from "./partner-avatar";
1112
import {
1213
getPayoutMethodIconConfig,
@@ -21,6 +22,7 @@ interface PartnerRowItemProps {
2122
id: string;
2223
name: string;
2324
image?: string | null;
25+
networkStatus?: PartnerNetworkStatus | null;
2426
defaultPayoutMethod?: PartnerPayoutMethod | null;
2527
payoutsEnabledAt?: Date | null;
2628
};
@@ -208,19 +210,25 @@ export function PartnerRowItem({
208210
</DynamicTooltipWrapper>
209211
</div>
210212

211-
<As
212-
href={`/${slug}/program/partners/${partner.id}`}
213-
{...(showPermalink && { target: "_blank" })}
214-
onClick={showPermalink ? (e) => e.stopPropagation() : undefined}
215-
onAuxClick={showPermalink ? (e) => e.stopPropagation() : undefined}
216-
className={cn(
217-
"min-w-0 truncate",
218-
showPermalink && "cursor-alias decoration-dotted hover:underline",
213+
<div className="flex min-w-0 items-center gap-1">
214+
<As
215+
href={`/${slug}/program/partners/${partner.id}`}
216+
{...(showPermalink && { target: "_blank" })}
217+
onClick={showPermalink ? (e) => e.stopPropagation() : undefined}
218+
onAuxClick={showPermalink ? (e) => e.stopPropagation() : undefined}
219+
className={cn(
220+
"min-w-0 truncate",
221+
showPermalink && "cursor-alias decoration-dotted hover:underline",
222+
)}
223+
title={partner.name}
224+
>
225+
{partner.name}
226+
</As>
227+
228+
{"networkStatus" in partner && partner.networkStatus && (
229+
<PartnerNetworkStatusBadge networkStatus={partner.networkStatus} />
219230
)}
220-
title={partner.name}
221-
>
222-
{partner.name}
223-
</As>
231+
</div>
224232

225233
{suffix}
226234

0 commit comments

Comments
 (0)