feat(payments): auto-populate payment due date with middle session date upon class selection
This commit is contained in:
+50
-14
@@ -42,6 +42,30 @@ export function formatClassSchedule(cls) {
|
||||
return days || time || '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses any date format (Jalali string, ISO string, Date object, Persian/Latin digits) into a valid moment object
|
||||
*/
|
||||
export function parseDateSmart(input) {
|
||||
if (!input) return null;
|
||||
if (input instanceof Date) {
|
||||
const m = moment(input);
|
||||
return m.isValid() ? m : null;
|
||||
}
|
||||
const latin = String(input)
|
||||
.replace(/[۰-۹]/g, (d) => '۰۱۲۳۴۵۶۷۸۹'.indexOf(d))
|
||||
.replace(/[٠-٩]/g, (d) => '٠١٢٣٤٥٦٧٨٩'.indexOf(d))
|
||||
.trim();
|
||||
const isJalaliPattern = /^(1[34]\d{2})[/-](\d{1,2})[/-](\d{1,2})/.test(latin);
|
||||
if (isJalaliPattern) {
|
||||
const m = moment(latin, ['jYYYY/jMM/jDD', 'jYYYY-jMM-jDD', 'jYYYY/jM/jD', 'jYYYY-jM-jD']);
|
||||
if (m.isValid()) return m;
|
||||
}
|
||||
const m = moment(latin);
|
||||
if (m.isValid()) return m;
|
||||
const mJalali = moment(latin, ['jYYYY/jMM/jDD', 'jYYYY-jMM-jDD']);
|
||||
return mJalali.isValid() ? mJalali : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the class end date in Jalali (jYYYY/jMM/jDD) based on start date, selected days, and number of sessions.
|
||||
* @param {string|Date} startDate - Jalali string (e.g. 1403/01/01) or ISO string / Date
|
||||
@@ -58,13 +82,8 @@ export function calculateClassEndDate(startDate, days = [], numberOfSessions = 0
|
||||
: [];
|
||||
if (!validDays.length) return '';
|
||||
|
||||
const latinStartDate = String(startDate)
|
||||
.replace(/[۰-۹]/g, (d) => '۰۱۲۳۴۵۶۷۸۹'.indexOf(d))
|
||||
.replace(/[٠-٩]/g, (d) => '٠١٢٣٤٥٦٧٨٩'.indexOf(d))
|
||||
.trim();
|
||||
|
||||
let current = moment(latinStartDate, ['jYYYY/jMM/jDD', 'YYYY-MM-DD', 'YYYY/MM/DD', moment.ISO_8601]);
|
||||
if (!current.isValid()) return '';
|
||||
let current = parseDateSmart(startDate);
|
||||
if (!current || !current.isValid()) return '';
|
||||
|
||||
let count = 0;
|
||||
let lastMatchingDate = null;
|
||||
@@ -85,11 +104,28 @@ export function calculateClassEndDate(startDate, days = [], numberOfSessions = 0
|
||||
|
||||
/**
|
||||
* Calculates the halfway due date for a class in Jalali (jYYYY/jMM/jDD).
|
||||
* If class has 10 sessions, due date is calculated until the 5th session.
|
||||
* If class has 10 sessions, due date is calculated as the date of the 5th session.
|
||||
* @param {Object} cls - Class object
|
||||
* @param {Array} [sessions] - Optional array of session objects
|
||||
* @returns {string} Jalali formatted date string, or today's date if not calculable
|
||||
*/
|
||||
export function calculateClassMidDate(cls) {
|
||||
export function calculateClassMidDate(cls, sessions = []) {
|
||||
if (Array.isArray(sessions) && sessions.length > 0) {
|
||||
const validSessions = sessions
|
||||
.filter((s) => s && (s.day || s.date))
|
||||
.map((s) => ({
|
||||
...s,
|
||||
momentDate: parseDateSmart(s.day || s.date)
|
||||
}))
|
||||
.filter((s) => s.momentDate && s.momentDate.isValid());
|
||||
|
||||
if (validSessions.length > 0) {
|
||||
validSessions.sort((a, b) => a.momentDate.valueOf() - b.momentDate.valueOf());
|
||||
const midIndex = Math.ceil(validSessions.length / 2) - 1;
|
||||
return validSessions[midIndex].momentDate.locale('fa').format('jYYYY/jMM/jDD');
|
||||
}
|
||||
}
|
||||
|
||||
if (!cls) return moment().locale('fa').format('jYYYY/jMM/jDD');
|
||||
|
||||
const totalSessions = parseInt(cls.numberOfSessions || cls.course?.sectionCount || 0, 10);
|
||||
@@ -101,17 +137,17 @@ export function calculateClassMidDate(cls) {
|
||||
}
|
||||
|
||||
if (cls.startDate && cls.endDate) {
|
||||
const startM = moment(cls.startDate);
|
||||
const endM = moment(cls.endDate);
|
||||
if (startM.isValid() && endM.isValid()) {
|
||||
const startM = parseDateSmart(cls.startDate);
|
||||
const endM = parseDateSmart(cls.endDate);
|
||||
if (startM && startM.isValid() && endM && endM.isValid()) {
|
||||
const midTime = startM.valueOf() + (endM.valueOf() - startM.valueOf()) / 2;
|
||||
return moment(midTime).locale('fa').format('jYYYY/jMM/jDD');
|
||||
}
|
||||
}
|
||||
|
||||
if (cls.startDate) {
|
||||
const startM = moment(cls.startDate);
|
||||
if (startM.isValid()) return startM.locale('fa').format('jYYYY/jMM/jDD');
|
||||
const startM = parseDateSmart(cls.startDate);
|
||||
if (startM && startM.isValid()) return startM.locale('fa').format('jYYYY/jMM/jDD');
|
||||
}
|
||||
|
||||
return moment().locale('fa').format('jYYYY/jMM/jDD');
|
||||
|
||||
Reference in New Issue
Block a user