diff --git a/apps/web/app/(ee)/api/partners/route.ts b/apps/web/app/(ee)/api/partners/route.ts index 99eafffdd1f..af6cc7c52c4 100644 --- a/apps/web/app/(ee)/api/partners/route.ts +++ b/apps/web/app/(ee)/api/partners/route.ts @@ -3,7 +3,6 @@ import { getPartners } from "@/lib/api/partners/get-partners"; import { getDefaultProgramIdOrThrow } from "@/lib/api/programs/get-default-program-id-or-throw"; import { getProgramOrThrow } from "@/lib/api/programs/get-program-or-throw"; import { parseRequestBody } from "@/lib/api/utils"; -import { applicationEventSchema } from "@/lib/application-events/schema"; import { withWorkspace } from "@/lib/auth"; import { throwIfPartnersLimitExceeded } from "@/lib/partners/throw-if-partners-limit-exceeded"; import { polyfillSocialMediaFields } from "@/lib/social-utils"; @@ -102,16 +101,11 @@ export const GET = withWorkspace( saleAmount: z.number().default(0), }); - const responseSchema = - parsedParams.includeApplicationEvent || - parsedParams.includePartnerPlatforms - ? baseSchema.extend({ - platforms: z.array(partnerPlatformSchema), - applicationEvent: applicationEventSchema - .pick({ referralSource: true }) - .nullish(), - }) - : baseSchema; + const responseSchema = parsedParams.includePartnerPlatforms + ? baseSchema.extend({ + platforms: z.array(partnerPlatformSchema), + }) + : baseSchema; return NextResponse.json( z.array(responseSchema).parse( diff --git a/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/analytics/applications/application-referral-source-icon.tsx b/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/analytics/applications/application-referral-source-icon.tsx index e5e58a49b41..c8ea7831790 100644 --- a/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/analytics/applications/application-referral-source-icon.tsx +++ b/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/analytics/applications/application-referral-source-icon.tsx @@ -3,17 +3,19 @@ import { Globe, Shop, UserArrowRight } from "@dub/ui/icons"; export function ApplicationReferralSourceIcon({ referralSource, + className, }: { referralSource: string; + className?: string; }) { switch (referralSource) { case "marketplace": - return ; + return ; case "direct": - return ; + return ; case "manual": - return ; + return ; default: - return ; + return ; } } diff --git a/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/applications/page-client.tsx b/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/applications/page-client.tsx index 3259082c66d..88c1a25da3e 100644 --- a/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/applications/page-client.tsx +++ b/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/applications/page-client.tsx @@ -103,7 +103,6 @@ export function ProgramPartnersApplicationsPageClient() { status: "pending", sortBy, sortOrder, - includeApplicationEvent: true, includePartnerPlatforms: true, }, { exclude: ["partnerId"] }, @@ -196,17 +195,6 @@ export function ProgramPartnersApplicationsPageClient() { header: "Applied", accessorFn: (d) => formatDate(d.createdAt, { month: "short" }), }, - // TODO: add source column back once we fix application source display - // { - // id: "source", - // header: "Source", - // minSize: 170, - // cell: ({ row }) => ( - // - // ), - // }, { id: "group", header: "Group", diff --git a/apps/web/lib/api/partners/get-partners.ts b/apps/web/lib/api/partners/get-partners.ts index c824f921612..2f9ae4d682f 100644 --- a/apps/web/lib/api/partners/get-partners.ts +++ b/apps/web/lib/api/partners/get-partners.ts @@ -19,7 +19,6 @@ export async function getPartners(filters: PartnerFilters) { sortBy, sortOrder, programId, - includeApplicationEvent, includePartnerPlatforms: _includePartnerPlatforms, includeGroup = false, ...enrollmentRest @@ -45,7 +44,6 @@ export async function getPartners(filters: PartnerFilters) { }, }, links: true, - ...(includeApplicationEvent ? { applicationEvent: true } : {}), ...(includeGroup ? { partnerGroup: { diff --git a/apps/web/lib/zod/schemas/partners.ts b/apps/web/lib/zod/schemas/partners.ts index 6faa6149947..45a0ce8a6de 100644 --- a/apps/web/lib/zod/schemas/partners.ts +++ b/apps/web/lib/zod/schemas/partners.ts @@ -212,7 +212,6 @@ export const getPartnersQuerySchemaExtended = getPartnersQuerySchema.extend({ country: z.union([z.string(), z.array(z.string())]).optional(), referredByPartnerId: z.string().optional(), includePartnerPlatforms: booleanQuerySchema.optional(), - includeApplicationEvent: booleanQuerySchema.optional(), // metric range query fields (TODO: Add to public API once we finalize the syntax) totalClicksMin: z.coerce .number() @@ -593,11 +592,6 @@ export const EnrolledPartnerSchemaExtended = EnrolledPartnerSchema.extend({ customerDataSharingEnabledAt: z.date().nullish(), groupMoveDisabledAt: z.date().nullish(), platforms: z.array(partnerPlatformSchema).nullable(), - applicationEvent: z - .object({ - referralSource: z.string(), - }) - .nullish(), discount: DiscountSchema.pick({ id: true, provider: true, diff --git a/apps/web/ui/partners/partner-application-source.tsx b/apps/web/ui/partners/partner-application-source.tsx deleted file mode 100644 index fa94546e081..00000000000 --- a/apps/web/ui/partners/partner-application-source.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { - getApplicationSourceLabelTooltip, - isMarketplaceReferralSource, -} from "@/lib/application-events/utils"; -import { BadgeCheck2Fill, Tooltip } from "@dub/ui"; -import { cn } from "@dub/utils"; - -export function PartnerApplicationSource({ - referralSource, - variant = "default", -}: { - referralSource: string | null | undefined; - variant?: "default" | "inline"; -}) { - const { label, tooltip } = getApplicationSourceLabelTooltip(referralSource); - - if (!label) { - return variant === "inline" ? null : "-"; - } - - const isMarketplace = isMarketplaceReferralSource(referralSource); - - const labelContent = ( - - {label} - - ); - - const labeledWithTooltip = tooltip ? ( - {labelContent} - ) : ( - labelContent - ); - - if (variant === "inline") { - return ( - - {isMarketplace && ( - - )} - {labeledWithTooltip} - - ); - } - - return ( -
- {isMarketplace && ( - - )} - {labeledWithTooltip} -
- ); -} diff --git a/apps/web/ui/partners/partner-info-cards.tsx b/apps/web/ui/partners/partner-info-cards.tsx index ce4181a8345..bf347f2f15d 100644 --- a/apps/web/ui/partners/partner-info-cards.tsx +++ b/apps/web/ui/partners/partner-info-cards.tsx @@ -47,6 +47,7 @@ import { import { PartnerFraudIndicator } from "./fraud-risks/partner-fraud-indicator"; import { PartnerAvatar } from "./partner-avatar"; import { PartnerInfoGroup } from "./partner-info-group"; +import { PartnerNetworkStatusBadge } from "./partner-network/partner-network-status-badge"; import { PartnerStarButton } from "./partner-star-button"; import { PartnerStatusBadgeWithTooltip } from "./partner-status-badge-with-tooltip"; import { PartnerTagsList } from "./partner-tags-list"; @@ -55,7 +56,6 @@ import { getPayoutMethodLabel, } from "./payouts/payout-method-config"; import { ProgramRewardList } from "./program-reward-list"; -import { TrustedPartnerBadge } from "./trusted-partner-badge"; import { UpdatePartnerTagsModal, useUpdatePartnerTagsModal, @@ -154,8 +154,6 @@ export function PartnerInfoCards({ if ((isEnrolled || isAdmin) && partner) { const isPendingApplication = "status" in partner && partner.status === "pending"; - const applicationReferralSource = - isEnrolled && partner.applicationEvent?.referralSource; basicFields = basicFields.concat([ { @@ -175,24 +173,11 @@ export function PartnerInfoCards({ > Applied {formatDate(partner.createdAt)} - {/* TODO: add source column back once we fix application source display */} - {/* {applicationReferralSource && ( - <> - via - - - )} */} ) : ( `${isPendingApplication ? "Applied" : "Partner since"} ${formatDate(partner.createdAt)}` ), - timestamp: - isPendingApplication && applicationReferralSource - ? undefined - : partner.createdAt, + timestamp: isPendingApplication ? undefined : partner.createdAt, }, { id: "payoutMethod" as const, @@ -279,9 +264,6 @@ export function PartnerInfoCards({ ) : (
)} - {partner?.networkStatus === "trusted" && ( - - )}
@@ -306,6 +288,13 @@ export function PartnerInfoCards({ {partner.name} + {"networkStatus" in partner && partner.networkStatus && ( + + )} + {showFraudIndicator && ( )} diff --git a/apps/web/ui/partners/partner-network/partner-network-status-badge.tsx b/apps/web/ui/partners/partner-network/partner-network-status-badge.tsx new file mode 100644 index 00000000000..b1e7904dfd1 --- /dev/null +++ b/apps/web/ui/partners/partner-network/partner-network-status-badge.tsx @@ -0,0 +1,45 @@ +import { PartnerNetworkStatus } from "@dub/prisma/client"; +import { BadgeCheck2Fill, Tooltip } from "@dub/ui"; +import { cn } from "@dub/utils"; +import { TrustedPartnerBadge } from "../trusted-partner-badge"; + +export function PartnerNetworkStatusBadge({ + networkStatus, + size = "small", +}: { + networkStatus: PartnerNetworkStatus; + size?: "small" | "large"; +}) { + if (networkStatus === "trusted") { + return ; + } + + if (networkStatus === "approved") { + return ( + + +
+ + Approved Partner + + + This partner is approved in the Dub Partner Network. + +
+
+ } + > + + + ); + } + + return null; +} diff --git a/apps/web/ui/partners/partner-row-item.tsx b/apps/web/ui/partners/partner-row-item.tsx index 76eddf08cc7..fed163f6a82 100644 --- a/apps/web/ui/partners/partner-row-item.tsx +++ b/apps/web/ui/partners/partner-row-item.tsx @@ -1,5 +1,5 @@ import useProgram from "@/lib/swr/use-program"; -import { PartnerPayoutMethod } from "@dub/prisma/client"; +import { PartnerNetworkStatus, PartnerPayoutMethod } from "@dub/prisma/client"; import { CircleArrowRight, DynamicTooltipWrapper, GreekTemple } from "@dub/ui"; import { cn, formatDateTimeSmart } from "@dub/utils"; import { CircleMinus } from "lucide-react"; @@ -7,6 +7,7 @@ import Link from "next/link"; import { useParams } from "next/navigation"; import type { ReactNode } from "react"; import { PartnerFraudIndicator } from "./fraud-risks/partner-fraud-indicator"; +import { PartnerNetworkStatusBadge } from "./partner-network/partner-network-status-badge"; import { PartnerAvatar } from "./partner-avatar"; import { getPayoutMethodIconConfig, @@ -21,6 +22,7 @@ interface PartnerRowItemProps { id: string; name: string; image?: string | null; + networkStatus?: PartnerNetworkStatus | null; defaultPayoutMethod?: PartnerPayoutMethod | null; payoutsEnabledAt?: Date | null; }; @@ -208,19 +210,25 @@ export function PartnerRowItem({ - e.stopPropagation() : undefined} - onAuxClick={showPermalink ? (e) => e.stopPropagation() : undefined} - className={cn( - "min-w-0 truncate", - showPermalink && "cursor-alias decoration-dotted hover:underline", +
+ e.stopPropagation() : undefined} + onAuxClick={showPermalink ? (e) => e.stopPropagation() : undefined} + className={cn( + "min-w-0 truncate", + showPermalink && "cursor-alias decoration-dotted hover:underline", + )} + title={partner.name} + > + {partner.name} + + + {"networkStatus" in partner && partner.networkStatus && ( + )} - title={partner.name} - > - {partner.name} - +
{suffix} diff --git a/apps/web/ui/partners/trusted-partner-badge.tsx b/apps/web/ui/partners/trusted-partner-badge.tsx index 7fc3656180c..d9008043b89 100644 --- a/apps/web/ui/partners/trusted-partner-badge.tsx +++ b/apps/web/ui/partners/trusted-partner-badge.tsx @@ -1,14 +1,31 @@ import { Tooltip } from "@dub/ui"; +import { cn } from "@dub/utils"; + +const TRUSTED_BADGE_SRC = "https://assets.dub.co/icons/trusted-badge.svg"; + +export function TrustedPartnerBadge({ + variant = "overlay", + size = "small", +}: { + variant?: "overlay" | "inline"; + size?: "small" | "large"; +}) { + const badge = ( + Trusted partner badge + ); -export function TrustedPartnerBadge() { return ( +
Trusted partner badge
@@ -22,13 +39,13 @@ export function TrustedPartnerBadge() {
} > -
- Trusted partner badge -
+ {variant === "inline" ? ( + {badge} + ) : ( +
+ {badge} +
+ )} ); }