Files
gameno-api/utils/classSchedule.js
T
kavehhn 0cdb9cec20 feat(sms): send class start date, days, and course time
Expose schedule fields on class and invoice templates so SMS can include Jalali start date, weekdays, and hour range.
2026-08-15 23:09:04 +03:30

86 lines
2.6 KiB
JavaScript

'use strict';
const PERSIAN_WEEKDAYS = ['یکشنبه', 'دوشنبه', 'سه‌شنبه', 'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'];
const IRAN_WEEK_ORDER = [6, 0, 1, 2, 3, 4, 5];
const toDate = (value) => {
if (!value) return null;
const date = value instanceof Date ? value : new Date(value);
return Number.isNaN(date.getTime()) ? null : date;
};
const formatClockPart = (time) => {
const raw = String(time || '').trim();
if (!raw) return '';
const [hoursRaw, minutesRaw] = raw.split(':');
const hours = String(parseInt(hoursRaw, 10));
if (hours === 'NaN') return '';
if (!minutesRaw || minutesRaw === '00') return hours;
return `${hours}:${minutesRaw}`;
};
const formatCourseTime = (startTime, endTime) => {
const start = formatClockPart(startTime);
const end = formatClockPart(endTime);
if (!start) return '';
if (!end) return start;
return `از ${start} تا ${end}`;
};
const weekdayIndex = (value) => {
const date = toDate(value);
return date ? date.getDay() : null;
};
const joinFaList = (items) => {
if (!items.length) return '';
if (items.length === 1) return items[0];
if (items.length === 2) return `${items[0]} و ${items[1]}`;
return `${items.slice(0, -1).join('، ')} و ${items[items.length - 1]}`;
};
const formatClassDays = (sessions = []) => {
const indexes = [];
const seen = new Set();
for (const session of sessions) {
const dayIndex = weekdayIndex(session?.day);
if (dayIndex == null || seen.has(dayIndex)) continue;
seen.add(dayIndex);
indexes.push(dayIndex);
}
indexes.sort((a, b) => IRAN_WEEK_ORDER.indexOf(a) - IRAN_WEEK_ORDER.indexOf(b));
return joinFaList(indexes.map((index) => PERSIAN_WEEKDAYS[index]).filter(Boolean));
};
const formatClassStartDate = (value) => {
const date = toDate(value);
if (!date) return '';
try {
return date.toLocaleDateString('fa-IR');
} catch {
return date.toISOString().slice(0, 10);
}
};
const buildClassScheduleContext = (classDoc, sessions = [], currentSession = null) => {
const sortedSessions = [...sessions].sort((a, b) => {
const left = toDate(a?.day)?.getTime() || 0;
const right = toDate(b?.day)?.getTime() || 0;
return left - right;
});
const sessionForTime = currentSession || sortedSessions[0] || null;
return {
classStartDate: formatClassStartDate(classDoc?.startDate || sortedSessions[0]?.day),
classDays: formatClassDays(sortedSessions),
courseTime: formatCourseTime(sessionForTime?.startTime, sessionForTime?.endTime)
};
};
module.exports = {
formatCourseTime,
formatClassDays,
formatClassStartDate,
buildClassScheduleContext
};