feat(classes): add class days and meeting times to class forms

Let admins set the weekly schedule on the class and show it in lists, details, and session generation.
This commit is contained in:
2026-08-15 23:59:08 +03:30
parent 3f220dda52
commit 91527e64bb
8 changed files with 141 additions and 5 deletions
+9
View File
@@ -33,6 +33,14 @@
{{ formatJalali(classData.startDate) }} {{ formatJalali(classData.endDate) }}
</span>
</div>
<div class="col-12 sm:col-4">
<span class="text-muted text-xs block mb-1">روزهای برگزاری</span>
<span class="font-bold text-color text-sm">{{ formatClassDays(classData.days) || '—' }}</span>
</div>
<div class="col-12 sm:col-4">
<span class="text-muted text-xs block mb-1">ساعت کلاس</span>
<span class="font-bold text-color text-sm" dir="ltr">{{ formatClassTime(classData.startTime, classData.endTime) || '—' }}</span>
</div>
<div class="col-12 sm:col-4">
<span class="text-muted text-xs block mb-1">وضعیت</span>
<StatusTag :status="classData.isActive !== false" />
@@ -125,6 +133,7 @@
import { ref, computed, onMounted } from 'vue';
import { useRoute } from 'vue-router';
import { classApi } from '@/api/classApi';
import { formatClassDays, formatClassTime } from '@/utils/classSchedule';
import { sessionApi } from '@/api/sessionApi';
import { usePersianDate } from '@/composables/usePersianDate';
import { useToast } from '@/composables/useToast';
+37
View File
@@ -55,6 +55,28 @@
<label class="font-semibold text-sm">کلاس فعال است</label>
</div>
<div class="col-12 flex flex-column gap-2">
<label class="font-semibold text-sm">روزهای برگزاری</label>
<SelectButton
v-model="form.days"
:options="weekdays"
optionLabel="label"
optionValue="value"
multiple
class="text-sm"
/>
</div>
<div class="col-12 md:col-6 flex flex-column gap-2">
<label class="font-semibold text-sm">ساعت شروع کلاس</label>
<InputText v-model.trim="form.startTime" class="w-full text-sm" dir="ltr" placeholder="19:00" />
</div>
<div class="col-12 md:col-6 flex flex-column gap-2">
<label class="font-semibold text-sm">ساعت پایان کلاس</label>
<InputText v-model.trim="form.endTime" class="w-full text-sm" dir="ltr" placeholder="21:00" />
</div>
<div class="col-12">
<AdminNotesField v-model="form.adminNotes" />
</div>
@@ -137,6 +159,9 @@
:course-id="form.course ? String(form.course) : ''"
:professor-id="form.professor ? String(form.professor) : null"
:default-session-count="defaultSessionCount"
:days="form.days"
:start-time="form.startTime"
:end-time="form.endTime"
/>
</template>
@@ -177,6 +202,8 @@ import Tag from 'primevue/tag';
import DataTable from 'primevue/datatable';
import Column from 'primevue/column';
import DatePicker from 'vue3-persian-datetime-picker';
import SelectButton from 'primevue/selectbutton';
import { WEEKDAYS } from '@/utils/classSchedule';
const route = useRoute();
const router = useRouter();
@@ -210,9 +237,13 @@ const form = reactive({
tuitionFee: 0,
startDate: '',
endDate: '',
days: [],
startTime: '',
endTime: '',
isActive: true,
adminNotes: []
});
const weekdays = WEEKDAYS;
const removeDialogMessage = computed(() => {
const name = studentToRemove.value?.name;
@@ -293,6 +324,9 @@ const fetchData = async () => {
tuitionFee: data.tuitionFee || 0,
startDate: toJalaliDisplay(data.startDate),
endDate: toJalaliDisplay(data.endDate),
days: Array.isArray(data.days) ? [...data.days] : [],
startTime: data.startTime || '',
endTime: data.endTime || '',
isActive: data.isActive !== false,
adminNotes: Array.isArray(data.adminNotes) ? [...data.adminNotes] : []
});
@@ -329,6 +363,9 @@ const handleSubmit = async () => {
tuitionFee: form.tuitionFee,
startDate: toGregorianIso(form.startDate),
endDate: toGregorianIso(form.endDate),
days: form.days || [],
startTime: form.startTime || '',
endTime: form.endTime || '',
isActive: form.isActive,
adminNotes: (form.adminNotes || []).map((n) => String(n).trim()).filter(Boolean)
};
+7
View File
@@ -29,6 +29,12 @@
</template>
</Column>
<Column header="برنامه کلاس">
<template #body="{ data }">
<span class="text-sm">{{ formatClassSchedule(data) || '—' }}</span>
</template>
</Column>
<Column field="capacity" header="ظرفیت">
<template #body="{ data }">
{{ toPersianDigits(data.capacity || 0) }} نفر
@@ -68,6 +74,7 @@ import { onMounted } from 'vue';
import { useDataTable } from '@/composables/useDataTable';
import { usePersianDate } from '@/composables/usePersianDate';
import { classApi } from '@/api/classApi';
import { formatClassSchedule } from '@/utils/classSchedule';
import PageHeader from '@/components/common/PageHeader.vue';
import DataTableWrapper from '@/components/common/DataTableWrapper.vue';
import PermissionGate from '@/components/common/PermissionGate.vue';
+6
View File
@@ -120,6 +120,11 @@
<Column header="دانشجو" style="width: 90px">
<template #body="{ data }">{{ toPersianDigits((data.students || []).length) }}</template>
</Column>
<Column header="برنامه کلاس">
<template #body="{ data }">
<span class="text-sm">{{ formatClassSchedule(data) || '—' }}</span>
</template>
</Column>
<Column header="وضعیت" style="width: 90px">
<template #body="{ data }">
<StatusTag :status="data.isActive !== false" />
@@ -164,6 +169,7 @@ import { useRoute, useRouter } from 'vue-router';
import { courseApi } from '@/api/courseApi';
import { professorApi } from '@/api/professorApi';
import { classApi } from '@/api/classApi';
import { formatClassSchedule } from '@/utils/classSchedule';
import { usePersianDate } from '@/composables/usePersianDate';
import { useToast } from '@/composables/useToast';