-
-
-
-
-
-
+
+
+
+
+
{{ $t('dashboard.continueLearningTitle') }}
-
-
-
-
-
{{ $t("discovery.searchBtn") }}
+
+
+
+
+
![]()
+
+
+
+
+
+
+ {{ course.category_name }}
+
+
{{ getLocalizedText(course.title) }}
+
+
+
+
+ {{ $t('course.progress') }}: {{ course.progress }}%
+
+
+
+
+
+
-
+
-
-
+
+
+
+
+
{{ $t('myCourses.title') }}
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
- {{ searchQuery ? $t('discovery.emptyTitle') : $t('myCourses.emptyTitle') }}
-
-
- {{ searchQuery ? $t('discovery.emptyDesc') : $t('myCourses.emptyDesc') }}
-
-
{{ $t('myCourses.goToDiscovery') }}
-
+
+
+
+
+
+
+
+
+
+
+
+
+
![]()
+
+
+ {{ course.category_name }}
+
+
+
+
+
+
{{ getLocalizedText(course.title) }}
+
+
+
+
+
+
{{ $t('course.progress') }}: {{ course.progress }}%
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
![]()
+
+
+ {{ course.category_name }}
+
+
+
+
+
+
+
+
{{ getLocalizedText(course.title) }}
+
+
+
+
+
+
+
+ {{ $t('course.progress') }}:
+ {{ course.progress }}%
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ $t('myCourses.searchNoResult') }}
+
{{ $t('myCourses.searchNoResultDesc') }}
+
+
+
-
- ✓
-
+ ✓
{{ $t('enrollment.successTitle') }}
{{ $t('enrollment.successDesc') }}
-
-
-
+
+
+
-
-
-
diff --git a/Frontend-Learner/pages/dashboard/profile.vue b/Frontend-Learner/pages/dashboard/profile.vue
index cd978e6a..74b4c141 100644
--- a/Frontend-Learner/pages/dashboard/profile.vue
+++ b/Frontend-Learner/pages/dashboard/profile.vue
@@ -4,13 +4,15 @@ definePageMeta({
middleware: 'auth'
})
-useHead({
- title: 'ตั้งค่าบัญชี - e-Learning'
-})
-
+const { locale, t } = useI18n()
const { currentUser, updateUserProfile, changePassword, uploadAvatar, sendVerifyEmail, fetchUserProfile } = useAuth()
const { getLocalizedText } = useCourse()
-const { locale, t } = useI18n()
+import { useQuasar } from 'quasar'
+const $q = useQuasar()
+
+useHead({
+ title: `${t('userMenu.settings')} - e-Learning`
+})
@@ -57,6 +59,13 @@ const passwordForm = reactive({
confirmPassword: ''
})
+const showPasswordModal = ref(false)
+const showPassword = reactive({
+ current: false,
+ new: false,
+ confirm: false
+})
+
// Rules have been moved to components
@@ -95,9 +104,10 @@ const handleFileUpload = async (fileOrEvent: File | Event) => {
if (result.success && result.data?.avatar_url) {
userData.value.photoURL = result.data.avatar_url
+ $q.notify({ type: 'positive', message: 'อัปเดตรูปโปรไฟล์สำเร็จ', position: 'top' })
} else {
console.error('Upload failed:', result.error)
- alert(result.error || t('profile.updateError'))
+ $q.notify({ type: 'negative', message: result.error || t('profile.updateError') || 'อัปเดตรูปโปรไฟล์ไม่สำเร็จ', position: 'top' })
}
}
}
@@ -131,9 +141,9 @@ const handleUpdateProfile = async () => {
const result = await updateUserProfile(payload)
if (result?.success) {
- // success logic
+ $q.notify({ type: 'positive', message: t('profile.updateSuccess'), position: 'top' })
} else {
- alert(result?.error || t('profile.updateError'))
+ $q.notify({ type: 'negative', message: result?.error || t('profile.updateError'), position: 'top' })
}
isProfileSaving.value = false
@@ -145,19 +155,19 @@ const handleSendVerifyEmail = async () => {
isSendingVerify.value = false
if (result.success) {
- alert(result.message || t('profile.verifyEmailSuccess') || 'ส่งอีเมลยืนยันสำเร็จ')
+ $q.notify({ type: 'positive', message: result.message || t('profile.verifyEmailSuccess') || 'ส่งอีเมลยืนยันสำเร็จ', position: 'top' })
} else {
if (result.code === 400) {
- alert(t('profile.emailAlreadyVerified') || 'อีเมลของคุณได้รับการยืนยันแล้ว')
+ $q.notify({ type: 'warning', message: t('profile.emailAlreadyVerified') || 'อีเมลของคุณได้รับการยืนยันแล้ว', position: 'top' })
} else {
- alert(result.error || t('profile.verifyEmailError') || 'ส่งอีเมลไม่สำเร็จ')
+ $q.notify({ type: 'negative', message: result.error || t('profile.verifyEmailError') || 'ส่งอีเมลไม่สำเร็จ', position: 'top' })
}
}
}
const handleUpdatePassword = async () => {
if (passwordForm.newPassword !== passwordForm.confirmPassword) {
- alert('รหัสผ่านใหม่ไม่ตรงกัน')
+ $q.notify({ type: 'negative', message: 'รหัสผ่านใหม่ไม่ตรงกัน', position: 'top' })
return
}
@@ -169,12 +179,13 @@ const handleUpdatePassword = async () => {
})
if (result.success) {
- alert(t('profile.passwordSuccess'))
+ $q.notify({ type: 'positive', message: t('profile.passwordSuccess') || 'เปลี่ยนรหัสผ่านสำเร็จ', position: 'top' })
passwordForm.currentPassword = ''
passwordForm.newPassword = ''
passwordForm.confirmPassword = ''
+ showPasswordModal.value = false
} else {
- alert(result.error || t('profile.passwordError'))
+ $q.notify({ type: 'negative', message: result.error || t('profile.passwordError') || 'เปลี่ยนรหัสผ่านไม่สำเร็จ', position: 'top' })
}
isPasswordSaving.value = false
@@ -203,169 +214,216 @@ onMounted(async () => {
-
+
-
-
-
-
-
-
- {{ (isHydrated && isEditing) ? $t('profile.editProfile') : $t('profile.myProfile') }}
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ userData.firstName }} {{ userData.lastName }}
-
-
-
-
- {{ userData.email }}
-
-
-
- {{ userData.emailVerifiedAt ? $t('profile.emailVerified') : $t('profile.verifyEmail') }}
-
-
-
-
+
+
+
+
{{ $t('profile.myProfile') }}
+
{{ $t('profile.publicInfo') }}
-
-
-
-
-
- {{ $t('profile.accountDetails') }}
-
-
-
-
-
-
-
-
{{ $t('profile.phone') }}
-
{{ userData.phone || '-' }}
-
-
-
-
-
-
-
-
{{ $t('profile.joinedAt') }}
-
{{ formatDate(userData.createdAt) }}
-
-
+
+
+
+
+
+
+
+
{{ $t('profile.avatarHint') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('profile.emailVerified') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
{{ $t('profile.security') }}
+
{{ $t('profile.securitySubtitle') }}
+
+
+
+
+
+
+
+
+
+
{{ $t('profile.password') }}
+
{{ $t('profile.securitySubtitle') }}
+
+
-
-
-
+
+
+
+
+
+
+ {{ $t('profile.changePasswordBtn') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -374,7 +432,13 @@ onMounted(async () => {
color: white;
}
-/* Removed card-premium and dark mode overrides as we used utility classes */
+.custom-pwd-input :deep(.q-field__control) {
+ border-radius: 8px;
+ background-color: #f8fafc;
+}
+.dark .custom-pwd-input :deep(.q-field__control) {
+ background-color: #1e293b;
+}
.fade-in {
animation: fadeIn 0.4s ease-out forwards;
diff --git a/Frontend-Learner/pages/index.vue b/Frontend-Learner/pages/index.vue
index caf12a55..4a01f6c3 100644
--- a/Frontend-Learner/pages/index.vue
+++ b/Frontend-Learner/pages/index.vue
@@ -22,15 +22,20 @@ const { user } = useAuth()
const categoryCards = CATEGORY_CARDS
const whyChooseUs = WHY_CHOOSE_US
+//ระดับความยาก
+const levelModel = ref('ระดับทั้งหมด')
+const levelOptions = ['ระดับทั้งหมด','ระดับเริ่มต้น', 'ระดับกลาง', 'ระดับสูง']
+
const categories = ref
([])
const topCourses = ref([])
const selectedCategory = ref('all')
const isLoading = ref(false)
const currentSlide = ref(0)
+
const courseChunks = computed(() => {
const chunkSize = 4
const chunks = []
- if (!topCourses.value) return []
+ if (!topCourses.value || topCourses.value.length === 0) return []
for (let i = 0; i < topCourses.value.length; i += chunkSize) {
chunks.push(topCourses.value.slice(i, i + chunkSize))
}
@@ -42,7 +47,7 @@ const loadData = async () => {
try {
const [catRes, courseRes] = await Promise.all([
fetchCategories(),
- fetchCourses({ limit: 8, forceRefresh: true })
+ fetchCourses({ limit: 12, forceRefresh: true })
])
if (catRes.success) categories.value = catRes.data || []
@@ -61,7 +66,7 @@ const goBrowse = (slug: string) => {
watch(selectedCategory, async (newVal) => {
isLoading.value = true
try {
- const params: any = { limit: 8 }
+ const params: any = { limit: 12 }
if (newVal !== 'all') {
const category = categories.value.find(c => c.slug === newVal)
if (category) {
@@ -87,41 +92,49 @@ onMounted(() => {
-
-
-
-
-
-
-
-
-
-
E-Learning Platform
+
+
+
+
+
+
+
+
+
+ มีคอร์สเรียนใหม่
+
-
- คอร์สเรียนออนไลน์
เพิ่มทักษะยุคดิจิทัล
+
+
+
+ ขยายขอบเขตความรู้ของคุณ
+ ด้วยการเรียนรู้ออนไลน์
-
- แหล่งรวมคอร์สออนไลน์คุณภาพสูงที่จะช่วยอัปสกิลให้คุณทำงานเก่งขึ้น พัฒนาทักษะที่ตลาดต้องการ พร้อมให้คุณก้าวไปข้างหน้าได้อย่างมั่นใจ!
+
+
+
+ จุดประกายความรู้ของคุณ และเริ่มต้นอัปสกิลกับผู้เชี่ยวชาญ
+ ในอุตสาหกรรมที่มีความรู้รอบด้านหลากหลายในหลายสาขา
+ เรียนได้ทุกที่ ทุกเวลา
-
-
-
-
-
-
-
-

-
+
+
+
+

+
-
-
-
-
+
+
-
+
-
-
+
+
+
-
+
ทำไมต้องเลือกแพลตฟอร์มของเรา?
-
+
เรามีเครื่องมือและความเชี่ยวชาญที่จะช่วยให้คุณประสบความสำเร็จในการเปลี่ยนสายอาชีพและการสร้างทักษะระดับมืออาชีพ
-
+
+
-
@@ -183,38 +208,39 @@ onMounted(() => {
-
+
+
+
-
+
เลือกเรียนตามเรื่องที่คุณสนใจ
-
-
+
+
-
-
-
-
-
+
-
+
+
-
คอร์สออนไลน์
-
เริ่มต้นเรียนรู้ทักษะใหม่ด้วยคอร์สคุณภาพจากผู้เชี่ยวชาญ
+
คอร์สออนไลน์
-
- คอร์สออนไลน์ทั้งหมด
+
+ ดูคอร์สทั้งหมด
+
-
-
+
+
+
+
+
+
+
+
+
+ พร้อมเริ่มต้นการเรียนรู้แล้วหรือยัง?
+
+
+ อัปสกิลและรับทักษะที่คุณต้องการเพื่อก้าวหน้าในระดับมืออาชีพ
+ เปิดประสบการณ์การเรียนรู้รูปแบบใหม่ สมัครเลยวันนี้เพื่อเริ่มต้นเข้าสู่บทเรียน
+
+
+
+ สำรวจคอร์สเรียน
+
+
+
+
+
+
+
-
-