Files
gameno-api/utils/classSchedule.js
T
kavehhn a6c760c3b7 fix(sms): prefix course time with ساعت
SMS courseTime now reads «از ساعت 19 تا 21» instead of «از 19 تا 21».
2026-08-16 00:16:40 +03:30

123 lines
3.8 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 normalizeWeekdays = (days) => {
if (!Array.isArray(days)) return [];
const unique = [];
const seen = new Set();
for (const value of days) {
const index = Number(value);
if (!Number.isInteger(index) || index < 0 || index > 6 || seen.has(index)) continue;
seen.add(index);
unique.push(index);
}
unique.sort((a, b) => IRAN_WEEK_ORDER.indexOf(a) - IRAN_WEEK_ORDER.indexOf(b));
return unique;
};
const normalizeClockTime = (value) => {
if (value == null) return '';
const raw = String(value).trim();
if (!raw) return '';
const match = raw.match(/^(\d{1,2})(?::(\d{1,2}))?$/);
if (!match) return '';
const hours = Number(match[1]);
const minutes = Number(match[2] || 0);
if (hours > 23 || minutes > 59) return '';
return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`;
};
const formatClassDaysFromIndexes = (days = []) => {
const indexes = normalizeWeekdays(days);
return joinFaList(indexes.map((index) => PERSIAN_WEEKDAYS[index]).filter(Boolean));
};
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);
}
return formatClassDaysFromIndexes(indexes);
};
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;
const storedDays = formatClassDaysFromIndexes(classDoc?.days);
const storedTime = formatCourseTime(classDoc?.startTime, classDoc?.endTime);
return {
classStartDate: formatClassStartDate(classDoc?.startDate || sortedSessions[0]?.day),
classDays: storedDays || formatClassDays(sortedSessions),
courseTime: storedTime || formatCourseTime(sessionForTime?.startTime, sessionForTime?.endTime)
};
};
module.exports = {
IRAN_WEEK_ORDER,
PERSIAN_WEEKDAYS,
formatCourseTime,
formatClassDays,
formatClassDaysFromIndexes,
formatClassStartDate,
normalizeWeekdays,
normalizeClockTime,
buildClassScheduleContext
};