diff --git a/src/composables/usePersianDate.js b/src/composables/usePersianDate.js
index a4c890e..ede3491 100644
--- a/src/composables/usePersianDate.js
+++ b/src/composables/usePersianDate.js
@@ -55,6 +55,10 @@ export function usePersianDate() {
const jalaliToIso = (jalaliStr) => toGregorianIso(jalaliStr) || null;
+ const getTodayJalali = (formatStr = 'jYYYY/jMM/jDD') => {
+ return moment().locale('fa').format(formatStr);
+ };
+
return {
toPersianDigits,
toLatinDigits,
@@ -62,6 +66,8 @@ export function usePersianDate() {
formatJalaliWithTime,
toJalaliPickerValue,
toGregorianIso,
- jalaliToIso
+ jalaliToIso,
+ getTodayJalali
};
}
+
diff --git a/src/utils/classSchedule.js b/src/utils/classSchedule.js
index 177608f..f106d1e 100644
--- a/src/utils/classSchedule.js
+++ b/src/utils/classSchedule.js
@@ -82,3 +82,38 @@ export function calculateClassEndDate(startDate, days = [], numberOfSessions = 0
return lastMatchingDate ? lastMatchingDate.locale('fa').format('jYYYY/jMM/jDD') : '';
}
+
+/**
+ * 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.
+ * @param {Object} cls - Class object
+ * @returns {string} Jalali formatted date string, or today's date if not calculable
+ */
+export function calculateClassMidDate(cls) {
+ if (!cls) return moment().locale('fa').format('jYYYY/jMM/jDD');
+
+ const totalSessions = parseInt(cls.numberOfSessions || cls.course?.sectionCount || 0, 10);
+ const midSessions = totalSessions > 0 ? Math.ceil(totalSessions / 2) : 0;
+
+ if (cls.startDate && Array.isArray(cls.days) && cls.days.length > 0 && midSessions >= 1) {
+ const computed = calculateClassEndDate(cls.startDate, cls.days, midSessions);
+ if (computed) return computed;
+ }
+
+ if (cls.startDate && cls.endDate) {
+ const startM = moment(cls.startDate);
+ const endM = moment(cls.endDate);
+ if (startM.isValid() && 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');
+ }
+
+ return moment().locale('fa').format('jYYYY/jMM/jDD');
+}
+
diff --git a/src/utils/classSchedule.test.js b/src/utils/classSchedule.test.js
index efd2f8d..275bd85 100644
--- a/src/utils/classSchedule.test.js
+++ b/src/utils/classSchedule.test.js
@@ -1,6 +1,6 @@
import { describe, it } from 'node:test';
import assert from 'node:assert/strict';
-import { formatClassDays, formatClassTime, formatClassSchedule, calculateClassEndDate } from './classSchedule.js';
+import { formatClassDays, formatClassTime, formatClassSchedule, calculateClassEndDate, calculateClassMidDate } from './classSchedule.js';
describe('class schedule display', () => {
it('formats weekdays in Iran week order', () => {
@@ -28,4 +28,21 @@ describe('class schedule display', () => {
const endDate = calculateClassEndDate('1403/01/01', [6, 2], 2);
assert.equal(endDate, '1403/01/07');
});
+
+ it('calculates class mid date (halfway through class sessions)', () => {
+ // For 10 sessions on [6, 2] starting 1403/01/01:
+ // Half is 5th session
+ const midDate = calculateClassMidDate({
+ startDate: '1403/01/01',
+ days: [6, 2],
+ numberOfSessions: 10
+ });
+ // Session 1: 1403/01/04 (Sat)
+ // Session 2: 1403/01/07 (Tue)
+ // Session 3: 1403/01/11 (Sat)
+ // Session 4: 1403/01/14 (Tue)
+ // Session 5: 1403/01/18 (Sat)
+ assert.equal(midDate, '1403/01/18');
+ });
});
+
diff --git a/src/views/classes/ClassFormView.vue b/src/views/classes/ClassFormView.vue
index 7615199..49ca007 100644
--- a/src/views/classes/ClassFormView.vue
+++ b/src/views/classes/ClassFormView.vue
@@ -117,7 +117,7 @@
-
+
@@ -324,7 +324,7 @@ const route = useRoute();
const router = useRouter();
const { showSuccess, showError } = useToast();
const { hasPermission } = usePermission();
-const { toPersianDigits, toLatinDigits } = usePersianDate();
+const { toPersianDigits, toLatinDigits, getTodayJalali } = usePersianDate();
const classId = route.params.id;
const queryCourseId = route.query.courseId ? String(route.query.courseId) : null;
@@ -354,9 +354,10 @@ const form = reactive({
discount: 0,
freeSpots: null,
showOnFrontend: true,
- startDate: '',
+ startDate: isEditMode.value ? '' : getTodayJalali(),
endDate: '',
days: [],
+
startTime: '',
endTime: '',
numberOfSessions: null,
diff --git a/src/views/expenses/ExpenseListView.vue b/src/views/expenses/ExpenseListView.vue
index b8ddb69..fb7cd19 100644
--- a/src/views/expenses/ExpenseListView.vue
+++ b/src/views/expenses/ExpenseListView.vue
@@ -84,7 +84,7 @@
-
+
@@ -126,7 +126,8 @@ import InputNumber from 'primevue/inputnumber';
import Textarea from 'primevue/textarea';
import DatePicker from 'vue3-persian-datetime-picker';
-const { toPersianDigits, formatJalali, toGregorianIso, toJalaliPickerValue } = usePersianDate();
+const { toPersianDigits, formatJalali, toGregorianIso, toJalaliPickerValue, getTodayJalali } = usePersianDate();
+
const { showSuccess, showError } = useToast();
const {
diff --git a/src/views/financialReports/FinancialReportsView.vue b/src/views/financialReports/FinancialReportsView.vue
index 090affe..a16f99b 100644
--- a/src/views/financialReports/FinancialReportsView.vue
+++ b/src/views/financialReports/FinancialReportsView.vue
@@ -171,11 +171,11 @@
-
+
-
+
@@ -340,7 +340,7 @@ import TabPanel from 'primevue/tabpanel';
import DatePicker from 'vue3-persian-datetime-picker';
const route = useRoute();
-const { toPersianDigits, formatJalali, toGregorianIso, toJalaliPickerValue } = usePersianDate();
+const { toPersianDigits, formatJalali, toGregorianIso, toJalaliPickerValue, getTodayJalali } = usePersianDate();
const { showError } = useToast();
const formatToman = (value) => `${toPersianDigits(Math.round(value || 0).toLocaleString())} تومان`;
diff --git a/src/views/payments/PaymentDetailView.vue b/src/views/payments/PaymentDetailView.vue
index e9124c5..df14fb0 100644
--- a/src/views/payments/PaymentDetailView.vue
+++ b/src/views/payments/PaymentDetailView.vue
@@ -164,11 +164,11 @@
-
+
-
+
@@ -185,6 +185,7 @@
placeholder="یادداشت داخلی درباره این تراکنش…"
/>
+
@@ -209,11 +210,11 @@