// src/utils/member-tiers.js import { differenceInDays } from 'date-fns'; import { DEFAULT_MEMBER_TIERS } from '../config/MemberTiers'; /** * Calculate tenure in years (with decimal precision) * @param {string|Date} memberSince - The date the member joined * @returns {number|null} - Years of membership or null if invalid */ export const getTenureYears = (memberSince) => { if (!memberSince) return null; const since = new Date(memberSince); if (Number.isNaN(since.getTime())) return null; const now = new Date(); const days = differenceInDays(now, since); // Convert to years with decimal precision return Math.max(0, days / 365.25); }; /** * Get the tier for a member based on their membership duration * @param {string|Date} memberSince - The date the member joined * @param {Array} tiers - Array of tier configurations * @returns {Object} - The matching tier object */ export const getTierForMember = (memberSince, tiers = DEFAULT_MEMBER_TIERS) => { const years = getTenureYears(memberSince); if (years == null) return tiers[0]; const match = tiers.find( (tier) => years >= tier.minYears && (tier.maxYears == null || years <= tier.maxYears) ); return match || tiers[0]; }; /** * Format tenure for display * @param {string|Date} memberSince - The date the member joined * @returns {string} - Human-readable tenure string */ export const formatTenure = (memberSince) => { const years = getTenureYears(memberSince); if (years == null) return 'Unknown'; if (years < 1) { const months = Math.floor(years * 12); return months <= 1 ? '< 1 month' : `${months} months`; } const wholeYears = Math.floor(years); return wholeYears === 1 ? '1 year' : `${wholeYears} years`; };