diff --git a/src/api/classesApi.js b/src/api/classesApi.js index d759ced..8784988 100644 --- a/src/api/classesApi.js +++ b/src/api/classesApi.js @@ -1,5 +1,6 @@ import axiosInstance from './axiosInstance' export const classesApi = { + getAll: (params = {}) => axiosInstance.get('/classes/user/get-all', { params }), getMyClasses: (params = {}) => axiosInstance.get('/classes/user/my-classes', { params }) } diff --git a/src/utils/format.js b/src/utils/format.js index 8fd2dcc..ccb04be 100644 --- a/src/utils/format.js +++ b/src/utils/format.js @@ -17,6 +17,14 @@ export function formatPrice(amount) { return `${toPersianDigits(Number(amount).toLocaleString('en-US'))} تومان` } +export function formatDaysUntilStart(days) { + if (days == null || Number.isNaN(Number(days))) return null + const value = Number(days) + if (value > 0) return `${toPersianDigits(value)} روز تا شروع` + if (value === 0) return 'امروز شروع می‌شود' + return `${toPersianDigits(Math.abs(value))} روز از شروع گذشته` +} + export function getApiErrorMessage(error, fallback = 'خطایی رخ داد. دوباره تلاش کنید.') { return ( error?.response?.data?.error?.message || diff --git a/src/views/LandingView.vue b/src/views/LandingView.vue index d6f515c..f1d4155 100644 --- a/src/views/LandingView.vue +++ b/src/views/LandingView.vue @@ -87,6 +87,51 @@ +
+
+
+

کلاس‌های فعال

+

ظرفیت، تخفیف و زمان شروع هر کلاس را ببینید و برای ثبت‌نام درخواست مشاوره دهید.

+
+ +
+
+
+ +
+

فعلاً کلاسی برای نمایش نیست

+

به زودی کلاس‌های جدید اینجا منتشر می‌شوند.

+
+ +
+
+
+ {{ cls.course?.title || 'کلاس' }} + تخفیف {{ formatPrice(cls.discount) }} +
+

{{ cls.name }}

+

+ استاد: {{ cls.professor.name }} {{ cls.professor.surname || '' }} +

+ +
+ {{ formatDaysUntilStart(cls.daysUntilStart) }} + {{ toPersianDigits(cls.freeSpots) }} ظرفیت آزاد + شروع {{ formatJalali(cls.startDate) }} +
+ +
+
+ {{ formatPrice(cls.finalTuitionFee ?? cls.tuitionFee) }} + {{ formatPrice(cls.tuitionFee) }} +
+
+ درخواست ثبت‌نام +
+
+
+
+
@@ -132,21 +177,30 @@ import { onMounted, ref } from 'vue' import { RouterLink } from 'vue-router' import ContactInquiryForm from '@/components/ContactInquiryForm.vue' import { coursesApi } from '@/api/coursesApi' +import { classesApi } from '@/api/classesApi' import { useAuthStore } from '@/stores/authStore' -import { formatPrice, toPersianDigits } from '@/utils/format' +import { formatPrice, formatJalali, formatDaysUntilStart, toPersianDigits } from '@/utils/format' const auth = useAuthStore() const courses = ref([]) +const classes = ref([]) const coursesLoading = ref(true) +const classesLoading = ref(true) onMounted(async () => { try { - const res = await coursesApi.getAll({ limit: 50, sort: '-createdAt' }) - courses.value = res.data || [] + const [coursesRes, classesRes] = await Promise.all([ + coursesApi.getAll({ limit: 50, sort: '-createdAt' }), + classesApi.getAll({ limit: 50 }) + ]) + courses.value = coursesRes.data || [] + classes.value = classesRes.data || [] } catch { courses.value = [] + classes.value = [] } finally { coursesLoading.value = false + classesLoading.value = false } }) @@ -396,6 +450,22 @@ onMounted(async () => { color: var(--ink-soft); } +.price-stack { + display: flex; + flex-direction: column; + gap: 0.15rem; +} + +.price-old { + font-size: 0.82rem; + color: var(--ink-soft); + text-decoration: line-through; +} + +.classes-section { + background: var(--chalk); +} + .course-cta { display: inline-flex; margin-top: 0.85rem;