mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-28 17:43:47 +00:00
Add subscription status colors: green (paid active), blue (trial active), red (paid expired), orange (trial expired). Extract NODE_COLORS constant as single source of truth. Add SubscriptionStatus union type. Show status badge in user detail panel. Add i18n for all 4 locales.
87 lines
2.3 KiB
TypeScript
87 lines
2.3 KiB
TypeScript
import type { SubscriptionStatus } from '@/types/referralNetwork';
|
|
|
|
/**
|
|
* Format kopeks to a human-readable ruble string.
|
|
*/
|
|
export function formatKopeksToRubles(kopeks: number): string {
|
|
return `${(kopeks / 100).toLocaleString('ru-RU')}`;
|
|
}
|
|
|
|
/**
|
|
* Single source of truth for user node colors.
|
|
*/
|
|
export const NODE_COLORS = {
|
|
partner: '#f0c261',
|
|
topReferrer: '#e85d9a',
|
|
activeReferrer: '#7c6aef',
|
|
paidActive: '#22c55e',
|
|
trialActive: '#38bdf8',
|
|
paidExpired: '#ef4444',
|
|
trialExpired: '#fb923c',
|
|
campaignUser: '#4dd9c0',
|
|
regular: '#6b7280',
|
|
} as const;
|
|
|
|
/**
|
|
* Map subscription status to its node color.
|
|
*/
|
|
const SUBSCRIPTION_STATUS_COLOR: Record<SubscriptionStatus, string> = {
|
|
paid_active: NODE_COLORS.paidActive,
|
|
trial_active: NODE_COLORS.trialActive,
|
|
paid_expired: NODE_COLORS.paidExpired,
|
|
trial_expired: NODE_COLORS.trialExpired,
|
|
};
|
|
|
|
export function getSubscriptionStatusColor(status: SubscriptionStatus): string {
|
|
return SUBSCRIPTION_STATUS_COLOR[status];
|
|
}
|
|
|
|
/**
|
|
* Campaign node color palette. Each campaign gets a distinct color
|
|
* based on its index position.
|
|
*/
|
|
const CAMPAIGN_COLORS = [
|
|
'#4dd9c0',
|
|
'#f0c261',
|
|
'#e85d9a',
|
|
'#6b9fff',
|
|
'#b97aff',
|
|
'#ff8a65',
|
|
'#66d9a0',
|
|
'#ff6b9d',
|
|
'#7ec8e3',
|
|
'#c4b5fd',
|
|
];
|
|
|
|
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.
|
|
*/
|
|
export function getUserNodeSize(directReferrals: number): number {
|
|
if (directReferrals === 0) return 5;
|
|
if (directReferrals <= 2) return 10;
|
|
return Math.min(40, 10 + Math.sqrt(directReferrals) * 4);
|
|
}
|