Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 5 additions & 11 deletions apps/web/app/(ee)/api/partners/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 <Shop />;
return <Shop className={className} />;
case "direct":
return <Globe />;
return <Globe className={className} />;
case "manual":
return <UserArrowRight />;
return <UserArrowRight className={className} />;
default:
return <ReferrerIcon display={referralSource} />;
return <ReferrerIcon display={referralSource} className={className} />;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ export function ProgramPartnersApplicationsPageClient() {
status: "pending",
sortBy,
sortOrder,
includeApplicationEvent: true,
includePartnerPlatforms: true,
},
{ exclude: ["partnerId"] },
Expand Down Expand Up @@ -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 }) => (
// <PartnerApplicationSource
// referralSource={row.original.applicationEvent?.referralSource}
// />
// ),
// },
{
id: "group",
header: "Group",
Expand Down
2 changes: 0 additions & 2 deletions apps/web/lib/api/partners/get-partners.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ export async function getPartners(filters: PartnerFilters) {
sortBy,
sortOrder,
programId,
includeApplicationEvent,
includePartnerPlatforms: _includePartnerPlatforms,
includeGroup = false,
...enrollmentRest
Expand All @@ -45,7 +44,6 @@ export async function getPartners(filters: PartnerFilters) {
},
},
links: true,
...(includeApplicationEvent ? { applicationEvent: true } : {}),
...(includeGroup
? {
partnerGroup: {
Expand Down
6 changes: 0 additions & 6 deletions apps/web/lib/zod/schemas/partners.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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,
Expand Down
59 changes: 0 additions & 59 deletions apps/web/ui/partners/partner-application-source.tsx

This file was deleted.

24 changes: 8 additions & 16 deletions apps/web/ui/partners/partner-info-cards.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import {
} from "./fraud-risks/partner-fraud-banner";
import { PartnerFraudIndicator } from "./fraud-risks/partner-fraud-indicator";
import { PartnerAvatar } from "./partner-avatar";
import { PartnerNetworkStatusBadge } from "./partner-network/partner-network-status-badge";
import { PartnerInfoGroup } from "./partner-info-group";
import { PartnerStarButton } from "./partner-star-button";
import { PartnerStatusBadgeWithTooltip } from "./partner-status-badge-with-tooltip";
Expand Down Expand Up @@ -154,8 +155,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([
{
Expand All @@ -175,24 +174,11 @@ export function PartnerInfoCards({
>
<span>Applied {formatDate(partner.createdAt)}</span>
</TimestampTooltip>
{/* TODO: add source column back once we fix application source display */}
{/* {applicationReferralSource && (
<>
<span>via</span>
<PartnerApplicationSource
referralSource={applicationReferralSource}
variant="inline"
/>
</>
)} */}
</span>
) : (
`${isPendingApplication ? "Applied" : "Partner since"} ${formatDate(partner.createdAt)}`
),
timestamp:
isPendingApplication && applicationReferralSource
? undefined
: partner.createdAt,
timestamp: isPendingApplication ? undefined : partner.createdAt,
},
{
id: "payoutMethod" as const,
Expand Down Expand Up @@ -306,6 +292,12 @@ export function PartnerInfoCards({
{partner.name}
</span>

{"networkStatus" in partner && partner.networkStatus && (
<PartnerNetworkStatusBadge
networkStatus={partner.networkStatus}
/>
)}

{showFraudIndicator && (
<PartnerFraudIndicator partnerId={partner.id} />
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { PartnerNetworkStatus } from "@dub/prisma/client";
import { BadgeCheck2Fill, Tooltip } from "@dub/ui";
import { TrustedPartnerBadge } from "../trusted-partner-badge";

export function PartnerNetworkStatusBadge({
networkStatus,
}: {
networkStatus: PartnerNetworkStatus;
}) {
if (networkStatus === "trusted") {
return <TrustedPartnerBadge variant="inline" />;
}

if (networkStatus === "approved") {
return (
<Tooltip
content={
<div className="flex max-w-xs items-start gap-1.5 p-3">
<BadgeCheck2Fill className="mt-0.5 size-5 shrink-0 text-blue-500" />
<div className="flex flex-col gap-1">
<span className="text-sm font-semibold text-neutral-900">
Approved Partner
</span>
<span className="text-sm font-normal text-neutral-600">
This partner is approved in the Dub Partner Network.
</span>
</div>
</div>
}
>
<BadgeCheck2Fill className="size-3.5 shrink-0 text-blue-500" />
</Tooltip>
Comment thread
steven-tey marked this conversation as resolved.
);
}

return null;
}
34 changes: 21 additions & 13 deletions apps/web/ui/partners/partner-row-item.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
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";
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,
Expand All @@ -21,6 +22,7 @@ interface PartnerRowItemProps {
id: string;
name: string;
image?: string | null;
networkStatus?: PartnerNetworkStatus | null;
defaultPayoutMethod?: PartnerPayoutMethod | null;
payoutsEnabledAt?: Date | null;
};
Expand Down Expand Up @@ -208,19 +210,25 @@ export function PartnerRowItem({
</DynamicTooltipWrapper>
</div>

<As
href={`/${slug}/program/partners/${partner.id}`}
{...(showPermalink && { target: "_blank" })}
onClick={showPermalink ? (e) => e.stopPropagation() : undefined}
onAuxClick={showPermalink ? (e) => e.stopPropagation() : undefined}
className={cn(
"min-w-0 truncate",
showPermalink && "cursor-alias decoration-dotted hover:underline",
<div className="flex min-w-0 items-center gap-1">
<As
href={`/${slug}/program/partners/${partner.id}`}
{...(showPermalink && { target: "_blank" })}
onClick={showPermalink ? (e) => 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}
</As>

{"networkStatus" in partner && partner.networkStatus && (
<PartnerNetworkStatusBadge networkStatus={partner.networkStatus} />
)}
title={partner.name}
>
{partner.name}
</As>
</div>

{suffix}

Expand Down
37 changes: 26 additions & 11 deletions apps/web/ui/partners/trusted-partner-badge.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,29 @@
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",
}: {
variant?: "overlay" | "inline";
}) {
const badge = (
<img
alt="Trusted partner badge"
src={TRUSTED_BADGE_SRC}
className={cn("shrink-0", variant === "inline" ? "size-3.5" : "size-6")}
/>
);

export function TrustedPartnerBadge() {
return (
<Tooltip
content={
<div className="flex max-w-xs items-start gap-2 p-3">
<div className="flex max-w-xs items-start gap-1.5 p-3">
<img
alt="Trusted partner badge"
src="https://assets.dub.co/icons/trusted-badge.svg"
className="size-6 shrink-0"
src={TRUSTED_BADGE_SRC}
className="size-5 shrink-0"
/>
<div className="flex flex-col gap-1">
<span className="text-sm font-semibold text-neutral-900">
Expand All @@ -22,13 +37,13 @@ export function TrustedPartnerBadge() {
</div>
}
>
<div className="absolute -bottom-1 -right-1 overflow-hidden transition-transform duration-100 hover:scale-[1.15]">
<img
alt="Trusted partner badge"
src="https://assets.dub.co/icons/trusted-badge.svg"
className="size-6"
/>
</div>
{variant === "inline" ? (
<span className="shrink-0">{badge}</span>
) : (
<div className="absolute -bottom-1 -right-1 overflow-hidden transition-transform duration-100 hover:scale-[1.15]">
{badge}
</div>
)}
</Tooltip>
);
}
Loading