71 lines
2.1 KiB
TypeScript
71 lines
2.1 KiB
TypeScript
import { jalaliMonthName, toJalali } from '../common/jalali';
|
|||
|
|
|
||
|
|
export const BIRTHDAY_SMS_DEFAULT = '{نام} عزیز، تولدتان مبارک.';
|
||
|
|
|
||
|
|
export type BirthdayRow = {
|
||
|
|
id: string;
|
||
|
|
firstName: string;
|
||
|
|
lastName: string;
|
||
|
|
mobile: string | null;
|
||
|
|
birthDate: Date;
|
||
|
|
};
|
||
|
|
|
||
|
|
export type BirthdayPick = {
|
||
|
|
id: string;
|
||
|
|
firstName: string;
|
||
|
|
lastName: string;
|
||
|
|
mobile: string | null;
|
||
|
|
day: number;
|
||
|
|
};
|
||
|
|
|
||
|
|
export function fillBirthdaySmsText(template: string, firstName: string, lastName: string) {
|
||
|
|
const name = `${firstName} ${lastName}`.trim().replace(/\s+/g, ' ');
|
||
|
|
return template.replaceAll('{نام}', name).replaceAll('{name}', name).trim();
|
||
|
|
}
|
||
|
|
|
||
|
|
function tehranJalali(d: Date) {
|
||
|
|
const [gy, gm, gd] = new Intl.DateTimeFormat('en-CA', {
|
||
|
|
timeZone: 'Asia/Tehran',
|
||
|
|
year: 'numeric',
|
||
|
|
month: '2-digit',
|
||
|
|
day: '2-digit',
|
||
|
|
})
|
||
|
|
.format(d)
|
||
|
|
.split('-')
|
||
|
|
.map(Number);
|
||
|
|
return toJalali(gy, gm, gd);
|
||
|
|
}
|
||
|
|
|
||
|
|
function birthJalali(d: Date) {
|
||
|
|
return toJalali(d.getUTCFullYear(), d.getUTCMonth() + 1, d.getUTCDate());
|
||
|
|
}
|
||
|
|
|
||
|
|
/** متولدین ماه جاری تهران. پیشنمایش فقط روزهای امروز و بعد است. */
|
||
|
|
export function selectMonthBirthdays(people: BirthdayRow[], now = new Date(), previewLimit = 6) {
|
||
|
|
const today = tehranJalali(now);
|
||
|
|
const matched = people.flatMap((person) => {
|
||
|
|
const birth = birthJalali(person.birthDate);
|
||
|
|
if (birth.jm !== today.jm) return [];
|
||
|
|
return [
|
||
|
|
{
|
||
|
|
id: person.id,
|
||
|
|
firstName: person.firstName,
|
||
|
|
lastName: person.lastName,
|
||
|
|
mobile: person.mobile,
|
||
|
|
day: birth.jd,
|
||
|
|
},
|
||
|
|
];
|
||
|
|
});
|
||
|
|
const byDay = (a: BirthdayPick, b: BirthdayPick) => a.day - b.day || a.firstName.localeCompare(b.firstName, 'fa');
|
||
|
|
const upcoming = matched.filter((row) => row.day >= today.jd).sort(byDay);
|
||
|
|
const passed = matched.filter((row) => row.day < today.jd).sort(byDay);
|
||
|
|
return {
|
||
|
|
month: today.jm,
|
||
|
|
monthName: jalaliMonthName(today.jm),
|
||
|
|
today: today.jd,
|
||
|
|
total: matched.length,
|
||
|
|
preview: upcoming.slice(0, previewLimit),
|
||
|
|
items: [...upcoming, ...passed],
|
||
|
|
};
|
||
|
|
}
|