56 lines
1.8 KiB
JavaScript
56 lines
1.8 KiB
JavaScript
// 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`;
|
|
}; |