feat: add fill+border dual-color nodes, radial layout, and dark labels

Node fill color now encodes subscription status (paid/trial active/expired),
while border color indicates referral role (partner/top/active referrer).
Added BFS-based radial initial positioning to spread referral branches outward.
Updated legend with two sections and adjusted FA2 gravity for less clustering.
This commit is contained in:
Fringg
2026-03-22 09:25:23 +03:00
parent b289ea9c23
commit b18f3fb211
9 changed files with 227 additions and 52 deletions

View File

@@ -36,6 +36,28 @@ export function getSubscriptionStatusColor(status: SubscriptionStatus): string {
return SUBSCRIPTION_STATUS_COLOR[status];
}
/**
* Fill color = subscription status (primary concern for campaign evaluation).
*/
export function getNodeFillColor(
subscriptionStatus: SubscriptionStatus | null,
campaignId: number | null,
): string {
if (subscriptionStatus) return SUBSCRIPTION_STATUS_COLOR[subscriptionStatus];
if (campaignId !== null) return NODE_COLORS.campaignUser;
return NODE_COLORS.regular;
}
/**
* Border color = referral role. Returns null if no special role.
*/
export function getNodeBorderColor(directReferrals: number, isPartner: boolean): string | null {
if (isPartner) return NODE_COLORS.partner;
if (directReferrals >= 10) return NODE_COLORS.topReferrer;
if (directReferrals >= 1) return NODE_COLORS.activeReferrer;
return null;
}
/**
* Campaign node color palette. Each campaign gets a distinct color
* based on its index position.
@@ -57,24 +79,6 @@ export function getCampaignColor(index: number): string {
return CAMPAIGN_COLORS[index % CAMPAIGN_COLORS.length];
}
/**
* Determine the visual color for a user node.
* Priority: partner > top referrer > active referrer > subscription status > campaign > regular.
*/
export function getUserNodeColor(
directReferrals: number,
isPartner: boolean,
campaignId: number | null,
subscriptionStatus: SubscriptionStatus | null,
): string {
if (isPartner) return NODE_COLORS.partner;
if (directReferrals >= 10) return NODE_COLORS.topReferrer;
if (directReferrals >= 1) return NODE_COLORS.activeReferrer;
if (subscriptionStatus) return SUBSCRIPTION_STATUS_COLOR[subscriptionStatus];
if (campaignId !== null) return NODE_COLORS.campaignUser;
return NODE_COLORS.regular;
}
/**
* Determine the visual size for a user node.
* Size is proportional to direct_referrals, clamped between min and max.